summaryrefslogtreecommitdiff
path: root/chromium/net
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/net
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/net')
-rw-r--r--chromium/net/OWNERS6
-rw-r--r--chromium/net/android/keystore_unittest.cc5
-rw-r--r--chromium/net/android/network_change_notifier_delegate_android.cc6
-rw-r--r--chromium/net/base/address_tracker_linux.cc2
-rw-r--r--chromium/net/base/address_tracker_linux_unittest.cc2
-rw-r--r--chromium/net/base/dir_header.html13
-rw-r--r--chromium/net/base/directory_lister.cc3
-rw-r--r--chromium/net/base/directory_lister_unittest.cc2
-rw-r--r--chromium/net/base/dns_util.cc14
-rw-r--r--chromium/net/base/dns_util.h4
-rw-r--r--chromium/net/base/dns_util_unittest.cc13
-rw-r--r--chromium/net/base/file_stream_context.cc29
-rw-r--r--chromium/net/base/file_stream_unittest.cc111
-rw-r--r--chromium/net/base/filter.cc6
-rw-r--r--chromium/net/base/gzip_filter_unittest.cc5
-rw-r--r--chromium/net/base/gzip_header.cc2
-rw-r--r--chromium/net/base/keygen_handler.cc4
-rw-r--r--chromium/net/base/keygen_handler.h20
-rw-r--r--chromium/net/base/keygen_handler_nss.cc22
-rw-r--r--chromium/net/base/keygen_handler_win.cc5
-rw-r--r--chromium/net/base/mime_util.cc78
-rw-r--r--chromium/net/base/mime_util_unittest.cc2
-rw-r--r--chromium/net/base/net_error_list.h20
-rw-r--r--chromium/net/base/net_errors.h4
-rw-r--r--chromium/net/base/net_errors_win.cc2
-rw-r--r--chromium/net/base/net_log_event_type_list.h50
-rw-r--r--chromium/net/base/net_log_logger_unittest.cc6
-rw-r--r--chromium/net/base/net_log_unittest.h17
-rw-r--r--chromium/net/base/net_util.cc134
-rw-r--r--chromium/net/base/net_util.h54
-rw-r--r--chromium/net/base/net_util_posix.cc47
-rw-r--r--chromium/net/base/net_util_unittest.cc60
-rw-r--r--chromium/net/base/net_util_win.cc60
-rw-r--r--chromium/net/base/network_change_notifier_win.cc25
-rw-r--r--chromium/net/base/network_change_notifier_win.h9
-rw-r--r--chromium/net/base/network_delegate.cc103
-rw-r--r--chromium/net/base/network_delegate.h46
-rw-r--r--chromium/net/base/platform_mime_util_linux.cc1
-rw-r--r--chromium/net/base/prioritized_dispatcher_unittest.cc8
-rw-r--r--chromium/net/base/priority_queue.h86
-rw-r--r--chromium/net/base/priority_queue_unittest.cc37
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.cc56997
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.dat918
-rw-r--r--chromium/net/base/registry_controlled_domains/effective_tld_names.gperf338
-rw-r--r--chromium/net/base/request_priority.cc28
-rw-r--r--chromium/net/base/request_priority.h17
-rw-r--r--chromium/net/base/upload_data_stream.cc8
-rw-r--r--chromium/net/base/upload_data_stream.h5
-rw-r--r--chromium/net/base/upload_data_stream_unittest.cc74
-rw-r--r--chromium/net/base/upload_file_element_reader.cc28
-rw-r--r--chromium/net/base/upload_file_element_reader_unittest.cc20
-rw-r--r--chromium/net/base/url_util.cc81
-rw-r--r--chromium/net/base/url_util.h26
-rw-r--r--chromium/net/base/url_util_unittest.cc51
-rw-r--r--chromium/net/cert/cert_database.cc4
-rw-r--r--chromium/net/cert/cert_database.h13
-rw-r--r--chromium/net/cert/cert_database_android.cc5
-rw-r--r--chromium/net/cert/cert_database_mac.cc2
-rw-r--r--chromium/net/cert/cert_database_nss.cc4
-rw-r--r--chromium/net/cert/cert_status_flags.cc12
-rw-r--r--chromium/net/cert/cert_status_flags.h3
-rw-r--r--chromium/net/cert/cert_verify_proc.cc145
-rw-r--r--chromium/net/cert/cert_verify_proc.h9
-rw-r--r--chromium/net/cert/cert_verify_proc_android.cc4
-rw-r--r--chromium/net/cert/cert_verify_proc_mac.cc4
-rw-r--r--chromium/net/cert/cert_verify_proc_nss.cc8
-rw-r--r--chromium/net/cert/cert_verify_proc_openssl.cc4
-rw-r--r--chromium/net/cert/cert_verify_proc_unittest.cc213
-rw-r--r--chromium/net/cert/cert_verify_proc_win.cc4
-rw-r--r--chromium/net/cert/cert_verify_result.cc1
-rw-r--r--chromium/net/cert/cert_verify_result.h4
-rw-r--r--chromium/net/cert/ct_known_logs.cc80
-rw-r--r--chromium/net/cert/ct_known_logs.h30
-rw-r--r--chromium/net/cert/ct_log_verifier.cc56
-rw-r--r--chromium/net/cert/ct_log_verifier.h78
-rw-r--r--chromium/net/cert/ct_log_verifier_nss.cc142
-rw-r--r--chromium/net/cert/ct_log_verifier_openssl.cc120
-rw-r--r--chromium/net/cert/ct_log_verifier_unittest.cc78
-rw-r--r--chromium/net/cert/ct_objects_extractor.h64
-rw-r--r--chromium/net/cert/ct_objects_extractor_nss.cc617
-rw-r--r--chromium/net/cert/ct_objects_extractor_openssl.cc41
-rw-r--r--chromium/net/cert/ct_objects_extractor_unittest.cc181
-rw-r--r--chromium/net/cert/ct_serialization.cc368
-rw-r--r--chromium/net/cert/ct_serialization.h75
-rw-r--r--chromium/net/cert/ct_serialization_unittest.cc166
-rw-r--r--chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc159
-rw-r--r--chromium/net/cert/ct_signed_certificate_timestamp_log_param.h35
-rw-r--r--chromium/net/cert/ct_verifier.h43
-rw-r--r--chromium/net/cert/ct_verify_result.cc17
-rw-r--r--chromium/net/cert/ct_verify_result.h37
-rw-r--r--chromium/net/cert/ev_root_ca_metadata.cc43
-rw-r--r--chromium/net/cert/ev_root_ca_metadata_unittest.cc12
-rw-r--r--chromium/net/cert/jwk_serializer.h2
-rw-r--r--chromium/net/cert/jwk_serializer_nss.cc2
-rw-r--r--chromium/net/cert/jwk_serializer_unittest.cc9
-rw-r--r--chromium/net/cert/multi_log_ct_verifier.cc177
-rw-r--r--chromium/net/cert/multi_log_ct_verifier.h71
-rw-r--r--chromium/net/cert/multi_log_ct_verifier_unittest.cc173
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier.cc2
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier.h2
-rw-r--r--chromium/net/cert/multi_threaded_cert_verifier_unittest.cc8
-rw-r--r--chromium/net/cert/nss_cert_database.cc65
-rw-r--r--chromium/net/cert/nss_cert_database.h21
-rw-r--r--chromium/net/cert/scoped_nss_types.h26
-rw-r--r--chromium/net/cert/sct_status_flags.h32
-rw-r--r--chromium/net/cert/signed_certificate_timestamp.cc94
-rw-r--r--chromium/net/cert/signed_certificate_timestamp.h129
-rw-r--r--chromium/net/cert/signed_certificate_timestamp_unittest.cc54
-rw-r--r--chromium/net/cert/x509_certificate.cc13
-rw-r--r--chromium/net/cert/x509_certificate.h13
-rw-r--r--chromium/net/cert/x509_certificate_mac.cc54
-rw-r--r--chromium/net/cert/x509_certificate_unittest.cc14
-rw-r--r--chromium/net/cert/x509_util.cc58
-rw-r--r--chromium/net/cert/x509_util.h49
-rw-r--r--chromium/net/cert/x509_util_android.cc25
-rw-r--r--chromium/net/cert/x509_util_android.h16
-rw-r--r--chromium/net/cert/x509_util_nss.cc22
-rw-r--r--chromium/net/cert/x509_util_nss_unittest.cc11
-rw-r--r--chromium/net/cert/x509_util_openssl.cc229
-rw-r--r--chromium/net/cert/x509_util_openssl_unittest.cc105
-rw-r--r--chromium/net/cert/x509_util_unittest.cc31
-rw-r--r--chromium/net/cookies/cookie_monster.cc359
-rw-r--r--chromium/net/cookies/cookie_monster.h7
-rw-r--r--chromium/net/cookies/cookie_monster_unittest.cc17
-rw-r--r--chromium/net/data/file_stream_unittest/red.pngbin0 -> 173 bytes
-rw-r--r--chromium/net/data/ftp/dir-listing-ls-3213
-rw-r--r--chromium/net/data/ftp/dir-listing-ls-32.expected98
-rw-r--r--chromium/net/data/ssl/certificates/README9
-rw-r--r--chromium/net/data/ssl/certificates/ct-test-embedded-cert.pem126
-rw-r--r--chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-chain.pem188
-rw-r--r--chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-preca-chain.pem188
-rw-r--r--chromium/net/data/ssl/certificates/ct-test-embedded-with-preca-chain.pem126
-rw-r--r--chromium/net/data/ssl/certificates/name_constraint_bad.crt109
-rw-r--r--chromium/net/data/ssl/certificates/name_constraint_ok.crt109
-rw-r--r--chromium/net/data/ssl/certificates/quic_intermediate.crt76
-rw-r--r--chromium/net/data/ssl/certificates/quic_intermediate.key27
-rw-r--r--chromium/net/data/ssl/certificates/quic_root.crt130
-rw-r--r--chromium/net/data/ssl/certificates/quic_root.key27
-rw-r--r--chromium/net/data/ssl/certificates/quic_test.example.com.crt77
-rw-r--r--chromium/net/data/ssl/certificates/quic_test.example.com.key27
-rw-r--r--chromium/net/data/ssl/certificates/quic_test_ecc.example.com.crt50
-rw-r--r--chromium/net/data/ssl/certificates/quic_test_ecc.example.com.key5
-rw-r--r--chromium/net/data/url_request_unittest/filedir-sentinel1
-rw-r--r--chromium/net/disk_cache/backend_impl.cc48
-rw-r--r--chromium/net/disk_cache/backend_impl.h3
-rw-r--r--chromium/net/disk_cache/backend_unittest.cc83
-rw-r--r--chromium/net/disk_cache/block_files.cc2
-rw-r--r--chromium/net/disk_cache/block_files_unittest.cc16
-rw-r--r--chromium/net/disk_cache/cache_creator.cc4
-rw-r--r--chromium/net/disk_cache/cache_util.cc44
-rw-r--r--chromium/net/disk_cache/cache_util.h7
-rw-r--r--chromium/net/disk_cache/cache_util_posix.cc2
-rw-r--r--chromium/net/disk_cache/cache_util_unittest.cc16
-rw-r--r--chromium/net/disk_cache/entry_unittest.cc204
-rw-r--r--chromium/net/disk_cache/file.h3
-rw-r--r--chromium/net/disk_cache/file_ios.cc312
-rw-r--r--chromium/net/disk_cache/file_posix.cc7
-rw-r--r--chromium/net/disk_cache/file_win.cc4
-rw-r--r--chromium/net/disk_cache/mem_backend_impl.cc8
-rw-r--r--chromium/net/disk_cache/simple/simple_backend_impl.cc57
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_format.cc5
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_format.h10
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.cc248
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.h33
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_operation.cc139
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_operation.h44
-rw-r--r--chromium/net/disk_cache/simple/simple_histogram_macros.h39
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file.cc7
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file.h8
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file_unittest.cc91
-rw-r--r--chromium/net/disk_cache/simple/simple_index_unittest.cc2
-rw-r--r--chromium/net/disk_cache/simple/simple_net_log_parameters.h6
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.cc551
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.h97
-rw-r--r--chromium/net/disk_cache/simple/simple_util.cc6
-rw-r--r--chromium/net/disk_cache/simple/simple_util.h3
-rw-r--r--chromium/net/disk_cache/simple/simple_version_upgrade_unittest.cc6
-rw-r--r--chromium/net/disk_cache/v3/backend_worker.cc2
-rw-r--r--chromium/net/dns/address_sorter_posix.cc31
-rw-r--r--chromium/net/dns/dns_config_service_posix.cc128
-rw-r--r--chromium/net/dns/dns_config_watcher_mac.cc106
-rw-r--r--chromium/net/dns/dns_config_watcher_mac.h26
-rw-r--r--chromium/net/dns/dns_hosts.cc2
-rw-r--r--chromium/net/dns/dns_socket_pool.cc16
-rw-r--r--chromium/net/dns/host_resolver.cc3
-rw-r--r--chromium/net/dns/host_resolver_impl.cc2
-rw-r--r--chromium/net/dns/host_resolver_impl_unittest.cc10
-rw-r--r--chromium/net/dns/mapped_host_resolver.cc8
-rw-r--r--chromium/net/dns/mapped_host_resolver.h2
-rw-r--r--chromium/net/dns/mdns_client.cc74
-rw-r--r--chromium/net/dns/mdns_client.h27
-rw-r--r--chromium/net/dns/mdns_client_impl.cc131
-rw-r--r--chromium/net/dns/mdns_client_impl.h46
-rw-r--r--chromium/net/dns/mdns_client_unittest.cc198
-rw-r--r--chromium/net/dns/mock_mdns_socket_factory.cc43
-rw-r--r--chromium/net/dns/mock_mdns_socket_factory.h33
-rw-r--r--chromium/net/dns/serial_worker.cc6
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc5
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_unittest.cc1
-rw-r--r--chromium/net/ftp/ftp_network_transaction.cc2
-rw-r--r--chromium/net/ftp/ftp_util.cc38
-rw-r--r--chromium/net/http/http_auth_cache.cc3
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.cc12
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.h4
-rw-r--r--chromium/net/http/http_auth_gssapi_posix_unittest.cc6
-rw-r--r--chromium/net/http/http_auth_handler_basic.cc10
-rw-r--r--chromium/net/http/http_auth_handler_digest.cc3
-rw-r--r--chromium/net/http/http_auth_handler_negotiate.cc11
-rw-r--r--chromium/net/http/http_auth_handler_negotiate.h6
-rw-r--r--chromium/net/http/http_auth_handler_negotiate_unittest.cc20
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.cc12
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.h2
-rw-r--r--chromium/net/http/http_auth_sspi_win.cc13
-rw-r--r--chromium/net/http/http_auth_sspi_win.h4
-rw-r--r--chromium/net/http/http_auth_sspi_win_unittest.cc6
-rw-r--r--chromium/net/http/http_basic_state.cc68
-rw-r--r--chromium/net/http/http_basic_state.h72
-rw-r--r--chromium/net/http/http_basic_state_unittest.cc78
-rw-r--r--chromium/net/http/http_basic_stream.cc91
-rw-r--r--chromium/net/http/http_basic_stream.h29
-rw-r--r--chromium/net/http/http_byte_range.cc41
-rw-r--r--chromium/net/http/http_byte_range.h14
-rw-r--r--chromium/net/http/http_byte_range_unittest.cc14
-rw-r--r--chromium/net/http/http_cache_transaction.cc43
-rw-r--r--chromium/net/http/http_cache_transaction.h11
-rw-r--r--chromium/net/http/http_cache_unittest.cc107
-rw-r--r--chromium/net/http/http_chunked_decoder.cc2
-rw-r--r--chromium/net/http/http_network_layer.cc13
-rw-r--r--chromium/net/http/http_network_layer.h6
-rw-r--r--chromium/net/http/http_network_layer_unittest.cc493
-rw-r--r--chromium/net/http/http_network_session.cc11
-rw-r--r--chromium/net/http/http_network_session.h9
-rw-r--r--chromium/net/http/http_network_session_peer.cc14
-rw-r--r--chromium/net/http/http_network_session_peer.h8
-rw-r--r--chromium/net/http/http_network_transaction.cc229
-rw-r--r--chromium/net/http/http_network_transaction.h26
-rw-r--r--chromium/net/http/http_network_transaction_ssl_unittest.cc146
-rw-r--r--chromium/net/http/http_network_transaction_unittest.cc526
-rw-r--r--chromium/net/http/http_pipelined_connection_impl.cc7
-rw-r--r--chromium/net/http/http_pipelined_connection_impl.h2
-rw-r--r--chromium/net/http/http_pipelined_host_forced_unittest.cc4
-rw-r--r--chromium/net/http/http_pipelined_host_impl_unittest.cc8
-rw-r--r--chromium/net/http/http_pipelined_stream.cc4
-rw-r--r--chromium/net/http/http_pipelined_stream.h2
-rw-r--r--chromium/net/http/http_proxy_client_socket_pool_unittest.cc9
-rw-r--r--chromium/net/http/http_request_headers.cc21
-rw-r--r--chromium/net/http/http_request_info.cc1
-rw-r--r--chromium/net/http/http_request_info.h4
-rw-r--r--chromium/net/http/http_response_body_drainer.cc4
-rw-r--r--chromium/net/http/http_response_body_drainer.h6
-rw-r--r--chromium/net/http/http_response_body_drainer_unittest.cc1
-rw-r--r--chromium/net/http/http_response_headers.cc71
-rw-r--r--chromium/net/http/http_response_headers.h29
-rw-r--r--chromium/net/http/http_response_headers_unittest.cc153
-rw-r--r--chromium/net/http/http_response_info.cc39
-rw-r--r--chromium/net/http/http_response_info.h2
-rw-r--r--chromium/net/http/http_security_headers.cc13
-rw-r--r--chromium/net/http/http_security_headers_unittest.cc14
-rw-r--r--chromium/net/http/http_server_properties.cc41
-rw-r--r--chromium/net/http/http_server_properties.h21
-rw-r--r--chromium/net/http/http_server_properties_impl.cc6
-rw-r--r--chromium/net/http/http_server_properties_impl.h4
-rw-r--r--chromium/net/http/http_server_properties_impl_unittest.cc18
-rw-r--r--chromium/net/http/http_stream_base.h5
-rw-r--r--chromium/net/http/http_stream_factory.cc82
-rw-r--r--chromium/net/http/http_stream_factory.h47
-rw-r--r--chromium/net/http/http_stream_factory_impl.cc30
-rw-r--r--chromium/net/http/http_stream_factory_impl.h9
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.cc36
-rw-r--r--chromium/net/http/http_stream_factory_impl_job.h4
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.cc21
-rw-r--r--chromium/net/http/http_stream_factory_impl_request.h19
-rw-r--r--chromium/net/http/http_stream_factory_impl_request_unittest.cc7
-rw-r--r--chromium/net/http/http_stream_factory_impl_unittest.cc278
-rw-r--r--chromium/net/http/http_stream_parser.cc6
-rw-r--r--chromium/net/http/http_stream_parser.h6
-rw-r--r--chromium/net/http/http_stream_parser_unittest.cc399
-rw-r--r--chromium/net/http/http_transaction.h7
-rw-r--r--chromium/net/http/http_transaction_unittest.cc6
-rw-r--r--chromium/net/http/http_transaction_unittest.h8
-rw-r--r--chromium/net/http/http_util_icu.cc7
-rw-r--r--chromium/net/http/http_util_unittest.cc22
-rw-r--r--chromium/net/http/partial_data.cc44
-rw-r--r--chromium/net/http/proxy_connect_redirect_http_stream.cc4
-rw-r--r--chromium/net/http/proxy_connect_redirect_http_stream.h2
-rw-r--r--chromium/net/http/transport_security_persister.cc318
-rw-r--r--chromium/net/http/transport_security_persister.h138
-rw-r--r--chromium/net/http/transport_security_persister_unittest.cc201
-rw-r--r--chromium/net/http/transport_security_state.cc13
-rw-r--r--chromium/net/http/transport_security_state.h2
-rw-r--r--chromium/net/http/transport_security_state_static.certs309
-rw-r--r--chromium/net/http/transport_security_state_static.h139
-rw-r--r--chromium/net/http/transport_security_state_static.json82
-rw-r--r--chromium/net/http/transport_security_state_unittest.cc180
-rw-r--r--chromium/net/net.gyp387
-rw-r--r--chromium/net/net_unittests.isolate30
-rw-r--r--chromium/net/ocsp/nss_ocsp.cc13
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc42
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h4
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc29
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc4
-rw-r--r--chromium/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc4
-rw-r--r--chromium/net/proxy/proxy_config_service_android.cc32
-rw-r--r--chromium/net/proxy/proxy_config_service_android.h7
-rw-r--r--chromium/net/proxy/proxy_config_service_linux.cc6
-rw-r--r--chromium/net/proxy/proxy_config_service_linux_unittest.cc8
-rw-r--r--chromium/net/proxy/proxy_config_service_mac.cc2
-rw-r--r--chromium/net/proxy/proxy_list.cc68
-rw-r--r--chromium/net/proxy/proxy_list.h24
-rw-r--r--chromium/net/proxy/proxy_resolver_v8.cc100
-rw-r--r--chromium/net/proxy/proxy_resolver_v8_unittest.cc11
-rw-r--r--chromium/net/proxy/proxy_script_decider.cc53
-rw-r--r--chromium/net/proxy/proxy_script_decider_unittest.cc82
-rw-r--r--chromium/net/proxy/proxy_script_fetcher_impl.cc8
-rw-r--r--chromium/net/proxy/proxy_server.cc16
-rw-r--r--chromium/net/proxy/proxy_server.h8
-rw-r--r--chromium/net/proxy/proxy_service.cc46
-rw-r--r--chromium/net/proxy/proxy_service.h46
-rw-r--r--chromium/net/quic/congestion_control/channel_estimator.cc4
-rw-r--r--chromium/net/quic/congestion_control/cubic.cc14
-rw-r--r--chromium/net/quic/congestion_control/cubic_test.cc8
-rw-r--r--chromium/net/quic/congestion_control/fix_rate_sender.cc51
-rw-r--r--chromium/net/quic/congestion_control/fix_rate_sender.h28
-rw-r--r--chromium/net/quic/congestion_control/fix_rate_test.cc30
-rw-r--r--chromium/net/quic/congestion_control/hybrid_slow_start.cc4
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc12
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_overuse_detector.cc20
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_probe.cc15
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_probe.h7
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_probe_test.cc23
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_sender.cc77
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_sender.h32
-rw-r--r--chromium/net/quic/congestion_control/inter_arrival_sender_test.cc40
-rw-r--r--chromium/net/quic/congestion_control/paced_sender.cc15
-rw-r--r--chromium/net/quic/congestion_control/paced_sender.h7
-rw-r--r--chromium/net/quic/congestion_control/paced_sender_test.cc19
-rw-r--r--chromium/net/quic/congestion_control/pacing_sender.cc138
-rw-r--r--chromium/net/quic/congestion_control/pacing_sender.h77
-rw-r--r--chromium/net/quic/congestion_control/pacing_sender_test.cc168
-rw-r--r--chromium/net/quic/congestion_control/quic_congestion_control_test.cc140
-rw-r--r--chromium/net/quic/congestion_control/quic_congestion_manager.cc234
-rw-r--r--chromium/net/quic/congestion_control/quic_congestion_manager.h121
-rw-r--r--chromium/net/quic/congestion_control/quic_congestion_manager_test.cc247
-rw-r--r--chromium/net/quic/congestion_control/receive_algorithm_interface.cc1
-rw-r--r--chromium/net/quic/congestion_control/receive_algorithm_interface.h3
-rw-r--r--chromium/net/quic/congestion_control/send_algorithm_interface.cc6
-rw-r--r--chromium/net/quic/congestion_control/send_algorithm_interface.h64
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender.cc146
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender.h50
-rw-r--r--chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc206
-rw-r--r--chromium/net/quic/congestion_control/tcp_receiver.cc3
-rw-r--r--chromium/net/quic/congestion_control/tcp_receiver.h3
-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.cc26
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc5
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_decrypter_test.cc115
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_encrypter.h5
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc36
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc23
-rw-r--r--chromium/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc105
-rw-r--r--chromium/net/quic/crypto/channel_id_test.cc86
-rw-r--r--chromium/net/quic/crypto/common_cert_set_test.cc2
-rw-r--r--chromium/net/quic/crypto/crypto_handshake.cc603
-rw-r--r--chromium/net/quic/crypto/crypto_handshake.h178
-rw-r--r--chromium/net/quic/crypto/crypto_protocol.h22
-rw-r--r--chromium/net/quic/crypto/crypto_server_test.cc255
-rw-r--r--chromium/net/quic/crypto/crypto_utils.cc24
-rw-r--r--chromium/net/quic/crypto/crypto_utils.h2
-rw-r--r--chromium/net/quic/crypto/local_strike_register_client.cc46
-rw-r--r--chromium/net/quic/crypto/local_strike_register_client.h42
-rw-r--r--chromium/net/quic/crypto/local_strike_register_client_test.cc119
-rw-r--r--chromium/net/quic/crypto/null_decrypter.cc32
-rw-r--r--chromium/net/quic/crypto/null_decrypter.h7
-rw-r--r--chromium/net/quic/crypto/null_decrypter_test.cc35
-rw-r--r--chromium/net/quic/crypto/null_encrypter.cc18
-rw-r--r--chromium/net/quic/crypto/null_encrypter.h4
-rw-r--r--chromium/net/quic/crypto/null_encrypter_test.cc25
-rw-r--r--chromium/net/quic/crypto/p256_key_exchange_nss.cc28
-rw-r--r--chromium/net/quic/crypto/p256_key_exchange_openssl.cc18
-rw-r--r--chromium/net/quic/crypto/proof_test.cc148
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium.cc2
-rw-r--r--chromium/net/quic/crypto/quic_crypto_client_config.cc650
-rw-r--r--chromium/net/quic/crypto/quic_crypto_client_config.h218
-rw-r--r--chromium/net/quic/crypto/quic_crypto_client_config_test.cc59
-rw-r--r--chromium/net/quic/crypto/quic_crypto_server_config.cc (renamed from chromium/net/quic/crypto/crypto_server_config.cc)474
-rw-r--r--chromium/net/quic/crypto/quic_crypto_server_config.h (renamed from chromium/net/quic/crypto/crypto_server_config.h)101
-rw-r--r--chromium/net/quic/crypto/quic_crypto_server_config_test.cc (renamed from chromium/net/quic/crypto/crypto_handshake_test.cc)11
-rw-r--r--chromium/net/quic/crypto/quic_random.cc7
-rw-r--r--chromium/net/quic/crypto/quic_random.h3
-rw-r--r--chromium/net/quic/crypto/quic_random_test.cc4
-rw-r--r--chromium/net/quic/crypto/strike_register_client.h57
-rw-r--r--chromium/net/quic/iovector.cc13
-rw-r--r--chromium/net/quic/iovector.h201
-rw-r--r--chromium/net/quic/iovector_test.cc283
-rw-r--r--chromium/net/quic/port_suggester.cc49
-rw-r--r--chromium/net/quic/port_suggester.h50
-rw-r--r--chromium/net/quic/port_suggester_unittest.cc112
-rw-r--r--chromium/net/quic/quic_ack_notifier.cc25
-rw-r--r--chromium/net/quic/quic_ack_notifier.h15
-rw-r--r--chromium/net/quic/quic_ack_notifier_manager.cc105
-rw-r--r--chromium/net/quic/quic_ack_notifier_manager.h78
-rw-r--r--chromium/net/quic/quic_ack_notifier_test.cc60
-rw-r--r--chromium/net/quic/quic_alarm_test.cc4
-rw-r--r--chromium/net/quic/quic_bandwidth.cc5
-rw-r--r--chromium/net/quic/quic_bandwidth.h2
-rw-r--r--chromium/net/quic/quic_bandwidth_test.cc5
-rw-r--r--chromium/net/quic/quic_client_session.cc161
-rw-r--r--chromium/net/quic/quic_client_session.h48
-rw-r--r--chromium/net/quic/quic_client_session_test.cc89
-rw-r--r--chromium/net/quic/quic_config.cc74
-rw-r--r--chromium/net/quic/quic_config.h18
-rw-r--r--chromium/net/quic/quic_config_test.cc34
-rw-r--r--chromium/net/quic/quic_connection.cc1046
-rw-r--r--chromium/net/quic/quic_connection.h312
-rw-r--r--chromium/net/quic/quic_connection_helper.cc81
-rw-r--r--chromium/net/quic/quic_connection_helper.h19
-rw-r--r--chromium/net/quic/quic_connection_helper_test.cc431
-rw-r--r--chromium/net/quic/quic_connection_logger.cc25
-rw-r--r--chromium/net/quic/quic_connection_logger.h5
-rw-r--r--chromium/net/quic/quic_connection_stats.cc22
-rw-r--r--chromium/net/quic/quic_connection_stats.h19
-rw-r--r--chromium/net/quic/quic_connection_test.cc1667
-rw-r--r--chromium/net/quic/quic_crypto_client_stream.cc29
-rw-r--r--chromium/net/quic/quic_crypto_client_stream.h2
-rw-r--r--chromium/net/quic/quic_crypto_client_stream_test.cc47
-rw-r--r--chromium/net/quic/quic_crypto_server_stream.cc58
-rw-r--r--chromium/net/quic/quic_crypto_server_stream.h31
-rw-r--r--chromium/net/quic/quic_crypto_server_stream_test.cc158
-rw-r--r--chromium/net/quic/quic_crypto_stream.cc18
-rw-r--r--chromium/net/quic/quic_crypto_stream.h7
-rw-r--r--chromium/net/quic/quic_crypto_stream_test.cc20
-rw-r--r--chromium/net/quic/quic_data_reader.cc34
-rw-r--r--chromium/net/quic/quic_data_reader.h5
-rw-r--r--chromium/net/quic/quic_data_stream.cc333
-rw-r--r--chromium/net/quic/quic_data_stream.h140
-rw-r--r--chromium/net/quic/quic_data_stream_test.cc450
-rw-r--r--chromium/net/quic/quic_data_writer.cc51
-rw-r--r--chromium/net/quic/quic_data_writer.h5
-rw-r--r--chromium/net/quic/quic_data_writer_test.cc131
-rw-r--r--chromium/net/quic/quic_default_packet_writer.cc62
-rw-r--r--chromium/net/quic/quic_default_packet_writer.h50
-rw-r--r--chromium/net/quic/quic_end_to_end_unittest.cc310
-rw-r--r--chromium/net/quic/quic_fec_group.cc2
-rw-r--r--chromium/net/quic/quic_fec_group_test.cc2
-rw-r--r--chromium/net/quic/quic_framer.cc849
-rw-r--r--chromium/net/quic/quic_framer.h98
-rw-r--r--chromium/net/quic/quic_framer_test.cc567
-rw-r--r--chromium/net/quic/quic_http_stream.cc100
-rw-r--r--chromium/net/quic/quic_http_stream.h17
-rw-r--r--chromium/net/quic/quic_http_stream_test.cc77
-rw-r--r--chromium/net/quic/quic_http_utils.cc2
-rw-r--r--chromium/net/quic/quic_network_transaction_unittest.cc62
-rw-r--r--chromium/net/quic/quic_packet_creator.cc223
-rw-r--r--chromium/net/quic/quic_packet_creator.h40
-rw-r--r--chromium/net/quic/quic_packet_creator_test.cc240
-rw-r--r--chromium/net/quic/quic_packet_generator.cc51
-rw-r--r--chromium/net/quic/quic_packet_generator.h15
-rw-r--r--chromium/net/quic/quic_packet_generator_test.cc82
-rw-r--r--chromium/net/quic/quic_packet_writer.h41
-rw-r--r--chromium/net/quic/quic_protocol.cc104
-rw-r--r--chromium/net/quic/quic_protocol.h141
-rw-r--r--chromium/net/quic/quic_protocol_test.cc43
-rw-r--r--chromium/net/quic/quic_received_packet_manager.cc83
-rw-r--r--chromium/net/quic/quic_received_packet_manager.h37
-rw-r--r--chromium/net/quic/quic_received_packet_manager_test.cc28
-rw-r--r--chromium/net/quic/quic_reliable_client_stream.cc24
-rw-r--r--chromium/net/quic/quic_reliable_client_stream.h29
-rw-r--r--chromium/net/quic/quic_reliable_client_stream_test.cc61
-rw-r--r--chromium/net/quic/quic_sent_packet_manager.cc762
-rw-r--r--chromium/net/quic/quic_sent_packet_manager.h290
-rw-r--r--chromium/net/quic/quic_sent_packet_manager_test.cc862
-rw-r--r--chromium/net/quic/quic_session.cc116
-rw-r--r--chromium/net/quic/quic_session.h57
-rw-r--r--chromium/net/quic/quic_session_test.cc110
-rw-r--r--chromium/net/quic/quic_spdy_compressor.cc5
-rw-r--r--chromium/net/quic/quic_spdy_compressor.h1
-rw-r--r--chromium/net/quic/quic_stream_factory.cc174
-rw-r--r--chromium/net/quic/quic_stream_factory.h71
-rw-r--r--chromium/net/quic/quic_stream_factory_test.cc309
-rw-r--r--chromium/net/quic/quic_stream_sequencer.cc46
-rw-r--r--chromium/net/quic/quic_stream_sequencer.h6
-rw-r--r--chromium/net/quic/quic_stream_sequencer_test.cc113
-rw-r--r--chromium/net/quic/quic_utils.cc28
-rw-r--r--chromium/net/quic/quic_utils.h15
-rw-r--r--chromium/net/quic/quic_utils_test.cc16
-rw-r--r--chromium/net/quic/reliable_quic_stream.cc381
-rw-r--r--chromium/net/quic/reliable_quic_stream.h156
-rw-r--r--chromium/net/quic/reliable_quic_stream_test.cc380
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils.cc46
-rw-r--r--chromium/net/quic/test_tools/crypto_test_utils.h11
-rw-r--r--chromium/net/quic/test_tools/delayed_verify_strike_register_client.cc53
-rw-r--r--chromium/net/quic/test_tools/delayed_verify_strike_register_client.h63
-rw-r--r--chromium/net/quic/test_tools/mock_random.cc14
-rw-r--r--chromium/net/quic/test_tools/mock_random.h7
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.cc66
-rw-r--r--chromium/net/quic/test_tools/quic_connection_peer.h25
-rw-r--r--chromium/net/quic/test_tools/quic_data_stream_peer.cc19
-rw-r--r--chromium/net/quic/test_tools/quic_data_stream_peer.h30
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc66
-rw-r--r--chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h47
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.cc141
-rw-r--r--chromium/net/quic/test_tools/quic_test_utils.h159
-rw-r--r--chromium/net/quic/test_tools/quic_test_writer.cc23
-rw-r--r--chromium/net/quic/test_tools/quic_test_writer.h33
-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.cc20
-rw-r--r--chromium/net/server/http_server_unittest.cc2
-rw-r--r--chromium/net/socket/buffered_write_stream_socket.cc4
-rw-r--r--chromium/net/socket/buffered_write_stream_socket.h3
-rw-r--r--chromium/net/socket/client_socket_factory.cc6
-rw-r--r--chromium/net/socket/client_socket_pool_base.cc136
-rw-r--r--chromium/net/socket/client_socket_pool_base.h41
-rw-r--r--chromium/net/socket/client_socket_pool_base_unittest.cc441
-rw-r--r--chromium/net/socket/client_socket_pool_manager.cc25
-rw-r--r--chromium/net/socket/client_socket_pool_manager.h15
-rw-r--r--chromium/net/socket/client_socket_pool_manager_impl.cc11
-rw-r--r--chromium/net/socket/client_socket_pool_manager_impl.h5
-rw-r--r--chromium/net/socket/next_proto.h20
-rw-r--r--chromium/net/socket/nss_ssl_util.cc118
-rw-r--r--chromium/net/socket/nss_ssl_util.h5
-rw-r--r--chromium/net/socket/socket_descriptor.cc15
-rw-r--r--chromium/net/socket/socket_test_util.cc10
-rw-r--r--chromium/net/socket/socket_test_util.h288
-rw-r--r--chromium/net/socket/socks5_client_socket.cc1
-rw-r--r--chromium/net/socket/socks_client_socket_pool_unittest.cc4
-rw-r--r--chromium/net/socket/ssl_client_socket.cc81
-rw-r--r--chromium/net/socket/ssl_client_socket.h43
-rw-r--r--chromium/net/socket/ssl_client_socket_nss.cc426
-rw-r--r--chromium/net/socket/ssl_client_socket_nss.h15
-rw-r--r--chromium/net/socket/ssl_client_socket_openssl.cc1367
-rw-r--r--chromium/net/socket/ssl_client_socket_openssl.h43
-rw-r--r--chromium/net/socket/ssl_client_socket_openssl_unittest.cc86
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.cc3
-rw-r--r--chromium/net/socket/ssl_client_socket_pool.h2
-rw-r--r--chromium/net/socket/ssl_client_socket_pool_unittest.cc6
-rw-r--r--chromium/net/socket/ssl_client_socket_unittest.cc264
-rw-r--r--chromium/net/socket/ssl_server_socket_nss.cc21
-rw-r--r--chromium/net/socket/ssl_server_socket_unittest.cc10
-rw-r--r--chromium/net/socket/ssl_session_cache_openssl.cc508
-rw-r--r--chromium/net/socket/ssl_session_cache_openssl.h141
-rw-r--r--chromium/net/socket/ssl_session_cache_openssl_unittest.cc378
-rw-r--r--chromium/net/socket/stream_listen_socket.cc10
-rw-r--r--chromium/net/socket/stream_listen_socket.h2
-rw-r--r--chromium/net/socket/tcp_listen_socket_unittest.cc10
-rw-r--r--chromium/net/socket/tcp_socket_libevent.cc20
-rw-r--r--chromium/net/socket/tcp_socket_win.cc18
-rw-r--r--chromium/net/socket/transport_client_socket_pool.cc62
-rw-r--r--chromium/net/socket/transport_client_socket_pool.h9
-rw-r--r--chromium/net/socket/transport_client_socket_pool_unittest.cc21
-rw-r--r--chromium/net/socket/unix_domain_socket_posix.cc4
-rw-r--r--chromium/net/socket/unix_domain_socket_posix_unittest.cc6
-rw-r--r--chromium/net/socket_stream/socket_stream.cc21
-rw-r--r--chromium/net/socket_stream/socket_stream.h2
-rw-r--r--chromium/net/socket_stream/socket_stream_unittest.cc88
-rw-r--r--chromium/net/spdy/buffered_spdy_framer.cc22
-rw-r--r--chromium/net/spdy/buffered_spdy_framer.h12
-rw-r--r--chromium/net/spdy/buffered_spdy_framer_unittest.cc12
-rw-r--r--chromium/net/spdy/spdy_bitmasks.h4
-rw-r--r--chromium/net/spdy/spdy_credential_builder.cc86
-rw-r--r--chromium/net/spdy/spdy_credential_builder.h36
-rw-r--r--chromium/net/spdy/spdy_credential_builder_unittest.cc145
-rw-r--r--chromium/net/spdy/spdy_credential_state.cc69
-rw-r--r--chromium/net/spdy/spdy_credential_state.h56
-rw-r--r--chromium/net/spdy/spdy_credential_state_unittest.cc108
-rw-r--r--chromium/net/spdy/spdy_frame_builder.h3
-rw-r--r--chromium/net/spdy/spdy_framer.cc34
-rw-r--r--chromium/net/spdy/spdy_framer.h7
-rw-r--r--chromium/net/spdy/spdy_framer_test.cc54
-rw-r--r--chromium/net/spdy/spdy_http_stream.cc12
-rw-r--r--chromium/net/spdy/spdy_http_stream.h2
-rw-r--r--chromium/net/spdy/spdy_http_stream_unittest.cc263
-rw-r--r--chromium/net/spdy/spdy_http_utils.cc31
-rw-r--r--chromium/net/spdy/spdy_http_utils.h10
-rw-r--r--chromium/net/spdy/spdy_http_utils_unittest.cc42
-rw-r--r--chromium/net/spdy/spdy_network_transaction_unittest.cc128
-rw-r--r--chromium/net/spdy/spdy_protocol.h4
-rw-r--r--chromium/net/spdy/spdy_protocol_test.cc2
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket_unittest.cc3
-rw-r--r--chromium/net/spdy/spdy_session.cc243
-rw-r--r--chromium/net/spdy/spdy_session.h46
-rw-r--r--chromium/net/spdy/spdy_session_pool.cc26
-rw-r--r--chromium/net/spdy/spdy_session_pool.h7
-rw-r--r--chromium/net/spdy/spdy_session_pool_unittest.cc3
-rw-r--r--chromium/net/spdy/spdy_session_unittest.cc80
-rw-r--r--chromium/net/spdy/spdy_stream.cc111
-rw-r--r--chromium/net/spdy/spdy_stream.h27
-rw-r--r--chromium/net/spdy/spdy_stream_unittest.cc67
-rw-r--r--chromium/net/spdy/spdy_test_util_common.cc18
-rw-r--r--chromium/net/spdy/spdy_websocket_stream_unittest.cc3
-rw-r--r--chromium/net/spdy/spdy_websocket_test_util.cc14
-rw-r--r--chromium/net/spdy/spdy_write_queue.cc20
-rw-r--r--chromium/net/spdy/write_blocked_list.h54
-rw-r--r--chromium/net/spdy/write_blocked_list_test.cc13
-rw-r--r--chromium/net/ssl/client_cert_store.h12
-rw-r--r--chromium/net/ssl/client_cert_store_impl_unittest.cc169
-rw-r--r--chromium/net/ssl/client_cert_store_mac.cc (renamed from chromium/net/ssl/client_cert_store_impl_mac.cc)48
-rw-r--r--chromium/net/ssl/client_cert_store_mac.h (renamed from chromium/net/ssl/client_cert_store_impl.h)36
-rw-r--r--chromium/net/ssl/client_cert_store_mac_unittest.cc89
-rw-r--r--chromium/net/ssl/client_cert_store_nss.cc (renamed from chromium/net/ssl/client_cert_store_impl_nss.cc)71
-rw-r--r--chromium/net/ssl/client_cert_store_nss.h56
-rw-r--r--chromium/net/ssl/client_cert_store_nss_unittest.cc31
-rw-r--r--chromium/net/ssl/client_cert_store_unittest-inl.h128
-rw-r--r--chromium/net/ssl/client_cert_store_win.cc (renamed from chromium/net/ssl/client_cert_store_impl_win.cc)35
-rw-r--r--chromium/net/ssl/client_cert_store_win.h43
-rw-r--r--chromium/net/ssl/client_cert_store_win_unittest.cc28
-rw-r--r--chromium/net/ssl/default_server_bound_cert_store_unittest.cc4
-rw-r--r--chromium/net/ssl/server_bound_cert_service.cc21
-rw-r--r--chromium/net/ssl/server_bound_cert_service.h3
-rw-r--r--chromium/net/ssl/server_bound_cert_service_unittest.cc27
-rw-r--r--chromium/net/ssl/signed_certificate_timestamp_and_status.cc18
-rw-r--r--chromium/net/ssl/signed_certificate_timestamp_and_status.h35
-rw-r--r--chromium/net/ssl/ssl_cipher_suite_names.cc2
-rw-r--r--chromium/net/ssl/ssl_config_service.cc4
-rw-r--r--chromium/net/ssl/ssl_config_service.h9
-rw-r--r--chromium/net/ssl/ssl_info.cc5
-rw-r--r--chromium/net/ssl/ssl_info.h9
-rw-r--r--chromium/net/test/cert_test_util.cc18
-rw-r--r--chromium/net/test/cert_test_util.h14
-rw-r--r--chromium/net/test/ct_test_util.cc245
-rw-r--r--chromium/net/test/ct_test_util.h69
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.cc80
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.h56
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc4
-rw-r--r--chromium/net/test/embedded_test_server/http_request.cc2
-rw-r--r--chromium/net/test/python_utils.cc10
-rw-r--r--chromium/net/test/run_all_unittests.cc4
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.cc24
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.h21
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server.cc8
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server_win.cc9
-rw-r--r--chromium/net/test/spawned_test_server/spawner_communicator.cc7
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp10
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp34
-rw-r--r--chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h5
-rw-r--r--chromium/net/third_party/nss/README.chromium40
-rwxr-xr-xchromium/net/third_party/nss/patches/applypatches.sh20
-rw-r--r--chromium/net/third_party/nss/patches/canfalsestart.patch960
-rw-r--r--chromium/net/third_party/nss/patches/chacha20poly1305.patch22
-rw-r--r--chromium/net/third_party/nss/patches/channelid.patch2
-rw-r--r--chromium/net/third_party/nss/patches/channelid2.patch155
-rw-r--r--chromium/net/third_party/nss/patches/cipherorder.patch106
-rw-r--r--chromium/net/third_party/nss/patches/disableticketrenewal.patch17
-rw-r--r--chromium/net/third_party/nss/patches/fallbackscsv.patch207
-rw-r--r--chromium/net/third_party/nss/patches/paddingextension.patch142
-rw-r--r--chromium/net/third_party/nss/patches/paddingextensionall.patch26
-rw-r--r--chromium/net/third_party/nss/patches/sessioncache.patch100
-rw-r--r--chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch421
-rw-r--r--chromium/net/third_party/nss/patches/sslnoncestatics.patch15
-rw-r--r--chromium/net/third_party/nss/patches/tls12backuphash2.patch127
-rw-r--r--chromium/net/third_party/nss/ssl/SSLerrs.h5
-rw-r--r--chromium/net/third_party/nss/ssl/exports_win.def6
-rw-r--r--chromium/net/third_party/nss/ssl/ssl.h101
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3con.c406
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3ext.c136
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3gthr.c61
-rw-r--r--chromium/net/third_party/nss/ssl/ssl3prot.h1
-rw-r--r--chromium/net/third_party/nss/ssl/sslerr.h1
-rw-r--r--chromium/net/third_party/nss/ssl/sslimpl.h95
-rw-r--r--chromium/net/third_party/nss/ssl/sslnonce.c32
-rw-r--r--chromium/net/third_party/nss/ssl/sslproto.h5
-rw-r--r--chromium/net/third_party/nss/ssl/sslsecur.c116
-rw-r--r--chromium/net/third_party/nss/ssl/sslsock.c69
-rw-r--r--chromium/net/third_party/nss/ssl/sslt.h6
-rw-r--r--chromium/net/tools/DEPS1
-rw-r--r--chromium/net/tools/balsa/balsa_enums.h (renamed from chromium/net/tools/flip_server/balsa_enums.h)8
-rw-r--r--chromium/net/tools/balsa/balsa_frame.cc (renamed from chromium/net/tools/flip_server/balsa_frame.cc)51
-rw-r--r--chromium/net/tools/balsa/balsa_frame.h (renamed from chromium/net/tools/flip_server/balsa_frame.h)20
-rw-r--r--chromium/net/tools/balsa/balsa_frame_test.cc (renamed from chromium/net/tools/flip_server/balsa_frame_test.cc)6
-rw-r--r--chromium/net/tools/balsa/balsa_headers.cc (renamed from chromium/net/tools/flip_server/balsa_headers.cc)14
-rw-r--r--chromium/net/tools/balsa/balsa_headers.h (renamed from chromium/net/tools/flip_server/balsa_headers.h)12
-rw-r--r--chromium/net/tools/balsa/balsa_headers_test.cc (renamed from chromium/net/tools/flip_server/balsa_headers_test.cc)4
-rw-r--r--chromium/net/tools/balsa/balsa_headers_token_utils.cc (renamed from chromium/net/tools/flip_server/balsa_headers_token_utils.cc)6
-rw-r--r--chromium/net/tools/balsa/balsa_headers_token_utils.h (renamed from chromium/net/tools/flip_server/balsa_headers_token_utils.h)10
-rw-r--r--chromium/net/tools/balsa/balsa_visitor_interface.h (renamed from chromium/net/tools/flip_server/balsa_visitor_interface.h)9
-rw-r--r--chromium/net/tools/balsa/buffer_interface.h (renamed from chromium/net/tools/flip_server/buffer_interface.h)8
-rw-r--r--chromium/net/tools/balsa/http_message_constants.cc146
-rw-r--r--chromium/net/tools/balsa/http_message_constants.h (renamed from chromium/net/tools/flip_server/http_message_constants.h)8
-rw-r--r--chromium/net/tools/balsa/noop_balsa_visitor.h60
-rw-r--r--chromium/net/tools/balsa/simple_buffer.cc (renamed from chromium/net/tools/flip_server/simple_buffer.cc)4
-rw-r--r--chromium/net/tools/balsa/simple_buffer.h (renamed from chromium/net/tools/flip_server/simple_buffer.h)10
-rw-r--r--chromium/net/tools/balsa/split.cc (renamed from chromium/net/tools/flip_server/split.cc)4
-rw-r--r--chromium/net/tools/balsa/split.h (renamed from chromium/net/tools/flip_server/split.h)8
-rw-r--r--chromium/net/tools/balsa/string_piece_utils.h (renamed from chromium/net/tools/flip_server/string_piece_utils.h)8
-rw-r--r--chromium/net/tools/crash_cache/crash_cache.cc4
-rw-r--r--chromium/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc13
-rw-r--r--chromium/net/tools/dump_cache/cache_dumper.cc8
-rw-r--r--chromium/net/tools/dump_cache/dump_cache.cc4
-rw-r--r--chromium/net/tools/epoll_server/epoll_server.cc (renamed from chromium/net/tools/flip_server/epoll_server.cc)4
-rw-r--r--chromium/net/tools/epoll_server/epoll_server.h (renamed from chromium/net/tools/flip_server/epoll_server.h)11
-rw-r--r--chromium/net/tools/flip_server/acceptor_thread.cc27
-rw-r--r--chromium/net/tools/flip_server/acceptor_thread.h30
-rw-r--r--chromium/net/tools/flip_server/constants.h7
-rw-r--r--chromium/net/tools/flip_server/create_listener.cc141
-rw-r--r--chromium/net/tools/flip_server/create_listener.h4
-rw-r--r--chromium/net/tools/flip_server/flip_config.cc25
-rw-r--r--chromium/net/tools/flip_server/flip_config.h21
-rw-r--r--chromium/net/tools/flip_server/flip_in_mem_edsm_server.cc170
-rw-r--r--chromium/net/tools/flip_server/flip_test_utils.cc6
-rw-r--r--chromium/net/tools/flip_server/flip_test_utils.h17
-rw-r--r--chromium/net/tools/flip_server/http_interface.cc76
-rw-r--r--chromium/net/tools/flip_server/http_interface.h44
-rw-r--r--chromium/net/tools/flip_server/http_interface_test.cc48
-rw-r--r--chromium/net/tools/flip_server/http_message_constants.cc53
-rw-r--r--chromium/net/tools/flip_server/loadtime_measurement.h9
-rw-r--r--chromium/net/tools/flip_server/mem_cache.cc35
-rw-r--r--chromium/net/tools/flip_server/mem_cache.h63
-rw-r--r--chromium/net/tools/flip_server/mem_cache_test.cc19
-rw-r--r--chromium/net/tools/flip_server/output_ordering.cc45
-rw-r--r--chromium/net/tools/flip_server/output_ordering.h3
-rw-r--r--chromium/net/tools/flip_server/ring_buffer.cc66
-rw-r--r--chromium/net/tools/flip_server/ring_buffer.h5
-rw-r--r--chromium/net/tools/flip_server/run_all_tests.cc8
-rw-r--r--chromium/net/tools/flip_server/sm_connection.cc177
-rw-r--r--chromium/net/tools/flip_server/sm_connection.h16
-rw-r--r--chromium/net/tools/flip_server/sm_interface.h23
-rw-r--r--chromium/net/tools/flip_server/spdy_interface.cc277
-rw-r--r--chromium/net/tools/flip_server/spdy_interface.h32
-rw-r--r--chromium/net/tools/flip_server/spdy_interface_test.cc419
-rw-r--r--chromium/net/tools/flip_server/spdy_ssl.cc32
-rw-r--r--chromium/net/tools/flip_server/spdy_ssl.h1
-rw-r--r--chromium/net/tools/flip_server/spdy_util.cc1
-rw-r--r--chromium/net/tools/flip_server/spdy_util.h1
-rw-r--r--chromium/net/tools/flip_server/streamer_interface.cc49
-rw-r--r--chromium/net/tools/flip_server/streamer_interface.h51
-rw-r--r--chromium/net/tools/gdig/gdig.cc2
-rw-r--r--chromium/net/tools/get_server_time/get_server_time.cc11
-rw-r--r--chromium/net/tools/net_watcher/net_watcher.cc24
-rw-r--r--chromium/net/tools/quic/end_to_end_test.cc628
-rw-r--r--chromium/net/tools/quic/quic_client.cc72
-rw-r--r--chromium/net/tools/quic/quic_client.h44
-rw-r--r--chromium/net/tools/quic/quic_client_bin.cc24
-rw-r--r--chromium/net/tools/quic/quic_client_session.cc9
-rw-r--r--chromium/net/tools/quic/quic_client_session.h9
-rw-r--r--chromium/net/tools/quic/quic_client_session_test.cc34
-rw-r--r--chromium/net/tools/quic/quic_default_packet_writer.cc30
-rw-r--r--chromium/net/tools/quic/quic_default_packet_writer.h40
-rw-r--r--chromium/net/tools/quic/quic_dispatcher.cc88
-rw-r--r--chromium/net/tools/quic/quic_dispatcher.h60
-rw-r--r--chromium/net/tools/quic/quic_dispatcher_test.cc137
-rw-r--r--chromium/net/tools/quic/quic_epoll_clock.cc2
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper.cc58
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper.h19
-rw-r--r--chromium/net/tools/quic/quic_epoll_connection_helper_test.cc250
-rw-r--r--chromium/net/tools/quic/quic_in_memory_cache.cc52
-rw-r--r--chromium/net/tools/quic/quic_in_memory_cache.h29
-rw-r--r--chromium/net/tools/quic/quic_in_memory_cache_test.cc5
-rw-r--r--chromium/net/tools/quic/quic_packet_writer.h33
-rw-r--r--chromium/net/tools/quic/quic_reliable_client_stream.cc27
-rw-r--r--chromium/net/tools/quic/quic_reliable_client_stream.h66
-rw-r--r--chromium/net/tools/quic/quic_reliable_server_stream.cc56
-rw-r--r--chromium/net/tools/quic/quic_reliable_server_stream.h65
-rw-r--r--chromium/net/tools/quic/quic_reliable_server_stream_test.cc228
-rw-r--r--chromium/net/tools/quic/quic_server.cc23
-rw-r--r--chromium/net/tools/quic/quic_server.h19
-rw-r--r--chromium/net/tools/quic/quic_server_bin.cc15
-rw-r--r--chromium/net/tools/quic/quic_server_session.cc18
-rw-r--r--chromium/net/tools/quic/quic_server_session.h11
-rw-r--r--chromium/net/tools/quic/quic_server_session_test.cc66
-rw-r--r--chromium/net/tools/quic/quic_server_test.cc4
-rw-r--r--chromium/net/tools/quic/quic_socket_utils.cc46
-rw-r--r--chromium/net/tools/quic/quic_socket_utils.h14
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream.cc55
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream.h41
-rw-r--r--chromium/net/tools/quic/quic_spdy_client_stream_test.cc (renamed from chromium/net/tools/quic/quic_reliable_client_stream_test.cc)30
-rw-r--r--chromium/net/tools/quic/quic_spdy_server_stream.cc79
-rw-r--r--chromium/net/tools/quic/quic_spdy_server_stream.h33
-rw-r--r--chromium/net/tools/quic/quic_spdy_server_stream_test.cc223
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager.cc133
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager.h95
-rw-r--r--chromium/net/tools/quic/quic_time_wait_list_manager_test.cc231
-rw-r--r--chromium/net/tools/quic/spdy_utils.cc4
-rw-r--r--chromium/net/tools/quic/spdy_utils.h2
-rw-r--r--chromium/net/tools/quic/test_tools/http_message_test_utils.h4
-rw-r--r--chromium/net/tools/quic/test_tools/mock_epoll_server.h2
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_dispatcher.cc4
-rw-r--r--chromium/net/tools/quic/test_tools/mock_quic_dispatcher.h7
-rw-r--r--chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc203
-rw-r--r--chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h146
-rw-r--r--chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc47
-rw-r--r--chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h35
-rw-r--r--chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.cc21
-rw-r--r--chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h31
-rw-r--r--chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.cc20
-rw-r--r--chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h27
-rw-r--r--chromium/net/tools/quic/test_tools/quic_server_peer.cc38
-rw-r--r--chromium/net/tools/quic/test_tools/quic_server_peer.h29
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_client.cc170
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_client.h71
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_utils.cc93
-rw-r--r--chromium/net/tools/quic/test_tools/quic_test_utils.h109
-rw-r--r--chromium/net/tools/quic/test_tools/server_thread.cc107
-rw-r--r--chromium/net/tools/quic/test_tools/server_thread.h79
-rw-r--r--chromium/net/tools/spdyshark/AUTHORS2
-rw-r--r--chromium/net/tools/spdyshark/COPYING340
-rw-r--r--chromium/net/tools/spdyshark/ChangeLog0
-rw-r--r--chromium/net/tools/spdyshark/INSTALL0
-rw-r--r--chromium/net/tools/spdyshark/Makefile.am126
-rw-r--r--chromium/net/tools/spdyshark/Makefile.common40
-rw-r--r--chromium/net/tools/spdyshark/Makefile.nmake104
-rw-r--r--chromium/net/tools/spdyshark/NEWS0
-rw-r--r--chromium/net/tools/spdyshark/README49
-rw-r--r--chromium/net/tools/spdyshark/README.chromium4
-rw-r--r--chromium/net/tools/spdyshark/moduleinfo.h16
-rw-r--r--chromium/net/tools/spdyshark/moduleinfo.nmake28
-rw-r--r--chromium/net/tools/spdyshark/packet-spdy.c1532
-rw-r--r--chromium/net/tools/spdyshark/packet-spdy.h46
-rw-r--r--chromium/net/tools/spdyshark/plugin.rc.in34
-rwxr-xr-xchromium/net/tools/testserver/testserver.py65
-rw-r--r--chromium/net/tools/tld_cleanup/tld_cleanup_util.cc3
-rw-r--r--chromium/net/udp/datagram_server_socket.h10
-rw-r--r--chromium/net/udp/udp_server_socket.cc8
-rw-r--r--chromium/net/udp/udp_server_socket.h5
-rw-r--r--chromium/net/udp/udp_socket_libevent.cc148
-rw-r--r--chromium/net/udp/udp_socket_libevent.h19
-rw-r--r--chromium/net/udp/udp_socket_unittest.cc5
-rw-r--r--chromium/net/udp/udp_socket_win.cc96
-rw-r--r--chromium/net/udp/udp_socket_win.h18
-rw-r--r--chromium/net/url_request/test_url_fetcher_factory.cc68
-rw-r--r--chromium/net/url_request/test_url_fetcher_factory.h98
-rw-r--r--chromium/net/url_request/url_fetcher.h19
-rw-r--r--chromium/net/url_request/url_fetcher_core.cc178
-rw-r--r--chromium/net/url_request/url_fetcher_core.h41
-rw-r--r--chromium/net/url_request/url_fetcher_delegate.cc7
-rw-r--r--chromium/net/url_request/url_fetcher_delegate.h13
-rw-r--r--chromium/net/url_request/url_fetcher_impl.cc15
-rw-r--r--chromium/net/url_request/url_fetcher_impl.h7
-rw-r--r--chromium/net/url_request/url_fetcher_impl_unittest.cc13
-rw-r--r--chromium/net/url_request/url_fetcher_response_writer.cc85
-rw-r--r--chromium/net/url_request/url_fetcher_response_writer.h65
-rw-r--r--chromium/net/url_request/url_request.cc221
-rw-r--r--chromium/net/url_request/url_request.h81
-rw-r--r--chromium/net/url_request/url_request_context.cc14
-rw-r--r--chromium/net/url_request/url_request_context.h17
-rw-r--r--chromium/net/url_request/url_request_context_builder.cc19
-rw-r--r--chromium/net/url_request/url_request_context_builder.h11
-rw-r--r--chromium/net/url_request/url_request_context_builder_unittest.cc13
-rw-r--r--chromium/net/url_request/url_request_file_dir_job.cc3
-rw-r--r--chromium/net/url_request/url_request_file_job.cc2
-rw-r--r--chromium/net/url_request/url_request_filter.cc10
-rw-r--r--chromium/net/url_request/url_request_filter.h6
-rw-r--r--chromium/net/url_request/url_request_filter_unittest.cc7
-rw-r--r--chromium/net/url_request/url_request_ftp_job.cc9
-rw-r--r--chromium/net/url_request/url_request_ftp_job_unittest.cc60
-rw-r--r--chromium/net/url_request/url_request_http_job.cc73
-rw-r--r--chromium/net/url_request/url_request_http_job_unittest.cc177
-rw-r--r--chromium/net/url_request/url_request_job.cc11
-rw-r--r--chromium/net/url_request/url_request_job.h7
-rw-r--r--chromium/net/url_request/url_request_job_factory_impl_unittest.cc7
-rw-r--r--chromium/net/url_request/url_request_job_manager.cc6
-rw-r--r--chromium/net/url_request/url_request_job_unittest.cc91
-rw-r--r--chromium/net/url_request/url_request_netlog_params.cc2
-rw-r--r--chromium/net/url_request/url_request_test_job.cc25
-rw-r--r--chromium/net/url_request/url_request_test_job.h10
-rw-r--r--chromium/net/url_request/url_request_test_util.cc28
-rw-r--r--chromium/net/url_request/url_request_test_util.h19
-rw-r--r--chromium/net/url_request/url_request_throttler_simulation_unittest.cc7
-rw-r--r--chromium/net/url_request/url_request_throttler_unittest.cc26
-rw-r--r--chromium/net/url_request/url_request_unittest.cc1795
-rw-r--r--chromium/net/url_request/websocket_handshake_userdata_key.cc11
-rw-r--r--chromium/net/url_request/websocket_handshake_userdata_key.h21
-rw-r--r--chromium/net/websockets/README30
-rw-r--r--chromium/net/websockets/websocket_basic_handshake_stream.cc318
-rw-r--r--chromium/net/websockets/websocket_basic_handshake_stream.h122
-rw-r--r--chromium/net/websockets/websocket_basic_stream.cc336
-rw-r--r--chromium/net/websockets/websocket_basic_stream.h80
-rw-r--r--chromium/net/websockets/websocket_basic_stream_test.cc842
-rw-r--r--chromium/net/websockets/websocket_channel.cc546
-rw-r--r--chromium/net/websockets/websocket_channel.h129
-rw-r--r--chromium/net/websockets/websocket_channel_test.cc1690
-rw-r--r--chromium/net/websockets/websocket_deflate_predictor.h58
-rw-r--r--chromium/net/websockets/websocket_deflate_predictor_impl.cc23
-rw-r--r--chromium/net/websockets/websocket_deflate_predictor_impl.h31
-rw-r--r--chromium/net/websockets/websocket_deflate_predictor_impl_test.cc29
-rw-r--r--chromium/net/websockets/websocket_deflate_stream.cc372
-rw-r--r--chromium/net/websockets/websocket_deflate_stream.h103
-rw-r--r--chromium/net/websockets/websocket_deflate_stream_test.cc1206
-rw-r--r--chromium/net/websockets/websocket_deflater.cc2
-rw-r--r--chromium/net/websockets/websocket_event_interface.h45
-rw-r--r--chromium/net/websockets/websocket_frame.cc27
-rw-r--r--chromium/net/websockets/websocket_frame.h34
-rw-r--r--chromium/net/websockets/websocket_handshake_constants.cc2
-rw-r--r--chromium/net/websockets/websocket_handshake_constants.h5
-rw-r--r--chromium/net/websockets/websocket_handshake_handler.cc231
-rw-r--r--chromium/net/websockets/websocket_handshake_handler.h71
-rw-r--r--chromium/net/websockets/websocket_handshake_handler_spdy_test.cc7
-rw-r--r--chromium/net/websockets/websocket_handshake_handler_test.cc358
-rw-r--r--chromium/net/websockets/websocket_handshake_stream_base.h77
-rw-r--r--chromium/net/websockets/websocket_handshake_stream_create_helper.cc43
-rw-r--r--chromium/net/websockets/websocket_handshake_stream_create_helper.h61
-rw-r--r--chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc145
-rw-r--r--chromium/net/websockets/websocket_inflater.cc283
-rw-r--r--chromium/net/websockets/websocket_inflater.h130
-rw-r--r--chromium/net/websockets/websocket_inflater_test.cc224
-rw-r--r--chromium/net/websockets/websocket_job.cc3
-rw-r--r--chromium/net/websockets/websocket_job_test.cc3
-rw-r--r--chromium/net/websockets/websocket_stream.cc175
-rw-r--r--chromium/net/websockets/websocket_stream.h108
-rw-r--r--chromium/net/websockets/websocket_stream_base.h55
-rw-r--r--chromium/net/websockets/websocket_stream_test.cc515
-rw-r--r--chromium/net/websockets/websocket_test_util.cc125
-rw-r--r--chromium/net/websockets/websocket_test_util.h114
902 files changed, 83176 insertions, 45594 deletions
diff --git a/chromium/net/OWNERS b/chromium/net/OWNERS
index 87e11faef93..96337499fe8 100644
--- a/chromium/net/OWNERS
+++ b/chromium/net/OWNERS
@@ -2,19 +2,23 @@ agl@chromium.org
akalin@chromium.org
asanka@chromium.org
cbentzel@chromium.org
+davidben@chromium.org
eroman@chromium.org
gavinp@chromium.org
jar@chromium.org
mattm@chromium.org
+mef@chromium.org
mmenke@chromium.org
+pauljensen@chromium.org
rch@chromium.org
rdsmith@chromium.org
rsleevi@chromium.org
rtenneti@chromium.org
rvargas@chromium.org
szym@chromium.org
+ttuttle@chromium.org
willchan@chromium.org
wtc@chromium.org
per-file *.isolate=csharp@chromium.org
-per-file *.isolate=maruel@chromium.org \ No newline at end of file
+per-file *.isolate=maruel@chromium.org
diff --git a/chromium/net/android/keystore_unittest.cc b/chromium/net/android/keystore_unittest.cc
index 98944e29bd0..58e3da796a5 100644
--- a/chromium/net/android/keystore_unittest.cc
+++ b/chromium/net/android/keystore_unittest.cc
@@ -117,8 +117,7 @@ EVP_PKEY* ImportPrivateKeyFile(const char* filename) {
// Load file in memory.
base::FilePath certs_dir = GetTestCertsDirectory();
base::FilePath file_path = certs_dir.AppendASCII(filename);
- ScopedStdioHandle handle(
- file_util::OpenFile(file_path, "rb"));
+ ScopedStdioHandle handle(base::OpenFile(file_path, "rb"));
if (!handle.get()) {
LOG(ERROR) << "Could not open private key file: " << filename;
return NULL;
@@ -167,7 +166,7 @@ EVP_PKEY* ImportPublicKeyFile(const char* filename) {
// Load file as PEM data.
base::FilePath certs_dir = GetTestCertsDirectory();
base::FilePath file_path = certs_dir.AppendASCII(filename);
- ScopedStdioHandle handle(file_util::OpenFile(file_path, "rb"));
+ ScopedStdioHandle handle(base::OpenFile(file_path, "rb"));
if (!handle.get()) {
LOG(ERROR) << "Could not open public key file: " << filename;
return NULL;
diff --git a/chromium/net/android/network_change_notifier_delegate_android.cc b/chromium/net/android/network_change_notifier_delegate_android.cc
index 0031260b73e..207f01b6c86 100644
--- a/chromium/net/android/network_change_notifier_delegate_android.cc
+++ b/chromium/net/android/network_change_notifier_delegate_android.cc
@@ -40,7 +40,8 @@ NetworkChangeNotifierDelegateAndroid::NetworkChangeNotifierDelegateAndroid()
Java_NetworkChangeNotifier_init(
env, base::android::GetApplicationContext()));
Java_NetworkChangeNotifier_addNativeObserver(
- env, java_network_change_notifier_.obj(), reinterpret_cast<jint>(this));
+ env, java_network_change_notifier_.obj(),
+ reinterpret_cast<intptr_t>(this));
SetCurrentConnectionType(
ConvertConnectionType(
Java_NetworkChangeNotifier_getCurrentConnectionType(
@@ -52,7 +53,8 @@ NetworkChangeNotifierDelegateAndroid::~NetworkChangeNotifierDelegateAndroid() {
observers_->AssertEmpty();
JNIEnv* env = base::android::AttachCurrentThread();
Java_NetworkChangeNotifier_removeNativeObserver(
- env, java_network_change_notifier_.obj(), reinterpret_cast<jint>(this));
+ env, java_network_change_notifier_.obj(),
+ reinterpret_cast<intptr_t>(this));
}
NetworkChangeNotifier::ConnectionType
diff --git a/chromium/net/base/address_tracker_linux.cc b/chromium/net/base/address_tracker_linux.cc
index 886811a7919..f863ccd625b 100644
--- a/chromium/net/base/address_tracker_linux.cc
+++ b/chromium/net/base/address_tracker_linux.cc
@@ -306,7 +306,7 @@ void AddressTrackerLinux::OnFileCanReadWithoutBlocking(int fd) {
void AddressTrackerLinux::OnFileCanWriteWithoutBlocking(int /* fd */) {}
void AddressTrackerLinux::CloseSocket() {
- if (netlink_fd_ >= 0 && HANDLE_EINTR(close(netlink_fd_)) < 0)
+ if (netlink_fd_ >= 0 && IGNORE_EINTR(close(netlink_fd_)) < 0)
PLOG(ERROR) << "Could not close NETLINK socket.";
netlink_fd_ = -1;
}
diff --git a/chromium/net/base/address_tracker_linux_unittest.cc b/chromium/net/base/address_tracker_linux_unittest.cc
index a9feed491dc..47083801224 100644
--- a/chromium/net/base/address_tracker_linux_unittest.cc
+++ b/chromium/net/base/address_tracker_linux_unittest.cc
@@ -136,8 +136,6 @@ const unsigned char kAddress1[] = { 10, 0, 0, 1 };
const unsigned char kAddress2[] = { 192, 168, 0, 1 };
const unsigned char kAddress3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1 };
-const unsigned char kAddress4[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255,
- 169, 254, 0, 1 };
TEST_F(AddressTrackerLinuxTest, NewAddress) {
const IPAddressNumber kEmpty;
diff --git a/chromium/net/base/dir_header.html b/chromium/net/base/dir_header.html
index b281a980376..77b48b1d38c 100644
--- a/chromium/net/base/dir_header.html
+++ b/chromium/net/base/dir_header.html
@@ -1,8 +1,9 @@
<!DOCTYPE html>
-<html>
+<html i18n-values="dir:textdirection">
<head>
+<meta charset="utf-8">
<script>
function addRow(name, url, isdir, size, date_modified) {
@@ -95,13 +96,13 @@ function onListingParsingError() {
}
td.detailsColumn {
- padding-left: 2em;
- text-align: right;
+ -webkit-padding-start: 2em;
+ text-align: end;
white-space: nowrap;
}
a.icon {
- padding-left: 1.5em;
+ -webkit-padding-start: 1.5em;
text-decoration: none;
}
@@ -121,6 +122,10 @@ function onListingParsingError() {
background : url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;
}
+ html[dir=rtl] a {
+ background-position-x: right;
+ }
+
#listingParsingErrorBox {
border: 1px solid black;
background: #fae691;
diff --git a/chromium/net/base/directory_lister.cc b/chromium/net/base/directory_lister.cc
index 046be32d49f..e75e9f808dc 100644
--- a/chromium/net/base/directory_lister.cc
+++ b/chromium/net/base/directory_lister.cc
@@ -20,8 +20,6 @@ namespace net {
namespace {
-const int kFilesPerEvent = 8;
-
bool IsDotDot(const base::FilePath& path) {
return FILE_PATH_LITERAL("..") == path.BaseName().value();
}
@@ -169,6 +167,7 @@ void DirectoryLister::Core::StartInternal() {
should be done from JS to give more flexibility in the page. When we do
that, we can uncomment this to send incremental updates to the page.
+ const int kFilesPerEvent = 8;
if (file_data.size() < kFilesPerEvent)
continue;
diff --git a/chromium/net/base/directory_lister_unittest.cc b/chromium/net/base/directory_lister_unittest.cc
index 0ad71af827c..0be09a5d7b4 100644
--- a/chromium/net/base/directory_lister_unittest.cc
+++ b/chromium/net/base/directory_lister_unittest.cc
@@ -122,7 +122,7 @@ class DirectoryListerTest : public PlatformTest {
for (int i = 0; i < kBranchingFactor; i++) {
std::string dir_name = base::StringPrintf("child_dir_%d", i);
base::FilePath dir_path = dir_data.first.AppendASCII(dir_name);
- ASSERT_TRUE(file_util::CreateDirectory(dir_path));
+ ASSERT_TRUE(base::CreateDirectory(dir_path));
directories.push_back(std::make_pair(dir_path, dir_data.second + 1));
}
}
diff --git a/chromium/net/base/dns_util.cc b/chromium/net/base/dns_util.cc
index 5d47d4b8b5a..c095eb80ad6 100644
--- a/chromium/net/base/dns_util.cc
+++ b/chromium/net/base/dns_util.cc
@@ -80,20 +80,6 @@ std::string DNSDomainToString(const base::StringPiece& domain) {
return ret;
}
-bool IsSTD3ASCIIValidCharacter(char c) {
- if (c <= 0x2c)
- return false;
- if (c >= 0x7b)
- return false;
- if (c >= 0x2e && c <= 0x2f)
- return false;
- if (c >= 0x3a && c <= 0x40)
- return false;
- if (c >= 0x5b && c <= 0x60)
- return false;
- return true;
-}
-
std::string TrimEndingDot(const base::StringPiece& host) {
base::StringPiece host_trimmed = host;
size_t len = host_trimmed.length();
diff --git a/chromium/net/base/dns_util.h b/chromium/net/base/dns_util.h
index f0d9574b99a..141f282f391 100644
--- a/chromium/net/base/dns_util.h
+++ b/chromium/net/base/dns_util.h
@@ -26,10 +26,6 @@ NET_EXPORT_PRIVATE bool DNSDomainFromDot(const base::StringPiece& dotted,
NET_EXPORT_PRIVATE std::string DNSDomainToString(
const base::StringPiece& domain);
-// Returns true iff the given character is in the set of valid DNS label
-// characters as given in RFC 3490, 4.1, 3(a)
-NET_EXPORT_PRIVATE bool IsSTD3ASCIIValidCharacter(char c);
-
// Returns the hostname by trimming the ending dot, if one exists.
NET_EXPORT std::string TrimEndingDot(const base::StringPiece& host);
diff --git a/chromium/net/base/dns_util_unittest.cc b/chromium/net/base/dns_util_unittest.cc
index 1e1e4f03811..d91753f4f73 100644
--- a/chromium/net/base/dns_util_unittest.cc
+++ b/chromium/net/base/dns_util_unittest.cc
@@ -70,17 +70,4 @@ TEST_F(DNSUtilTest, DNSDomainToString) {
EXPECT_EQ("", DNSDomainToString("\x06"));
}
-TEST_F(DNSUtilTest, STD3ASCII) {
- EXPECT_TRUE(IsSTD3ASCIIValidCharacter('a'));
- EXPECT_TRUE(IsSTD3ASCIIValidCharacter('b'));
- EXPECT_TRUE(IsSTD3ASCIIValidCharacter('c'));
- EXPECT_TRUE(IsSTD3ASCIIValidCharacter('1'));
- EXPECT_TRUE(IsSTD3ASCIIValidCharacter('2'));
- EXPECT_TRUE(IsSTD3ASCIIValidCharacter('3'));
-
- EXPECT_FALSE(IsSTD3ASCIIValidCharacter('.'));
- EXPECT_FALSE(IsSTD3ASCIIValidCharacter('/'));
- EXPECT_FALSE(IsSTD3ASCIIValidCharacter('\x00'));
-}
-
} // namespace net
diff --git a/chromium/net/base/file_stream_context.cc b/chromium/net/base/file_stream_context.cc
index 2e774752045..e7fe100df27 100644
--- a/chromium/net/base/file_stream_context.cc
+++ b/chromium/net/base/file_stream_context.cc
@@ -11,6 +11,10 @@
#include "net/base/file_stream_net_log_parameters.h"
#include "net/base/net_errors.h"
+#if defined(OS_ANDROID)
+#include "base/android/content_uri_utils.h"
+#endif
+
namespace {
void CallInt64ToInt(const net::CompletionCallback& callback, int64 result) {
@@ -193,13 +197,24 @@ void FileStream::Context::BeginOpenEvent(const base::FilePath& path) {
FileStream::Context::OpenResult FileStream::Context::OpenFileImpl(
const base::FilePath& path, int open_flags) {
- // FileStream::Context actually closes the file asynchronously, independently
- // from FileStream's destructor. It can cause problems for users wanting to
- // delete the file right after FileStream deletion. Thus we are always
- // adding SHARE_DELETE flag to accommodate such use case.
- open_flags |= base::PLATFORM_FILE_SHARE_DELETE;
- base::PlatformFile file =
- base::CreatePlatformFile(path, open_flags, NULL, NULL);
+ base::PlatformFile file;
+#if defined(OS_ANDROID)
+ if (path.IsContentUri()) {
+ // Check that only Read flags are set.
+ DCHECK_EQ(open_flags & ~base::PLATFORM_FILE_ASYNC,
+ base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
+ file = base::OpenContentUriForRead(path);
+ } else {
+#endif // defined(OS_ANDROID)
+ // FileStream::Context actually closes the file asynchronously,
+ // independently from FileStream's destructor. It can cause problems for
+ // users wanting to delete the file right after FileStream deletion. Thus
+ // we are always adding SHARE_DELETE flag to accommodate such use case.
+ open_flags |= base::PLATFORM_FILE_SHARE_DELETE;
+ file = base::CreatePlatformFile(path, open_flags, NULL, NULL);
+#if defined(OS_ANDROID)
+ }
+#endif // defined(OS_ANDROID)
if (file == base::kInvalidPlatformFileValue)
return OpenResult(file, IOResult::FromOSError(GetLastErrno()));
diff --git a/chromium/net/base/file_stream_unittest.cc b/chromium/net/base/file_stream_unittest.cc
index c76f3d939ac..b055c78b5d1 100644
--- a/chromium/net/base/file_stream_unittest.cc
+++ b/chromium/net/base/file_stream_unittest.cc
@@ -21,6 +21,10 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#if defined(OS_ANDROID)
+#include "base/test/test_file_util.h"
+#endif
+
namespace net {
namespace {
@@ -42,7 +46,7 @@ class FileStreamTest : public PlatformTest {
virtual void SetUp() {
PlatformTest::SetUp();
- file_util::CreateTemporaryFile(&temp_file_path_);
+ base::CreateTemporaryFile(&temp_file_path_);
file_util::WriteFile(temp_file_path_, kTestData, kTestDataSize);
}
virtual void TearDown() {
@@ -196,7 +200,7 @@ TEST_F(FileStreamTest, UseFileHandle) {
// Read into buffer and compare to make sure the handle worked fine.
ASSERT_EQ(kTestDataSize,
- file_util::ReadFile(temp_file_path(), buffer, kTestDataSize));
+ base::ReadFile(temp_file_path(), buffer, kTestDataSize));
ASSERT_EQ(0, memcmp(kTestData, buffer, kTestDataSize));
}
@@ -221,7 +225,7 @@ TEST_F(FileStreamTest, UseClosedStream) {
TEST_F(FileStreamTest, BasicRead) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
FileStream stream(NULL, base::MessageLoopProxy::current());
@@ -251,7 +255,7 @@ TEST_F(FileStreamTest, BasicRead) {
TEST_F(FileStreamTest, AsyncRead) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
FileStream stream(NULL, base::MessageLoopProxy::current());
@@ -286,7 +290,7 @@ TEST_F(FileStreamTest, AsyncRead) {
TEST_F(FileStreamTest, AsyncRead_EarlyDelete) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -317,7 +321,7 @@ TEST_F(FileStreamTest, AsyncRead_EarlyDelete) {
TEST_F(FileStreamTest, BasicRead_FromOffset) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
FileStream stream(NULL, base::MessageLoopProxy::current());
@@ -352,7 +356,7 @@ TEST_F(FileStreamTest, BasicRead_FromOffset) {
TEST_F(FileStreamTest, AsyncRead_FromOffset) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
FileStream stream(NULL, base::MessageLoopProxy::current());
@@ -460,7 +464,7 @@ TEST_F(FileStreamTest, BasicWrite) {
EXPECT_EQ(OK, rv);
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(0, file_size);
@@ -468,7 +472,7 @@ TEST_F(FileStreamTest, BasicWrite) {
EXPECT_EQ(kTestDataSize, rv);
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize, file_size);
}
@@ -484,7 +488,7 @@ TEST_F(FileStreamTest, AsyncWrite) {
EXPECT_EQ(OK, callback.WaitForResult());
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(0, file_size);
@@ -504,7 +508,7 @@ TEST_F(FileStreamTest, AsyncWrite) {
drainable->DidConsume(rv);
total_bytes_written += rv;
}
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(file_size, total_bytes_written);
}
@@ -521,7 +525,7 @@ TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) {
EXPECT_EQ(OK, callback.WaitForResult());
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(0, file_size);
@@ -534,7 +538,7 @@ TEST_F(FileStreamTest, AsyncWrite_EarlyDelete) {
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(callback.have_result());
} else {
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(file_size, rv);
}
@@ -549,7 +553,7 @@ TEST_F(FileStreamTest, BasicWrite_FromOffset) {
EXPECT_EQ(OK, rv);
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize, file_size);
@@ -561,14 +565,14 @@ TEST_F(FileStreamTest, BasicWrite_FromOffset) {
EXPECT_EQ(kTestDataSize, rv);
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
}
TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
FileStream stream(NULL, base::MessageLoopProxy::current());
@@ -603,14 +607,14 @@ TEST_F(FileStreamTest, AsyncWrite_FromOffset) {
drainable->DidConsume(rv);
total_bytes_written += rv;
}
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(file_size, kTestDataSize * 2);
}
TEST_F(FileStreamTest, BasicReadWrite) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -643,14 +647,14 @@ TEST_F(FileStreamTest, BasicReadWrite) {
EXPECT_EQ(kTestDataSize, rv);
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
}
TEST_F(FileStreamTest, BasicWriteRead) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -687,7 +691,7 @@ TEST_F(FileStreamTest, BasicWriteRead) {
}
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
EXPECT_EQ(kTestDataSize * 2, total_bytes_read);
@@ -699,7 +703,7 @@ TEST_F(FileStreamTest, BasicWriteRead) {
TEST_F(FileStreamTest, BasicAsyncReadWrite) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -752,14 +756,14 @@ TEST_F(FileStreamTest, BasicAsyncReadWrite) {
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
}
TEST_F(FileStreamTest, BasicAsyncWriteRead) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -822,7 +826,7 @@ TEST_F(FileStreamTest, BasicAsyncWriteRead) {
}
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
@@ -926,7 +930,7 @@ class TestWriteReadCompletionCallback {
TEST_F(FileStreamTest, AsyncWriteRead) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -961,7 +965,7 @@ TEST_F(FileStreamTest, AsyncWriteRead) {
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
@@ -1036,7 +1040,7 @@ class TestWriteCloseCompletionCallback {
TEST_F(FileStreamTest, AsyncWriteClose) {
int64 file_size;
- bool ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ bool ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
scoped_ptr<FileStream> stream(
@@ -1068,7 +1072,7 @@ TEST_F(FileStreamTest, AsyncWriteClose) {
stream.reset();
- ok = file_util::GetFileSize(temp_file_path(), &file_size);
+ ok = base::GetFileSize(temp_file_path(), &file_size);
EXPECT_TRUE(ok);
EXPECT_EQ(kTestDataSize * 2, file_size);
}
@@ -1173,6 +1177,55 @@ TEST_F(FileStreamTest, AsyncReadError) {
base::ClosePlatformFile(file);
}
+#if defined(OS_ANDROID)
+TEST_F(FileStreamTest, ContentUriAsyncRead) {
+ base::FilePath test_dir;
+ PathService::Get(base::DIR_SOURCE_ROOT, &test_dir);
+ test_dir = test_dir.AppendASCII("net");
+ test_dir = test_dir.AppendASCII("data");
+ test_dir = test_dir.AppendASCII("file_stream_unittest");
+ ASSERT_TRUE(base::PathExists(test_dir));
+ base::FilePath image_file = test_dir.Append(FILE_PATH_LITERAL("red.png"));
+
+ // Insert the image into MediaStore. MediaStore will do some conversions, and
+ // return the content URI.
+ base::FilePath path = file_util::InsertImageIntoMediaStore(image_file);
+ EXPECT_TRUE(path.IsContentUri());
+ EXPECT_TRUE(base::PathExists(path));
+ int64 file_size;
+ EXPECT_TRUE(base::GetFileSize(path, &file_size));
+ EXPECT_LT(0, file_size);
+
+ FileStream stream(NULL, base::MessageLoopProxy::current());
+ int flags = base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_ASYNC;
+ TestCompletionCallback callback;
+ int rv = stream.Open(path, flags, callback.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+ EXPECT_EQ(OK, callback.WaitForResult());
+
+ int64 total_bytes_avail = stream.Available();
+ EXPECT_EQ(file_size, total_bytes_avail);
+
+ int total_bytes_read = 0;
+
+ std::string data_read;
+ for (;;) {
+ scoped_refptr<IOBufferWithSize> buf = new IOBufferWithSize(4);
+ rv = stream.Read(buf.get(), buf->size(), callback.callback());
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_LE(0, rv);
+ if (rv <= 0)
+ break;
+ total_bytes_read += rv;
+ data_read.append(buf->data(), rv);
+ }
+ EXPECT_EQ(file_size, total_bytes_read);
+}
+#endif
+
} // namespace
} // namespace net
diff --git a/chromium/net/base/filter.cc b/chromium/net/base/filter.cc
index 36d301426f9..42313fd9ffe 100644
--- a/chromium/net/base/filter.cc
+++ b/chromium/net/base/filter.cc
@@ -21,17 +21,11 @@ const char kSdch[] = "sdch";
// compress and x-compress are currently not supported. If we decide to support
// them, we'll need the same mime type compatibility hack we have for gzip. For
// more information, see Firefox's nsHttpChannel::ProcessNormal.
-const char kCompress[] = "compress";
-const char kXCompress[] = "x-compress";
-const char kIdentity[] = "identity";
-const char kUncompressed[] = "uncompressed";
// Mime types:
const char kApplicationXGzip[] = "application/x-gzip";
const char kApplicationGzip[] = "application/gzip";
const char kApplicationXGunzip[] = "application/x-gunzip";
-const char kApplicationXCompress[] = "application/x-compress";
-const char kApplicationCompress[] = "application/compress";
const char kTextHtml[] = "text/html";
// Buffer size allocated when de-compressing data.
diff --git a/chromium/net/base/gzip_filter_unittest.cc b/chromium/net/base/gzip_filter_unittest.cc
index 2ac4a3fc13b..5e14a4584cc 100644
--- a/chromium/net/base/gzip_filter_unittest.cc
+++ b/chromium/net/base/gzip_filter_unittest.cc
@@ -20,11 +20,6 @@ namespace {
const int kDefaultBufferSize = 4096;
const int kSmallBufferSize = 128;
-const char kApplicationOctetStream[] = "application/octet-stream";
-const char kApplicationXGzip[] = "application/x-gzip";
-const char kApplicationGzip[] = "application/gzip";
-const char kApplicationXGunzip[] = "application/x-gunzip";
-
// The GZIP header (see RFC 1952):
// +---+---+---+---+---+---+---+---+---+---+
// |ID1|ID2|CM |FLG| MTIME |XFL|OS |
diff --git a/chromium/net/base/gzip_header.cc b/chromium/net/base/gzip_header.cc
index 81cb1d8efd3..88ad4d7a840 100644
--- a/chromium/net/base/gzip_header.cc
+++ b/chromium/net/base/gzip_header.cc
@@ -4,6 +4,8 @@
#include "net/base/gzip_header.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "third_party/zlib/zlib.h"
diff --git a/chromium/net/base/keygen_handler.cc b/chromium/net/base/keygen_handler.cc
index 7d63f4d5e12..88013bcb0d1 100644
--- a/chromium/net/base/keygen_handler.cc
+++ b/chromium/net/base/keygen_handler.cc
@@ -4,6 +4,10 @@
#include "net/base/keygen_handler.h"
+#if defined(USE_NSS)
+#include "crypto/nss_crypto_module_delegate.h"
+#endif // defined(USE_NSS)
+
namespace net {
// The constructor and destructor must be defined in a .cc file so that
diff --git a/chromium/net/base/keygen_handler.h b/chromium/net/base/keygen_handler.h
index 4895dacb57e..8262775505c 100644
--- a/chromium/net/base/keygen_handler.h
+++ b/chromium/net/base/keygen_handler.h
@@ -7,14 +7,15 @@
#include <string>
+#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "net/base/net_export.h"
#include "url/gurl.h"
-#if defined(USE_NSS)
-#include "crypto/crypto_module_blocking_password_delegate.h"
-#endif // defined(USE_NSS)
+namespace crypto {
+class NSSCryptoModuleDelegate;
+}
namespace net {
@@ -41,12 +42,12 @@ class NET_EXPORT KeygenHandler {
void set_stores_key(bool store) { stores_key_ = store;}
#if defined(USE_NSS)
- // Register the password delegate to be used if the token is unauthenticated.
- // GenKeyAndSignChallenge runs on a worker thread, so using the blocking
+ // Register the delegate to be used to get the token to store the key in, and
+ // to get the password if the token is unauthenticated.
+ // GenKeyAndSignChallenge runs on a worker thread, so using a blocking
// password callback is okay here.
- // Takes ownership of the delegate.
- void set_crypto_module_password_delegate(
- crypto::CryptoModuleBlockingPasswordDelegate* delegate);
+ void set_crypto_module_delegate(
+ scoped_ptr<crypto::NSSCryptoModuleDelegate> delegate);
#endif // defined(USE_NSS)
private:
@@ -56,8 +57,7 @@ class NET_EXPORT KeygenHandler {
bool stores_key_; // should the generated key-pair be stored persistently?
#if defined(USE_NSS)
// The callback for requesting a password to the PKCS#11 token.
- scoped_ptr<crypto::CryptoModuleBlockingPasswordDelegate>
- crypto_module_password_delegate_;
+ scoped_ptr<crypto::NSSCryptoModuleDelegate> crypto_module_delegate_;
#endif // defined(USE_NSS)
};
diff --git a/chromium/net/base/keygen_handler_nss.cc b/chromium/net/base/keygen_handler_nss.cc
index 5e97807866a..ad0f0ebe672 100644
--- a/chromium/net/base/keygen_handler_nss.cc
+++ b/chromium/net/base/keygen_handler_nss.cc
@@ -5,7 +5,7 @@
#include "net/base/keygen_handler.h"
#include "base/logging.h"
-#include "crypto/crypto_module_blocking_password_delegate.h"
+#include "crypto/nss_crypto_module_delegate.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "crypto/scoped_nss_types.h"
@@ -20,16 +20,22 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
// Ensure NSS is initialized.
crypto::EnsureNSSInit();
- // TODO(mattm): allow choosing which slot to generate and store the key.
- crypto::ScopedPK11Slot slot(crypto::GetPrivateNSSKeySlot());
+ crypto::ScopedPK11Slot slot;
+ if (crypto_module_delegate_)
+ slot = crypto_module_delegate_->RequestSlot().Pass();
+ else
+ slot.reset(crypto::GetPrivateNSSKeySlot());
if (!slot.get()) {
LOG(ERROR) << "Couldn't get private key slot from NSS!";
return std::string();
}
// Authenticate to the token.
- if (SECSuccess != PK11_Authenticate(slot.get(), PR_TRUE,
- crypto_module_password_delegate_.get())) {
+ if (SECSuccess !=
+ PK11_Authenticate(
+ slot.get(),
+ PR_TRUE,
+ crypto_module_delegate_ ? crypto_module_delegate_->wincx() : NULL)) {
LOG(ERROR) << "Couldn't authenticate to private key slot!";
return std::string();
}
@@ -38,9 +44,9 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
slot.get(), stores_key_);
}
-void KeygenHandler::set_crypto_module_password_delegate(
- crypto::CryptoModuleBlockingPasswordDelegate* delegate) {
- crypto_module_password_delegate_.reset(delegate);
+void KeygenHandler::set_crypto_module_delegate(
+ scoped_ptr<crypto::NSSCryptoModuleDelegate> delegate) {
+ crypto_module_delegate_ = delegate.Pass();
}
} // namespace net
diff --git a/chromium/net/base/keygen_handler_win.cc b/chromium/net/base/keygen_handler_win.cc
index e1d432ce401..59d90e8b40c 100644
--- a/chromium/net/base/keygen_handler_win.cc
+++ b/chromium/net/base/keygen_handler_win.cc
@@ -211,10 +211,7 @@ std::string KeygenHandler::GenKeyAndSignChallenge() {
}
std::string result;
- if (!base::Base64Encode(spkac, &result)) {
- LOG(ERROR) << "Keygen failed: Couldn't convert signed key into base64";
- return std::string();
- }
+ base::Base64Encode(spkac, &result);
VLOG(1) << "Keygen succeeded";
return result;
diff --git a/chromium/net/base/mime_util.cc b/chromium/net/base/mime_util.cc
index 70dd3530df2..c68965c3133 100644
--- a/chromium/net/base/mime_util.cc
+++ b/chromium/net/base/mime_util.cc
@@ -17,6 +17,10 @@
#include "net/base/mime_util.h"
#include "net/base/platform_mime_util.h"
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
using std::string;
namespace {
@@ -120,7 +124,7 @@ struct MimeInfo {
};
static const MimeInfo primary_mappings[] = {
- { "text/html", "html,htm" },
+ { "text/html", "html,htm,shtml,shtm" },
{ "text/css", "css" },
{ "text/xml", "xml" },
{ "image/gif", "gif" },
@@ -135,7 +139,7 @@ static const MimeInfo primary_mappings[] = {
{ "video/webm", "webm" },
{ "audio/webm", "webm" },
{ "audio/wav", "wav" },
- { "application/xhtml+xml", "xhtml,xht" },
+ { "application/xhtml+xml", "xhtml,xht,xhtm" },
{ "application/x-chrome-extension", "crx" },
{ "multipart/related", "mhtml,mht" }
};
@@ -156,10 +160,10 @@ static const MimeInfo secondary_mappings[] = {
{ "image/svg+xml", "svg,svgz" },
{ "message/rfc822", "eml" },
{ "text/plain", "txt,text" },
- { "text/html", "shtml,ehtml" },
+ { "text/html", "ehtml" },
{ "application/rss+xml", "rss" },
{ "application/rdf+xml", "rdf" },
- { "text/xml", "xsl,xbl" },
+ { "text/xml", "xsl,xbl,xslt" },
{ "application/vnd.mozilla.xul+xml", "xul" },
{ "application/x-shockwave-flash", "swf,swl" },
{ "application/pkcs7-mime", "p7m,p7c,p7z" },
@@ -304,35 +308,26 @@ static const char* const proprietary_media_types[] = {
static const char* const common_media_codecs[] = {
#if !defined(OS_ANDROID) // Android doesn't support Ogg Theora.
"theora",
- "vp9", // TODO(tomfinegan): Move vp9 back down with vp8 once VP9 is supported
- // on Android. https://crbug.com/285016
#endif
+ "opus",
"vorbis",
"vp8",
+ "vp9",
"1" // WAVE_FORMAT_PCM.
};
// List of proprietary codecs only supported by Google Chrome.
static const char* const proprietary_media_codecs[] = {
"avc1",
+ "avc3",
"mp4a"
};
-// Note: does not include javascript types list (see supported_javascript_types)
+// Note:
+// - does not include javascript types list (see supported_javascript_types)
+// - does not include types starting with "text/" (see
+// IsSupportedNonImageMimeType())
static const char* const supported_non_image_types[] = {
- "text/cache-manifest",
- "text/html",
- "text/xml",
- "text/xsl",
- "text/plain",
- // Many users complained about css files served for
- // download instead of displaying in the browser:
- // http://code.google.com/p/chromium/issues/detail?id=7192
- // So, by including "text/css" into this list we choose Firefox
- // behavior - css files will be displayed:
- "text/css",
- "text/vnd.chromium.ftp-dir",
- "text/",
"image/svg+xml", // SVG is text-based XML, even though it has an image/ type
"application/xml",
"application/atom+xml",
@@ -408,20 +403,31 @@ static const char* const supported_javascript_types[] = {
"text/livescript"
};
+#if defined(OS_ANDROID)
+static bool IsCodecSupportedOnAndroid(const std::string& codec) {
+ // VP9 is supported only in KitKat+ (API Level 19).
+ if ((!codec.compare("vp9") || !codec.compare("vp9.0")) &&
+ base::android::BuildInfo::GetInstance()->sdk_int() < 19) {
+ return false;
+ }
+
+ // TODO(vigneshv): Change this similar to the VP9 check once Opus is
+ // supported on Android (http://crbug.com/318436).
+ if (!codec.compare("opus")) {
+ return false;
+ }
+ return true;
+}
+#endif
+
struct MediaFormatStrict {
const char* mime_type;
const char* codecs_list;
};
static const MediaFormatStrict format_codec_mappings[] = {
- // TODO(tomfinegan): Remove this if/else when VP9 is supported on Android.
- // https://crbug.com/285016
-#if !defined(OS_ANDROID)
- { "video/webm", "vorbis,vp8,vp8.0,vp9,vp9.0" },
-#else
- { "video/webm", "vorbis,vp8,vp8.0" },
-#endif
- { "audio/webm", "vorbis" },
+ { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" },
+ { "audio/webm", "opus,vorbis" },
{ "audio/wav", "1" }
};
@@ -470,8 +476,13 @@ void MimeUtil::InitializeMimeTypeMaps() {
for (size_t i = 0; i < arraysize(supported_javascript_types); ++i)
javascript_map_.insert(supported_javascript_types[i]);
- for (size_t i = 0; i < arraysize(common_media_codecs); ++i)
+ for (size_t i = 0; i < arraysize(common_media_codecs); ++i) {
+#if defined(OS_ANDROID)
+ if (!IsCodecSupportedOnAndroid(common_media_codecs[i]))
+ continue;
+#endif
codecs_map_.insert(common_media_codecs[i]);
+ }
#if defined(USE_PROPRIETARY_CODECS)
for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i)
codecs_map_.insert(proprietary_media_codecs[i]);
@@ -485,8 +496,13 @@ void MimeUtil::InitializeMimeTypeMaps() {
false);
MimeMappings codecs;
- for (size_t j = 0; j < mime_type_codecs.size(); ++j)
+ for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
+#if defined(OS_ANDROID)
+ if (!IsCodecSupportedOnAndroid(mime_type_codecs[j]))
+ continue;
+#endif
codecs.insert(mime_type_codecs[j]);
+ }
strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
}
}
@@ -652,7 +668,7 @@ void MimeUtil::ParseCodecString(const std::string& codecs,
std::vector<std::string>* codecs_out,
bool strip) {
std::string no_quote_codecs;
- TrimString(codecs, "\"", &no_quote_codecs);
+ base::TrimString(codecs, "\"", &no_quote_codecs);
base::SplitString(no_quote_codecs, ',', codecs_out);
if (!strip)
diff --git a/chromium/net/base/mime_util_unittest.cc b/chromium/net/base/mime_util_unittest.cc
index 1a260147bfd..cc6f4aade7d 100644
--- a/chromium/net/base/mime_util_unittest.cc
+++ b/chromium/net/base/mime_util_unittest.cc
@@ -67,6 +67,8 @@ TEST(MimeUtilTest, LookupTypes) {
EXPECT_TRUE(IsSupportedImageMimeType("image/jpeg"));
EXPECT_FALSE(IsSupportedImageMimeType("image/lolcat"));
EXPECT_TRUE(IsSupportedNonImageMimeType("text/html"));
+ EXPECT_TRUE(IsSupportedNonImageMimeType("text/css"));
+ EXPECT_TRUE(IsSupportedNonImageMimeType("text/"));
EXPECT_TRUE(IsSupportedNonImageMimeType("text/banana"));
EXPECT_FALSE(IsSupportedNonImageMimeType("text/vcard"));
EXPECT_FALSE(IsSupportedNonImageMimeType("application/virus"));
diff --git a/chromium/net/base/net_error_list.h b/chromium/net/base/net_error_list.h
index 4379d540018..0585c3e18ca 100644
--- a/chromium/net/base/net_error_list.h
+++ b/chromium/net/base/net_error_list.h
@@ -303,6 +303,10 @@ NET_ERROR(TOO_MANY_SOCKET_STREAMS, -155)
// The SSL server certificate changed in a renegotiation.
NET_ERROR(SSL_SERVER_CERT_CHANGED, -156)
+// The SSL server indicated that an unnecessary TLS version fallback was
+// performed.
+NET_ERROR(SSL_INAPPROPRIATE_FALLBACK, -157)
+
// Certificate error codes
//
// The values of certificate error codes must be consecutive.
@@ -400,13 +404,20 @@ NET_ERROR(CERT_NON_UNIQUE_NAME, -210)
// a too-small RSA key).
NET_ERROR(CERT_WEAK_KEY, -211)
+// The certificate claimed DNS names that are in violation of name constraints.
+NET_ERROR(CERT_NAME_CONSTRAINT_VIOLATION, -212)
+
// Add new certificate error codes here.
//
// Update the value of CERT_END whenever you add a new certificate error
// code.
// The value immediately past the last certificate error code.
-NET_ERROR(CERT_END, -212)
+NET_ERROR(CERT_END, -213)
+
+// Certificate Transparency: All Signed Certificate Timestamps failed to verify.
+// XXX(eranm): Move this error to a more appropriate category.
+NET_ERROR(CT_NO_SCTS_VERIFIED_OK, -299)
// The URL is invalid.
NET_ERROR(INVALID_URL, -300)
@@ -555,6 +566,10 @@ NET_ERROR(QUIC_PROTOCOL_ERROR, -356)
// The HTTP headers were truncated by an EOF.
NET_ERROR(RESPONSE_HEADERS_TRUNCATED, -357)
+// The QUIC crytpo handshake failed. This means that the server was unable
+// to read any requests sent, so they may be resent.
+NET_ERROR(QUIC_HANDSHAKE_FAILED, -358)
+
// The cache does not have the requested entry.
NET_ERROR(CACHE_MISS, -400)
@@ -674,6 +689,9 @@ NET_ERROR(PRIVATE_KEY_EXPORT_FAILED, -712)
// Self-signed certificate generation failed.
NET_ERROR(SELF_SIGNED_CERT_GENERATION_FAILED, -713)
+// The certificate database changed in some way.
+NET_ERROR(CERT_DATABASE_CHANGED, -714)
+
// DNS error codes.
// DNS resolver received a malformed response.
diff --git a/chromium/net/base/net_errors.h b/chromium/net/base/net_errors.h
index 21749d8b76b..34e355e1104 100644
--- a/chromium/net/base/net_errors.h
+++ b/chromium/net/base/net_errors.h
@@ -36,7 +36,9 @@ NET_EXPORT const char* ErrorToString(int error);
inline bool IsCertificateError(int error) {
// Certificate errors are negative integers from net::ERR_CERT_BEGIN
// (inclusive) to net::ERR_CERT_END (exclusive) in *decreasing* order.
- return error <= ERR_CERT_BEGIN && error > ERR_CERT_END;
+ return (error <= ERR_CERT_BEGIN && error > ERR_CERT_END) ||
+ (error == ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY) ||
+ (error == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN);
}
// Map system error code to Error.
diff --git a/chromium/net/base/net_errors_win.cc b/chromium/net/base/net_errors_win.cc
index 2cde82f4d25..7f27deec7ef 100644
--- a/chromium/net/base/net_errors_win.cc
+++ b/chromium/net/base/net_errors_win.cc
@@ -110,6 +110,8 @@ Error MapSystemError(int os_error) {
return ERR_ACCESS_DENIED; // been detected.
case ERROR_BAD_DEVICE: // The specified device name is invalid.
return ERR_INVALID_ARGUMENT;
+ case ERROR_BROKEN_PIPE: // Pipe is not connected.
+ return ERR_CONNECTION_RESET;
case ERROR_SUCCESS:
return OK;
diff --git a/chromium/net/base/net_log_event_type_list.h b/chromium/net/base/net_log_event_type_list.h
index 837de5f3ef4..ca43b1bf12c 100644
--- a/chromium/net/base/net_log_event_type_list.h
+++ b/chromium/net/base/net_log_event_type_list.h
@@ -558,6 +558,38 @@ EVENT_TYPE(SOCKET_WRITE_ERROR)
// }
EVENT_TYPE(SSL_CERTIFICATES_RECEIVED)
+// Signed Certificate Timestamps were received from the server.
+// The following parameters are attached to the event:
+// {
+// "embedded_scts": Base64-encoded SignedCertificateTimestampList,
+// "scts_from_ocsp_response": Base64-encoded SignedCertificateTimestampList,
+// "scts_from_tls_extension": Base64-encoded SignedCertificateTimestampList,
+// }
+//
+// The SignedCertificateTimestampList is defined in RFC6962 and is exactly as
+// received from the server.
+EVENT_TYPE(SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED)
+
+// Signed Certificate Timestamps were checked.
+// The following parameters are attached to the event:
+// {
+// "verified_scts": <A list of SCTs>,
+// "invalid_scts": <A list of SCTs>,
+// "scts_from_unknown_logs": <A list of SCTs>,
+// }
+//
+// Where each SCT is an object:
+// {
+// "origin": <one of: "embedded_in_certificate", "tls_extension", "ocsp">,
+// "version": <numeric version>,
+// "log_id": <base64-encoded log id>,
+// "timestamp": <numeric timestamp in milliseconds since the Unix epoch>,
+// "hash_algorithm": <name of the hash algorithm>,
+// "signature_algorithm": <name of the signature algorithm>,
+// "signature_data": <base64-encoded signature bytes>,
+// }
+EVENT_TYPE(SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED)
+
// ------------------------------------------------------------------------
// DatagramSocket
// ------------------------------------------------------------------------
@@ -666,8 +698,8 @@ EVENT_TYPE(TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKET)
EVENT_TYPE(TCP_CLIENT_SOCKET_POOL_REQUESTED_SOCKETS)
-// A backup socket is created due to slow connect
-EVENT_TYPE(SOCKET_BACKUP_CREATED)
+// A backup connect job is created due to slow connect.
+EVENT_TYPE(BACKUP_CONNECT_JOB_CREATED)
// This event is sent when a connect job is eventually bound to a request
// (because of late binding and socket backup jobs, we don't assign the job to
@@ -726,14 +758,16 @@ EVENT_TYPE(URL_REQUEST_START_JOB)
// }
EVENT_TYPE(URL_REQUEST_REDIRECTED)
-// Measures the time a net::URLRequest is blocked waiting for either the
-// NetworkDelegate or a URLRequest::Delegate to respond.
-//
-// The parameters attached to the event are:
+// Measures the time between when a net::URLRequest calls a delegate that can
+// block it, and when the delegate allows the request to resume.
+EVENT_TYPE(URL_REQUEST_DELEGATE)
+
+// Logged when a delegate informs the URL_REQUEST of what's currently blocking
+// the request. The parameters attached to the begin event are:
// {
-// "delegate": <What's blocking the request, if known>,
+// "delegate_info": <Information about what's blocking the request>,
// }
-EVENT_TYPE(URL_REQUEST_BLOCKED_ON_DELEGATE)
+EVENT_TYPE(DELEGATE_INFO)
// The specified number of bytes were read from the net::URLRequest.
// The filtered event is used when the bytes were passed through a filter before
diff --git a/chromium/net/base/net_log_logger_unittest.cc b/chromium/net/base/net_log_logger_unittest.cc
index 3dd6915915d..05c16c72fed 100644
--- a/chromium/net/base/net_log_logger_unittest.cc
+++ b/chromium/net/base/net_log_logger_unittest.cc
@@ -28,7 +28,7 @@ class NetLogLoggerTest : public testing::Test {
TEST_F(NetLogLoggerTest, GeneratesValidJSONForNoEvents) {
{
// Create and destroy a logger.
- FILE* file = file_util::OpenFile(log_path_, "w");
+ FILE* file = base::OpenFile(log_path_, "w");
ASSERT_TRUE(file);
scoped_ptr<base::Value> constants(NetLogLogger::GetConstants());
NetLogLogger logger(file, *constants);
@@ -50,7 +50,7 @@ TEST_F(NetLogLoggerTest, GeneratesValidJSONForNoEvents) {
TEST_F(NetLogLoggerTest, GeneratesValidJSONWithOneEvent) {
{
- FILE* file = file_util::OpenFile(log_path_, "w");
+ FILE* file = base::OpenFile(log_path_, "w");
ASSERT_TRUE(file);
scoped_ptr<base::Value> constants(NetLogLogger::GetConstants());
NetLogLogger logger(file, *constants);
@@ -82,7 +82,7 @@ TEST_F(NetLogLoggerTest, GeneratesValidJSONWithOneEvent) {
TEST_F(NetLogLoggerTest, GeneratesValidJSONWithMultipleEvents) {
{
- FILE* file = file_util::OpenFile(log_path_, "w");
+ FILE* file = base::OpenFile(log_path_, "w");
ASSERT_TRUE(file);
scoped_ptr<base::Value> constants(NetLogLogger::GetConstants());
NetLogLogger logger(file, *constants);
diff --git a/chromium/net/base/net_log_unittest.h b/chromium/net/base/net_log_unittest.h
index 32fb5f82399..574e318a091 100644
--- a/chromium/net/base/net_log_unittest.h
+++ b/chromium/net/base/net_log_unittest.h
@@ -107,6 +107,23 @@ inline ::testing::AssertionResult LogContainsEntryWithType(
return ::testing::AssertionSuccess();
}
+// Check if the log contains any entry of the given type at |min_index| or
+// after.
+inline ::testing::AssertionResult LogContainsEntryWithTypeAfter(
+ const CapturingNetLog::CapturedEntryList& entries,
+ int min_index, // Negative indices are reverse indices.
+ NetLog::EventType type) {
+ // Negative indices are reverse indices.
+ size_t real_index = (min_index < 0) ?
+ static_cast<size_t>(static_cast<int>(entries.size()) + min_index) :
+ static_cast<size_t>(min_index);
+ for (size_t i = real_index; i < entries.size(); ++i) {
+ const CapturingNetLog::CapturedEntry& entry = entries[i];
+ if (entry.type == type)
+ return ::testing::AssertionSuccess();
+ }
+ return ::testing::AssertionFailure();
+}
// Expect that the log contains an event, but don't care about where
// as long as the first index where it is found is at least |min_index|.
diff --git a/chromium/net/base/net_util.cc b/chromium/net/base/net_util.cc
index dd0826c6a54..1f69ee71800 100644
--- a/chromium/net/base/net_util.cc
+++ b/chromium/net/base/net_util.cc
@@ -324,7 +324,7 @@ bool IsIDNComponentSafe(const base::char16* str,
UErrorCode status = U_ZERO_ERROR;
#ifdef U_WCHAR_IS_UTF16
icu::UnicodeSet dangerous_characters(icu::UnicodeString(
- L"[[\\ \u00bc\u00bd\u01c3\u0337\u0338"
+ L"[[\\ \u00ad\u00bc\u00bd\u01c3\u0337\u0338"
L"\u05c3\u05f4\u06d4\u0702\u115f\u1160][\u2000-\u200b]"
L"[\u2024\u2027\u2028\u2029\u2039\u203a\u2044\u205f]"
L"[\u2154-\u2156][\u2159-\u215b][\u215f\u2215\u23ae"
@@ -341,7 +341,7 @@ bool IsIDNComponentSafe(const base::char16* str,
0, status);
#else
icu::UnicodeSet dangerous_characters(icu::UnicodeString(
- "[[\\u0020\\u00bc\\u00bd\\u01c3\\u0337\\u0338"
+ "[[\\u0020\\u00ad\\u00bc\\u00bd\\u01c3\\u0337\\u0338"
"\\u05c3\\u05f4\\u06d4\\u0702\\u115f\\u1160][\\u2000-\\u200b]"
"[\\u2024\\u2027\\u2028\\u2029\\u2039\\u203a\\u2044\\u205f]"
"[\\u2154-\\u2156][\\u2159-\\u215b][\\u215f\\u2215\\u23ae"
@@ -398,6 +398,42 @@ bool IsIDNComponentSafe(const base::char16* str,
return false;
}
+// A wrapper to use LazyInstance<>::Leaky with ICU's UIDNA, a C pointer to
+// a UTS46/IDNA 2008 handling object opened with uidna_openUTS46().
+//
+// We use UTS46 with BiDiCheck to migrate from IDNA 2003 to IDNA 2008 with
+// the backward compatibility in mind. What it does:
+//
+// 1. Use the up-to-date Unicode data.
+// 2. Define a case folding/mapping with the up-to-date Unicode data as
+// in IDNA 2003.
+// 3. Use transitional mechanism for 4 deviation characters (sharp-s,
+// final sigma, ZWJ and ZWNJ) for now.
+// 4. Continue to allow symbols and punctuations.
+// 5. Apply new BiDi check rules more permissive than the IDNA 2003 BiDI rules.
+// 6. Do not apply STD3 rules
+// 7. Do not allow unassigned code points.
+//
+// It also closely matches what IE 10 does except for the BiDi check (
+// http://goo.gl/3XBhqw ).
+// See http://http://unicode.org/reports/tr46/ and references therein
+// for more details.
+struct UIDNAWrapper {
+ UIDNAWrapper() {
+ UErrorCode err = U_ZERO_ERROR;
+ // TODO(jungshik): Change options as different parties (browsers,
+ // registrars, search engines) converge toward a consensus.
+ value = uidna_openUTS46(UIDNA_CHECK_BIDI, &err);
+ if (U_FAILURE(err))
+ value = NULL;
+ }
+
+ UIDNA* value;
+};
+
+static base::LazyInstance<UIDNAWrapper>::Leaky
+ g_uidna = LAZY_INSTANCE_INITIALIZER;
+
// Converts one component of a host (between dots) to IDN if safe. The result
// will be APPENDED to the given output string and will be the same as the input
// if it is not IDN or the IDN is unsafe to display. Returns whether any
@@ -414,29 +450,33 @@ bool IDNToUnicodeOneComponent(const base::char16* comp,
static const base::char16 kIdnPrefix[] = {'x', 'n', '-', '-'};
if ((comp_len > arraysize(kIdnPrefix)) &&
!memcmp(comp, kIdnPrefix, arraysize(kIdnPrefix) * sizeof(base::char16))) {
- // Repeatedly expand the output string until it's big enough. It looks like
- // ICU will return the required size of the buffer, but that's not
- // documented, so we'll just grow by 2x. This should be rare and is not on a
- // critical path.
+ UIDNA* uidna = g_uidna.Get().value;
+ DCHECK(uidna != NULL);
size_t original_length = out->length();
- for (int extra_space = 64; ; extra_space *= 2) {
- UErrorCode status = U_ZERO_ERROR;
- out->resize(out->length() + extra_space);
- int output_chars = uidna_IDNToUnicode(comp,
- static_cast<int32_t>(comp_len), &(*out)[original_length], extra_space,
- UIDNA_DEFAULT, NULL, &status);
- if (status == U_ZERO_ERROR) {
- // Converted successfully.
- out->resize(original_length + output_chars);
- if (IsIDNComponentSafe(out->data() + original_length, output_chars,
- languages))
- return true;
- }
-
- if (status != U_BUFFER_OVERFLOW_ERROR)
- break;
+ int output_length = 64;
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ UErrorCode status;
+ do {
+ out->resize(original_length + output_length);
+ status = U_ZERO_ERROR;
+ // This returns the actual length required. If this is more than 64
+ // code units, |status| will be U_BUFFER_OVERFLOW_ERROR and we'll try
+ // the conversion again, but with a sufficiently large buffer.
+ output_length = uidna_labelToUnicode(
+ uidna, comp, static_cast<int32_t>(comp_len), &(*out)[original_length],
+ output_length, &info, &status);
+ } while ((status == U_BUFFER_OVERFLOW_ERROR && info.errors == 0));
+
+ if (U_SUCCESS(status) && info.errors == 0) {
+ // Converted successfully. Ensure that the converted component
+ // can be safely displayed to the user.
+ out->resize(original_length + output_length);
+ if (IsIDNComponentSafe(out->data() + original_length, output_length,
+ languages))
+ return true;
}
- // Failed, revert back to original string.
+
+ // Something went wrong. Revert to original string.
out->resize(original_length);
}
@@ -733,7 +773,7 @@ void SanitizeGeneratedFileName(base::FilePath::StringType* filename,
if (trimmed)
filename->insert(filename->end(), trimmed, kReplace[0]);
}
- TrimString(*filename, FILE_PATH_LITERAL("."), filename);
+ base::TrimString(*filename, FILE_PATH_LITERAL("."), filename);
if (filename->empty())
return;
// Replace any path information by changing path separators.
@@ -1055,7 +1095,7 @@ std::string GetDirectoryListingHeader(const base::string16& title) {
result.assign(header.data(), header.size());
result.append("<script>start(");
- base::JsonDoubleQuote(title, true, &result);
+ base::EscapeJSONString(title, true, &result);
result.append(");</script>\n");
return result;
@@ -1109,13 +1149,12 @@ std::string GetDirectoryListingEntry(const base::string16& name,
Time modified) {
std::string result;
result.append("<script>addRow(");
- base::JsonDoubleQuote(name, true, &result);
+ base::EscapeJSONString(name, true, &result);
result.append(",");
if (raw_bytes.empty()) {
- base::JsonDoubleQuote(EscapePath(UTF16ToUTF8(name)),
- true, &result);
+ base::EscapeJSONString(EscapePath(UTF16ToUTF8(name)), true, &result);
} else {
- base::JsonDoubleQuote(EscapePath(raw_bytes), true, &result);
+ base::EscapeJSONString(EscapePath(raw_bytes), true, &result);
}
if (is_dir) {
result.append(",1,");
@@ -1127,7 +1166,7 @@ std::string GetDirectoryListingEntry(const base::string16& name,
base::string16 size_string;
if (size >= 0)
size_string = FormatBytesUnlocalized(size);
- base::JsonDoubleQuote(size_string, true, &result);
+ base::EscapeJSONString(size_string, true, &result);
result.append(",");
@@ -1136,7 +1175,7 @@ std::string GetDirectoryListingEntry(const base::string16& name,
if (!modified.is_null()) {
modified_str = base::TimeFormatShortDateAndTime(modified);
}
- base::JsonDoubleQuote(modified_str, true, &result);
+ base::EscapeJSONString(modified_str, true, &result);
result.append(");</script>\n");
@@ -2142,15 +2181,42 @@ bool IsLocalhost(const std::string& host) {
return false;
}
-NetworkInterface::NetworkInterface() {
+NetworkInterface::NetworkInterface() : network_prefix(0) {
}
NetworkInterface::NetworkInterface(const std::string& name,
- const IPAddressNumber& address)
- : name(name), address(address) {
+ uint32 interface_index,
+ const IPAddressNumber& address,
+ size_t network_prefix)
+ : name(name),
+ interface_index(interface_index),
+ address(address),
+ network_prefix(network_prefix) {
}
NetworkInterface::~NetworkInterface() {
}
+unsigned CommonPrefixLength(const IPAddressNumber& a1,
+ const IPAddressNumber& a2) {
+ DCHECK_EQ(a1.size(), a2.size());
+ for (size_t i = 0; i < a1.size(); ++i) {
+ unsigned diff = a1[i] ^ a2[i];
+ if (!diff)
+ continue;
+ for (unsigned j = 0; j < CHAR_BIT; ++j) {
+ if (diff & (1 << (CHAR_BIT - 1)))
+ return i * CHAR_BIT + j;
+ diff <<= 1;
+ }
+ NOTREACHED();
+ }
+ return a1.size() * CHAR_BIT;
+}
+
+unsigned MaskPrefixLength(const IPAddressNumber& mask) {
+ IPAddressNumber all_ones(mask.size(), 0xFF);
+ return CommonPrefixLength(mask, all_ones);
+}
+
} // namespace net
diff --git a/chromium/net/base/net_util.h b/chromium/net/base/net_util.h
index 6b8884dd114..baa68e3a097 100644
--- a/chromium/net/base/net_util.h
+++ b/chromium/net/base/net_util.h
@@ -15,8 +15,6 @@
#include <sys/socket.h>
#endif
-#include <list>
-#include <set>
#include <string>
#include <vector>
@@ -175,8 +173,8 @@ NET_EXPORT std::string GetHostName();
// Extracts the unescaped username/password from |url|, saving the results
// into |*username| and |*password|.
NET_EXPORT_PRIVATE void GetIdentityFromURL(const GURL& url,
- base::string16* username,
- base::string16* password);
+ base::string16* username,
+ base::string16* password);
// Returns either the host from |url|, or, if the host is empty, the full spec.
NET_EXPORT std::string GetHostOrSpecFromURL(const GURL& url);
@@ -203,7 +201,7 @@ NET_EXPORT std::string GetSpecificHeader(const std::string& headers,
// script-language pairs (currently Han, Kana and Hangul for zh,ja and ko).
// When |languages| is empty, even that mixing is not allowed.
NET_EXPORT base::string16 IDNToUnicode(const std::string& host,
- const std::string& languages);
+ const std::string& languages);
// Canonicalizes |host| and returns it. Also fills |host_info| with
// IP address information. |host_info| must not be NULL.
@@ -430,7 +428,7 @@ NET_EXPORT void SetExplicitlyAllowedPorts(const std::string& allowed_ports);
class NET_EXPORT ScopedPortException {
public:
- ScopedPortException(int port);
+ explicit ScopedPortException(int port);
~ScopedPortException();
private:
@@ -449,7 +447,7 @@ NET_EXPORT_PRIVATE AddressFamily GetAddressFamily(
const IPAddressNumber& address);
// Maps the given AddressFamily to either AF_INET, AF_INET6 or AF_UNSPEC.
-int ConvertAddressFamily(AddressFamily address_family);
+NET_EXPORT_PRIVATE int ConvertAddressFamily(AddressFamily address_family);
// 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.
@@ -516,11 +514,16 @@ NET_EXPORT_PRIVATE bool IsLocalhost(const std::string& host);
// interface.
struct NET_EXPORT NetworkInterface {
NetworkInterface();
- NetworkInterface(const std::string& name, const IPAddressNumber& address);
+ NetworkInterface(const std::string& name,
+ uint32 interface_index,
+ const IPAddressNumber& address,
+ size_t network_prefix);
~NetworkInterface();
std::string name;
+ uint32 interface_index; // Always 0 on Android.
IPAddressNumber address;
+ size_t network_prefix;
};
typedef std::vector<NetworkInterface> NetworkInterfaceList;
@@ -553,6 +556,41 @@ enum WifiPHYLayerProtocol {
// Currently only available on OS_WIN.
NET_EXPORT WifiPHYLayerProtocol GetWifiPHYLayerProtocol();
+// Returns number of matching initial bits between the addresses |a1| and |a2|.
+unsigned CommonPrefixLength(const IPAddressNumber& a1,
+ const IPAddressNumber& a2);
+
+// Computes the number of leading 1-bits in |mask|.
+unsigned MaskPrefixLength(const IPAddressNumber& mask);
+
+// Differentiated Services Code Point.
+// See http://tools.ietf.org/html/rfc2474 for details.
+enum DiffServCodePoint {
+ DSCP_NO_CHANGE = -1,
+ DSCP_DEFAULT = 0, // Same as DSCP_CS0
+ DSCP_CS0 = 0, // The default
+ DSCP_CS1 = 8, // Bulk/background traffic
+ DSCP_AF11 = 10,
+ DSCP_AF12 = 12,
+ DSCP_AF13 = 14,
+ DSCP_CS2 = 16,
+ DSCP_AF21 = 18,
+ DSCP_AF22 = 20,
+ DSCP_AF23 = 22,
+ DSCP_CS3 = 24,
+ DSCP_AF31 = 26,
+ DSCP_AF32 = 28,
+ DSCP_AF33 = 30,
+ DSCP_CS4 = 32,
+ DSCP_AF41 = 34, // Video
+ DSCP_AF42 = 36, // Video
+ DSCP_AF43 = 38, // Video
+ DSCP_CS5 = 40, // Video
+ DSCP_EF = 46, // Voice
+ DSCP_CS6 = 48, // Voice
+ DSCP_CS7 = 56, // Control messages
+};
+
} // namespace net
#endif // NET_BASE_NET_UTIL_H_
diff --git a/chromium/net/base/net_util_posix.cc b/chromium/net/base/net_util_posix.cc
index 904d8028bc2..5e1042b4304 100644
--- a/chromium/net/base/net_util_posix.cc
+++ b/chromium/net/base/net_util_posix.cc
@@ -8,7 +8,7 @@
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/posix/eintr_wrapper.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
@@ -66,24 +66,27 @@ bool FileURLToFilePath(const GURL& url, base::FilePath* path) {
bool GetNetworkList(NetworkInterfaceList* networks) {
#if defined(OS_ANDROID)
std::string network_list = android::GetNetworkList();
- base::StringTokenizer network_interfaces(network_list, ";");
+ base::StringTokenizer network_interfaces(network_list, "\n");
while (network_interfaces.GetNext()) {
std::string network_item = network_interfaces.token();
- base::StringTokenizer network_tokenizer(network_item, ",");
- std::string name;
- if (!network_tokenizer.GetNext())
- continue;
- name = network_tokenizer.token();
-
- std::string literal_address;
- if (!network_tokenizer.GetNext())
- continue;
- literal_address = network_tokenizer.token();
+ base::StringTokenizer network_tokenizer(network_item, "\t");
+ CHECK(network_tokenizer.GetNext());
+ std::string name = network_tokenizer.token();
+ CHECK(network_tokenizer.GetNext());
+ std::string interface_address = network_tokenizer.token();
IPAddressNumber address;
- if (!ParseIPLiteralToNumber(literal_address, &address))
- continue;
- networks->push_back(NetworkInterface(name, address));
+ size_t network_prefix = 0;
+ CHECK(ParseCIDRBlock(network_tokenizer.token(),
+ &address,
+ &network_prefix));
+
+ CHECK(network_tokenizer.GetNext());
+ uint32 index = 0;
+ CHECK(base::StringToUint(network_tokenizer.token(), &index));
+
+ networks->push_back(
+ NetworkInterface(name, index, address, network_prefix));
}
return true;
#else
@@ -109,6 +112,7 @@ bool GetNetworkList(NetworkInterfaceList* networks) {
struct sockaddr* addr = interface->ifa_addr;
if (!addr)
continue;
+
// Skip unspecified addresses (i.e. made of zeroes) and loopback addresses
// configured on non-loopback interfaces.
int addr_size = 0;
@@ -133,10 +137,21 @@ bool GetNetworkList(NetworkInterfaceList* networks) {
// Skip non-IP addresses.
continue;
}
+
IPEndPoint address;
std::string name = interface->ifa_name;
if (address.FromSockAddr(addr, addr_size)) {
- networks->push_back(NetworkInterface(name, address.address()));
+ uint8 net_mask = 0;
+ if (interface->ifa_netmask) {
+ IPEndPoint netmask;
+ if (netmask.FromSockAddr(interface->ifa_netmask, addr_size)) {
+ net_mask = MaskPrefixLength(netmask.address());
+ }
+ }
+
+ networks->push_back(
+ NetworkInterface(name, if_nametoindex(name.c_str()),
+ address.address(), net_mask));
}
}
diff --git a/chromium/net/base/net_util_unittest.cc b/chromium/net/base/net_util_unittest.cc
index 207e05a1cc0..2259629209f 100644
--- a/chromium/net/base/net_util_unittest.cc
+++ b/chromium/net/base/net_util_unittest.cc
@@ -10,6 +10,7 @@
#include "base/files/file_path.h"
#include "base/format_macros.h"
+#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -21,6 +22,14 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#if defined(OS_WIN)
+#include <iphlpapi.h>
+#include <objbase.h>
+#include "base/win/windows_version.h"
+#elif !defined(OS_ANDROID)
+#include <net/if.h>
+#endif // OS_WIN
+
namespace net {
namespace {
@@ -2251,8 +2260,8 @@ TEST(NetUtilTest, GetDirectoryListingEntry) {
false,
10000,
base::Time(),
- "<script>addRow(\"\\uD55C\\uAE00.txt\",\"%ED%95%9C%EA%B8%80.txt\""
- ",0,\"9.8 kB\",\"\");</script>\n"},
+ "<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",
@@ -2260,7 +2269,7 @@ TEST(NetUtilTest, GetDirectoryListingEntry) {
false,
10000,
base::Time(),
- "<script>addRow(\"\\uD55C\\uAE00.txt\",\"%C7%D1%B1%DB.txt\""
+ "<script>addRow(\"\xED\x95\x9C\xEA\xB8\x80.txt\",\"%C7%D1%B1%DB.txt\""
",0,\"9.8 kB\",\"\");</script>\n"},
};
@@ -3026,9 +3035,9 @@ TEST(NetUtilTest, SimplifyUrlForRequest) {
"ftp://user:pass@google.com:80/sup?yo#X#X",
"ftp://google.com:80/sup?yo",
},
- { // Try an nonstandard URL
- "foobar://user:pass@google.com:80/sup?yo#X#X",
+ { // 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_UNSAFE(tests); ++i) {
@@ -3291,7 +3300,6 @@ TEST(NetUtilTest, IsLocalhost) {
TEST(NetUtilTest, GetNetworkList) {
NetworkInterfaceList list;
ASSERT_TRUE(GetNetworkList(&list));
-
for (NetworkInterfaceList::iterator it = list.begin();
it != list.end(); ++it) {
// Verify that the name is not empty.
@@ -3309,6 +3317,46 @@ TEST(NetUtilTest, GetNetworkList) {
}
}
EXPECT_FALSE(all_zeroes);
+ EXPECT_GT(it->network_prefix, 1u);
+ EXPECT_LE(it->network_prefix, it->address.size() * 8);
+
+#if defined(OS_WIN)
+ // On Windows |name| is NET_LUID.
+ base::ScopedNativeLibrary phlpapi_lib(
+ base::FilePath(FILE_PATH_LITERAL("iphlpapi.dll")));
+ ASSERT_TRUE(phlpapi_lib.is_valid());
+ typedef NETIO_STATUS (WINAPI* ConvertInterfaceIndexToLuid)(NET_IFINDEX,
+ PNET_LUID);
+ ConvertInterfaceIndexToLuid interface_to_luid =
+ reinterpret_cast<ConvertInterfaceIndexToLuid>(
+ phlpapi_lib.GetFunctionPointer("ConvertInterfaceIndexToLuid"));
+
+ typedef NETIO_STATUS (WINAPI* ConvertInterfaceLuidToGuid)(NET_LUID*,
+ GUID*);
+ ConvertInterfaceLuidToGuid luid_to_guid =
+ reinterpret_cast<ConvertInterfaceLuidToGuid>(
+ phlpapi_lib.GetFunctionPointer("ConvertInterfaceLuidToGuid"));
+
+ if (interface_to_luid && luid_to_guid) {
+ NET_LUID luid;
+ EXPECT_EQ(interface_to_luid(it->interface_index, &luid), NO_ERROR);
+ GUID guid;
+ EXPECT_EQ(luid_to_guid(&luid, &guid), NO_ERROR);
+ LPOLESTR name;
+ StringFromCLSID(guid, &name);
+ EXPECT_STREQ(UTF8ToWide(it->name).c_str(), name);
+ CoTaskMemFree(name);
+ continue;
+ } else {
+ EXPECT_LT(base::win::GetVersion(), base::win::VERSION_VISTA);
+ EXPECT_LT(it->interface_index, 1u << 24u); // Must fit 0.x.x.x.
+ EXPECT_NE(it->interface_index, 0u); // 0 means to use default.
+ }
+#elif !defined(OS_ANDROID)
+ char name[IF_NAMESIZE];
+ EXPECT_TRUE(if_indextoname(it->interface_index, name));
+ EXPECT_STREQ(it->name.c_str(), name);
+#endif
}
}
diff --git a/chromium/net/base/net_util_win.cc b/chromium/net/base/net_util_win.cc
index 986af79eac7..d0efe392dc2 100644
--- a/chromium/net/base/net_util_win.cc
+++ b/chromium/net/base/net_util_win.cc
@@ -18,6 +18,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
#include "net/base/escape.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -60,6 +61,17 @@ struct WlanApi {
close_handle_func;
}
+ template <typename T>
+ DWORD OpenHandle(DWORD client_version, DWORD* cur_version, T* handle) const {
+ HANDLE temp_handle;
+ DWORD result = open_handle_func(client_version, NULL, cur_version,
+ &temp_handle);
+ if (result != ERROR_SUCCESS)
+ return result;
+ handle->Set(temp_handle);
+ return ERROR_SUCCESS;
+ }
+
HMODULE module;
WlanOpenHandleFunc open_handle_func;
WlanEnumInterfacesFunc enum_interfaces_func;
@@ -129,21 +141,19 @@ bool FileURLToFilePath(const GURL& url, base::FilePath* file_path) {
bool GetNetworkList(NetworkInterfaceList* networks) {
// GetAdaptersAddresses() may require IO operations.
base::ThreadRestrictions::AssertIOAllowed();
-
- IP_ADAPTER_ADDRESSES info_temp;
+ bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
ULONG len = 0;
-
+ ULONG flags = is_xp ? GAA_FLAG_INCLUDE_PREFIX : 0;
// First get number of networks.
- ULONG result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, &info_temp, &len);
+ ULONG result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &len);
if (result != ERROR_BUFFER_OVERFLOW) {
// There are 0 networks.
return true;
}
-
scoped_ptr<char[]> buf(new char[len]);
IP_ADAPTER_ADDRESSES *adapters =
reinterpret_cast<IP_ADAPTER_ADDRESSES *>(buf.get());
- result = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
+ result = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapters, &len);
if (result != NO_ERROR) {
LOG(ERROR) << "GetAdaptersAddresses failed: " << result;
return false;
@@ -160,16 +170,41 @@ bool GetNetworkList(NetworkInterfaceList* networks) {
continue;
}
- IP_ADAPTER_UNICAST_ADDRESS* address;
- for (address = adapter->FirstUnicastAddress; address != NULL;
- address = address->Next) {
+ std::string name = adapter->AdapterName;
+
+ for (IP_ADAPTER_UNICAST_ADDRESS* address = adapter->FirstUnicastAddress;
+ address; address = address->Next) {
int family = address->Address.lpSockaddr->sa_family;
if (family == AF_INET || family == AF_INET6) {
IPEndPoint endpoint;
if (endpoint.FromSockAddr(address->Address.lpSockaddr,
address->Address.iSockaddrLength)) {
- std::string name = adapter->AdapterName;
- networks->push_back(NetworkInterface(name, endpoint.address()));
+ // XP has no OnLinkPrefixLength field.
+ size_t net_prefix = is_xp ? 0 : address->OnLinkPrefixLength;
+ if (is_xp) {
+ // Prior to Windows Vista the FirstPrefix pointed to the list with
+ // single prefix for each IP address assigned to the adapter.
+ // Order of FirstPrefix does not match order of FirstUnicastAddress,
+ // so we need to find corresponding prefix.
+ for (IP_ADAPTER_PREFIX* prefix = adapter->FirstPrefix; prefix;
+ prefix = prefix->Next) {
+ int prefix_family = prefix->Address.lpSockaddr->sa_family;
+ IPEndPoint network_endpoint;
+ if (prefix_family == family &&
+ network_endpoint.FromSockAddr(prefix->Address.lpSockaddr,
+ prefix->Address.iSockaddrLength) &&
+ IPNumberMatchesPrefix(endpoint.address(),
+ network_endpoint.address(),
+ prefix->PrefixLength)) {
+ net_prefix = std::max<size_t>(net_prefix, prefix->PrefixLength);
+ }
+ }
+ }
+ uint32 index =
+ (family == AF_INET) ? adapter->IfIndex : adapter->Ipv6IfIndex;
+ networks->push_back(
+ NetworkInterface(adapter->AdapterName, index, endpoint.address(),
+ net_prefix));
}
}
}
@@ -214,8 +249,7 @@ WifiPHYLayerProtocol GetWifiPHYLayerProtocol() {
WlanHandle client;
DWORD cur_version = 0;
const DWORD kMaxClientVersion = 2;
- DWORD result = wlanapi.open_handle_func(kMaxClientVersion, NULL, &cur_version,
- client.Receive());
+ DWORD result = wlanapi.OpenHandle(kMaxClientVersion, &cur_version, &client);
if (result != ERROR_SUCCESS)
return WIFI_PHY_LAYER_PROTOCOL_NONE;
diff --git a/chromium/net/base/network_change_notifier_win.cc b/chromium/net/base/network_change_notifier_win.cc
index d53b346c440..569793fee6e 100644
--- a/chromium/net/base/network_change_notifier_win.cc
+++ b/chromium/net/base/network_change_notifier_win.cc
@@ -57,7 +57,9 @@ NetworkChangeNotifierWin::NetworkChangeNotifierWin()
sequential_failures_(0),
weak_factory_(this),
dns_config_service_thread_(new DnsConfigServiceThread()),
- last_announced_offline_(IsOffline()) {
+ last_computed_connection_type_(RecomputeCurrentConnectionType()),
+ last_announced_offline_(
+ last_computed_connection_type_ == CONNECTION_NONE) {
memset(&addr_overlapped_, 0, sizeof addr_overlapped_);
addr_overlapped_.hEvent = WSACreateEvent();
dns_config_service_thread_->StartWithOptions(
@@ -135,11 +137,8 @@ NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() {
// executing 'ipconfig /release'.
//
NetworkChangeNotifier::ConnectionType
-NetworkChangeNotifierWin::GetCurrentConnectionType() const {
-
- // TODO(eroman): We could cache this value, and only re-calculate it on
- // network changes. For now we recompute it each time asked,
- // since it is relatively fast (sub 1ms) and not called often.
+NetworkChangeNotifierWin::RecomputeCurrentConnectionType() const {
+ DCHECK(CalledOnValidThread());
EnsureWinsockInit();
@@ -208,6 +207,18 @@ NetworkChangeNotifierWin::GetCurrentConnectionType() const {
NetworkChangeNotifier::CONNECTION_NONE;
}
+NetworkChangeNotifier::ConnectionType
+NetworkChangeNotifierWin::GetCurrentConnectionType() const {
+ base::AutoLock auto_lock(last_computed_connection_type_lock_);
+ return last_computed_connection_type_;
+}
+
+void NetworkChangeNotifierWin::SetCurrentConnectionType(
+ ConnectionType connection_type) {
+ base::AutoLock auto_lock(last_computed_connection_type_lock_);
+ last_computed_connection_type_ = connection_type;
+}
+
void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) {
DCHECK(CalledOnValidThread());
DCHECK(is_watching_);
@@ -221,6 +232,7 @@ void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) {
void NetworkChangeNotifierWin::NotifyObservers() {
DCHECK(CalledOnValidThread());
+ SetCurrentConnectionType(RecomputeCurrentConnectionType());
NotifyObserversOfIPAddressChange();
// Calling GetConnectionType() at this very moment is likely to give
@@ -289,6 +301,7 @@ bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() {
}
void NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange() {
+ SetCurrentConnectionType(RecomputeCurrentConnectionType());
bool current_offline = IsOffline();
offline_polls_++;
// If we continue to appear offline, delay sending out the notification in
diff --git a/chromium/net/base/network_change_notifier_win.h b/chromium/net/base/network_change_notifier_win.h
index 47a97dfac9c..177bad2f7f7 100644
--- a/chromium/net/base/network_change_notifier_win.h
+++ b/chromium/net/base/network_change_notifier_win.h
@@ -57,6 +57,12 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin
// Must only be called on the thread |this| was created on.
virtual void OnObjectSignaled(HANDLE object) OVERRIDE;
+ // Does the actual work to determine the current connection type.
+ // It is not thread safe, see crbug.com/324913.
+ ConnectionType RecomputeCurrentConnectionType() const;
+
+ void SetCurrentConnectionType(ConnectionType connection_type);
+
// Notifies IP address change observers of a change immediately, and notifies
// network state change observers on a delay. Must only be called on the
// thread |this| was created on.
@@ -95,6 +101,9 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierWin
// Thread on which we can run DnsConfigService.
scoped_ptr<DnsConfigServiceThread> dns_config_service_thread_;
+ mutable base::Lock last_computed_connection_type_lock_;
+ ConnectionType last_computed_connection_type_;
+
// Result of IsOffline() when NotifyObserversOfConnectionTypeChange()
// was last called.
bool last_announced_offline_;
diff --git a/chromium/net/base/network_delegate.cc b/chromium/net/base/network_delegate.cc
index 5a69b863e62..834769c84e1 100644
--- a/chromium/net/base/network_delegate.cc
+++ b/chromium/net/base/network_delegate.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "net/base/load_flags.h"
+#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
namespace net {
@@ -92,6 +93,21 @@ NetworkDelegate::AuthRequiredResponse NetworkDelegate::NotifyAuthRequired(
return OnAuthRequired(request, auth_info, callback, credentials);
}
+int NetworkDelegate::NotifyBeforeSocketStreamConnect(
+ SocketStream* socket,
+ const CompletionCallback& callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(socket);
+ DCHECK(!callback.is_null());
+ return OnBeforeSocketStreamConnect(socket, callback);
+}
+
+void NetworkDelegate::NotifyRequestWaitStateChange(const URLRequest& request,
+ RequestWaitState state) {
+ DCHECK(CalledOnValidThread());
+ OnRequestWaitStateChange(request, state);
+}
+
bool NetworkDelegate::CanGetCookies(const URLRequest& request,
const CookieList& cookie_list) {
DCHECK(CalledOnValidThread());
@@ -125,26 +141,93 @@ bool NetworkDelegate::CanEnablePrivacyMode(
return OnCanEnablePrivacyMode(url, first_party_for_cookies);
}
+int NetworkDelegate::OnBeforeURLRequest(URLRequest* request,
+ const CompletionCallback& callback,
+ GURL* new_url) {
+ return OK;
+}
+
+int NetworkDelegate::OnBeforeSendHeaders(URLRequest* request,
+ const CompletionCallback& callback,
+ HttpRequestHeaders* headers) {
+ return OK;
+}
+
+void NetworkDelegate::OnSendHeaders(URLRequest* request,
+ const HttpRequestHeaders& headers) {
+}
+
+int NetworkDelegate::OnHeadersReceived(
+ URLRequest* request,
+ const CompletionCallback& callback,
+ const HttpResponseHeaders* original_response_headers,
+ scoped_refptr<HttpResponseHeaders>* override_response_headers) {
+ return OK;
+}
+
+void NetworkDelegate::OnBeforeRedirect(URLRequest* request,
+ const GURL& new_location) {
+}
+
+void NetworkDelegate::OnResponseStarted(URLRequest* request) {
+}
+
+void NetworkDelegate::OnRawBytesRead(const URLRequest& request,
+ int bytes_read) {
+}
+
+void NetworkDelegate::OnCompleted(URLRequest* request, bool started) {
+}
+
+void NetworkDelegate::OnURLRequestDestroyed(URLRequest* request) {
+}
+
+void NetworkDelegate::OnPACScriptError(int line_number,
+ const base::string16& error) {
+}
+
+NetworkDelegate::AuthRequiredResponse NetworkDelegate::OnAuthRequired(
+ URLRequest* request,
+ const AuthChallengeInfo& auth_info,
+ const AuthCallback& callback,
+ AuthCredentials* credentials) {
+ return AUTH_REQUIRED_RESPONSE_NO_ACTION;
+}
+
+bool NetworkDelegate::OnCanGetCookies(const URLRequest& request,
+ const CookieList& cookie_list) {
+ return true;
+}
+
+bool NetworkDelegate::OnCanSetCookie(const URLRequest& request,
+ const std::string& cookie_line,
+ CookieOptions* options) {
+ return true;
+}
+
+bool NetworkDelegate::OnCanAccessFile(const URLRequest& request,
+ const base::FilePath& path) const {
+ return false;
+}
+
+bool NetworkDelegate::OnCanThrottleRequest(const URLRequest& request) const {
+ return false;
+}
+
bool NetworkDelegate::OnCanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const {
- // Default implementation disables privacy mode.
return false;
}
-int NetworkDelegate::NotifyBeforeSocketStreamConnect(
+int NetworkDelegate::OnBeforeSocketStreamConnect(
SocketStream* socket,
const CompletionCallback& callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(socket);
- DCHECK(!callback.is_null());
- return OnBeforeSocketStreamConnect(socket, callback);
+ return OK;
}
-void NetworkDelegate::NotifyRequestWaitStateChange(const URLRequest& request,
- RequestWaitState state) {
- DCHECK(CalledOnValidThread());
- OnRequestWaitStateChange(request, state);
+void NetworkDelegate::OnRequestWaitStateChange(const URLRequest& request,
+ RequestWaitState state) {
}
} // namespace net
diff --git a/chromium/net/base/network_delegate.h b/chromium/net/base/network_delegate.h
index 4b649642dd1..21c8e6530f6 100644
--- a/chromium/net/base/network_delegate.h
+++ b/chromium/net/base/network_delegate.h
@@ -118,67 +118,66 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
// ERR_IO_PENDING if the result is not ready yet. A status code other than OK
// and ERR_IO_PENDING will cancel the request and report the status code as
// the reason.
+ //
+ // The default implementation returns OK (continue with request).
virtual int OnBeforeURLRequest(URLRequest* request,
const CompletionCallback& callback,
- GURL* new_url) = 0;
+ GURL* new_url);
// 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
// request.
- // Returns a net status code.
+ // See OnBeforeURLRequest for return value description. Returns OK by default.
virtual int OnBeforeSendHeaders(URLRequest* request,
const CompletionCallback& callback,
- HttpRequestHeaders* headers) = 0;
+ HttpRequestHeaders* headers);
// Called right before the HTTP request(s) are being sent to the network.
// |headers| is only valid until OnCompleted or OnURLRequestDestroyed is
// called for this request.
virtual void OnSendHeaders(URLRequest* request,
- const HttpRequestHeaders& headers) = 0;
+ const HttpRequestHeaders& headers);
- // Called for HTTP requests when the headers have been received. Returns a net
- // status code, generally either OK to continue with the request or
- // ERR_IO_PENDING if the result is not ready yet. A status code other than OK
- // and ERR_IO_PENDING will cancel the request and report the status code as
- // the reason.
+ // Called for HTTP requests when the headers have been received.
// |original_response_headers| contains the headers as received over the
// network, these must not be modified. |override_response_headers| can be set
// to new values, that should be considered as overriding
// |original_response_headers|.
// |callback|, |original_response_headers|, and |override_response_headers|
// are only valid until OnURLRequestDestroyed is called for this request.
+ // See OnBeforeURLRequest for return value description. Returns OK by default.
virtual int OnHeadersReceived(
URLRequest* request,
const CompletionCallback& callback,
const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers) = 0;
+ scoped_refptr<HttpResponseHeaders>* override_response_headers);
// Called right after a redirect response code was received.
// |new_location| is only valid until OnURLRequestDestroyed is called for this
// request.
virtual void OnBeforeRedirect(URLRequest* request,
- const GURL& new_location) = 0;
+ const GURL& new_location);
// This corresponds to URLRequestDelegate::OnResponseStarted.
- virtual void OnResponseStarted(URLRequest* request) = 0;
+ virtual void OnResponseStarted(URLRequest* request);
// Called every time we read raw bytes.
- virtual void OnRawBytesRead(const URLRequest& request, int bytes_read) = 0;
+ virtual void OnRawBytesRead(const URLRequest& request, int bytes_read);
// Indicates that the URL request has been completed or failed.
// |started| indicates whether the request has been started. If false,
// some information like the socket address is not available.
- virtual void OnCompleted(URLRequest* request, bool started) = 0;
+ virtual void OnCompleted(URLRequest* request, bool started);
// Called when an URLRequest is being destroyed. Note that the request is
// being deleted, so it's not safe to call any methods that may result in
// a virtual method call.
- virtual void OnURLRequestDestroyed(URLRequest* request) = 0;
+ virtual void OnURLRequestDestroyed(URLRequest* request);
// Corresponds to ProxyResolverJSBindings::OnError.
virtual void OnPACScriptError(int line_number,
- const base::string16& error) = 0;
+ const base::string16& error);
// Called when a request receives an authentication challenge
// specified by |auth_info|, and is unable to respond using cached
@@ -201,31 +200,31 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
URLRequest* request,
const AuthChallengeInfo& auth_info,
const AuthCallback& callback,
- AuthCredentials* credentials) = 0;
+ AuthCredentials* credentials);
// Called when reading cookies to allow the network delegate to block access
// to the cookie. This method will never be invoked when
// LOAD_DO_NOT_SEND_COOKIES is specified.
virtual bool OnCanGetCookies(const URLRequest& request,
- const CookieList& cookie_list) = 0;
+ const CookieList& cookie_list);
// Called when a cookie is set to allow the network delegate to block access
// to the cookie. This method will never be invoked when
// LOAD_DO_NOT_SAVE_COOKIES is specified.
virtual bool OnCanSetCookie(const URLRequest& request,
const std::string& cookie_line,
- CookieOptions* options) = 0;
+ CookieOptions* options);
// Called when a file access is attempted to allow the network delegate to
// allow or block access to the given file path. Returns true if access is
// allowed.
virtual bool OnCanAccessFile(const URLRequest& request,
- const base::FilePath& path) const = 0;
+ const base::FilePath& path) const;
// Returns true if the given request may be rejected when the
// URLRequestThrottlerManager believes the server servicing the
// request is overloaded or down.
- virtual bool OnCanThrottleRequest(const URLRequest& request) const = 0;
+ virtual bool OnCanThrottleRequest(const URLRequest& request) const;
// Returns true if the given |url| has to be requested over connection that
// is not tracked by the server. Usually is false, unless user privacy
@@ -235,15 +234,16 @@ class NET_EXPORT NetworkDelegate : public base::NonThreadSafe {
const GURL& first_party_for_cookies) const;
// Called before a SocketStream tries to connect.
+ // See OnBeforeURLRequest for return value description. Returns OK by default.
virtual int OnBeforeSocketStreamConnect(
- SocketStream* socket, const CompletionCallback& callback) = 0;
+ SocketStream* socket, const CompletionCallback& callback);
// Called when the completion of a URLRequest is blocking on a cache
// action or a network action, or when that is no longer the case.
// REQUEST_WAIT_STATE_RESET indicates for a given URLRequest
// cancellation of any pending waits for this request.
virtual void OnRequestWaitStateChange(const URLRequest& request,
- RequestWaitState state) = 0;
+ RequestWaitState state);
};
} // namespace net
diff --git a/chromium/net/base/platform_mime_util_linux.cc b/chromium/net/base/platform_mime_util_linux.cc
index f4099e4b1d4..ff7f79b1549 100644
--- a/chromium/net/base/platform_mime_util_linux.cc
+++ b/chromium/net/base/platform_mime_util_linux.cc
@@ -62,6 +62,7 @@ struct MimeToExt {
const struct MimeToExt mime_type_ext_map[] = {
{"application/pdf", "pdf"},
{"application/x-tar", "tar"},
+ {"application/zip", "zip"},
{"audio/mpeg", "mp3"},
{"image/gif", "gif"},
{"image/jpeg", "jpg"},
diff --git a/chromium/net/base/prioritized_dispatcher_unittest.cc b/chromium/net/base/prioritized_dispatcher_unittest.cc
index cef455f3671..30360387ab1 100644
--- a/chromium/net/base/prioritized_dispatcher_unittest.cc
+++ b/chromium/net/base/prioritized_dispatcher_unittest.cc
@@ -23,7 +23,7 @@ COMPILE_ASSERT(MINIMUM_PRIORITY == 0u &&
MINIMUM_PRIORITY == IDLE &&
IDLE < LOWEST &&
LOWEST < HIGHEST &&
- HIGHEST < NUM_PRIORITIES,
+ HIGHEST <= MAXIMUM_PRIORITY,
priority_indexes_incompatible);
class PrioritizedDispatcherTest : public testing::Test {
@@ -178,7 +178,8 @@ TEST_F(PrioritizedDispatcherTest, GetLimits) {
PrioritizedDispatcher::Limits retrieved_limits = dispatcher_->GetLimits();
ASSERT_EQ(original_limits.total_jobs, retrieved_limits.total_jobs);
ASSERT_EQ(NUM_PRIORITIES, retrieved_limits.reserved_slots.size());
- for (size_t priority = 0; priority < NUM_PRIORITIES; ++priority) {
+ for (size_t priority = MINIMUM_PRIORITY; priority <= MAXIMUM_PRIORITY;
+ ++priority) {
EXPECT_EQ(original_limits.reserved_slots[priority],
retrieved_limits.reserved_slots[priority]);
}
@@ -193,7 +194,8 @@ TEST_F(PrioritizedDispatcherTest, GetLimits) {
retrieved_limits = dispatcher_->GetLimits();
ASSERT_EQ(new_limits.total_jobs, retrieved_limits.total_jobs);
ASSERT_EQ(NUM_PRIORITIES, retrieved_limits.reserved_slots.size());
- for (size_t priority = 0; priority < NUM_PRIORITIES; ++priority) {
+ for (size_t priority = MINIMUM_PRIORITY; priority <= MAXIMUM_PRIORITY;
+ ++priority) {
EXPECT_EQ(new_limits.reserved_slots[priority],
retrieved_limits.reserved_slots[priority]);
}
diff --git a/chromium/net/base/priority_queue.h b/chromium/net/base/priority_queue.h
index c6845805354..9b17d61b21e 100644
--- a/chromium/net/base/priority_queue.h
+++ b/chromium/net/base/priority_queue.h
@@ -50,9 +50,16 @@ class PriorityQueue : public base::NonThreadSafe {
#if !defined(NDEBUG)
id_ = static_cast<unsigned>(-1);
#endif
+ // TODO(syzm)
+ // An uninitialized iterator behaves like an uninitialized pointer as per
+ // the STL docs. The fix below is ugly and should possibly be replaced
+ // with a better approach.
+ iterator_ = dummy_empty_list_.end();
}
- Pointer(const Pointer& p) : priority_(p.priority_), iterator_(p.iterator_) {
+ Pointer(const Pointer& p)
+ : priority_(p.priority_),
+ iterator_(p.iterator_) {
#if !defined(NDEBUG)
id_ = p.id_;
#endif
@@ -90,13 +97,16 @@ class PriorityQueue : public base::NonThreadSafe {
private:
friend class PriorityQueue;
- // Note that we need iterator not const_iterator to pass to List::erase.
- // When C++0x comes, this could be changed to const_iterator and const could
- // be added to First, Last, and OldestLowest.
+ // Note that we need iterator and not const_iterator to pass to
+ // List::erase. When C++11 is turned on for Chromium, this could
+ // be changed to const_iterator and the const_casts in the rest of
+ // the file can be removed.
typedef typename PriorityQueue::List::iterator ListIterator;
static const Priority kNullPriority = static_cast<Priority>(-1);
+ // It is guaranteed that Pointer will treat |iterator| as a
+ // const_iterator.
Pointer(Priority priority, const ListIterator& iterator)
: priority_(priority), iterator_(iterator) {
#if !defined(NDEBUG)
@@ -106,6 +116,10 @@ class PriorityQueue : public base::NonThreadSafe {
Priority priority_;
ListIterator iterator_;
+ // The STL iterators when uninitialized are like uninitialized pointers
+ // which cause crashes when assigned to other iterators. We need to
+ // initialize a NULL iterator to the end of a valid list.
+ List dummy_empty_list_;
#if !defined(NDEBUG)
// Used by the queue to check if a Pointer is valid.
@@ -175,50 +189,80 @@ class PriorityQueue : public base::NonThreadSafe {
// Returns a pointer to the first value of minimum priority or a null-pointer
// if empty.
- Pointer FirstMin() {
+ Pointer FirstMin() const {
DCHECK(CalledOnValidThread());
for (size_t i = 0; i < lists_.size(); ++i) {
- if (!lists_[i].empty())
- return Pointer(i, lists_[i].begin());
+ List* list = const_cast<List*>(&lists_[i]);
+ if (!list->empty())
+ return Pointer(i, list->begin());
}
return Pointer();
}
// Returns a pointer to the last value of minimum priority or a null-pointer
// if empty.
- Pointer LastMin() {
+ Pointer LastMin() const {
DCHECK(CalledOnValidThread());
for (size_t i = 0; i < lists_.size(); ++i) {
- if (!lists_[i].empty())
- return Pointer(i, --lists_[i].end());
+ List* list = const_cast<List*>(&lists_[i]);
+ if (!list->empty())
+ return Pointer(i, --list->end());
}
return Pointer();
}
// Returns a pointer to the first value of maximum priority or a null-pointer
// if empty.
- Pointer FirstMax() {
+ Pointer FirstMax() const {
DCHECK(CalledOnValidThread());
for (size_t i = lists_.size(); i > 0; --i) {
size_t index = i - 1;
- if (!lists_[index].empty())
- return Pointer(index, lists_[index].begin());
+ List* list = const_cast<List*>(&lists_[index]);
+ if (!list->empty())
+ return Pointer(index, list->begin());
}
return Pointer();
}
// Returns a pointer to the last value of maximum priority or a null-pointer
// if empty.
- Pointer LastMax() {
+ Pointer LastMax() const {
DCHECK(CalledOnValidThread());
for (size_t i = lists_.size(); i > 0; --i) {
size_t index = i - 1;
- if (!lists_[index].empty())
- return Pointer(index, --lists_[index].end());
+ List* list = const_cast<List*>(&lists_[index]);
+ if (!list->empty())
+ return Pointer(index, --list->end());
}
return Pointer();
}
+ // Given an ordering of the values in this queue by decreasing
+ // priority and then FIFO, returns a pointer to the value following
+ // the value of the given pointer (which must be non-NULL).
+ //
+ // (One could also implement GetNextTowardsFirstMin() [decreasing
+ // priority, then reverse FIFO] as well as
+ // GetNextTowards{First,Last}Max() [increasing priority, then
+ // {,reverse} FIFO].)
+ Pointer GetNextTowardsLastMin(const Pointer& pointer) const {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!pointer.is_null());
+ DCHECK_LT(pointer.priority_, lists_.size());
+
+ typename Pointer::ListIterator it = pointer.iterator_;
+ Priority priority = pointer.priority_;
+ DCHECK(it != lists_[priority].end());
+ ++it;
+ while (it == lists_[priority].end()) {
+ if (priority == 0u)
+ return Pointer();
+ --priority;
+ it = const_cast<List*>(&lists_[priority])->begin();
+ }
+ return Pointer(priority, it);
+ }
+
// Empties the queue. All pointers become invalid.
void Clear() {
DCHECK(CalledOnValidThread());
@@ -232,7 +276,15 @@ class PriorityQueue : public base::NonThreadSafe {
}
// Returns the number of priorities the queue supports.
- size_t num_priorities() const { return lists_.size(); }
+ size_t num_priorities() const {
+ DCHECK(CalledOnValidThread());
+ return lists_.size();
+ }
+
+ bool empty() const {
+ DCHECK(CalledOnValidThread());
+ return size_ == 0;
+ }
// Returns number of queued values.
size_t size() const {
diff --git a/chromium/net/base/priority_queue_unittest.cc b/chromium/net/base/priority_queue_unittest.cc
index 7e3e045fe19..8093319fddb 100644
--- a/chromium/net/base/priority_queue_unittest.cc
+++ b/chromium/net/base/priority_queue_unittest.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "net/base/priority_queue.h"
+
+#include <cstddef>
+
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -14,7 +17,7 @@ const Priority kPriorities[] = { 2, 1, 2, 0, 4, 3, 1, 4, 0 };
const Priority kNumPriorities = 5; // max(kPriorities) + 1
const size_t kNumElements = arraysize(kPriorities);
const int kFirstMinOrder[kNumElements] = { 3, 8, 1, 6, 0, 2, 5, 4, 7 };
-const int kLastMaxOrder[kNumElements] = { 7, 4, 5, 2, 0, 6, 1, 8, 3 };
+const int kLastMaxOrderErase[kNumElements] = { 7, 4, 5, 2, 0, 6, 1, 8, 3 };
const int kFirstMaxOrder[kNumElements] = { 4, 7, 5, 0, 2, 1, 6, 3, 8 };
const int kLastMinOrder[kNumElements] = { 8, 3, 6, 1, 2, 0, 5, 7, 4 };
@@ -27,11 +30,13 @@ class PriorityQueueTest : public testing::Test {
for (size_t i = 0; i < kNumElements; ++i) {
EXPECT_EQ(i, queue_.size());
pointers_[i] = queue_.Insert(static_cast<int>(i), kPriorities[i]);
+ EXPECT_FALSE(queue_.empty());
}
EXPECT_EQ(kNumElements, queue_.size());
}
void CheckEmpty() {
+ EXPECT_TRUE(queue_.empty());
EXPECT_EQ(0u, queue_.size());
EXPECT_TRUE(queue_.FirstMin().is_null());
EXPECT_TRUE(queue_.LastMin().is_null());
@@ -72,6 +77,32 @@ TEST_F(PriorityQueueTest, LastMinOrder) {
}
TEST_F(PriorityQueueTest, FirstMaxOrder) {
+ PriorityQueue<int>::Pointer p = queue_.FirstMax();
+ size_t i = 0;
+ for (; !p.is_null() && i < kNumElements;
+ p = queue_.GetNextTowardsLastMin(p), ++i) {
+ EXPECT_EQ(kFirstMaxOrder[i], p.value());
+ }
+ EXPECT_TRUE(p.is_null());
+ EXPECT_EQ(kNumElements, i);
+ queue_.Clear();
+ CheckEmpty();
+}
+
+TEST_F(PriorityQueueTest, GetNextTowardsLastMinAndErase) {
+ PriorityQueue<int>::Pointer current = queue_.FirstMax();
+ for (size_t i = 0; i < kNumElements; ++i) {
+ EXPECT_FALSE(current.is_null());
+ EXPECT_EQ(kFirstMaxOrder[i], current.value());
+ PriorityQueue<int>::Pointer next = queue_.GetNextTowardsLastMin(current);
+ queue_.Erase(current);
+ current = next;
+ }
+ EXPECT_TRUE(current.is_null());
+ CheckEmpty();
+}
+
+TEST_F(PriorityQueueTest, FirstMaxOrderErase) {
for (size_t i = 0; i < kNumElements; ++i) {
EXPECT_EQ(kFirstMaxOrder[i], queue_.FirstMax().value());
queue_.Erase(queue_.FirstMax());
@@ -79,9 +110,9 @@ TEST_F(PriorityQueueTest, FirstMaxOrder) {
CheckEmpty();
}
-TEST_F(PriorityQueueTest, LastMaxOrder) {
+TEST_F(PriorityQueueTest, LastMaxOrderErase) {
for (size_t i = 0; i < kNumElements; ++i) {
- EXPECT_EQ(kLastMaxOrder[i], queue_.LastMax().value());
+ EXPECT_EQ(kLastMaxOrderErase[i], queue_.LastMax().value());
queue_.Erase(queue_.LastMax());
}
CheckEmpty();
diff --git a/chromium/net/base/registry_controlled_domains/effective_tld_names.cc b/chromium/net/base/registry_controlled_domains/effective_tld_names.cc
index 68d0464ef13..1fa77a702e0 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.cc
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.cc
@@ -42,12 +42,12 @@ struct DomainRule {
int type; // flags: 1: exception, 2: wildcard, 4: private
};
-#define TOTAL_KEYWORDS 6103
+#define TOTAL_KEYWORDS 6375
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 43
-#define MIN_HASH_VALUE 15
-#define MAX_HASH_VALUE 90773
-/* maximum key range = 90759, duplicates = 0 */
+#define MIN_HASH_VALUE 8
+#define MAX_HASH_VALUE 170276
+/* maximum key range = 170269, duplicates = 0 */
class Perfect_Hash
{
@@ -62,36 +62,35 @@ Perfect_Hash::hash (register const char *str, register unsigned int len)
{
static const unsigned int asso_values[] =
{
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 175, 27, 4476, 6, 5,
- 1274, 11, 5, 93, 137, 6, 6, 5, 5, 90774,
- 21, 5, 189, 5981, 90774, 5, 5, 5, 5, 5,
- 5, 5, 90774, 21, 10, 8, 18, 17, 16, 7,
- 15, 13, 11, 90774, 90774, 90774, 90774, 888, 127, 90774,
- 90774, 90774, 90774, 5, 5, 5, 90774, 670, 742, 10326,
- 10, 200, 12855, 2916, 941, 425, 261, 964, 592, 18,
- 461, 6, 872, 2438, 74, 180, 134, 8, 7, 1701,
- 40, 2147, 23, 656, 14, 506, 6, 398, 5, 1971,
- 18836, 396, 95, 322, 271, 13922, 9787, 26534, 6705, 28,
- 20, 318, 21887, 801, 19816, 32348, 18578, 4947, 162, 29168,
- 30467, 23403, 1115, 14117, 32320, 13, 22934, 91, 12, 25882,
- 1815, 880, 6, 15905, 820, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774,
- 90774, 90774, 90774, 90774, 90774, 90774, 90774, 90774
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 434, 45, 402, 9, 114,
+ 4, 8, 2, 3, 1, 2, 1, 2, 74, 24819,
+ 4, 10, 16557, 244, 3, 1, 1, 1, 1, 1,
+ 1, 170277, 170277, 1, 25, 16, 6, 15, 12, 11,
+ 5, 10, 9, 8, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 906, 394, 26936,
+ 8, 242, 28033, 10542, 1450, 450, 671, 1852, 78, 713,
+ 191, 4, 1002, 279, 47, 37, 288, 124, 1074, 3503,
+ 6105, 585, 10, 58, 102, 13, 29084, 4, 111, 1,
+ 3, 2, 42941, 3276, 48382, 480, 9056, 20956, 33679, 14,
+ 11166, 13469, 34929, 660, 6669, 1943, 1230, 16306, 334, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277, 170277,
+ 170277, 170277
};
register int hval = len;
@@ -197,7 +196,7 @@ Perfect_Hash::hash (register const char *str, register unsigned int len)
hval += asso_values[(unsigned char)str[10]];
/*FALLTHROUGH*/
case 10:
- hval += asso_values[(unsigned char)str[9]];
+ hval += asso_values[(unsigned char)str[9]+1];
/*FALLTHROUGH*/
case 9:
hval += asso_values[(unsigned char)str[8]];
@@ -206,25 +205,25 @@ Perfect_Hash::hash (register const char *str, register unsigned int len)
hval += asso_values[(unsigned char)str[7]+1];
/*FALLTHROUGH*/
case 7:
- hval += asso_values[(unsigned char)str[6]+8];
+ hval += asso_values[(unsigned char)str[6]+3];
/*FALLTHROUGH*/
case 6:
- hval += asso_values[(unsigned char)str[5]+17];
+ hval += asso_values[(unsigned char)str[5]+16];
/*FALLTHROUGH*/
case 5:
- hval += asso_values[(unsigned char)str[4]+42];
+ hval += asso_values[(unsigned char)str[4]];
/*FALLTHROUGH*/
case 4:
- hval += asso_values[(unsigned char)str[3]+15];
+ hval += asso_values[(unsigned char)str[3]+14];
/*FALLTHROUGH*/
case 3:
- hval += asso_values[(unsigned char)str[2]];
+ hval += asso_values[(unsigned char)str[2]+13];
/*FALLTHROUGH*/
case 2:
hval += asso_values[(unsigned char)str[1]];
/*FALLTHROUGH*/
case 1:
- hval += asso_values[(unsigned char)str[0]+25];
+ hval += asso_values[(unsigned char)str[0]+26];
break;
}
return hval;
@@ -232,12215 +231,12759 @@ Perfect_Hash::hash (register const char *str, register unsigned int len)
struct stringpool_t
{
- char stringpool_str0[sizeof("gu")];
- char stringpool_str1[sizeof("eu")];
+ char stringpool_str0[sizeof("io")];
+ char stringpool_str1[sizeof("gov")];
char stringpool_str2[sizeof("gd")];
- char stringpool_str3[sizeof("gov")];
- char stringpool_str4[sizeof("co")];
- char stringpool_str5[sizeof("cv")];
- char stringpool_str6[sizeof("cu")];
- char stringpool_str7[sizeof("gm")];
- char stringpool_str8[sizeof("cd")];
- char stringpool_str9[sizeof("edu")];
- char stringpool_str10[sizeof("so")];
- char stringpool_str11[sizeof("sv")];
- char stringpool_str12[sizeof("su")];
- char stringpool_str13[sizeof("ao")];
- char stringpool_str14[sizeof("sd")];
- char stringpool_str15[sizeof("au")];
- char stringpool_str16[sizeof("cm")];
- char stringpool_str17[sizeof("ad")];
- char stringpool_str18[sizeof("ro")];
- char stringpool_str19[sizeof("ru")];
- char stringpool_str20[sizeof("cz")];
- char stringpool_str21[sizeof("sm")];
- char stringpool_str22[sizeof("com")];
- char stringpool_str23[sizeof("am")];
- char stringpool_str24[sizeof("sz")];
- char stringpool_str25[sizeof("gov.to")];
- char stringpool_str26[sizeof("gov.tm")];
- char stringpool_str27[sizeof("az")];
- char stringpool_str28[sizeof("edu.to")];
- char stringpool_str29[sizeof("edu.tm")];
- char stringpool_str30[sizeof("gov.bo")];
- char stringpool_str31[sizeof("gov.bm")];
- char stringpool_str32[sizeof("cx")];
- char stringpool_str33[sizeof("edu.bo")];
- char stringpool_str34[sizeof("edu.bm")];
- char stringpool_str35[sizeof("sx")];
- char stringpool_str36[sizeof("gov.ae")];
- char stringpool_str37[sizeof("ax")];
- char stringpool_str38[sizeof("com.to")];
- char stringpool_str39[sizeof("com.tm")];
- char stringpool_str40[sizeof("com.bo")];
- char stringpool_str41[sizeof("com.bm")];
- char stringpool_str42[sizeof("gov.bz")];
- char stringpool_str43[sizeof("edu.bi")];
- char stringpool_str44[sizeof("gr")];
- char stringpool_str45[sizeof("er")];
- char stringpool_str46[sizeof("edu.bz")];
- char stringpool_str47[sizeof("gov.az")];
- char stringpool_str48[sizeof("cr")];
- char stringpool_str49[sizeof("edu.az")];
- char stringpool_str50[sizeof("com.bi")];
- char stringpool_str51[sizeof("co.ma")];
- char stringpool_str52[sizeof("go.it")];
- char stringpool_str53[sizeof("sr")];
- char stringpool_str54[sizeof("com.bz")];
- char stringpool_str55[sizeof("ar")];
- char stringpool_str56[sizeof("com.ai")];
- char stringpool_str57[sizeof("co.it")];
- char stringpool_str58[sizeof("com.az")];
- char stringpool_str59[sizeof("so.it")];
- char stringpool_str60[sizeof("sv.it")];
- char stringpool_str61[sizeof("ao.it")];
- char stringpool_str62[sizeof("av.it")];
- char stringpool_str63[sizeof("km")];
- char stringpool_str64[sizeof("gov.qa")];
- char stringpool_str65[sizeof("com.ag")];
- char stringpool_str66[sizeof("ro.it")];
- char stringpool_str67[sizeof("kz")];
- char stringpool_str68[sizeof("cz.it")];
- char stringpool_str69[sizeof("edu.qa")];
- char stringpool_str70[sizeof("gov.ba")];
- char stringpool_str71[sizeof("gov.sd")];
- char stringpool_str72[sizeof("edu.ba")];
- char stringpool_str73[sizeof("rm.it")];
- char stringpool_str74[sizeof("edu.sd")];
- char stringpool_str75[sizeof("com.qa")];
- char stringpool_str76[sizeof("gt")];
- char stringpool_str77[sizeof("et")];
- char stringpool_str78[sizeof("com.ba")];
- char stringpool_str79[sizeof("gov.bs")];
- char stringpool_str80[sizeof("com.so")];
- char stringpool_str81[sizeof("com.sd")];
- char stringpool_str82[sizeof("edu.bs")];
- char stringpool_str83[sizeof("gov.as")];
- char stringpool_str84[sizeof("co.ca")];
- char stringpool_str85[sizeof("st")];
- char stringpool_str86[sizeof("at")];
- char stringpool_str87[sizeof("gov.sg")];
- char stringpool_str88[sizeof("gr.it")];
- char stringpool_str89[sizeof("com.bs")];
- char stringpool_str90[sizeof("edu.sg")];
- char stringpool_str91[sizeof("kr")];
- char stringpool_str92[sizeof("cr.it")];
- char stringpool_str93[sizeof("co.ua")];
- char stringpool_str94[sizeof("cv.ua")];
- char stringpool_str95[sizeof("sr.it")];
- char stringpool_str96[sizeof("com.sg")];
- char stringpool_str97[sizeof("ar.it")];
- char stringpool_str98[sizeof("gs")];
- char stringpool_str99[sizeof("es")];
- char stringpool_str100[sizeof("rv.ua")];
- char stringpool_str101[sizeof("gov.ac")];
- char stringpool_str102[sizeof("sm.ua")];
- char stringpool_str103[sizeof("gov.sa")];
- char stringpool_str104[sizeof("gov.jo")];
- char stringpool_str105[sizeof("edu.ac")];
- char stringpool_str106[sizeof("gov.je")];
- char stringpool_str107[sizeof("edu.sa")];
- char stringpool_str108[sizeof("edu.jo")];
- char stringpool_str109[sizeof("as")];
- char stringpool_str110[sizeof("ge")];
- char stringpool_str111[sizeof("ee")];
- char stringpool_str112[sizeof("rs")];
- char stringpool_str113[sizeof("com.ac")];
- char stringpool_str114[sizeof("com.sa")];
- char stringpool_str115[sizeof("como.it")];
- char stringpool_str116[sizeof("com.jo")];
- char stringpool_str117[sizeof("se")];
- char stringpool_str118[sizeof("ae")];
- char stringpool_str119[sizeof("gov.bb")];
- char stringpool_str120[sizeof("re")];
- char stringpool_str121[sizeof("gu.us")];
- char stringpool_str122[sizeof("ct.it")];
- char stringpool_str123[sizeof("edu.bb")];
- char stringpool_str124[sizeof("co.us")];
- char stringpool_str125[sizeof("at.it")];
- char stringpool_str126[sizeof("cr.ua")];
- char stringpool_str127[sizeof("sd.us")];
- char stringpool_str128[sizeof("com.bb")];
- char stringpool_str129[sizeof("kr.it")];
- char stringpool_str130[sizeof("gov.sc")];
- char stringpool_str131[sizeof("kv.ua")];
- char stringpool_str132[sizeof("edu.sc")];
- char stringpool_str133[sizeof("az.us")];
- char stringpool_str134[sizeof("km.ua")];
- char stringpool_str135[sizeof("com.sc")];
- char stringpool_str136[sizeof("cs.it")];
- char stringpool_str137[sizeof("mo")];
- char stringpool_str138[sizeof("mv")];
- char stringpool_str139[sizeof("mu")];
- char stringpool_str140[sizeof("md")];
- char stringpool_str141[sizeof("ss.it")];
- char stringpool_str142[sizeof("ge.it")];
- char stringpool_str143[sizeof("mm")];
- char stringpool_str144[sizeof("mz")];
- char stringpool_str145[sizeof("ke")];
- char stringpool_str146[sizeof("ce.it")];
- char stringpool_str147[sizeof("gov.sb")];
- char stringpool_str148[sizeof("edu.sb")];
- char stringpool_str149[sizeof("aero")];
- char stringpool_str150[sizeof("re.it")];
- char stringpool_str151[sizeof("mx")];
- char stringpool_str152[sizeof("ar.us")];
- char stringpool_str153[sizeof("com.sb")];
- char stringpool_str154[sizeof("kr.ua")];
- char stringpool_str155[sizeof("to")];
- char stringpool_str156[sizeof("tv")];
- char stringpool_str157[sizeof("gov.au")];
- char stringpool_str158[sizeof("educ.ar")];
- char stringpool_str159[sizeof("td")];
- char stringpool_str160[sizeof("lv")];
- char stringpool_str161[sizeof("lu")];
- char stringpool_str162[sizeof("edu.au")];
- char stringpool_str163[sizeof("tm")];
- char stringpool_str164[sizeof("tz")];
- char stringpool_str165[sizeof("mr")];
- char stringpool_str166[sizeof("com.au")];
- char stringpool_str167[sizeof("g.se")];
- char stringpool_str168[sizeof("e.se")];
- char stringpool_str169[sizeof("gov.co")];
- char stringpool_str170[sizeof("gov.cm")];
- char stringpool_str171[sizeof("gov.cd")];
- char stringpool_str172[sizeof("rome.it")];
- char stringpool_str173[sizeof("edu.co")];
- char stringpool_str174[sizeof("c.se")];
- char stringpool_str175[sizeof("mo.it")];
- char stringpool_str176[sizeof("gov.tt")];
- char stringpool_str177[sizeof("s.se")];
- char stringpool_str178[sizeof("ct.us")];
- char stringpool_str179[sizeof("a.se")];
- char stringpool_str180[sizeof("edu.tt")];
- char stringpool_str181[sizeof("gov.bt")];
- char stringpool_str182[sizeof("com.co")];
- char stringpool_str183[sizeof("r.se")];
- char stringpool_str184[sizeof("edu.ci")];
- char stringpool_str185[sizeof("edu.bt")];
- char stringpool_str186[sizeof("com.tt")];
- char stringpool_str187[sizeof("com.ci")];
- char stringpool_str188[sizeof("com.bt")];
- char stringpool_str189[sizeof("tr")];
- char stringpool_str190[sizeof("lr")];
- char stringpool_str191[sizeof("jo")];
- char stringpool_str192[sizeof("fo")];
- char stringpool_str193[sizeof("mt")];
- char stringpool_str194[sizeof("to.it")];
- char stringpool_str195[sizeof("tv.it")];
- char stringpool_str196[sizeof("lo.it")];
- char stringpool_str197[sizeof("lu.it")];
- char stringpool_str198[sizeof("jm")];
- char stringpool_str199[sizeof("fm")];
- char stringpool_str200[sizeof("as.us")];
- char stringpool_str201[sizeof("coop")];
- char stringpool_str202[sizeof("ks.ua")];
+ char stringpool_str3[sizeof("id")];
+ char stringpool_str4[sizeof("edu")];
+ char stringpool_str5[sizeof("co")];
+ char stringpool_str6[sizeof("gop")];
+ char stringpool_str7[sizeof("cd")];
+ char stringpool_str8[sizeof("cz")];
+ char stringpool_str9[sizeof("gov.do")];
+ char stringpool_str10[sizeof("com")];
+ char stringpool_str11[sizeof("gob.do")];
+ char stringpool_str12[sizeof("gov.om")];
+ char stringpool_str13[sizeof("edu.do")];
+ char stringpool_str14[sizeof("gov.dm")];
+ char stringpool_str15[sizeof("gs")];
+ char stringpool_str16[sizeof("is")];
+ char stringpool_str17[sizeof("edu.om")];
+ char stringpool_str18[sizeof("es")];
+ char stringpool_str19[sizeof("edu.dm")];
+ char stringpool_str20[sizeof("com.do")];
+ char stringpool_str21[sizeof("gr")];
+ char stringpool_str22[sizeof("ir")];
+ char stringpool_str23[sizeof("hr")];
+ char stringpool_str24[sizeof("er")];
+ char stringpool_str25[sizeof("com.om")];
+ char stringpool_str26[sizeof("com.dm")];
+ char stringpool_str27[sizeof("cr")];
+ char stringpool_str28[sizeof("ao")];
+ char stringpool_str29[sizeof("gov.rs")];
+ char stringpool_str30[sizeof("ad")];
+ char stringpool_str31[sizeof("az")];
+ char stringpool_str32[sizeof("edu.rs")];
+ char stringpool_str33[sizeof("com.so")];
+ char stringpool_str34[sizeof("gl")];
+ char stringpool_str35[sizeof("il")];
+ char stringpool_str36[sizeof("com.ro")];
+ char stringpool_str37[sizeof("gov.sc")];
+ char stringpool_str38[sizeof("cl")];
+ char stringpool_str39[sizeof("homes")];
+ char stringpool_str40[sizeof("as")];
+ char stringpool_str41[sizeof("gov.lr")];
+ char stringpool_str42[sizeof("edu.sc")];
+ char stringpool_str43[sizeof("gov.sb")];
+ char stringpool_str44[sizeof("edu.lr")];
+ char stringpool_str45[sizeof("ar")];
+ char stringpool_str46[sizeof("bo")];
+ char stringpool_str47[sizeof("edu.sb")];
+ char stringpool_str48[sizeof("com.sc")];
+ char stringpool_str49[sizeof("bd")];
+ char stringpool_str50[sizeof("bz")];
+ char stringpool_str51[sizeof("fo")];
+ char stringpool_str52[sizeof("com.lr")];
+ char stringpool_str53[sizeof("com.sb")];
+ char stringpool_str54[sizeof("arpa")];
+ char stringpool_str55[sizeof("gu")];
+ char stringpool_str56[sizeof("art.do")];
+ char stringpool_str57[sizeof("hu")];
+ char stringpool_str58[sizeof("eu")];
+ char stringpool_str59[sizeof("gov.lc")];
+ char stringpool_str60[sizeof("cool")];
+ char stringpool_str61[sizeof("condos")];
+ char stringpool_str62[sizeof("guru")];
+ char stringpool_str63[sizeof("al")];
+ char stringpool_str64[sizeof("cu")];
+ char stringpool_str65[sizeof("edu.lc")];
+ char stringpool_str66[sizeof("bs")];
+ char stringpool_str67[sizeof("gov.lb")];
+ char stringpool_str68[sizeof("edu.lb")];
+ char stringpool_str69[sizeof("br")];
+ char stringpool_str70[sizeof("com.lc")];
+ char stringpool_str71[sizeof("gov.lk")];
+ char stringpool_str72[sizeof("gov.sl")];
+ char stringpool_str73[sizeof("fr")];
+ char stringpool_str74[sizeof("edu.lk")];
+ char stringpool_str75[sizeof("com.lb")];
+ char stringpool_str76[sizeof("edu.sl")];
+ char stringpool_str77[sizeof("com.de")];
+ char stringpool_str78[sizeof("com.lk")];
+ char stringpool_str79[sizeof("com.sl")];
+ char stringpool_str80[sizeof("g.bg")];
+ char stringpool_str81[sizeof("i.bg")];
+ char stringpool_str82[sizeof("h.bg")];
+ char stringpool_str83[sizeof("e.bg")];
+ char stringpool_str84[sizeof("6.bg")];
+ char stringpool_str85[sizeof("2.bg")];
+ char stringpool_str86[sizeof("au")];
+ char stringpool_str87[sizeof("9.bg")];
+ char stringpool_str88[sizeof("8.bg")];
+ char stringpool_str89[sizeof("7.bg")];
+ char stringpool_str90[sizeof("5.bg")];
+ char stringpool_str91[sizeof("4.bg")];
+ char stringpool_str92[sizeof("c.bg")];
+ char stringpool_str93[sizeof("q.bg")];
+ char stringpool_str94[sizeof("3.bg")];
+ char stringpool_str95[sizeof("1.bg")];
+ char stringpool_str96[sizeof("gn")];
+ char stringpool_str97[sizeof("in")];
+ char stringpool_str98[sizeof("hn")];
+ char stringpool_str99[sizeof("int")];
+ char stringpool_str100[sizeof("g.se")];
+ char stringpool_str101[sizeof("i.se")];
+ char stringpool_str102[sizeof("h.se")];
+ char stringpool_str103[sizeof("e.se")];
+ char stringpool_str104[sizeof("0.bg")];
+ char stringpool_str105[sizeof("cn")];
+ char stringpool_str106[sizeof("grp.lk")];
+ char stringpool_str107[sizeof("com.re")];
+ char stringpool_str108[sizeof("arts.ro")];
+ char stringpool_str109[sizeof("c.se")];
+ char stringpool_str110[sizeof("gov.nr")];
+ char stringpool_str111[sizeof("edu.nr")];
+ char stringpool_str112[sizeof("blue")];
+ char stringpool_str113[sizeof("com.nr")];
+ char stringpool_str114[sizeof("a.bg")];
+ char stringpool_str115[sizeof("autos")];
+ char stringpool_str116[sizeof("eus")];
+ char stringpool_str117[sizeof("arts.co")];
+ char stringpool_str118[sizeof("ge")];
+ char stringpool_str119[sizeof("ie")];
+ char stringpool_str120[sizeof("info")];
+ char stringpool_str121[sizeof("ee")];
+ char stringpool_str122[sizeof("hof.no")];
+ char stringpool_str123[sizeof("an")];
+ char stringpool_str124[sizeof("a.se")];
+ char stringpool_str125[sizeof("house")];
+ char stringpool_str126[sizeof("horse")];
+ char stringpool_str127[sizeof("gob.es")];
+ char stringpool_str128[sizeof("b.br")];
+ char stringpool_str129[sizeof("edu.es")];
+ char stringpool_str130[sizeof("b.bg")];
+ char stringpool_str131[sizeof("com.es")];
+ char stringpool_str132[sizeof("gq")];
+ char stringpool_str133[sizeof("iq")];
+ char stringpool_str134[sizeof("f.bg")];
+ char stringpool_str135[sizeof("gt")];
+ char stringpool_str136[sizeof("it")];
+ char stringpool_str137[sizeof("ht")];
+ char stringpool_str138[sizeof("et")];
+ char stringpool_str139[sizeof("bn")];
+ char stringpool_str140[sizeof("gov.ec")];
+ char stringpool_str141[sizeof("gob.ec")];
+ char stringpool_str142[sizeof("b.se")];
+ char stringpool_str143[sizeof("ae")];
+ char stringpool_str144[sizeof("edu.ec")];
+ char stringpool_str145[sizeof("f.se")];
+ char stringpool_str146[sizeof("gov.to")];
+ char stringpool_str147[sizeof("glass")];
+ char stringpool_str148[sizeof("gov.tj")];
+ char stringpool_str149[sizeof("com.ec")];
+ char stringpool_str150[sizeof("edu.to")];
+ char stringpool_str151[sizeof("gov.tm")];
+ char stringpool_str152[sizeof("aero")];
+ char stringpool_str153[sizeof("edu.tj")];
+ char stringpool_str154[sizeof("edu.tm")];
+ char stringpool_str155[sizeof("com.to")];
+ char stringpool_str156[sizeof("gov.sa")];
+ char stringpool_str157[sizeof("com.tj")];
+ char stringpool_str158[sizeof("com.tm")];
+ char stringpool_str159[sizeof("aq")];
+ char stringpool_str160[sizeof("int.lk")];
+ char stringpool_str161[sizeof("edu.sa")];
+ char stringpool_str162[sizeof("gov.sd")];
+ char stringpool_str163[sizeof("info.ro")];
+ char stringpool_str164[sizeof("be")];
+ char stringpool_str165[sizeof("at")];
+ char stringpool_str166[sizeof("edu.sd")];
+ char stringpool_str167[sizeof("com.sa")];
+ char stringpool_str168[sizeof("ceo")];
+ char stringpool_str169[sizeof("com.sd")];
+ char stringpool_str170[sizeof("auto.pl")];
+ char stringpool_str171[sizeof("isa.us")];
+ char stringpool_str172[sizeof("gov.la")];
+ char stringpool_str173[sizeof("codes")];
+ char stringpool_str174[sizeof("info.co")];
+ char stringpool_str175[sizeof("edu.la")];
+ char stringpool_str176[sizeof("gov.ee")];
+ char stringpool_str177[sizeof("asso.ci")];
+ char stringpool_str178[sizeof("edu.ee")];
+ char stringpool_str179[sizeof("bt")];
+ char stringpool_str180[sizeof("com.la")];
+ char stringpool_str181[sizeof("com.ee")];
+ char stringpool_str182[sizeof("info.la")];
+ char stringpool_str183[sizeof("gov.tl")];
+ char stringpool_str184[sizeof("info.pl")];
+ char stringpool_str185[sizeof("gov.bs")];
+ char stringpool_str186[sizeof("gov.br")];
+ char stringpool_str187[sizeof("gov.bo")];
+ char stringpool_str188[sizeof("gob.bo")];
+ char stringpool_str189[sizeof("gov.ua")];
+ char stringpool_str190[sizeof("edu.bs")];
+ char stringpool_str191[sizeof("edu.br")];
+ char stringpool_str192[sizeof("edu.bo")];
+ char stringpool_str193[sizeof("gov.bm")];
+ char stringpool_str194[sizeof("edu.ua")];
+ char stringpool_str195[sizeof("info.ki")];
+ char stringpool_str196[sizeof("edu.bm")];
+ char stringpool_str197[sizeof("com.bs")];
+ char stringpool_str198[sizeof("com.br")];
+ char stringpool_str199[sizeof("com.bo")];
+ char stringpool_str200[sizeof("zone")];
+ char stringpool_str201[sizeof("com.ua")];
+ char stringpool_str202[sizeof("com.bm")];
char stringpool_str203[sizeof("gi")];
- char stringpool_str204[sizeof("gov.tn")];
- char stringpool_str205[sizeof("k.se")];
- char stringpool_str206[sizeof("ci")];
- char stringpool_str207[sizeof("gov.st")];
- char stringpool_str208[sizeof("gov.br")];
- char stringpool_str209[sizeof("si")];
- char stringpool_str210[sizeof("edu.st")];
- char stringpool_str211[sizeof("aero.mv")];
- char stringpool_str212[sizeof("ai")];
- char stringpool_str213[sizeof("edu.br")];
- char stringpool_str214[sizeof("ms")];
- char stringpool_str215[sizeof("tt")];
- char stringpool_str216[sizeof("lt")];
- char stringpool_str217[sizeof("com.tn")];
- char stringpool_str218[sizeof("co.tt")];
- char stringpool_str219[sizeof("edu.an")];
- char stringpool_str220[sizeof("com.st")];
- char stringpool_str221[sizeof("com.br")];
- char stringpool_str222[sizeof("adv.br")];
- char stringpool_str223[sizeof("gn")];
- char stringpool_str224[sizeof("me")];
- char stringpool_str225[sizeof("fr")];
- char stringpool_str226[sizeof("com.an")];
- char stringpool_str227[sizeof("tr.it")];
- char stringpool_str228[sizeof("cn")];
- char stringpool_str229[sizeof("adm.br")];
- char stringpool_str230[sizeof("sn")];
- char stringpool_str231[sizeof("lv.ua")];
- char stringpool_str232[sizeof("an")];
- char stringpool_str233[sizeof("mt.it")];
- char stringpool_str234[sizeof("ks.us")];
- char stringpool_str235[sizeof("mo.us")];
- char stringpool_str236[sizeof("gouv.km")];
- char stringpool_str237[sizeof("md.us")];
- char stringpool_str238[sizeof("fm.it")];
- char stringpool_str239[sizeof("ls")];
- char stringpool_str240[sizeof("do")];
- char stringpool_str241[sizeof("ki")];
- char stringpool_str242[sizeof("ci.it")];
- char stringpool_str243[sizeof("edu.sn")];
- char stringpool_str244[sizeof("dm")];
- char stringpool_str245[sizeof("srv.br")];
- char stringpool_str246[sizeof("si.it")];
- char stringpool_str247[sizeof("dz")];
- char stringpool_str248[sizeof("ms.it")];
- char stringpool_str249[sizeof("ri.it")];
- char stringpool_str250[sizeof("com.sn")];
- char stringpool_str251[sizeof("lt.it")];
- char stringpool_str252[sizeof("asso.km")];
- char stringpool_str253[sizeof("gov.tl")];
- char stringpool_str254[sizeof("asti.it")];
- char stringpool_str255[sizeof("lodi.it")];
- char stringpool_str256[sizeof("en.it")];
- char stringpool_str257[sizeof("me.it")];
- char stringpool_str258[sizeof("fr.it")];
- char stringpool_str259[sizeof("kn")];
- char stringpool_str260[sizeof("cn.it")];
- char stringpool_str261[sizeof("gov.al")];
- char stringpool_str262[sizeof("an.it")];
- char stringpool_str263[sizeof("edu.al")];
- char stringpool_str264[sizeof("coop.mv")];
- char stringpool_str265[sizeof("rn.it")];
- char stringpool_str266[sizeof("tx.us")];
- char stringpool_str267[sizeof("gouv.sn")];
- char stringpool_str268[sizeof("coop.km")];
- char stringpool_str269[sizeof("tj")];
- char stringpool_str270[sizeof("ts.it")];
- char stringpool_str271[sizeof("com.al")];
- char stringpool_str272[sizeof("co.na")];
- char stringpool_str273[sizeof("ato.br")];
- char stringpool_str274[sizeof("med.sd")];
- char stringpool_str275[sizeof("je")];
- char stringpool_str276[sizeof("gl")];
- char stringpool_str277[sizeof("go.tj")];
- char stringpool_str278[sizeof("te.it")];
- char stringpool_str279[sizeof("asso.gp")];
- char stringpool_str280[sizeof("le.it")];
- char stringpool_str281[sizeof("cl")];
- char stringpool_str282[sizeof("co.tj")];
- char stringpool_str283[sizeof("lt.ua")];
- char stringpool_str284[sizeof("sl")];
- char stringpool_str285[sizeof("gouv.ml")];
- char stringpool_str286[sizeof("m.se")];
- char stringpool_str287[sizeof("al")];
- char stringpool_str288[sizeof("gov.cu")];
- char stringpool_str289[sizeof("mt.us")];
- char stringpool_str290[sizeof("edu.cu")];
- char stringpool_str291[sizeof("gov.sl")];
- char stringpool_str292[sizeof("cn.ua")];
- char stringpool_str293[sizeof("edu.sl")];
- char stringpool_str294[sizeof("com.cu")];
- char stringpool_str295[sizeof("com.sl")];
- char stringpool_str296[sizeof("med.sa")];
- char stringpool_str297[sizeof("art.br")];
- char stringpool_str298[sizeof("fj")];
- char stringpool_str299[sizeof("t.se")];
- char stringpool_str300[sizeof("bo")];
- char stringpool_str301[sizeof("tromso.no")];
- char stringpool_str302[sizeof("l.se")];
- char stringpool_str303[sizeof("bd")];
- char stringpool_str304[sizeof("ms.us")];
- char stringpool_str305[sizeof("ri.us")];
- char stringpool_str306[sizeof("te.ua")];
- char stringpool_str307[sizeof("bm")];
- char stringpool_str308[sizeof("ga")];
- char stringpool_str309[sizeof("bz")];
- char stringpool_str310[sizeof("fe.it")];
- char stringpool_str311[sizeof("ca")];
- char stringpool_str312[sizeof("me.us")];
- char stringpool_str313[sizeof("cl.it")];
- char stringpool_str314[sizeof("sa")];
- char stringpool_str315[sizeof("gov.tj")];
- char stringpool_str316[sizeof("al.it")];
- char stringpool_str317[sizeof("tm.mc")];
- char stringpool_str318[sizeof("edu.tj")];
- char stringpool_str319[sizeof("de")];
- char stringpool_str320[sizeof("com.tj")];
- char stringpool_str321[sizeof("gouv.bj")];
- char stringpool_str322[sizeof("art.sn")];
- char stringpool_str323[sizeof("br")];
- char stringpool_str324[sizeof("mn")];
- char stringpool_str325[sizeof("tromsa.no")];
- char stringpool_str326[sizeof("f.se")];
- char stringpool_str327[sizeof("gov.cn")];
- char stringpool_str328[sizeof("bo.it")];
- char stringpool_str329[sizeof("li")];
- char stringpool_str330[sizeof("edu.cn")];
- char stringpool_str331[sizeof("coop.br")];
- char stringpool_str332[sizeof("bz.it")];
- char stringpool_str333[sizeof("sb")];
- char stringpool_str334[sizeof("com.cn")];
- char stringpool_str335[sizeof("ca.it")];
- char stringpool_str336[sizeof("dj")];
- char stringpool_str337[sizeof("aero.tt")];
- char stringpool_str338[sizeof("sa.it")];
- char stringpool_str339[sizeof("asso.bj")];
- char stringpool_str340[sizeof("mi.it")];
- char stringpool_str341[sizeof("tn")];
- char stringpool_str342[sizeof("ra.it")];
- char stringpool_str343[sizeof("g.bg")];
- char stringpool_str344[sizeof("e.bg")];
- char stringpool_str345[sizeof("6.bg")];
- char stringpool_str346[sizeof("2.bg")];
- char stringpool_str347[sizeof("gob.bo")];
- char stringpool_str348[sizeof("1.bg")];
- char stringpool_str349[sizeof("9.bg")];
- char stringpool_str350[sizeof("bt")];
- char stringpool_str351[sizeof("8.bg")];
- char stringpool_str352[sizeof("c.bg")];
- char stringpool_str353[sizeof("7.bg")];
- char stringpool_str354[sizeof("5.bg")];
- char stringpool_str355[sizeof("4.bg")];
- char stringpool_str356[sizeof("3.bg")];
- char stringpool_str357[sizeof("co.ls")];
- char stringpool_str358[sizeof("s.bg")];
- char stringpool_str359[sizeof("0.bg")];
- char stringpool_str360[sizeof("a.bg")];
- char stringpool_str361[sizeof("r.bg")];
- char stringpool_str362[sizeof("vu")];
- char stringpool_str363[sizeof("br.it")];
- char stringpool_str364[sizeof("mn.it")];
- char stringpool_str365[sizeof("cat")];
- char stringpool_str366[sizeof("fi")];
- char stringpool_str367[sizeof("tur.br")];
- char stringpool_str368[sizeof("trd.br")];
- char stringpool_str369[sizeof("li.it")];
- char stringpool_str370[sizeof("al.us")];
- char stringpool_str371[sizeof("gov.ee")];
- char stringpool_str372[sizeof("bs")];
- char stringpool_str373[sizeof("cb.it")];
- char stringpool_str374[sizeof("edu.ee")];
- char stringpool_str375[sizeof("d.se")];
- char stringpool_str376[sizeof("gov.cl")];
- char stringpool_str377[sizeof("com.ee")];
- char stringpool_str378[sizeof("be")];
- char stringpool_str379[sizeof("tn.it")];
- char stringpool_str380[sizeof("ml")];
- char stringpool_str381[sizeof("co.me")];
- char stringpool_str382[sizeof("gov.eg")];
- char stringpool_str383[sizeof("ruovat.no")];
- char stringpool_str384[sizeof("bt.it")];
- char stringpool_str385[sizeof("k.bg")];
- char stringpool_str386[sizeof("edu.eg")];
- char stringpool_str387[sizeof("mx.na")];
- char stringpool_str388[sizeof("gp")];
- char stringpool_str389[sizeof("cim.br")];
- char stringpool_str390[sizeof("mus.br")];
- char stringpool_str391[sizeof("com.eg")];
- char stringpool_str392[sizeof("tv.na")];
- char stringpool_str393[sizeof("vv.it")];
- char stringpool_str394[sizeof("ga.us")];
- char stringpool_str395[sizeof("coop.tt")];
- char stringpool_str396[sizeof("ab.ca")];
- char stringpool_str397[sizeof("ca.us")];
- char stringpool_str398[sizeof("jor.br")];
- char stringpool_str399[sizeof("fi.it")];
- char stringpool_str400[sizeof("med.br")];
- char stringpool_str401[sizeof("tl")];
- char stringpool_str402[sizeof("mi.us")];
- char stringpool_str403[sizeof("sb.ua")];
- char stringpool_str404[sizeof("rnu.tn")];
- char stringpool_str405[sizeof("bj")];
- char stringpool_str406[sizeof("bs.it")];
- char stringpool_str407[sizeof("de.us")];
- char stringpool_str408[sizeof("gv.at")];
- char stringpool_str409[sizeof("edu.es")];
- char stringpool_str410[sizeof("co.at")];
- char stringpool_str411[sizeof("asso.re")];
- char stringpool_str412[sizeof("ma")];
- char stringpool_str413[sizeof("kurgan.ru")];
- char stringpool_str414[sizeof("com.es")];
- char stringpool_str415[sizeof("co.mw")];
- char stringpool_str416[sizeof("gh")];
- char stringpool_str417[sizeof("mn.us")];
- char stringpool_str418[sizeof("teo.br")];
- char stringpool_str419[sizeof("ch")];
- char stringpool_str420[sizeof("vr.it")];
- char stringpool_str421[sizeof("coop.mw")];
- char stringpool_str422[sizeof("sh")];
- char stringpool_str423[sizeof("gov.ec")];
- char stringpool_str424[sizeof("fot.br")];
- char stringpool_str425[sizeof("co.uz")];
- char stringpool_str426[sizeof("kp")];
- char stringpool_str427[sizeof("edu.ec")];
- char stringpool_str428[sizeof("crew.aero")];
- char stringpool_str429[sizeof("asn.au")];
- char stringpool_str430[sizeof("sp.it")];
- char stringpool_str431[sizeof("ap.it")];
- char stringpool_str432[sizeof("ck")];
- char stringpool_str433[sizeof("com.ec")];
- char stringpool_str434[sizeof("sk")];
- char stringpool_str435[sizeof("eti.br")];
- char stringpool_str436[sizeof("la")];
- char stringpool_str437[sizeof("tn.us")];
- char stringpool_str438[sizeof("b.se")];
- char stringpool_str439[sizeof("ve")];
- char stringpool_str440[sizeof("gov.ws")];
- char stringpool_str441[sizeof("edu.ws")];
- char stringpool_str442[sizeof("jus.br")];
- char stringpool_str443[sizeof("vt.it")];
- char stringpool_str444[sizeof("com.ws")];
- char stringpool_str445[sizeof("co.lc")];
- char stringpool_str446[sizeof("cnt.br")];
- char stringpool_str447[sizeof("kh")];
- char stringpool_str448[sizeof("ch.it")];
- char stringpool_str449[sizeof("m.bg")];
- char stringpool_str450[sizeof("riik.ee")];
- char stringpool_str451[sizeof("mobi")];
- char stringpool_str452[sizeof("vs.it")];
- char stringpool_str453[sizeof("lb")];
- char stringpool_str454[sizeof("ens.tn")];
- char stringpool_str455[sizeof("ta.it")];
- char stringpool_str456[sizeof("firm.in")];
- char stringpool_str457[sizeof("andebu.no")];
- char stringpool_str458[sizeof("bi")];
- char stringpool_str459[sizeof("ve.it")];
- char stringpool_str460[sizeof("rns.tn")];
- char stringpool_str461[sizeof("roma.it")];
- char stringpool_str462[sizeof("mb.it")];
- char stringpool_str463[sizeof("t.bg")];
- char stringpool_str464[sizeof("l.bg")];
- char stringpool_str465[sizeof("biz")];
- char stringpool_str466[sizeof("bmd.br")];
- char stringpool_str467[sizeof("tel")];
- char stringpool_str468[sizeof("sk.ca")];
- char stringpool_str469[sizeof("bn")];
- char stringpool_str470[sizeof("dn.ua")];
- char stringpool_str471[sizeof("jeju.kr")];
- char stringpool_str472[sizeof("ck.ua")];
- char stringpool_str473[sizeof("conf.lv")];
- char stringpool_str474[sizeof("fst.br")];
- char stringpool_str475[sizeof("mp")];
- char stringpool_str476[sizeof("dr.na")];
- char stringpool_str477[sizeof("mb.ca")];
- char stringpool_str478[sizeof("vt.us")];
- char stringpool_str479[sizeof("ma.us")];
- char stringpool_str480[sizeof("bi.it")];
- char stringpool_str481[sizeof("biz.az")];
- char stringpool_str482[sizeof("co.ve")];
- char stringpool_str483[sizeof("j.bg")];
- char stringpool_str484[sizeof("f.bg")];
- char stringpool_str485[sizeof("gov.ng")];
- char stringpool_str486[sizeof("edu.ng")];
- char stringpool_str487[sizeof("kh.ua")];
- char stringpool_str488[sizeof("komi.ru")];
- char stringpool_str489[sizeof("bn.it")];
- char stringpool_str490[sizeof("conf.au")];
- char stringpool_str491[sizeof("com.ng")];
- char stringpool_str492[sizeof("ak.us")];
- char stringpool_str493[sizeof("co.in")];
- char stringpool_str494[sizeof("fl.us")];
- char stringpool_str495[sizeof("la.us")];
- char stringpool_str496[sizeof("mh")];
- char stringpool_str497[sizeof("ltd.co.im")];
- char stringpool_str498[sizeof("vi")];
- char stringpool_str499[sizeof("gd.cn")];
- char stringpool_str500[sizeof("mk")];
- char stringpool_str501[sizeof("com.na")];
- char stringpool_str502[sizeof("gz.cn")];
- char stringpool_str503[sizeof("ca.na")];
- char stringpool_str504[sizeof("sd.cn")];
- char stringpool_str505[sizeof("go.tz")];
- char stringpool_str506[sizeof("th")];
- char stringpool_str507[sizeof("vn")];
- char stringpool_str508[sizeof("gx.cn")];
- char stringpool_str509[sizeof("co.tz")];
- char stringpool_str510[sizeof("gouv.rw")];
- char stringpool_str511[sizeof("jp")];
- char stringpool_str512[sizeof("mobi.gp")];
- char stringpool_str513[sizeof("tp.it")];
- char stringpool_str514[sizeof("sx.cn")];
- char stringpool_str515[sizeof("tk")];
- char stringpool_str516[sizeof("d.bg")];
- char stringpool_str517[sizeof("lk")];
- char stringpool_str518[sizeof("mil")];
- char stringpool_str519[sizeof("fnd.br")];
- char stringpool_str520[sizeof("med.ee")];
- char stringpool_str521[sizeof("vi.it")];
- char stringpool_str522[sizeof("biz.bb")];
- char stringpool_str523[sizeof("mil.to")];
- char stringpool_str524[sizeof("mil.tm")];
- char stringpool_str525[sizeof("go.pw")];
- char stringpool_str526[sizeof("emp.br")];
- char stringpool_str527[sizeof("mil.bo")];
- char stringpool_str528[sizeof("ed.pw")];
- char stringpool_str529[sizeof("eun.eg")];
- char stringpool_str530[sizeof("ba")];
- char stringpool_str531[sizeof("co.pw")];
- char stringpool_str532[sizeof("bl.it")];
- char stringpool_str533[sizeof("mil.ae")];
- char stringpool_str534[sizeof("mil.tz")];
- char stringpool_str535[sizeof("flog.br")];
- char stringpool_str536[sizeof("eidfjord.no")];
- char stringpool_str537[sizeof("res.aero")];
- char stringpool_str538[sizeof("mil.az")];
- char stringpool_str539[sizeof("fk")];
- char stringpool_str540[sizeof("mil.qa")];
- char stringpool_str541[sizeof("mk.ua")];
- char stringpool_str542[sizeof("sirdal.no")];
- char stringpool_str543[sizeof("mil.ba")];
- char stringpool_str544[sizeof("bb")];
- char stringpool_str545[sizeof("taxi.br")];
- char stringpool_str546[sizeof("gs.cn")];
- char stringpool_str547[sizeof("ba.it")];
- char stringpool_str548[sizeof("vn.ua")];
- char stringpool_str549[sizeof("rnrt.tn")];
- char stringpool_str550[sizeof("med.ec")];
- char stringpool_str551[sizeof("b.bg")];
- char stringpool_str552[sizeof("vi.us")];
- char stringpool_str553[sizeof("biz.tt")];
- char stringpool_str554[sizeof("fhv.se")];
- char stringpool_str555[sizeof("mil.ac")];
- char stringpool_str556[sizeof("biz.at")];
- char stringpool_str557[sizeof("mil.jo")];
- char stringpool_str558[sizeof("lerdal.no")];
- char stringpool_str559[sizeof("dk")];
- char stringpool_str560[sizeof("va")];
- char stringpool_str561[sizeof("lom.no")];
- char stringpool_str562[sizeof("tas.au")];
- char stringpool_str563[sizeof("taxi.aero")];
- char stringpool_str564[sizeof("esp.br")];
- char stringpool_str565[sizeof("suldal.no")];
- char stringpool_str566[sizeof("asso.mc")];
- char stringpool_str567[sizeof("alvdal.no")];
- char stringpool_str568[sizeof("frog.museum")];
- char stringpool_str569[sizeof("skodje.no")];
- char stringpool_str570[sizeof("mo.cn")];
- char stringpool_str571[sizeof("gov.nc.tr")];
- char stringpool_str572[sizeof("mat.br")];
- char stringpool_str573[sizeof("asia")];
- char stringpool_str574[sizeof("rollag.no")];
- char stringpool_str575[sizeof("c.la")];
- char stringpool_str576[sizeof("bio.br")];
- char stringpool_str577[sizeof("antiques.museum")];
- char stringpool_str578[sizeof("eu.int")];
- char stringpool_str579[sizeof("mobi.tt")];
- char stringpool_str580[sizeof("dp.ua")];
- char stringpool_str581[sizeof("gov.nr")];
- char stringpool_str582[sizeof("lel.br")];
- char stringpool_str583[sizeof("edu.nr")];
- char stringpool_str584[sizeof("va.it")];
- char stringpool_str585[sizeof("com.nr")];
- char stringpool_str586[sizeof("assisi.museum")];
- char stringpool_str587[sizeof("vet.br")];
- char stringpool_str588[sizeof("co.pn")];
- char stringpool_str589[sizeof("far.br")];
- char stringpool_str590[sizeof("eid.no")];
- char stringpool_str591[sizeof("tv.tz")];
- char stringpool_str592[sizeof("v.bg")];
- char stringpool_str593[sizeof("gob.cl")];
- char stringpool_str594[sizeof("surnadal.no")];
- char stringpool_str595[sizeof("blog.br")];
- char stringpool_str596[sizeof("bh")];
- char stringpool_str597[sizeof("bari.it")];
- char stringpool_str598[sizeof("mil.co")];
- char stringpool_str599[sizeof("test.tj")];
- char stringpool_str600[sizeof("vb.it")];
- char stringpool_str601[sizeof("tmp.br")];
- char stringpool_str602[sizeof("asmatart.museum")];
- char stringpool_str603[sizeof("show.aero")];
- char stringpool_str604[sizeof("trento.it")];
- char stringpool_str605[sizeof("jx.cn")];
- char stringpool_str606[sizeof("gob.es")];
- char stringpool_str607[sizeof("lindas.no")];
- char stringpool_str608[sizeof("kvafjord.no")];
- char stringpool_str609[sizeof("fuel.aero")];
- char stringpool_str610[sizeof("game.tw")];
- char stringpool_str611[sizeof("snoasa.no")];
- char stringpool_str612[sizeof("va.us")];
- char stringpool_str613[sizeof("gob.ec")];
- char stringpool_str614[sizeof("sn.cn")];
- char stringpool_str615[sizeof("fin.tn")];
- char stringpool_str616[sizeof("gw")];
- char stringpool_str617[sizeof("assn.lk")];
- char stringpool_str618[sizeof("g12.br")];
- char stringpool_str619[sizeof("mil.st")];
- char stringpool_str620[sizeof("mil.br")];
- char stringpool_str621[sizeof("gotdns.com")];
- char stringpool_str622[sizeof("cw")];
- char stringpool_str623[sizeof("me.tz")];
- char stringpool_str624[sizeof("co.ae")];
- char stringpool_str625[sizeof("aw")];
- char stringpool_str626[sizeof("rw")];
- char stringpool_str627[sizeof("gol.no")];
- char stringpool_str628[sizeof("jondal.no")];
- char stringpool_str629[sizeof("tree.museum")];
- char stringpool_str630[sizeof("vlog.br")];
- char stringpool_str631[sizeof("gov.bf")];
- char stringpool_str632[sizeof("k12.ak.us")];
- char stringpool_str633[sizeof("gov.af")];
- char stringpool_str634[sizeof("vdonsk.ru")];
- char stringpool_str635[sizeof("edu.af")];
- char stringpool_str636[sizeof("k12.az.us")];
- char stringpool_str637[sizeof("evenes.no")];
- char stringpool_str638[sizeof("com.af")];
- char stringpool_str639[sizeof("biz.tj")];
- char stringpool_str640[sizeof("rindal.no")];
- char stringpool_str641[sizeof("fhsk.se")];
- char stringpool_str642[sizeof("js.cn")];
- char stringpool_str643[sizeof("kw")];
- char stringpool_str644[sizeof("tj.cn")];
- char stringpool_str645[sizeof("kobe.jp")];
- char stringpool_str646[sizeof("k12.sd.us")];
- char stringpool_str647[sizeof("stuttgart.museum")];
- char stringpool_str648[sizeof("mil.al")];
- char stringpool_str649[sizeof("k12.as.us")];
- char stringpool_str650[sizeof("fie.ee")];
- char stringpool_str651[sizeof("arpa")];
- char stringpool_str652[sizeof("juif.museum")];
- char stringpool_str653[sizeof("gov.ve")];
- char stringpool_str654[sizeof("jevnaker.no")];
- char stringpool_str655[sizeof("edu.ve")];
- char stringpool_str656[sizeof("fet.no")];
- char stringpool_str657[sizeof("lib.ak.us")];
- char stringpool_str658[sizeof("com.ve")];
- char stringpool_str659[sizeof("kiev.ua")];
- char stringpool_str660[sizeof("fj.cn")];
- char stringpool_str661[sizeof("se.net")];
- char stringpool_str662[sizeof("lib.az.us")];
- char stringpool_str663[sizeof("asso.nc")];
- char stringpool_str664[sizeof("com.vi")];
- char stringpool_str665[sizeof("military.museum")];
- char stringpool_str666[sizeof("sshn.se")];
- char stringpool_str667[sizeof("crafts.museum")];
- char stringpool_str668[sizeof("firm.nf")];
- char stringpool_str669[sizeof("time.museum")];
- char stringpool_str670[sizeof("lviv.ua")];
- char stringpool_str671[sizeof("kustanai.ru")];
- char stringpool_str672[sizeof("gaular.no")];
- char stringpool_str673[sizeof("lib.sd.us")];
- char stringpool_str674[sizeof("rendalen.no")];
- char stringpool_str675[sizeof("roma.museum")];
- char stringpool_str676[sizeof("meldal.no")];
- char stringpool_str677[sizeof("k12.sc.us")];
- char stringpool_str678[sizeof("lardal.no")];
- char stringpool_str679[sizeof("sel.no")];
- char stringpool_str680[sizeof("verdal.no")];
- char stringpool_str681[sizeof("trogstad.no")];
- char stringpool_str682[sizeof("lib.as.us")];
- char stringpool_str683[sizeof("sor-aurdal.no")];
- char stringpool_str684[sizeof("mil.tj")];
- char stringpool_str685[sizeof("enna.it")];
- char stringpool_str686[sizeof("mw")];
- char stringpool_str687[sizeof("gov.vc")];
- char stringpool_str688[sizeof("hu")];
- char stringpool_str689[sizeof("edu.vc")];
- char stringpool_str690[sizeof("hm")];
- char stringpool_str691[sizeof("voagat.no")];
- char stringpool_str692[sizeof("solund.no")];
- char stringpool_str693[sizeof("com.vc")];
- char stringpool_str694[sizeof("ln.cn")];
- char stringpool_str695[sizeof("mil.cn")];
- char stringpool_str696[sizeof("mobi.na")];
- char stringpool_str697[sizeof("tw")];
- char stringpool_str698[sizeof("muenster.museum")];
- char stringpool_str699[sizeof("k12.co.us")];
- char stringpool_str700[sizeof("hr")];
- char stringpool_str701[sizeof("lib.sc.us")];
- char stringpool_str702[sizeof("grimstad.no")];
- char stringpool_str703[sizeof("lodingen.no")];
- char stringpool_str704[sizeof("silk.museum")];
- char stringpool_str705[sizeof("jpn.com")];
- char stringpool_str706[sizeof("chieti.it")];
- char stringpool_str707[sizeof("mari.ru")];
- char stringpool_str708[sizeof("torino.it")];
- char stringpool_str709[sizeof("k12.ca.us")];
- char stringpool_str710[sizeof("ht")];
- char stringpool_str711[sizeof("bievat.no")];
- char stringpool_str712[sizeof("co.rs")];
- char stringpool_str713[sizeof("k12.tn.us")];
- char stringpool_str714[sizeof("mil.cl")];
- char stringpool_str715[sizeof("test.ru")];
- char stringpool_str716[sizeof("k12.ar.us")];
- char stringpool_str717[sizeof("bj.cn")];
- char stringpool_str718[sizeof("aip.ee")];
- char stringpool_str719[sizeof("mil.eg")];
- char stringpool_str720[sizeof("stalbans.museum")];
- char stringpool_str721[sizeof("fosnes.no")];
- char stringpool_str722[sizeof("lib.co.us")];
- char stringpool_str723[sizeof("modena.it")];
- char stringpool_str724[sizeof("gy")];
- char stringpool_str725[sizeof("murmansk.ru")];
- char stringpool_str726[sizeof("cy")];
- char stringpool_str727[sizeof("farm.museum")];
- char stringpool_str728[sizeof("sy")];
- char stringpool_str729[sizeof("svalbard.no")];
- char stringpool_str730[sizeof("moma.museum")];
- char stringpool_str731[sizeof("sh.cn")];
- char stringpool_str732[sizeof("ah.cn")];
- char stringpool_str733[sizeof("rimini.it")];
- char stringpool_str734[sizeof("gov.bh")];
- char stringpool_str735[sizeof("gouv.fr")];
- char stringpool_str736[sizeof("edu.bh")];
- char stringpool_str737[sizeof("jl.cn")];
- char stringpool_str738[sizeof("com.bh")];
- char stringpool_str739[sizeof("lib.ca.us")];
- char stringpool_str740[sizeof("crimea.ua")];
- char stringpool_str741[sizeof("fin.ec")];
- char stringpool_str742[sizeof("masfjorden.no")];
- char stringpool_str743[sizeof("mil.ec")];
- char stringpool_str744[sizeof("estate.museum")];
- char stringpool_str745[sizeof("santacruz.museum")];
- char stringpool_str746[sizeof("lib.tn.us")];
- char stringpool_str747[sizeof("tuva.ru")];
- char stringpool_str748[sizeof("gov.vn")];
- char stringpool_str749[sizeof("ky")];
- char stringpool_str750[sizeof("k12.al.us")];
- char stringpool_str751[sizeof("asso.fr")];
- char stringpool_str752[sizeof("edu.vn")];
- char stringpool_str753[sizeof("lib.ar.us")];
- char stringpool_str754[sizeof("luster.no")];
- char stringpool_str755[sizeof("com.vn")];
- char stringpool_str756[sizeof("evenassi.no")];
- char stringpool_str757[sizeof("gov.sh")];
- char stringpool_str758[sizeof("edunet.tn")];
- char stringpool_str759[sizeof("mandal.no")];
- char stringpool_str760[sizeof("snaase.no")];
- char stringpool_str761[sizeof("com.sh")];
- char stringpool_str762[sizeof("bergen.no")];
- char stringpool_str763[sizeof("caa.aero")];
- char stringpool_str764[sizeof("lib.ee")];
- char stringpool_str765[sizeof("baseball.museum")];
- char stringpool_str766[sizeof("h.se")];
- char stringpool_str767[sizeof("varese.it")];
- char stringpool_str768[sizeof("k12.ec")];
- char stringpool_str769[sizeof("mine.nu")];
- char stringpool_str770[sizeof("moskenes.no")];
- char stringpool_str771[sizeof("k12.ct.us")];
- char stringpool_str772[sizeof("coal.museum")];
- char stringpool_str773[sizeof("bw")];
- char stringpool_str774[sizeof("lib.al.us")];
- char stringpool_str775[sizeof("venice.it")];
- char stringpool_str776[sizeof("strand.no")];
- char stringpool_str777[sizeof("beauxarts.museum")];
- char stringpool_str778[sizeof("marker.no")];
- char stringpool_str779[sizeof("freiburg.museum")];
- char stringpool_str780[sizeof("maritimo.museum")];
- char stringpool_str781[sizeof("suedtirol.it")];
- char stringpool_str782[sizeof("gb.net")];
- char stringpool_str783[sizeof("auto.pl")];
- char stringpool_str784[sizeof("bindal.no")];
- char stringpool_str785[sizeof("finearts.museum")];
- char stringpool_str786[sizeof("mil.no")];
- char stringpool_str787[sizeof("my")];
- char stringpool_str788[sizeof("cadaques.museum")];
- char stringpool_str789[sizeof("savona.it")];
- char stringpool_str790[sizeof("hn")];
- char stringpool_str791[sizeof("film.museum")];
- char stringpool_str792[sizeof("gq")];
- char stringpool_str793[sizeof("bern.museum")];
- char stringpool_str794[sizeof("grue.no")];
- char stringpool_str795[sizeof("amursk.ru")];
- char stringpool_str796[sizeof("ky.us")];
- char stringpool_str797[sizeof("reklam.hu")];
- char stringpool_str798[sizeof("aq")];
- char stringpool_str799[sizeof("lib.ct.us")];
- char stringpool_str800[sizeof("ly")];
- char stringpool_str801[sizeof("aure.no")];
- char stringpool_str802[sizeof("kirkenes.no")];
- char stringpool_str803[sizeof("tank.museum")];
- char stringpool_str804[sizeof("rubtsovsk.ru")];
- char stringpool_str805[sizeof("kvalsund.no")];
- char stringpool_str806[sizeof("marine.ru")];
- char stringpool_str807[sizeof("baidar.no")];
- char stringpool_str808[sizeof("co.ba")];
- char stringpool_str809[sizeof("fuettertdasnetz.de")];
- char stringpool_str810[sizeof("ski.no")];
- char stringpool_str811[sizeof("aq.it")];
- char stringpool_str812[sizeof("retina.ar")];
- char stringpool_str813[sizeof("torino.museum")];
- char stringpool_str814[sizeof("casino.hu")];
- char stringpool_str815[sizeof("trentino.it")];
- char stringpool_str816[sizeof("hi.us")];
- char stringpool_str817[sizeof("k12.wi.us")];
- char stringpool_str818[sizeof("biz.nr")];
- char stringpool_str819[sizeof("gouv.ht")];
- char stringpool_str820[sizeof("bonn.museum")];
- char stringpool_str821[sizeof("baikal.ru")];
- char stringpool_str822[sizeof("fhs.no")];
- char stringpool_str823[sizeof("lunner.no")];
- char stringpool_str824[sizeof("k12.wa.us")];
- char stringpool_str825[sizeof("amot.no")];
- char stringpool_str826[sizeof("dinosaur.museum")];
- char stringpool_str827[sizeof("asso.ht")];
- char stringpool_str828[sizeof("travel")];
- char stringpool_str829[sizeof("servebbs.net")];
- char stringpool_str830[sizeof("rs.ba")];
- char stringpool_str831[sizeof("dep.no")];
- char stringpool_str832[sizeof("mq")];
- char stringpool_str833[sizeof("coop.ht")];
- char stringpool_str834[sizeof("berkeley.museum")];
- char stringpool_str835[sizeof("lib.wi.us")];
- char stringpool_str836[sizeof("exhibition.museum")];
- char stringpool_str837[sizeof("museet.museum")];
- char stringpool_str838[sizeof("eastcoast.museum")];
- char stringpool_str839[sizeof("h.bg")];
- char stringpool_str840[sizeof("karate.museum")];
- char stringpool_str841[sizeof("lib.wa.us")];
- char stringpool_str842[sizeof("research.museum")];
- char stringpool_str843[sizeof("fla.no")];
- char stringpool_str844[sizeof("from.hr")];
- char stringpool_str845[sizeof("by")];
- char stringpool_str846[sizeof("verona.it")];
- char stringpool_str847[sizeof("farmstead.museum")];
- char stringpool_str848[sizeof("dali.museum")];
- char stringpool_str849[sizeof("tula.ru")];
- char stringpool_str850[sizeof("k12.nm.us")];
- char stringpool_str851[sizeof("k12.ne.us")];
- char stringpool_str852[sizeof("k12.nd.us")];
- char stringpool_str853[sizeof("rost.no")];
- char stringpool_str854[sizeof("chel.ru")];
- char stringpool_str855[sizeof("exeter.museum")];
- char stringpool_str856[sizeof("com.nf")];
- char stringpool_str857[sizeof("firm.co")];
- char stringpool_str858[sizeof("sendai.jp")];
- char stringpool_str859[sizeof("latina.it")];
- char stringpool_str860[sizeof("sund.no")];
- char stringpool_str861[sizeof("co.rw")];
- char stringpool_str862[sizeof("amli.no")];
- char stringpool_str863[sizeof("bodo.no")];
- char stringpool_str864[sizeof("gg")];
- char stringpool_str865[sizeof("eg")];
- char stringpool_str866[sizeof("hurdal.no")];
- char stringpool_str867[sizeof("jp.net")];
- char stringpool_str868[sizeof("cg")];
- char stringpool_str869[sizeof("hk")];
- char stringpool_str870[sizeof("sg")];
- char stringpool_str871[sizeof("ag")];
- char stringpool_str872[sizeof("frei.no")];
- char stringpool_str873[sizeof("lib.nm.us")];
- char stringpool_str874[sizeof("lib.ne.us")];
- char stringpool_str875[sizeof("lib.nd.us")];
- char stringpool_str876[sizeof("mill.museum")];
- char stringpool_str877[sizeof("k12.nc.us")];
- char stringpool_str878[sizeof("arq.br")];
- char stringpool_str879[sizeof("etne.no")];
- char stringpool_str880[sizeof("living.museum")];
- char stringpool_str881[sizeof("travel.tt")];
- char stringpool_str882[sizeof("co.je")];
- char stringpool_str883[sizeof("kg")];
- char stringpool_str884[sizeof("ralingen.no")];
- char stringpool_str885[sizeof("kvam.no")];
- char stringpool_str886[sizeof("ag.it")];
- char stringpool_str887[sizeof("rg.it")];
- char stringpool_str888[sizeof("birkenes.no")];
- char stringpool_str889[sizeof("mie.jp")];
- char stringpool_str890[sizeof("gouv.ci")];
- char stringpool_str891[sizeof("servebbs.org")];
- char stringpool_str892[sizeof("amur.ru")];
- char stringpool_str893[sizeof("bale.museum")];
- char stringpool_str894[sizeof("aseral.no")];
- char stringpool_str895[sizeof("rade.no")];
- char stringpool_str896[sizeof("lib.nc.us")];
- char stringpool_str897[sizeof("asso.ci")];
- char stringpool_str898[sizeof("genova.it")];
- char stringpool_str899[sizeof("e12.ve")];
- char stringpool_str900[sizeof("mil.ve")];
- char stringpool_str901[sizeof("broker.aero")];
- char stringpool_str902[sizeof("time.no")];
- char stringpool_str903[sizeof("firm.ro")];
- char stringpool_str904[sizeof("garden.museum")];
- char stringpool_str905[sizeof("krym.ua")];
- char stringpool_str906[sizeof("berg.no")];
- char stringpool_str907[sizeof("mg")];
- char stringpool_str908[sizeof("divtasvuodna.no")];
- char stringpool_str909[sizeof("lund.no")];
- char stringpool_str910[sizeof("fortworth.museum")];
- char stringpool_str911[sizeof("firm.ht")];
- char stringpool_str912[sizeof("meland.no")];
- char stringpool_str913[sizeof("k12.vi")];
- char stringpool_str914[sizeof("drobak.no")];
- char stringpool_str915[sizeof("flakstad.no")];
- char stringpool_str916[sizeof("tg")];
- char stringpool_str917[sizeof("tw.cn")];
- char stringpool_str918[sizeof("mil.vc")];
- char stringpool_str919[sizeof("levanger.no")];
- char stringpool_str920[sizeof("smolensk.ru")];
- char stringpool_str921[sizeof("sumoto.kumamoto.jp")];
- char stringpool_str922[sizeof("krokstadelva.no")];
- char stringpool_str923[sizeof("center.museum")];
- char stringpool_str924[sizeof("deatnu.no")];
- char stringpool_str925[sizeof("vik.no")];
- char stringpool_str926[sizeof("biz.vn")];
- char stringpool_str927[sizeof("creation.museum")];
- char stringpool_str928[sizeof("chuvashia.ru")];
- char stringpool_str929[sizeof("bill.museum")];
- char stringpool_str930[sizeof("fjaler.no")];
- char stringpool_str931[sizeof("durham.museum")];
- char stringpool_str932[sizeof("co.bw")];
- char stringpool_str933[sizeof("mining.museum")];
- char stringpool_str934[sizeof("he.cn")];
- char stringpool_str935[sizeof("lg.ua")];
- char stringpool_str936[sizeof("fg.it")];
- char stringpool_str937[sizeof("b.br")];
- char stringpool_str938[sizeof("educator.aero")];
- char stringpool_str939[sizeof("agr.br")];
- char stringpool_str940[sizeof("roan.no")];
- char stringpool_str941[sizeof("suli.hu")];
- char stringpool_str942[sizeof("vercelli.it")];
- char stringpool_str943[sizeof("research.aero")];
- char stringpool_str944[sizeof("stat.no")];
- char stringpool_str945[sizeof("vantaa.museum")];
- char stringpool_str946[sizeof("club.aero")];
- char stringpool_str947[sizeof("kviteseid.no")];
- char stringpool_str948[sizeof("k12.nj.us")];
- char stringpool_str949[sizeof("gran.no")];
- char stringpool_str950[sizeof("e164.arpa")];
- char stringpool_str951[sizeof("aviation.museum")];
- char stringpool_str952[sizeof("capebreton.museum")];
- char stringpool_str953[sizeof("kunisaki.oita.jp")];
- char stringpool_str954[sizeof("krodsherad.no")];
- char stringpool_str955[sizeof("tver.ru")];
- char stringpool_str956[sizeof("mil.sh")];
- char stringpool_str957[sizeof("town.museum")];
- char stringpool_str958[sizeof("tysfjord.no")];
- char stringpool_str959[sizeof("tysvar.no")];
- char stringpool_str960[sizeof("k12.vi.us")];
- char stringpool_str961[sizeof("landes.museum")];
- char stringpool_str962[sizeof("lavangen.no")];
- char stringpool_str963[sizeof("khakassia.ru")];
- char stringpool_str964[sizeof("royken.no")];
- char stringpool_str965[sizeof("dallas.museum")];
- char stringpool_str966[sizeof("bg")];
- char stringpool_str967[sizeof("brunel.museum")];
- char stringpool_str968[sizeof("stpetersburg.museum")];
- char stringpool_str969[sizeof("avocat.fr")];
- char stringpool_str970[sizeof("lib.nj.us")];
- char stringpool_str971[sizeof("k12.va.us")];
- char stringpool_str972[sizeof("mosreg.ru")];
- char stringpool_str973[sizeof("shop.pl")];
- char stringpool_str974[sizeof("trader.aero")];
- char stringpool_str975[sizeof("hi.cn")];
- char stringpool_str976[sizeof("verran.no")];
- char stringpool_str977[sizeof("audnedaln.no")];
- char stringpool_str978[sizeof("amsterdam.museum")];
- char stringpool_str979[sizeof("hu.net")];
- char stringpool_str980[sizeof("hn.cn")];
- char stringpool_str981[sizeof("bg.it")];
- char stringpool_str982[sizeof("shop.ht")];
- char stringpool_str983[sizeof("arna.no")];
- char stringpool_str984[sizeof("lib.vi.us")];
- char stringpool_str985[sizeof("cq.cn")];
- char stringpool_str986[sizeof("fitjar.no")];
- char stringpool_str987[sizeof("tingvoll.no")];
- char stringpool_str988[sizeof("fusa.no")];
- char stringpool_str989[sizeof("hol.no")];
- char stringpool_str990[sizeof("evje-og-hornnes.no")];
- char stringpool_str991[sizeof("lib.va.us")];
- char stringpool_str992[sizeof("vg")];
- char stringpool_str993[sizeof("sola.no")];
- char stringpool_str994[sizeof("sula.no")];
- char stringpool_str995[sizeof("hemnes.no")];
- char stringpool_str996[sizeof("balestrand.no")];
- char stringpool_str997[sizeof("surgeonshall.museum")];
- char stringpool_str998[sizeof("arao.kumamoto.jp")];
- char stringpool_str999[sizeof("benevento.it")];
- char stringpool_str1000[sizeof("siljan.no")];
- char stringpool_str1001[sizeof("bahn.museum")];
- char stringpool_str1002[sizeof("hl.cn")];
- char stringpool_str1003[sizeof("fyresdal.no")];
- char stringpool_str1004[sizeof("horten.no")];
- char stringpool_str1005[sizeof("eng.br")];
- char stringpool_str1006[sizeof("cng.br")];
- char stringpool_str1007[sizeof("kyiv.ua")];
- char stringpool_str1008[sizeof("milano.it")];
- char stringpool_str1009[sizeof("eisenbahn.museum")];
- char stringpool_str1010[sizeof("salangen.no")];
- char stringpool_str1011[sizeof("filatelia.museum")];
- char stringpool_str1012[sizeof("k12.vt.us")];
- char stringpool_str1013[sizeof("alta.no")];
- char stringpool_str1014[sizeof("ha.cn")];
- char stringpool_str1015[sizeof("guernsey.museum")];
- char stringpool_str1016[sizeof("collection.museum")];
- char stringpool_str1017[sizeof("leg.br")];
- char stringpool_str1018[sizeof("cheltenham.museum")];
- char stringpool_str1019[sizeof("losangeles.museum")];
- char stringpool_str1020[sizeof("kurotaki.nara.jp")];
- char stringpool_str1021[sizeof("mypets.ws")];
- char stringpool_str1022[sizeof("muenchen.museum")];
- char stringpool_str1023[sizeof("kuji.iwate.jp")];
- char stringpool_str1024[sizeof("club.tw")];
- char stringpool_str1025[sizeof("contemporary.museum")];
- char stringpool_str1026[sizeof("catanzaro.it")];
- char stringpool_str1027[sizeof("hb.cn")];
- char stringpool_str1028[sizeof("tinn.no")];
- char stringpool_str1029[sizeof("loabat.no")];
- char stringpool_str1030[sizeof("slg.br")];
- char stringpool_str1031[sizeof("lib.vt.us")];
- char stringpool_str1032[sizeof("siracusa.it")];
- char stringpool_str1033[sizeof("lancashire.museum")];
- char stringpool_str1034[sizeof("gjerstad.no")];
- char stringpool_str1035[sizeof("jorpeland.no")];
- char stringpool_str1036[sizeof("kirovograd.ua")];
- char stringpool_str1037[sizeof("tyumen.ru")];
- char stringpool_str1038[sizeof("holtalen.no")];
- char stringpool_str1039[sizeof("hokksund.no")];
- char stringpool_str1040[sizeof("kosa.kumamoto.jp")];
- char stringpool_str1041[sizeof("k-uralsk.ru")];
- char stringpool_str1042[sizeof("shop.hu")];
- char stringpool_str1043[sizeof("hk.cn")];
- char stringpool_str1044[sizeof("avoues.fr")];
- char stringpool_str1045[sizeof("vang.no")];
- char stringpool_str1046[sizeof("tananger.no")];
- char stringpool_str1047[sizeof("toon.ehime.jp")];
- char stringpool_str1048[sizeof("lierne.no")];
- char stringpool_str1049[sizeof("tysnes.no")];
- char stringpool_str1050[sizeof("film.hu")];
- char stringpool_str1051[sizeof("sandnessjoen.no")];
- char stringpool_str1052[sizeof("sigdal.no")];
- char stringpool_str1053[sizeof("mesaverde.museum")];
- char stringpool_str1054[sizeof("vennesla.no")];
- char stringpool_str1055[sizeof("mo-i-rana.no")];
- char stringpool_str1056[sizeof("mail.pl")];
- char stringpool_str1057[sizeof("rana.no")];
- char stringpool_str1058[sizeof("tono.iwate.jp")];
- char stringpool_str1059[sizeof("lyngen.no")];
- char stringpool_str1060[sizeof("steiermark.museum")];
- char stringpool_str1061[sizeof("slupsk.pl")];
- char stringpool_str1062[sizeof("rennesoy.no")];
- char stringpool_str1063[sizeof("sweden.museum")];
- char stringpool_str1064[sizeof("komono.mie.jp")];
- char stringpool_str1065[sizeof("geelvinck.museum")];
- char stringpool_str1066[sizeof("bokn.no")];
- char stringpool_str1067[sizeof("viking.museum")];
- char stringpool_str1068[sizeof("ragusa.it")];
- char stringpool_str1069[sizeof("matta-varjjat.no")];
- char stringpool_str1070[sizeof("giehtavuoatna.no")];
- char stringpool_str1071[sizeof("bolt.hu")];
- char stringpool_str1072[sizeof("kazo.saitama.jp")];
- char stringpool_str1073[sizeof("gdansk.pl")];
- char stringpool_str1074[sizeof("coop.py")];
- char stringpool_str1075[sizeof("fuji.shizuoka.jp")];
- char stringpool_str1076[sizeof("astrakhan.ru")];
- char stringpool_str1077[sizeof("tana.no")];
- char stringpool_str1078[sizeof("tobe.ehime.jp")];
- char stringpool_str1079[sizeof("meeres.museum")];
- char stringpool_str1080[sizeof("hellas.museum")];
- char stringpool_str1081[sizeof("riodejaneiro.museum")];
- char stringpool_str1082[sizeof("kamijima.ehime.jp")];
- char stringpool_str1083[sizeof("leka.no")];
- char stringpool_str1084[sizeof("bahccavuotna.no")];
- char stringpool_str1085[sizeof("cahcesuolo.no")];
- char stringpool_str1086[sizeof("arai.shizuoka.jp")];
- char stringpool_str1087[sizeof("hvaler.no")];
- char stringpool_str1088[sizeof("dyndns.tv")];
- char stringpool_str1089[sizeof("vindafjord.no")];
- char stringpool_str1090[sizeof("kalisz.pl")];
- char stringpool_str1091[sizeof("education.museum")];
- char stringpool_str1092[sizeof("lillesand.no")];
- char stringpool_str1093[sizeof("rakkestad.no")];
- char stringpool_str1094[sizeof("sauherad.no")];
- char stringpool_str1095[sizeof("likescandy.com")];
- char stringpool_str1096[sizeof("habmer.no")];
- char stringpool_str1097[sizeof("kuki.saitama.jp")];
- char stringpool_str1098[sizeof("halden.no")];
- char stringpool_str1099[sizeof("contemporaryart.museum")];
- char stringpool_str1100[sizeof("sorreisa.no")];
- char stringpool_str1101[sizeof("andasuolo.no")];
- char stringpool_str1102[sizeof("altoadige.it")];
- char stringpool_str1103[sizeof("toda.saitama.jp")];
- char stringpool_str1104[sizeof("gyeonggi.kr")];
- char stringpool_str1105[sizeof("gose.nara.jp")];
- char stringpool_str1106[sizeof("dyndns.ws")];
- char stringpool_str1107[sizeof("misasa.tottori.jp")];
- char stringpool_str1108[sizeof("joso.ibaraki.jp")];
- char stringpool_str1109[sizeof("jogasz.hu")];
- char stringpool_str1110[sizeof("sells-it.net")];
- char stringpool_str1111[sizeof("broke-it.net")];
- char stringpool_str1112[sizeof("sandefjord.no")];
- char stringpool_str1113[sizeof("syzran.ru")];
- char stringpool_str1114[sizeof("agents.aero")];
- char stringpool_str1115[sizeof("hole.no")];
- char stringpool_str1116[sizeof("fundacio.museum")];
- char stringpool_str1117[sizeof("zm")];
- char stringpool_str1118[sizeof("k12.nh.us")];
- char stringpool_str1119[sizeof("gov.im")];
- char stringpool_str1120[sizeof("gov.ie")];
- char stringpool_str1121[sizeof("gildeskal.no")];
- char stringpool_str1122[sizeof("donostia.museum")];
- char stringpool_str1123[sizeof("com.io")];
- char stringpool_str1124[sizeof("vgs.no")];
- char stringpool_str1125[sizeof("ando.nara.jp")];
- char stringpool_str1126[sizeof("kumatori.osaka.jp")];
- char stringpool_str1127[sizeof("go.ci")];
- char stringpool_str1128[sizeof("soni.nara.jp")];
- char stringpool_str1129[sizeof("santabarbara.museum")];
- char stringpool_str1130[sizeof("ed.ci")];
- char stringpool_str1131[sizeof("gov.is")];
- char stringpool_str1132[sizeof("co.ci")];
- char stringpool_str1133[sizeof("edu.is")];
- char stringpool_str1134[sizeof("journalism.museum")];
- char stringpool_str1135[sizeof("lib.nh.us")];
- char stringpool_str1136[sizeof("com.is")];
- char stringpool_str1137[sizeof("divttasvuotna.no")];
- char stringpool_str1138[sizeof("kawasaki.jp")];
- char stringpool_str1139[sizeof("blogspot.mx")];
- char stringpool_str1140[sizeof("mito.ibaraki.jp")];
- char stringpool_str1141[sizeof("blogspot.ro")];
- char stringpool_str1142[sizeof("lier.no")];
- char stringpool_str1143[sizeof("blogspot.mr")];
- char stringpool_str1144[sizeof("bilbao.museum")];
- char stringpool_str1145[sizeof("dagestan.ru")];
- char stringpool_str1146[sizeof("kumano.mie.jp")];
- char stringpool_str1147[sizeof("blogspot.td")];
- char stringpool_str1148[sizeof("tone.ibaraki.jp")];
- char stringpool_str1149[sizeof("kvinnherad.no")];
- char stringpool_str1150[sizeof("kvinesdal.no")];
- char stringpool_str1151[sizeof("zt.ua")];
- char stringpool_str1152[sizeof("elblag.pl")];
- char stringpool_str1153[sizeof("marnardal.no")];
- char stringpool_str1154[sizeof("karasjok.no")];
- char stringpool_str1155[sizeof("agro.pl")];
- char stringpool_str1156[sizeof("blogspot.de")];
- char stringpool_str1157[sizeof("francaise.museum")];
- char stringpool_str1158[sizeof("z.se")];
- char stringpool_str1159[sizeof("gov.it")];
- char stringpool_str1160[sizeof("edu.it")];
- char stringpool_str1161[sizeof("saga.jp")];
- char stringpool_str1162[sizeof("kunitomi.miyazaki.jp")];
- char stringpool_str1163[sizeof("ama.aichi.jp")];
- char stringpool_str1164[sizeof("co.vi")];
- char stringpool_str1165[sizeof("suzu.ishikawa.jp")];
- char stringpool_str1166[sizeof("kongsberg.no")];
- char stringpool_str1167[sizeof("md.ci")];
- char stringpool_str1168[sizeof("troandin.no")];
- char stringpool_str1169[sizeof("journalist.aero")];
- char stringpool_str1170[sizeof("blogspot.re")];
- char stringpool_str1171[sizeof("saintlouis.museum")];
- char stringpool_str1172[sizeof("gov.ir")];
- char stringpool_str1173[sizeof("gov.in")];
- char stringpool_str1174[sizeof("edu.in")];
- char stringpool_str1175[sizeof("television.museum")];
- char stringpool_str1176[sizeof("shinto.gunma.jp")];
- char stringpool_str1177[sizeof("misawa.aomori.jp")];
- char stringpool_str1178[sizeof("limanowa.pl")];
- char stringpool_str1179[sizeof("rakpetroleum.om")];
- char stringpool_str1180[sizeof("minnesota.museum")];
- char stringpool_str1181[sizeof("haugesund.no")];
- char stringpool_str1182[sizeof("blogspot.se")];
- char stringpool_str1183[sizeof("gyeongnam.kr")];
- char stringpool_str1184[sizeof("futtsu.chiba.jp")];
- char stringpool_str1185[sizeof("kurobe.toyama.jp")];
- char stringpool_str1186[sizeof("dell-ogliastra.it")];
- char stringpool_str1187[sizeof("soka.saitama.jp")];
- char stringpool_str1188[sizeof("salvadordali.museum")];
- char stringpool_str1189[sizeof("blogspot.no")];
- char stringpool_str1190[sizeof("gotdns.org")];
- char stringpool_str1191[sizeof("tomobe.ibaraki.jp")];
- char stringpool_str1192[sizeof("botanical.museum")];
- char stringpool_str1193[sizeof("humanities.museum")];
- char stringpool_str1194[sizeof("lowicz.pl")];
- char stringpool_str1195[sizeof("tosu.saga.jp")];
- char stringpool_str1196[sizeof("jewish.museum")];
- char stringpool_str1197[sizeof("chernivtsi.ua")];
- char stringpool_str1198[sizeof("figueres.museum")];
- char stringpool_str1199[sizeof("stateofdelaware.museum")];
- char stringpool_str1200[sizeof("za")];
- char stringpool_str1201[sizeof("blogspot.it")];
- char stringpool_str1202[sizeof("barcelona.museum")];
- char stringpool_str1203[sizeof("kizu.kyoto.jp")];
- char stringpool_str1204[sizeof("hokkaido.jp")];
- char stringpool_str1205[sizeof("chuo.chiba.jp")];
- char stringpool_str1206[sizeof("dyndns-web.com")];
- char stringpool_str1207[sizeof("fujisato.akita.jp")];
- char stringpool_str1208[sizeof("mielec.pl")];
- char stringpool_str1209[sizeof("kamisato.saitama.jp")];
- char stringpool_str1210[sizeof("servegame.org")];
- char stringpool_str1211[sizeof("saskatchewan.museum")];
- char stringpool_str1212[sizeof("cranbrook.museum")];
- char stringpool_str1213[sizeof("blogspot.ie")];
- char stringpool_str1214[sizeof("gjovik.no")];
- char stringpool_str1215[sizeof("engine.aero")];
- char stringpool_str1216[sizeof("z.bg")];
- char stringpool_str1217[sizeof("franziskaner.museum")];
- char stringpool_str1218[sizeof("heimatunduhren.museum")];
- char stringpool_str1219[sizeof("goto.nagasaki.jp")];
- char stringpool_str1220[sizeof("sosa.chiba.jp")];
- char stringpool_str1221[sizeof("res.in")];
- char stringpool_str1222[sizeof("jewishart.museum")];
- char stringpool_str1223[sizeof("kamo.kyoto.jp")];
- char stringpool_str1224[sizeof("susono.shizuoka.jp")];
- char stringpool_str1225[sizeof("davvesiida.no")];
- char stringpool_str1226[sizeof("vlaanderen.museum")];
- char stringpool_str1227[sizeof("epilepsy.museum")];
- char stringpool_str1228[sizeof("engineer.aero")];
- char stringpool_str1229[sizeof("hjartdal.no")];
- char stringpool_str1230[sizeof("mielno.pl")];
- char stringpool_str1231[sizeof("settsu.osaka.jp")];
- char stringpool_str1232[sizeof("mediaphone.om")];
- char stringpool_str1233[sizeof("travel.pl")];
- char stringpool_str1234[sizeof("aremark.no")];
- char stringpool_str1235[sizeof("misato.saitama.jp")];
- char stringpool_str1236[sizeof("carrara-massa.it")];
- char stringpool_str1237[sizeof("mosvik.no")];
- char stringpool_str1238[sizeof("kraanghke.no")];
- char stringpool_str1239[sizeof("kami.kochi.jp")];
- char stringpool_str1240[sizeof("gyeongbuk.kr")];
- char stringpool_str1241[sizeof("hirosaki.aomori.jp")];
- char stringpool_str1242[sizeof("chernigov.ua")];
- char stringpool_str1243[sizeof("miho.ibaraki.jp")];
- char stringpool_str1244[sizeof("blogspot.in")];
- char stringpool_str1245[sizeof("fylkesbibl.no")];
- char stringpool_str1246[sizeof("zp.ua")];
- char stringpool_str1247[sizeof("fareast.ru")];
- char stringpool_str1248[sizeof("dvrdns.org")];
- char stringpool_str1249[sizeof("misato.shimane.jp")];
- char stringpool_str1250[sizeof("chuo.osaka.jp")];
- char stringpool_str1251[sizeof("blogspot.be")];
- char stringpool_str1252[sizeof("fuoisku.no")];
- char stringpool_str1253[sizeof("blogspot.hu")];
- char stringpool_str1254[sizeof("gen.in")];
- char stringpool_str1255[sizeof("randaberg.no")];
- char stringpool_str1256[sizeof("blogspot.dk")];
- char stringpool_str1257[sizeof("chonan.chiba.jp")];
- char stringpool_str1258[sizeof("biz.id")];
- char stringpool_str1259[sizeof("blogspot.bj")];
- char stringpool_str1260[sizeof("blogspot.pt")];
- char stringpool_str1261[sizeof("misato.akita.jp")];
- char stringpool_str1262[sizeof("shikatsu.aichi.jp")];
- char stringpool_str1263[sizeof("blogspot.kr")];
- char stringpool_str1264[sizeof("transport.museum")];
- char stringpool_str1265[sizeof("alto-adige.it")];
- char stringpool_str1266[sizeof("blogspot.nl")];
- char stringpool_str1267[sizeof("koenig.ru")];
- char stringpool_str1268[sizeof("gamvik.no")];
- char stringpool_str1269[sizeof("egersund.no")];
- char stringpool_str1270[sizeof("laspezia.it")];
- char stringpool_str1271[sizeof("chernihiv.ua")];
- char stringpool_str1272[sizeof("blogspot.jp")];
- char stringpool_str1273[sizeof("furubira.hokkaido.jp")];
- char stringpool_str1274[sizeof("livinghistory.museum")];
- char stringpool_str1275[sizeof("blogspot.sk")];
- char stringpool_str1276[sizeof("miyazaki.jp")];
- char stringpool_str1277[sizeof("saratov.ru")];
- char stringpool_str1278[sizeof("muko.kyoto.jp")];
- char stringpool_str1279[sizeof("seto.aichi.jp")];
- char stringpool_str1280[sizeof("mil.id")];
- char stringpool_str1281[sizeof("cesena-forli.it")];
- char stringpool_str1282[sizeof("karasjohka.no")];
- char stringpool_str1283[sizeof("shiojiri.nagano.jp")];
- char stringpool_str1284[sizeof("serveftp.net")];
- char stringpool_str1285[sizeof("takatori.nara.jp")];
- char stringpool_str1286[sizeof("kazuno.akita.jp")];
- char stringpool_str1287[sizeof("sennan.osaka.jp")];
- char stringpool_str1288[sizeof("egyptian.museum")];
- char stringpool_str1289[sizeof("kusu.oita.jp")];
- char stringpool_str1290[sizeof("minobu.yamanashi.jp")];
- char stringpool_str1291[sizeof("kamisu.ibaraki.jp")];
- char stringpool_str1292[sizeof("assabu.hokkaido.jp")];
- char stringpool_str1293[sizeof("carraramassa.it")];
- char stringpool_str1294[sizeof("fujisawa.iwate.jp")];
- char stringpool_str1295[sizeof("lenvik.no")];
- char stringpool_str1296[sizeof("trieste.it")];
- char stringpool_str1297[sizeof("zj.cn")];
- char stringpool_str1298[sizeof("medecin.km")];
- char stringpool_str1299[sizeof("kitaaiki.nagano.jp")];
- char stringpool_str1300[sizeof("gorizia.it")];
- char stringpool_str1301[sizeof("kuju.oita.jp")];
- char stringpool_str1302[sizeof("sakhalin.ru")];
- char stringpool_str1303[sizeof("toei.aichi.jp")];
- char stringpool_str1304[sizeof("caltanissetta.it")];
- char stringpool_str1305[sizeof("tosa.kochi.jp")];
- char stringpool_str1306[sizeof("fuso.aichi.jp")];
- char stringpool_str1307[sizeof("larvik.no")];
- char stringpool_str1308[sizeof("mizusawa.iwate.jp")];
- char stringpool_str1309[sizeof("kita.kyoto.jp")];
- char stringpool_str1310[sizeof("kumano.hiroshima.jp")];
- char stringpool_str1311[sizeof("donetsk.ua")];
- char stringpool_str1312[sizeof("ebetsu.hokkaido.jp")];
- char stringpool_str1313[sizeof("kita.osaka.jp")];
- char stringpool_str1314[sizeof("media.pl")];
- char stringpool_str1315[sizeof("shinjuku.tokyo.jp")];
- char stringpool_str1316[sizeof("shintomi.miyazaki.jp")];
- char stringpool_str1317[sizeof("lipetsk.ru")];
- char stringpool_str1318[sizeof("realestate.pl")];
- char stringpool_str1319[sizeof("kainan.tokushima.jp")];
- char stringpool_str1320[sizeof("serveftp.org")];
- char stringpool_str1321[sizeof("shonai.yamagata.jp")];
- char stringpool_str1322[sizeof("tako.chiba.jp")];
- char stringpool_str1323[sizeof("anjo.aichi.jp")];
- char stringpool_str1324[sizeof("mil.in")];
- char stringpool_str1325[sizeof("zw")];
- char stringpool_str1326[sizeof("mari-el.ru")];
- char stringpool_str1327[sizeof("k12.id.us")];
- char stringpool_str1328[sizeof("hino.tottori.jp")];
- char stringpool_str1329[sizeof("swidnica.pl")];
- char stringpool_str1330[sizeof("health.museum")];
- char stringpool_str1331[sizeof("dudinka.ru")];
- char stringpool_str1332[sizeof("augustow.pl")];
- char stringpool_str1333[sizeof("ringerike.no")];
- char stringpool_str1334[sizeof("aurland.no")];
- char stringpool_str1335[sizeof("k12.ia.us")];
- char stringpool_str1336[sizeof("kimino.wakayama.jp")];
- char stringpool_str1337[sizeof("rawa-maz.pl")];
- char stringpool_str1338[sizeof("gov.by")];
- char stringpool_str1339[sizeof("com.by")];
- char stringpool_str1340[sizeof("shoo.okayama.jp")];
- char stringpool_str1341[sizeof("lib.id.us")];
- char stringpool_str1342[sizeof("minato.osaka.jp")];
- char stringpool_str1343[sizeof("kimobetsu.hokkaido.jp")];
- char stringpool_str1344[sizeof("chuo.fukuoka.jp")];
- char stringpool_str1345[sizeof("muncie.museum")];
- char stringpool_str1346[sizeof("alaheadju.no")];
- char stringpool_str1347[sizeof("shimamoto.osaka.jp")];
- char stringpool_str1348[sizeof("misato.wakayama.jp")];
- char stringpool_str1349[sizeof("gov.sy")];
- char stringpool_str1350[sizeof("edu.sy")];
- char stringpool_str1351[sizeof("com.sy")];
- char stringpool_str1352[sizeof("lib.ia.us")];
- char stringpool_str1353[sizeof("hoyanger.no")];
- char stringpool_str1354[sizeof("gs.jan-mayen.no")];
- char stringpool_str1355[sizeof("sowa.ibaraki.jp")];
- char stringpool_str1356[sizeof("blogspot.tw")];
- char stringpool_str1357[sizeof("kawaba.gunma.jp")];
- char stringpool_str1358[sizeof("shintoku.hokkaido.jp")];
- char stringpool_str1359[sizeof("slattum.no")];
- char stringpool_str1360[sizeof("assassination.museum")];
- char stringpool_str1361[sizeof("tara.saga.jp")];
- char stringpool_str1362[sizeof("kijo.miyazaki.jp")];
- char stringpool_str1363[sizeof("koebenhavn.museum")];
- char stringpool_str1364[sizeof("services.aero")];
- char stringpool_str1365[sizeof("cosenza.it")];
- char stringpool_str1366[sizeof("koge.tottori.jp")];
- char stringpool_str1367[sizeof("sopot.pl")];
- char stringpool_str1368[sizeof("kuwana.mie.jp")];
- char stringpool_str1369[sizeof("soja.okayama.jp")];
- char stringpool_str1370[sizeof("sevastopol.ua")];
- char stringpool_str1371[sizeof("malvik.no")];
- char stringpool_str1372[sizeof("blogspot.hk")];
- char stringpool_str1373[sizeof("austin.museum")];
- char stringpool_str1374[sizeof("association.museum")];
- char stringpool_str1375[sizeof("kota.aichi.jp")];
- char stringpool_str1376[sizeof("koto.tokyo.jp")];
- char stringpool_str1377[sizeof("babia-gora.pl")];
- char stringpool_str1378[sizeof("vega.no")];
- char stringpool_str1379[sizeof("siemens.om")];
- char stringpool_str1380[sizeof("gmina.pl")];
- char stringpool_str1381[sizeof("sor-varanger.no")];
- char stringpool_str1382[sizeof("taku.saga.jp")];
- char stringpool_str1383[sizeof("k12.in.us")];
- char stringpool_str1384[sizeof("koto.shiga.jp")];
- char stringpool_str1385[sizeof("roros.no")];
- char stringpool_str1386[sizeof("budejju.no")];
- char stringpool_str1387[sizeof("lorenskog.no")];
- char stringpool_str1388[sizeof("toho.fukuoka.jp")];
- char stringpool_str1389[sizeof("soma.fukushima.jp")];
- char stringpool_str1390[sizeof("jeonbuk.kr")];
- char stringpool_str1391[sizeof("froland.no")];
- char stringpool_str1392[sizeof("sugito.saitama.jp")];
- char stringpool_str1393[sizeof("hagebostad.no")];
- char stringpool_str1394[sizeof("kumejima.okinawa.jp")];
- char stringpool_str1395[sizeof("mitane.akita.jp")];
- char stringpool_str1396[sizeof("biratori.hokkaido.jp")];
- char stringpool_str1397[sizeof("kainan.wakayama.jp")];
- char stringpool_str1398[sizeof("k12.il.us")];
- char stringpool_str1399[sizeof("shinjo.yamagata.jp")];
- char stringpool_str1400[sizeof("lib.in.us")];
- char stringpool_str1401[sizeof("gjemnes.no")];
- char stringpool_str1402[sizeof("copenhagen.museum")];
- char stringpool_str1403[sizeof("firenze.it")];
- char stringpool_str1404[sizeof("minano.saitama.jp")];
- char stringpool_str1405[sizeof("kakinoki.shimane.jp")];
- char stringpool_str1406[sizeof("za.net")];
- char stringpool_str1407[sizeof("lib.il.us")];
- char stringpool_str1408[sizeof("tozawa.yamagata.jp")];
- char stringpool_str1409[sizeof("stavern.no")];
- char stringpool_str1410[sizeof("chernovtsy.ua")];
- char stringpool_str1411[sizeof("celtic.museum")];
- char stringpool_str1412[sizeof("council.aero")];
- char stringpool_str1413[sizeof("furano.hokkaido.jp")];
- char stringpool_str1414[sizeof("greta.fr")];
- char stringpool_str1415[sizeof("kyonan.chiba.jp")];
- char stringpool_str1416[sizeof("minato.tokyo.jp")];
- char stringpool_str1417[sizeof("kira.aichi.jp")];
- char stringpool_str1418[sizeof("ringebu.no")];
- char stringpool_str1419[sizeof("essex.museum")];
- char stringpool_str1420[sizeof("tondabayashi.osaka.jp")];
- char stringpool_str1421[sizeof("tsumagoi.gunma.jp")];
- char stringpool_str1422[sizeof("qa")];
- char stringpool_str1423[sizeof("amagasaki.hyogo.jp")];
- char stringpool_str1424[sizeof("tanabe.wakayama.jp")];
- char stringpool_str1425[sizeof("media.museum")];
- char stringpool_str1426[sizeof("tanabe.kyoto.jp")];
- char stringpool_str1427[sizeof("media.hu")];
- char stringpool_str1428[sizeof("ashibetsu.hokkaido.jp")];
- char stringpool_str1429[sizeof("gs.va.no")];
- char stringpool_str1430[sizeof("co.bi")];
- char stringpool_str1431[sizeof("somna.no")];
- char stringpool_str1432[sizeof("shimane.jp")];
- char stringpool_str1433[sizeof("gs.oslo.no")];
- char stringpool_str1434[sizeof("q.bg")];
- char stringpool_str1435[sizeof("kagawa.jp")];
- char stringpool_str1436[sizeof("vaga.no")];
- char stringpool_str1437[sizeof("kamoenai.hokkaido.jp")];
- char stringpool_str1438[sizeof("association.aero")];
- char stringpool_str1439[sizeof("swiebodzin.pl")];
- char stringpool_str1440[sizeof("gamo.shiga.jp")];
- char stringpool_str1441[sizeof("kaho.fukuoka.jp")];
- char stringpool_str1442[sizeof("mikasa.hokkaido.jp")];
- char stringpool_str1443[sizeof("joyo.kyoto.jp")];
- char stringpool_str1444[sizeof("gangwon.kr")];
- char stringpool_str1445[sizeof("aejrie.no")];
- char stringpool_str1446[sizeof("toyo.kochi.jp")];
- char stringpool_str1447[sizeof("adult.ht")];
- char stringpool_str1448[sizeof("mima.tokushima.jp")];
- char stringpool_str1449[sizeof("toyotomi.hokkaido.jp")];
- char stringpool_str1450[sizeof("skanit.no")];
- char stringpool_str1451[sizeof("saitama.jp")];
- char stringpool_str1452[sizeof("sandiego.museum")];
- char stringpool_str1453[sizeof("from-la.net")];
- char stringpool_str1454[sizeof("smola.no")];
- char stringpool_str1455[sizeof("gs.nt.no")];
- char stringpool_str1456[sizeof("stranda.no")];
- char stringpool_str1457[sizeof("sarpsborg.no")];
- char stringpool_str1458[sizeof("furniture.museum")];
- char stringpool_str1459[sizeof("rauma.no")];
- char stringpool_str1460[sizeof("qld.au")];
- char stringpool_str1461[sizeof("date.fukushima.jp")];
- char stringpool_str1462[sizeof("katano.osaka.jp")];
- char stringpool_str1463[sizeof("rennebu.no")];
- char stringpool_str1464[sizeof("tas.edu.au")];
- char stringpool_str1465[sizeof("anan.tokushima.jp")];
- char stringpool_str1466[sizeof("turen.tn")];
- char stringpool_str1467[sizeof("music.museum")];
- char stringpool_str1468[sizeof("starnberg.museum")];
- char stringpool_str1469[sizeof("murata.miyagi.jp")];
- char stringpool_str1470[sizeof("sebastopol.ua")];
- char stringpool_str1471[sizeof("minowa.nagano.jp")];
- char stringpool_str1472[sizeof("verbania.it")];
- char stringpool_str1473[sizeof("bergamo.it")];
- char stringpool_str1474[sizeof("sakata.yamagata.jp")];
- char stringpool_str1475[sizeof("chuo.tokyo.jp")];
- char stringpool_str1476[sizeof("sumoto.hyogo.jp")];
- char stringpool_str1477[sizeof("gorge.museum")];
- char stringpool_str1478[sizeof("rikubetsu.hokkaido.jp")];
- char stringpool_str1479[sizeof("asnes.no")];
- char stringpool_str1480[sizeof("konin.pl")];
- char stringpool_str1481[sizeof("monticello.museum")];
- char stringpool_str1482[sizeof("sauda.no")];
- char stringpool_str1483[sizeof("semine.miyagi.jp")];
- char stringpool_str1484[sizeof("games.hu")];
- char stringpool_str1485[sizeof("lezajsk.pl")];
- char stringpool_str1486[sizeof("tolga.no")];
- char stringpool_str1487[sizeof("ravenna.it")];
- char stringpool_str1488[sizeof("chita.ru")];
- char stringpool_str1489[sizeof("jeonnam.kr")];
- char stringpool_str1490[sizeof("kunitachi.tokyo.jp")];
- char stringpool_str1491[sizeof("dominic.ua")];
- char stringpool_str1492[sizeof("svelvik.no")];
- char stringpool_str1493[sizeof("motobu.okinawa.jp")];
- char stringpool_str1494[sizeof("student.aero")];
- char stringpool_str1495[sizeof("vestvagoy.no")];
- char stringpool_str1496[sizeof("stadt.museum")];
- char stringpool_str1497[sizeof("tvedestrand.no")];
- char stringpool_str1498[sizeof("qsl.br")];
- char stringpool_str1499[sizeof("venezia.it")];
- char stringpool_str1500[sizeof("hokuto.hokkaido.jp")];
- char stringpool_str1501[sizeof("kuzbass.ru")];
- char stringpool_str1502[sizeof("selfip.com")];
- char stringpool_str1503[sizeof("vaapste.no")];
- char stringpool_str1504[sizeof("mukawa.hokkaido.jp")];
- char stringpool_str1505[sizeof("kvitsoy.no")];
- char stringpool_str1506[sizeof("campidanomedio.it")];
- char stringpool_str1507[sizeof("berlin.museum")];
- char stringpool_str1508[sizeof("hareid.no")];
- char stringpool_str1509[sizeof("health.vn")];
- char stringpool_str1510[sizeof("hokuto.yamanashi.jp")];
- char stringpool_str1511[sizeof("gs.aa.no")];
- char stringpool_str1512[sizeof("joetsu.niigata.jp")];
- char stringpool_str1513[sizeof("mil.by")];
- char stringpool_str1514[sizeof("hamatama.saga.jp")];
- char stringpool_str1515[sizeof("takasu.hokkaido.jp")];
- char stringpool_str1516[sizeof("granvin.no")];
- char stringpool_str1517[sizeof("blogspot.gr")];
- char stringpool_str1518[sizeof("sandnes.no")];
- char stringpool_str1519[sizeof("tsunan.niigata.jp")];
- char stringpool_str1520[sizeof("kiyose.tokyo.jp")];
- char stringpool_str1521[sizeof("kawajima.saitama.jp")];
- char stringpool_str1522[sizeof("alstahaug.no")];
- char stringpool_str1523[sizeof("mil.sy")];
- char stringpool_str1524[sizeof("takatsuki.osaka.jp")];
- char stringpool_str1525[sizeof("6bone.pl")];
- char stringpool_str1526[sizeof("skedsmo.no")];
- char stringpool_str1527[sizeof("shiraoka.saitama.jp")];
- char stringpool_str1528[sizeof("misato.miyagi.jp")];
- char stringpool_str1529[sizeof("american.museum")];
- char stringpool_str1530[sizeof("jelenia-gora.pl")];
- char stringpool_str1531[sizeof("barlettatraniandria.it")];
- char stringpool_str1532[sizeof("blogspot.sg")];
- char stringpool_str1533[sizeof("kokubunji.tokyo.jp")];
- char stringpool_str1534[sizeof("koga.ibaraki.jp")];
- char stringpool_str1535[sizeof("sherbrooke.museum")];
- char stringpool_str1536[sizeof("force.museum")];
- char stringpool_str1537[sizeof("selfip.net")];
- char stringpool_str1538[sizeof("lukow.pl")];
- char stringpool_str1539[sizeof("skoczow.pl")];
- char stringpool_str1540[sizeof("takasaki.gunma.jp")];
- char stringpool_str1541[sizeof("hasvik.no")];
- char stringpool_str1542[sizeof("tjome.no")];
- char stringpool_str1543[sizeof("lubin.pl")];
- char stringpool_str1544[sizeof("county.museum")];
- char stringpool_str1545[sizeof("enebakk.no")];
- char stringpool_str1546[sizeof("godo.gifu.jp")];
- char stringpool_str1547[sizeof("kita.tokyo.jp")];
- char stringpool_str1548[sizeof("catania.it")];
- char stringpool_str1549[sizeof("giske.no")];
- char stringpool_str1550[sizeof("vestnes.no")];
- char stringpool_str1551[sizeof("taketomi.okinawa.jp")];
- char stringpool_str1552[sizeof("forde.no")];
- char stringpool_str1553[sizeof("toyono.osaka.jp")];
- char stringpool_str1554[sizeof("for-the.biz")];
- char stringpool_str1555[sizeof("toyonaka.osaka.jp")];
- char stringpool_str1556[sizeof("mbone.pl")];
- char stringpool_str1557[sizeof("donna.no")];
- char stringpool_str1558[sizeof("texas.museum")];
- char stringpool_str1559[sizeof("kitaakita.akita.jp")];
- char stringpool_str1560[sizeof("hyllestad.no")];
- char stringpool_str1561[sizeof("volkenkunde.museum")];
- char stringpool_str1562[sizeof("komatsushima.tokushima.jp")];
- char stringpool_str1563[sizeof("shinagawa.tokyo.jp")];
- char stringpool_str1564[sizeof("takizawa.iwate.jp")];
- char stringpool_str1565[sizeof("kirov.ru")];
- char stringpool_str1566[sizeof("savannahga.museum")];
- char stringpool_str1567[sizeof("tranby.no")];
- char stringpool_str1568[sizeof("depot.museum")];
- char stringpool_str1569[sizeof("kure.hiroshima.jp")];
- char stringpool_str1570[sizeof("vestby.no")];
- char stringpool_str1571[sizeof("trana.no")];
- char stringpool_str1572[sizeof("kariwa.niigata.jp")];
- char stringpool_str1573[sizeof("frogn.no")];
- char stringpool_str1574[sizeof("kherson.ua")];
- char stringpool_str1575[sizeof("volda.no")];
- char stringpool_str1576[sizeof("loppa.no")];
- char stringpool_str1577[sizeof("from-co.net")];
- char stringpool_str1578[sizeof("dyndns.org")];
- char stringpool_str1579[sizeof("juedisches.museum")];
- char stringpool_str1580[sizeof("karlsoy.no")];
- char stringpool_str1581[sizeof("miyota.nagano.jp")];
- char stringpool_str1582[sizeof("suginami.tokyo.jp")];
- char stringpool_str1583[sizeof("seranishi.hiroshima.jp")];
- char stringpool_str1584[sizeof("ferrara.it")];
- char stringpool_str1585[sizeof("frana.no")];
- char stringpool_str1586[sizeof("kiyosato.hokkaido.jp")];
- char stringpool_str1587[sizeof("cincinnati.museum")];
- char stringpool_str1588[sizeof("gujo.gifu.jp")];
- char stringpool_str1589[sizeof("trainer.aero")];
- char stringpool_str1590[sizeof("loten.no")];
- char stringpool_str1591[sizeof("agematsu.nagano.jp")];
- char stringpool_str1592[sizeof("takazaki.miyazaki.jp")];
- char stringpool_str1593[sizeof("lebesby.no")];
- char stringpool_str1594[sizeof("mikawa.yamagata.jp")];
- char stringpool_str1595[sizeof("tainai.niigata.jp")];
- char stringpool_str1596[sizeof("chtr.k12.ma.us")];
- char stringpool_str1597[sizeof("groundhandling.aero")];
- char stringpool_str1598[sizeof("morotsuka.miyazaki.jp")];
- char stringpool_str1599[sizeof("tama.tokyo.jp")];
- char stringpool_str1600[sizeof("hazu.aichi.jp")];
- char stringpool_str1601[sizeof("kayabe.hokkaido.jp")];
- char stringpool_str1602[sizeof("johana.toyama.jp")];
- char stringpool_str1603[sizeof("hiji.oita.jp")];
- char stringpool_str1604[sizeof("spydeberg.no")];
- char stringpool_str1605[sizeof("kragero.no")];
- char stringpool_str1606[sizeof("mytis.ru")];
- char stringpool_str1607[sizeof("moareke.no")];
- char stringpool_str1608[sizeof("dolls.museum")];
- char stringpool_str1609[sizeof("kunneppu.hokkaido.jp")];
- char stringpool_str1610[sizeof("molde.no")];
- char stringpool_str1611[sizeof("gulen.no")];
- char stringpool_str1612[sizeof("koka.shiga.jp")];
- char stringpool_str1613[sizeof("hannan.osaka.jp")];
- char stringpool_str1614[sizeof("kurate.fukuoka.jp")];
- char stringpool_str1615[sizeof("2000.hu")];
- char stringpool_str1616[sizeof("kazan.ru")];
- char stringpool_str1617[sizeof("sasebo.nagasaki.jp")];
- char stringpool_str1618[sizeof("kuban.ru")];
- char stringpool_str1619[sizeof("qh.cn")];
- char stringpool_str1620[sizeof("americana.museum")];
- char stringpool_str1621[sizeof("state.museum")];
- char stringpool_str1622[sizeof("zlg.br")];
- char stringpool_str1623[sizeof("from-me.org")];
- char stringpool_str1624[sizeof("foggia.it")];
- char stringpool_str1625[sizeof("land-4-sale.us")];
- char stringpool_str1626[sizeof("madrid.museum")];
- char stringpool_str1627[sizeof("futaba.fukushima.jp")];
- char stringpool_str1628[sizeof("kawazu.shizuoka.jp")];
- char stringpool_str1629[sizeof("bjugn.no")];
- char stringpool_str1630[sizeof("grane.no")];
- char stringpool_str1631[sizeof("koeln.museum")];
- char stringpool_str1632[sizeof("shimamaki.hokkaido.jp")];
- char stringpool_str1633[sizeof("ginoza.okinawa.jp")];
- char stringpool_str1634[sizeof("saikai.nagasaki.jp")];
- char stringpool_str1635[sizeof("game-host.org")];
- char stringpool_str1636[sizeof("tokke.no")];
- char stringpool_str1637[sizeof("agriculture.museum")];
- char stringpool_str1638[sizeof("rivne.ua")];
- char stringpool_str1639[sizeof("kyotamba.kyoto.jp")];
- char stringpool_str1640[sizeof("gunma.jp")];
- char stringpool_str1641[sizeof("hapmir.no")];
- char stringpool_str1642[sizeof("from-ny.net")];
- char stringpool_str1643[sizeof("tomi.nagano.jp")];
- char stringpool_str1644[sizeof("salat.no")];
- char stringpool_str1645[sizeof("sano.tochigi.jp")];
- char stringpool_str1646[sizeof("barletta-trani-andria.it")];
- char stringpool_str1647[sizeof("aosta.it")];
- char stringpool_str1648[sizeof("kawanishi.nara.jp")];
- char stringpool_str1649[sizeof("genoa.it")];
- char stringpool_str1650[sizeof("togo.aichi.jp")];
- char stringpool_str1651[sizeof("tsugaru.aomori.jp")];
- char stringpool_str1652[sizeof("kokonoe.oita.jp")];
- char stringpool_str1653[sizeof("busan.kr")];
- char stringpool_str1654[sizeof("cesenaforli.it")];
- char stringpool_str1655[sizeof("kuroishi.aomori.jp")];
- char stringpool_str1656[sizeof("mugi.tokushima.jp")];
- char stringpool_str1657[sizeof("shinjo.nara.jp")];
- char stringpool_str1658[sizeof("shonai.fukuoka.jp")];
- char stringpool_str1659[sizeof("kadena.okinawa.jp")];
- char stringpool_str1660[sizeof("shiiba.miyazaki.jp")];
- char stringpool_str1661[sizeof("agrinet.tn")];
- char stringpool_str1662[sizeof("kyotango.kyoto.jp")];
- char stringpool_str1663[sizeof("bronnoy.no")];
- char stringpool_str1664[sizeof("fujinomiya.shizuoka.jp")];
- char stringpool_str1665[sizeof("space.museum")];
- char stringpool_str1666[sizeof("k12.wy.us")];
- char stringpool_str1667[sizeof("skole.museum")];
- char stringpool_str1668[sizeof("sera.hiroshima.jp")];
- char stringpool_str1669[sizeof("biei.hokkaido.jp")];
- char stringpool_str1670[sizeof("mombetsu.hokkaido.jp")];
- char stringpool_str1671[sizeof("khabarovsk.ru")];
- char stringpool_str1672[sizeof("bato.tochigi.jp")];
- char stringpool_str1673[sizeof("kiso.nagano.jp")];
- char stringpool_str1674[sizeof("klodzko.pl")];
- char stringpool_str1675[sizeof("trapani.it")];
- char stringpool_str1676[sizeof("esan.hokkaido.jp")];
- char stringpool_str1677[sizeof("hakuba.nagano.jp")];
- char stringpool_str1678[sizeof("better-than.tv")];
- char stringpool_str1679[sizeof("hita.oita.jp")];
- char stringpool_str1680[sizeof("mimata.miyazaki.jp")];
- char stringpool_str1681[sizeof("togane.chiba.jp")];
- char stringpool_str1682[sizeof("mibu.tochigi.jp")];
- char stringpool_str1683[sizeof("lib.wy.us")];
- char stringpool_str1684[sizeof("bandai.fukushima.jp")];
- char stringpool_str1685[sizeof("hikawa.shimane.jp")];
- char stringpool_str1686[sizeof("mino.gifu.jp")];
- char stringpool_str1687[sizeof("date.hokkaido.jp")];
- char stringpool_str1688[sizeof("shinjo.okayama.jp")];
- char stringpool_str1689[sizeof("saga.saga.jp")];
- char stringpool_str1690[sizeof("miyazaki.miyazaki.jp")];
- char stringpool_str1691[sizeof("seki.gifu.jp")];
- char stringpool_str1692[sizeof("lanbib.se")];
- char stringpool_str1693[sizeof("christiansburg.museum")];
- char stringpool_str1694[sizeof("skien.no")];
- char stringpool_str1695[sizeof("k12.ny.us")];
- char stringpool_str1696[sizeof("kani.gifu.jp")];
- char stringpool_str1697[sizeof("homeip.net")];
- char stringpool_str1698[sizeof("bo.telemark.no")];
- char stringpool_str1699[sizeof("tsubetsu.hokkaido.jp")];
- char stringpool_str1700[sizeof("sado.niigata.jp")];
- char stringpool_str1701[sizeof("delmenhorst.museum")];
- char stringpool_str1702[sizeof("store.st")];
- char stringpool_str1703[sizeof("vikna.no")];
- char stringpool_str1704[sizeof("toki.gifu.jp")];
- char stringpool_str1705[sizeof("simbirsk.ru")];
- char stringpool_str1706[sizeof("siena.it")];
- char stringpool_str1707[sizeof("kawasaki.miyagi.jp")];
- char stringpool_str1708[sizeof("hino.tokyo.jp")];
- char stringpool_str1709[sizeof("lib.ny.us")];
- char stringpool_str1710[sizeof("kamo.niigata.jp")];
- char stringpool_str1711[sizeof("maebashi.gunma.jp")];
- char stringpool_str1712[sizeof("tsaritsyn.ru")];
- char stringpool_str1713[sizeof("balat.no")];
- char stringpool_str1714[sizeof("rikuzentakata.iwate.jp")];
- char stringpool_str1715[sizeof("gokase.miyazaki.jp")];
- char stringpool_str1716[sizeof("aoki.nagano.jp")];
- char stringpool_str1717[sizeof("toyosato.shiga.jp")];
- char stringpool_str1718[sizeof("bryansk.ru")];
- char stringpool_str1719[sizeof("koga.fukuoka.jp")];
- char stringpool_str1720[sizeof("kaga.ishikawa.jp")];
- char stringpool_str1721[sizeof("skaun.no")];
- char stringpool_str1722[sizeof("mizunami.gifu.jp")];
- char stringpool_str1723[sizeof("lesja.no")];
- char stringpool_str1724[sizeof("sport.hu")];
- char stringpool_str1725[sizeof("sannan.hyogo.jp")];
- char stringpool_str1726[sizeof("kamiichi.toyama.jp")];
- char stringpool_str1727[sizeof("holmestrand.no")];
- char stringpool_str1728[sizeof("lakas.hu")];
- char stringpool_str1729[sizeof("maniwa.okayama.jp")];
- char stringpool_str1730[sizeof("makinohara.shizuoka.jp")];
- char stringpool_str1731[sizeof("om")];
- char stringpool_str1732[sizeof("agdenes.no")];
- char stringpool_str1733[sizeof("store.ro")];
- char stringpool_str1734[sizeof("baltimore.museum")];
- char stringpool_str1735[sizeof("gov.tw")];
- char stringpool_str1736[sizeof("edu.tw")];
- char stringpool_str1737[sizeof("aoste.it")];
- char stringpool_str1738[sizeof("com.tw")];
- char stringpool_str1739[sizeof("daejeon.kr")];
- char stringpool_str1740[sizeof("aukra.no")];
- char stringpool_str1741[sizeof("flora.no")];
- char stringpool_str1742[sizeof("com.aw")];
- char stringpool_str1743[sizeof("miyazu.kyoto.jp")];
- char stringpool_str1744[sizeof("leirvik.no")];
- char stringpool_str1745[sizeof("gniezno.pl")];
- char stringpool_str1746[sizeof("bronnoysund.no")];
- char stringpool_str1747[sizeof("shiga.jp")];
- char stringpool_str1748[sizeof("tokushima.jp")];
- char stringpool_str1749[sizeof("vladimir.ru")];
- char stringpool_str1750[sizeof("charter.aero")];
- char stringpool_str1751[sizeof("or.it")];
- char stringpool_str1752[sizeof("od.ua")];
- char stringpool_str1753[sizeof("tempio-olbia.it")];
- char stringpool_str1754[sizeof("turin.it")];
- char stringpool_str1755[sizeof("moka.tochigi.jp")];
- char stringpool_str1756[sizeof("ot.it")];
- char stringpool_str1757[sizeof("journal.aero")];
- char stringpool_str1758[sizeof("fukushima.jp")];
- char stringpool_str1759[sizeof("botanicalgarden.museum")];
- char stringpool_str1760[sizeof("taketa.oita.jp")];
- char stringpool_str1761[sizeof("akaiwa.okayama.jp")];
- char stringpool_str1762[sizeof("or.us")];
- char stringpool_str1763[sizeof("baths.museum")];
- char stringpool_str1764[sizeof("taranto.it")];
- char stringpool_str1765[sizeof("kumenan.okayama.jp")];
- char stringpool_str1766[sizeof("o.se")];
- char stringpool_str1767[sizeof("bible.museum")];
- char stringpool_str1768[sizeof("edu.cw")];
- char stringpool_str1769[sizeof("com.cw")];
- char stringpool_str1770[sizeof("fukusaki.hyogo.jp")];
- char stringpool_str1771[sizeof("cagliari.it")];
- char stringpool_str1772[sizeof("dovre.no")];
- char stringpool_str1773[sizeof("fujiidera.osaka.jp")];
- char stringpool_str1774[sizeof("kamiamakusa.kumamoto.jp")];
- char stringpool_str1775[sizeof("odo.br")];
- char stringpool_str1776[sizeof("barreau.bj")];
- char stringpool_str1777[sizeof("virginia.museum")];
- char stringpool_str1778[sizeof("saitama.saitama.jp")];
- char stringpool_str1779[sizeof("takatsuki.shiga.jp")];
- char stringpool_str1780[sizeof("soeda.fukuoka.jp")];
- char stringpool_str1781[sizeof("anan.nagano.jp")];
- char stringpool_str1782[sizeof("ec")];
- char stringpool_str1783[sizeof("akita.jp")];
- char stringpool_str1784[sizeof("cc")];
- char stringpool_str1785[sizeof("sc")];
- char stringpool_str1786[sizeof("ac")];
- char stringpool_str1787[sizeof("kawatana.nagasaki.jp")];
- char stringpool_str1788[sizeof("hemne.no")];
- char stringpool_str1789[sizeof("bozen.it")];
- char stringpool_str1790[sizeof("on.ca")];
- char stringpool_str1791[sizeof("meiwa.mie.jp")];
- char stringpool_str1792[sizeof("valle.no")];
- char stringpool_str1793[sizeof("tamano.okayama.jp")];
- char stringpool_str1794[sizeof("saku.nagano.jp")];
- char stringpool_str1795[sizeof("educational.museum")];
- char stringpool_str1796[sizeof("aioi.hyogo.jp")];
- char stringpool_str1797[sizeof("himeji.hyogo.jp")];
- char stringpool_str1798[sizeof("ac.ma")];
- char stringpool_str1799[sizeof("fedje.no")];
- char stringpool_str1800[sizeof("or.na")];
- char stringpool_str1801[sizeof("shibetsu.hokkaido.jp")];
- char stringpool_str1802[sizeof("rc.it")];
- char stringpool_str1803[sizeof("colonialwilliamsburg.museum")];
- char stringpool_str1804[sizeof("gc.ca")];
- char stringpool_str1805[sizeof("kamitonda.wakayama.jp")];
- char stringpool_str1806[sizeof("botany.museum")];
- char stringpool_str1807[sizeof("sc.us")];
- char stringpool_str1808[sizeof("o.bg")];
- char stringpool_str1809[sizeof("kawanehon.shizuoka.jp")];
- char stringpool_str1810[sizeof("kusatsu.shiga.jp")];
- char stringpool_str1811[sizeof("mc")];
- char stringpool_str1812[sizeof("surrey.museum")];
- char stringpool_str1813[sizeof("lewismiller.museum")];
- char stringpool_str1814[sizeof("shima.mie.jp")];
- char stringpool_str1815[sizeof("takata.fukuoka.jp")];
- char stringpool_str1816[sizeof("selje.no")];
- char stringpool_str1817[sizeof("himeshima.oita.jp")];
- char stringpool_str1818[sizeof("tc")];
- char stringpool_str1819[sizeof("lc")];
- char stringpool_str1820[sizeof("sumy.ua")];
- char stringpool_str1821[sizeof("saka.hiroshima.jp")];
- char stringpool_str1822[sizeof("lugansk.ua")];
- char stringpool_str1823[sizeof("magnitka.ru")];
- char stringpool_str1824[sizeof("mc.it")];
- char stringpool_str1825[sizeof("ehime.jp")];
- char stringpool_str1826[sizeof("aridagawa.wakayama.jp")];
- char stringpool_str1827[sizeof("lc.it")];
- char stringpool_str1828[sizeof("express.aero")];
- char stringpool_str1829[sizeof("eco.br")];
- char stringpool_str1830[sizeof("or.at")];
- char stringpool_str1831[sizeof("embetsu.hokkaido.jp")];
- char stringpool_str1832[sizeof("sobetsu.hokkaido.jp")];
- char stringpool_str1833[sizeof("takino.hyogo.jp")];
- char stringpool_str1834[sizeof("act.au")];
- char stringpool_str1835[sizeof("kanazawa.ishikawa.jp")];
- char stringpool_str1836[sizeof("ac.pa")];
- char stringpool_str1837[sizeof("fc.it")];
- char stringpool_str1838[sizeof("cody.museum")];
- char stringpool_str1839[sizeof("hirata.fukushima.jp")];
- char stringpool_str1840[sizeof("shimane.shimane.jp")];
- char stringpool_str1841[sizeof("britishcolumbia.museum")];
- char stringpool_str1842[sizeof("gdynia.pl")];
- char stringpool_str1843[sizeof("rec.co")];
- char stringpool_str1844[sizeof("genkai.saga.jp")];
- char stringpool_str1845[sizeof("etc.br")];
- char stringpool_str1846[sizeof("shikabe.hokkaido.jp")];
- char stringpool_str1847[sizeof("cc.na")];
- char stringpool_str1848[sizeof("aikawa.kanagawa.jp")];
- char stringpool_str1849[sizeof("ac.tj")];
- char stringpool_str1850[sizeof("oh.us")];
- char stringpool_str1851[sizeof("hikone.shiga.jp")];
- char stringpool_str1852[sizeof("ok.us")];
- char stringpool_str1853[sizeof("rec.br")];
- char stringpool_str1854[sizeof("hirono.fukushima.jp")];
- char stringpool_str1855[sizeof("hiroshima.jp")];
- char stringpool_str1856[sizeof("omsk.ru")];
- char stringpool_str1857[sizeof("dc.us")];
- char stringpool_str1858[sizeof("bryne.no")];
- char stringpool_str1859[sizeof("bushey.museum")];
- char stringpool_str1860[sizeof("lillehammer.no")];
- char stringpool_str1861[sizeof("kawanishi.hyogo.jp")];
- char stringpool_str1862[sizeof("tobetsu.hokkaido.jp")];
- char stringpool_str1863[sizeof("stor-elvdal.no")];
- char stringpool_str1864[sizeof("mil.tw")];
- char stringpool_str1865[sizeof("or.tz")];
- char stringpool_str1866[sizeof("bc.ca")];
- char stringpool_str1867[sizeof("sogne.no")];
- char stringpool_str1868[sizeof("shimabara.nagasaki.jp")];
- char stringpool_str1869[sizeof("royrvik.no")];
- char stringpool_str1870[sizeof("vc")];
- char stringpool_str1871[sizeof("or.pw")];
- char stringpool_str1872[sizeof("shibecha.hokkaido.jp")];
- char stringpool_str1873[sizeof("ac.me")];
- char stringpool_str1874[sizeof("hornindal.no")];
- char stringpool_str1875[sizeof("aibetsu.hokkaido.jp")];
- char stringpool_str1876[sizeof("hawaii.museum")];
- char stringpool_str1877[sizeof("vc.it")];
- char stringpool_str1878[sizeof("sydney.museum")];
- char stringpool_str1879[sizeof("ecn.br")];
- char stringpool_str1880[sizeof("kamiizumi.saitama.jp")];
- char stringpool_str1881[sizeof("valley.museum")];
- char stringpool_str1882[sizeof("suwa.nagano.jp")];
- char stringpool_str1883[sizeof("ac.at")];
- char stringpool_str1884[sizeof("ac.mw")];
- char stringpool_str1885[sizeof("erotika.hu")];
- char stringpool_str1886[sizeof("quebec.museum")];
- char stringpool_str1887[sizeof("kanmaki.nara.jp")];
- char stringpool_str1888[sizeof("tagajo.miyagi.jp")];
- char stringpool_str1889[sizeof("sch.ae")];
- char stringpool_str1890[sizeof("musashino.tokyo.jp")];
- char stringpool_str1891[sizeof("toya.hokkaido.jp")];
- char stringpool_str1892[sizeof("jgora.pl")];
- char stringpool_str1893[sizeof("shimada.shizuoka.jp")];
- char stringpool_str1894[sizeof("reggioemilia.it")];
- char stringpool_str1895[sizeof("sch.qa")];
- char stringpool_str1896[sizeof("hitra.no")];
- char stringpool_str1897[sizeof("kesennuma.miyagi.jp")];
- char stringpool_str1898[sizeof("erotica.hu")];
- char stringpool_str1899[sizeof("fujieda.shizuoka.jp")];
- char stringpool_str1900[sizeof("sch.sa")];
- char stringpool_str1901[sizeof("sch.jo")];
- char stringpool_str1902[sizeof("sch.je")];
- char stringpool_str1903[sizeof("honbetsu.hokkaido.jp")];
- char stringpool_str1904[sizeof("fujisawa.kanagawa.jp")];
- char stringpool_str1905[sizeof("ac.gn")];
- char stringpool_str1906[sizeof("chattanooga.museum")];
- char stringpool_str1907[sizeof("ac.in")];
- char stringpool_str1908[sizeof("hida.gifu.jp")];
- char stringpool_str1909[sizeof("rybnik.pl")];
- char stringpool_str1910[sizeof("sc.cn")];
- char stringpool_str1911[sizeof("kibichuo.okayama.jp")];
- char stringpool_str1912[sizeof("ac.cn")];
- char stringpool_str1913[sizeof("showa.fukushima.jp")];
- char stringpool_str1914[sizeof("sc.tz")];
- char stringpool_str1915[sizeof("ac.tz")];
- char stringpool_str1916[sizeof("himi.toyama.jp")];
- char stringpool_str1917[sizeof("shiranuka.hokkaido.jp")];
- char stringpool_str1918[sizeof("miki.hyogo.jp")];
- char stringpool_str1919[sizeof("sci.eg")];
- char stringpool_str1920[sizeof("for-better.biz")];
- char stringpool_str1921[sizeof("orkdal.no")];
- char stringpool_str1922[sizeof("kaita.hiroshima.jp")];
- char stringpool_str1923[sizeof("milan.it")];
- char stringpool_str1924[sizeof("selfip.org")];
- char stringpool_str1925[sizeof("gorlice.pl")];
- char stringpool_str1926[sizeof("buzen.fukuoka.jp")];
- char stringpool_str1927[sizeof("ac.vn")];
- char stringpool_str1928[sizeof("tranibarlettaandria.it")];
- char stringpool_str1929[sizeof("asaka.saitama.jp")];
- char stringpool_str1930[sizeof("store.nf")];
- char stringpool_str1931[sizeof("vic.au")];
- char stringpool_str1932[sizeof("tsuwano.shimane.jp")];
- char stringpool_str1933[sizeof("kusatsu.gunma.jp")];
- char stringpool_str1934[sizeof("orenburg.ru")];
- char stringpool_str1935[sizeof("takasago.hyogo.jp")];
- char stringpool_str1936[sizeof("ginowan.okinawa.jp")];
- char stringpool_str1937[sizeof("daiwa.hiroshima.jp")];
- char stringpool_str1938[sizeof("oita.jp")];
- char stringpool_str1939[sizeof("ac.ae")];
- char stringpool_str1940[sizeof("targi.pl")];
- char stringpool_str1941[sizeof("bearalvahki.no")];
- char stringpool_str1942[sizeof("bykle.no")];
- char stringpool_str1943[sizeof("shinshinotsu.hokkaido.jp")];
- char stringpool_str1944[sizeof("koshigaya.saitama.jp")];
- char stringpool_str1945[sizeof("davvenjarga.no")];
- char stringpool_str1946[sizeof("kagoshima.jp")];
- char stringpool_str1947[sizeof("kamaishi.iwate.jp")];
- char stringpool_str1948[sizeof("hara.nagano.jp")];
- char stringpool_str1949[sizeof("asaminami.hiroshima.jp")];
- char stringpool_str1950[sizeof("hakata.fukuoka.jp")];
- char stringpool_str1951[sizeof("kaminoyama.yamagata.jp")];
- char stringpool_str1952[sizeof("hanawa.fukushima.jp")];
- char stringpool_str1953[sizeof("hadano.kanagawa.jp")];
- char stringpool_str1954[sizeof("gliwice.pl")];
- char stringpool_str1955[sizeof("bygland.no")];
- char stringpool_str1956[sizeof("chiba.jp")];
- char stringpool_str1957[sizeof("tsubame.niigata.jp")];
- char stringpool_str1958[sizeof("home.dyndns.org")];
- char stringpool_str1959[sizeof("hiraizumi.iwate.jp")];
- char stringpool_str1960[sizeof("trani-andria-barletta.it")];
- char stringpool_str1961[sizeof("katashina.gunma.jp")];
- char stringpool_str1962[sizeof("oppdal.no")];
- char stringpool_str1963[sizeof("hakone.kanagawa.jp")];
- char stringpool_str1964[sizeof("tourism.tn")];
- char stringpool_str1965[sizeof("ac.rs")];
- char stringpool_str1966[sizeof("trani-barletta-andria.it")];
- char stringpool_str1967[sizeof("karatsu.saga.jp")];
- char stringpool_str1968[sizeof("oksnes.no")];
- char stringpool_str1969[sizeof("andriabarlettatrani.it")];
- char stringpool_str1970[sizeof("ancona.it")];
- char stringpool_str1971[sizeof("americanantiques.museum")];
- char stringpool_str1972[sizeof("altai.ru")];
- char stringpool_str1973[sizeof("orland.no")];
- char stringpool_str1974[sizeof("tokushima.tokushima.jp")];
- char stringpool_str1975[sizeof("miyashiro.saitama.jp")];
- char stringpool_str1976[sizeof("zarow.pl")];
- char stringpool_str1977[sizeof("seika.kyoto.jp")];
- char stringpool_str1978[sizeof("tsukigata.hokkaido.jp")];
- char stringpool_str1979[sizeof("treviso.it")];
- char stringpool_str1980[sizeof("tome.miyagi.jp")];
- char stringpool_str1981[sizeof("kurashiki.okayama.jp")];
- char stringpool_str1982[sizeof("sciences.museum")];
- char stringpool_str1983[sizeof("resistance.museum")];
- char stringpool_str1984[sizeof("taka.hyogo.jp")];
- char stringpool_str1985[sizeof("forlicesena.it")];
- char stringpool_str1986[sizeof("sayo.hyogo.jp")];
- char stringpool_str1987[sizeof("takaishi.osaka.jp")];
- char stringpool_str1988[sizeof("rygge.no")];
- char stringpool_str1989[sizeof("org")];
- char stringpool_str1990[sizeof("og.it")];
- char stringpool_str1991[sizeof("oslo.no")];
- char stringpool_str1992[sizeof("org.to")];
- char stringpool_str1993[sizeof("org.tm")];
- char stringpool_str1994[sizeof("ama.shimane.jp")];
- char stringpool_str1995[sizeof("org.bo")];
- char stringpool_str1996[sizeof("org.bm")];
- char stringpool_str1997[sizeof("org.ae")];
- char stringpool_str1998[sizeof("servebbs.com")];
- char stringpool_str1999[sizeof("org.bi")];
- char stringpool_str2000[sizeof("org.bz")];
- char stringpool_str2001[sizeof("org.ai")];
- char stringpool_str2002[sizeof("org.az")];
- char stringpool_str2003[sizeof("airline.aero")];
- char stringpool_str2004[sizeof("org.ag")];
- char stringpool_str2005[sizeof("gliding.aero")];
- char stringpool_str2006[sizeof("gf")];
- char stringpool_str2007[sizeof("vinnica.ua")];
- char stringpool_str2008[sizeof("muika.niigata.jp")];
- char stringpool_str2009[sizeof("cf")];
- char stringpool_str2010[sizeof("org.qa")];
- char stringpool_str2011[sizeof("af")];
- char stringpool_str2012[sizeof("org.ba")];
- char stringpool_str2013[sizeof("org.so")];
- char stringpool_str2014[sizeof("org.se")];
- char stringpool_str2015[sizeof("org.sd")];
- char stringpool_str2016[sizeof("trading.aero")];
- char stringpool_str2017[sizeof("org.bs")];
- char stringpool_str2018[sizeof("osen.no")];
- char stringpool_str2019[sizeof("org.sz")];
- char stringpool_str2020[sizeof("odda.no")];
- char stringpool_str2021[sizeof("org.sg")];
- char stringpool_str2022[sizeof("satte.saitama.jp")];
- char stringpool_str2023[sizeof("org.ac")];
- char stringpool_str2024[sizeof("org.sa")];
- char stringpool_str2025[sizeof("chigasaki.kanagawa.jp")];
- char stringpool_str2026[sizeof("org.jo")];
- char stringpool_str2027[sizeof("org.je")];
- char stringpool_str2028[sizeof("eniwa.hokkaido.jp")];
- char stringpool_str2029[sizeof("ryokami.saitama.jp")];
- char stringpool_str2030[sizeof("ome.tokyo.jp")];
- char stringpool_str2031[sizeof("org.bb")];
- char stringpool_str2032[sizeof("org.sc")];
- char stringpool_str2033[sizeof("online.museum")];
- char stringpool_str2034[sizeof("kami.miyagi.jp")];
- char stringpool_str2035[sizeof("andria-trani-barletta.it")];
- char stringpool_str2036[sizeof("aeroclub.aero")];
- char stringpool_str2037[sizeof("org.sb")];
- char stringpool_str2038[sizeof("musashimurayama.tokyo.jp")];
- char stringpool_str2039[sizeof("tateshina.nagano.jp")];
- char stringpool_str2040[sizeof("komatsu.ishikawa.jp")];
- char stringpool_str2041[sizeof("tohma.hokkaido.jp")];
- char stringpool_str2042[sizeof("org.au")];
- char stringpool_str2043[sizeof("shinichi.hiroshima.jp")];
- char stringpool_str2044[sizeof("org.co")];
- char stringpool_str2045[sizeof("org.tt")];
- char stringpool_str2046[sizeof("org.ci")];
- char stringpool_str2047[sizeof("org.bt")];
- char stringpool_str2048[sizeof("city.hu")];
- char stringpool_str2049[sizeof("shikaoi.hokkaido.jp")];
- char stringpool_str2050[sizeof("kamisunagawa.hokkaido.jp")];
- char stringpool_str2051[sizeof("chuo.yamanashi.jp")];
- char stringpool_str2052[sizeof("tf")];
- char stringpool_str2053[sizeof("org.tn")];
- char stringpool_str2054[sizeof("org.st")];
- char stringpool_str2055[sizeof("org.br")];
- char stringpool_str2056[sizeof("org.an")];
- char stringpool_str2057[sizeof("tamatsukuri.ibaraki.jp")];
- char stringpool_str2058[sizeof("zama.kanagawa.jp")];
- char stringpool_str2059[sizeof("ac.rw")];
- char stringpool_str2060[sizeof("vagan.no")];
- char stringpool_str2061[sizeof("toga.toyama.jp")];
- char stringpool_str2062[sizeof("org.sn")];
- char stringpool_str2063[sizeof("conference.aero")];
- char stringpool_str2064[sizeof("tourism.pl")];
- char stringpool_str2065[sizeof("org.al")];
- char stringpool_str2066[sizeof("fukushima.hokkaido.jp")];
- char stringpool_str2067[sizeof("certification.aero")];
- char stringpool_str2068[sizeof("british-library.uk")];
- char stringpool_str2069[sizeof("org.cu")];
- char stringpool_str2070[sizeof("rec.nf")];
- char stringpool_str2071[sizeof("org.sl")];
- char stringpool_str2072[sizeof("ftpaccess.cc")];
- char stringpool_str2073[sizeof("satosho.okayama.jp")];
- char stringpool_str2074[sizeof("tagawa.fukuoka.jp")];
- char stringpool_str2075[sizeof("org.tj")];
- char stringpool_str2076[sizeof("maibara.shiga.jp")];
- char stringpool_str2077[sizeof("org.cn")];
- char stringpool_str2078[sizeof("karuizawa.nagano.jp")];
- char stringpool_str2079[sizeof("bf")];
- char stringpool_str2080[sizeof("zentsuji.kagawa.jp")];
- char stringpool_str2081[sizeof("americanart.museum")];
- char stringpool_str2082[sizeof("kodaira.tokyo.jp")];
- char stringpool_str2083[sizeof("gosen.niigata.jp")];
- char stringpool_str2084[sizeof("orkanger.no")];
- char stringpool_str2085[sizeof("ota.tokyo.jp")];
- char stringpool_str2086[sizeof("tokashiki.okinawa.jp")];
- char stringpool_str2087[sizeof("org.ee")];
- char stringpool_str2088[sizeof("est-a-la-maison.com")];
- char stringpool_str2089[sizeof("oji.nara.jp")];
- char stringpool_str2090[sizeof("ac.be")];
- char stringpool_str2091[sizeof("org.eg")];
- char stringpool_str2092[sizeof("org.es")];
- char stringpool_str2093[sizeof("reggiocalabria.it")];
- char stringpool_str2094[sizeof("kannami.shizuoka.jp")];
- char stringpool_str2095[sizeof("est-a-la-masion.com")];
- char stringpool_str2096[sizeof("org.ec")];
- char stringpool_str2097[sizeof("org.ws")];
- char stringpool_str2098[sizeof("arita.saga.jp")];
- char stringpool_str2099[sizeof("qld.edu.au")];
- char stringpool_str2100[sizeof("operaunite.com")];
- char stringpool_str2101[sizeof("muroto.kochi.jp")];
- char stringpool_str2102[sizeof("kitanakagusuku.okinawa.jp")];
- char stringpool_str2103[sizeof("likes-pie.com")];
- char stringpool_str2104[sizeof("ami.ibaraki.jp")];
- char stringpool_str2105[sizeof("lapy.pl")];
- char stringpool_str2106[sizeof("gushikami.okinawa.jp")];
- char stringpool_str2107[sizeof("no")];
- char stringpool_str2108[sizeof("nu")];
- char stringpool_str2109[sizeof("beskidy.pl")];
- char stringpool_str2110[sizeof("org.ng")];
- char stringpool_str2111[sizeof("oirase.aomori.jp")];
- char stringpool_str2112[sizeof("nz")];
- char stringpool_str2113[sizeof("rebun.hokkaido.jp")];
- char stringpool_str2114[sizeof("meiwa.gunma.jp")];
- char stringpool_str2115[sizeof("nom.tm")];
- char stringpool_str2116[sizeof("org.na")];
- char stringpool_str2117[sizeof("shibata.niigata.jp")];
- char stringpool_str2118[sizeof("nom.ad")];
- char stringpool_str2119[sizeof("nr")];
- char stringpool_str2120[sizeof("no.it")];
- char stringpool_str2121[sizeof("nu.it")];
- char stringpool_str2122[sizeof("nom.ag")];
- char stringpool_str2123[sizeof("showa.gunma.jp")];
- char stringpool_str2124[sizeof("kikuchi.kumamoto.jp")];
- char stringpool_str2125[sizeof("nu.ca")];
- char stringpool_str2126[sizeof("hashikami.aomori.jp")];
- char stringpool_str2127[sizeof("ne")];
- char stringpool_str2128[sizeof("nv.us")];
- char stringpool_str2129[sizeof("nd.us")];
- char stringpool_str2130[sizeof("nm.us")];
- char stringpool_str2131[sizeof("konyvelo.hu")];
- char stringpool_str2132[sizeof("kashihara.nara.jp")];
- char stringpool_str2133[sizeof("buryatia.ru")];
- char stringpool_str2134[sizeof("nt.ca")];
- char stringpool_str2135[sizeof("shikama.miyagi.jp")];
- char stringpool_str2136[sizeof("gifu.jp")];
- char stringpool_str2137[sizeof("elb.amazonaws.com")];
- char stringpool_str2138[sizeof("koganei.tokyo.jp")];
- char stringpool_str2139[sizeof("ns.ca")];
- char stringpool_str2140[sizeof("arida.wakayama.jp")];
- char stringpool_str2141[sizeof("eu.com")];
- char stringpool_str2142[sizeof("ovre-eiker.no")];
- char stringpool_str2143[sizeof("net")];
- char stringpool_str2144[sizeof("ru.com")];
- char stringpool_str2145[sizeof("n.se")];
- char stringpool_str2146[sizeof("nom.co")];
- char stringpool_str2147[sizeof("net.to")];
- char stringpool_str2148[sizeof("net.tm")];
- char stringpool_str2149[sizeof("net.bo")];
- char stringpool_str2150[sizeof("net.bm")];
- char stringpool_str2151[sizeof("org.nr")];
- char stringpool_str2152[sizeof("net.ae")];
- char stringpool_str2153[sizeof("haga.tochigi.jp")];
- char stringpool_str2154[sizeof("gr.com")];
- char stringpool_str2155[sizeof("net.bz")];
- char stringpool_str2156[sizeof("net.ai")];
- char stringpool_str2157[sizeof("net.az")];
- char stringpool_str2158[sizeof("kyowa.hokkaido.jp")];
- char stringpool_str2159[sizeof("ar.com")];
- char stringpool_str2160[sizeof("net.ag")];
- char stringpool_str2161[sizeof("ne.us")];
- char stringpool_str2162[sizeof("os.hedmark.no")];
- char stringpool_str2163[sizeof("ni")];
- char stringpool_str2164[sizeof("net.qa")];
- char stringpool_str2165[sizeof("groks-the.info")];
- char stringpool_str2166[sizeof("net.ba")];
- char stringpool_str2167[sizeof("net.so")];
- char stringpool_str2168[sizeof("net.sd")];
- char stringpool_str2169[sizeof("toshima.tokyo.jp")];
- char stringpool_str2170[sizeof("kchr.ru")];
- char stringpool_str2171[sizeof("nom.br")];
- char stringpool_str2172[sizeof("maritime.museum")];
- char stringpool_str2173[sizeof("net.bs")];
- char stringpool_str2174[sizeof("kikonai.hokkaido.jp")];
- char stringpool_str2175[sizeof("net.sg")];
- char stringpool_str2176[sizeof("kr.com")];
- char stringpool_str2177[sizeof("nj.us")];
- char stringpool_str2178[sizeof("jerusalem.museum")];
- char stringpool_str2179[sizeof("net.ac")];
- char stringpool_str2180[sizeof("rieti.it")];
- char stringpool_str2181[sizeof("net.sa")];
- char stringpool_str2182[sizeof("net.jo")];
- char stringpool_str2183[sizeof("net.je")];
- char stringpool_str2184[sizeof("laquila.it")];
- char stringpool_str2185[sizeof("se.com")];
- char stringpool_str2186[sizeof("takashima.shiga.jp")];
- char stringpool_str2187[sizeof("shobara.hiroshima.jp")];
- char stringpool_str2188[sizeof("net.bb")];
- char stringpool_str2189[sizeof("terni.it")];
- char stringpool_str2190[sizeof("not.br")];
- char stringpool_str2191[sizeof("tempioolbia.it")];
- char stringpool_str2192[sizeof("net.sc")];
- char stringpool_str2193[sizeof("space-to-rent.com")];
- char stringpool_str2194[sizeof("oshu.iwate.jp")];
- char stringpool_str2195[sizeof("omi.nagano.jp")];
- char stringpool_str2196[sizeof("nl")];
- char stringpool_str2197[sizeof("org.af")];
- char stringpool_str2198[sizeof("kanna.gunma.jp")];
- char stringpool_str2199[sizeof("net.sb")];
- char stringpool_str2200[sizeof("ntr.br")];
- char stringpool_str2201[sizeof("net.au")];
- char stringpool_str2202[sizeof("shirataka.yamagata.jp")];
- char stringpool_str2203[sizeof("showa.yamanashi.jp")];
- char stringpool_str2204[sizeof("net.co")];
- char stringpool_str2205[sizeof("na")];
- char stringpool_str2206[sizeof("net.tt")];
- char stringpool_str2207[sizeof("net.ci")];
- char stringpool_str2208[sizeof("net.bt")];
- char stringpool_str2209[sizeof("org.ve")];
- char stringpool_str2210[sizeof("org.vi")];
- char stringpool_str2211[sizeof("nl.ca")];
- char stringpool_str2212[sizeof("co.no")];
- char stringpool_str2213[sizeof("na.it")];
- char stringpool_str2214[sizeof("net.tn")];
- char stringpool_str2215[sizeof("city.kawasaki.jp")];
- char stringpool_str2216[sizeof("net.st")];
- char stringpool_str2217[sizeof("net.br")];
- char stringpool_str2218[sizeof("adygeya.ru")];
- char stringpool_str2219[sizeof("hiranai.aomori.jp")];
- char stringpool_str2220[sizeof("net.an")];
- char stringpool_str2221[sizeof("sellsyourhome.org")];
- char stringpool_str2222[sizeof("n.bg")];
- char stringpool_str2223[sizeof("cn.com")];
- char stringpool_str2224[sizeof("asahikawa.hokkaido.jp")];
- char stringpool_str2225[sizeof("olkusz.pl")];
- char stringpool_str2226[sizeof("org.vc")];
- char stringpool_str2227[sizeof("name")];
- char stringpool_str2228[sizeof("turystyka.pl")];
- char stringpool_str2229[sizeof("codespot.com")];
- char stringpool_str2230[sizeof("ogliastra.it")];
- char stringpool_str2231[sizeof("np")];
- char stringpool_str2232[sizeof("nb.ca")];
- char stringpool_str2233[sizeof("net.al")];
- char stringpool_str2234[sizeof("st.no")];
- char stringpool_str2235[sizeof("corvette.museum")];
- char stringpool_str2236[sizeof("nom.es")];
- char stringpool_str2237[sizeof("net.cu")];
- char stringpool_str2238[sizeof("net.sl")];
- char stringpool_str2239[sizeof("name.mv")];
- char stringpool_str2240[sizeof("name.eg")];
- char stringpool_str2241[sizeof("fukui.jp")];
- char stringpool_str2242[sizeof("or.ci")];
- char stringpool_str2243[sizeof("sa.com")];
- char stringpool_str2244[sizeof("artcenter.museum")];
- char stringpool_str2245[sizeof("tadotsu.kagawa.jp")];
- char stringpool_str2246[sizeof("net.tj")];
- char stringpool_str2247[sizeof("de.com")];
- char stringpool_str2248[sizeof("aogashima.tokyo.jp")];
- char stringpool_str2249[sizeof("org.bh")];
- char stringpool_str2250[sizeof("br.com")];
- char stringpool_str2251[sizeof("abira.hokkaido.jp")];
- char stringpool_str2252[sizeof("gb.com")];
- char stringpool_str2253[sizeof("net.cn")];
- char stringpool_str2254[sizeof("tm.no")];
- char stringpool_str2255[sizeof("hitachiota.ibaraki.jp")];
- char stringpool_str2256[sizeof("mr.no")];
- char stringpool_str2257[sizeof("org.vn")];
- char stringpool_str2258[sizeof("akune.kagoshima.jp")];
- char stringpool_str2259[sizeof("org.sh")];
- char stringpool_str2260[sizeof("kicks-ass.org")];
- char stringpool_str2261[sizeof("taira.toyama.jp")];
- char stringpool_str2262[sizeof("gv.ao")];
- char stringpool_str2263[sizeof("dgca.aero")];
- char stringpool_str2264[sizeof("ed.ao")];
- char stringpool_str2265[sizeof("co.ao")];
- char stringpool_str2266[sizeof("tr.no")];
- char stringpool_str2267[sizeof("groks-this.info")];
- char stringpool_str2268[sizeof("name.mk")];
- char stringpool_str2269[sizeof("fm.no")];
- char stringpool_str2270[sizeof("nh.us")];
- char stringpool_str2271[sizeof("shiraoi.hokkaido.jp")];
- char stringpool_str2272[sizeof("net.eg")];
- char stringpool_str2273[sizeof("taiwa.miyagi.jp")];
- char stringpool_str2274[sizeof("obu.aichi.jp")];
- char stringpool_str2275[sizeof("nat.tn")];
- char stringpool_str2276[sizeof("kawanishi.yamagata.jp")];
- char stringpool_str2277[sizeof("statecouncil.om")];
- char stringpool_str2278[sizeof("nm.cn")];
- char stringpool_str2279[sizeof("eastafrica.museum")];
- char stringpool_str2280[sizeof("nx.cn")];
- char stringpool_str2281[sizeof("tsubata.ishikawa.jp")];
- char stringpool_str2282[sizeof("sor-odal.no")];
- char stringpool_str2283[sizeof("net.ec")];
- char stringpool_str2284[sizeof("recreation.aero")];
- char stringpool_str2285[sizeof("name.tt")];
- char stringpool_str2286[sizeof("ouda.nara.jp")];
- char stringpool_str2287[sizeof("ogi.saga.jp")];
- char stringpool_str2288[sizeof("hiratsuka.kanagawa.jp")];
- char stringpool_str2289[sizeof("aga.niigata.jp")];
- char stringpool_str2290[sizeof("net.ws")];
- char stringpool_str2291[sizeof("al.no")];
- char stringpool_str2292[sizeof("name.tj")];
- char stringpool_str2293[sizeof("rl.no")];
- char stringpool_str2294[sizeof("blogsite.org")];
- char stringpool_str2295[sizeof("bu.no")];
- char stringpool_str2296[sizeof("for-some.biz")];
- char stringpool_str2297[sizeof("tatebayashi.gunma.jp")];
- char stringpool_str2298[sizeof("hakusan.ishikawa.jp")];
- char stringpool_str2299[sizeof("aa.no")];
- char stringpool_str2300[sizeof("ne.tz")];
- char stringpool_str2301[sizeof("legnica.pl")];
- char stringpool_str2302[sizeof("ac.ci")];
- char stringpool_str2303[sizeof("blogspot.cv")];
- char stringpool_str2304[sizeof("chambagri.fr")];
- char stringpool_str2305[sizeof("blogspot.cz")];
- char stringpool_str2306[sizeof("net.ng")];
- char stringpool_str2307[sizeof("dyndns.biz")];
- char stringpool_str2308[sizeof("ne.pw")];
- char stringpool_str2309[sizeof("teshikaga.hokkaido.jp")];
- char stringpool_str2310[sizeof("sande.more-og-romsdal.no")];
- char stringpool_str2311[sizeof("higashiizu.shizuoka.jp")];
- char stringpool_str2312[sizeof("vladikavkaz.ru")];
- char stringpool_str2313[sizeof("ringsaker.no")];
- char stringpool_str2314[sizeof("taiki.mie.jp")];
- char stringpool_str2315[sizeof("kashima.kumamoto.jp")];
- char stringpool_str2316[sizeof("tomisato.chiba.jp")];
- char stringpool_str2317[sizeof("ainan.ehime.jp")];
- char stringpool_str2318[sizeof("dyndns-remote.com")];
- char stringpool_str2319[sizeof("ah.no")];
- char stringpool_str2320[sizeof("omantel.om")];
- char stringpool_str2321[sizeof("kamishihoro.hokkaido.jp")];
- char stringpool_str2322[sizeof("heritage.museum")];
- char stringpool_str2323[sizeof("bremanger.no")];
- char stringpool_str2324[sizeof("akita.akita.jp")];
- char stringpool_str2325[sizeof("name.na")];
- char stringpool_str2326[sizeof("leikanger.no")];
- char stringpool_str2327[sizeof("nnov.ru")];
- char stringpool_str2328[sizeof("satx.museum")];
- char stringpool_str2329[sizeof("net.nr")];
- char stringpool_str2330[sizeof("kashiba.nara.jp")];
- char stringpool_str2331[sizeof("kisosaki.mie.jp")];
- char stringpool_str2332[sizeof("miyoshi.saitama.jp")];
- char stringpool_str2333[sizeof("higashiyoshino.nara.jp")];
- char stringpool_str2334[sizeof("k12.ok.us")];
- char stringpool_str2335[sizeof("haibara.shizuoka.jp")];
- char stringpool_str2336[sizeof("blogspot.com")];
- char stringpool_str2337[sizeof("shirahama.wakayama.jp")];
- char stringpool_str2338[sizeof("stavanger.no")];
- char stringpool_str2339[sizeof("ketrzyn.pl")];
- char stringpool_str2340[sizeof("steinkjer.no")];
- char stringpool_str2341[sizeof("sciencesnaturelles.museum")];
- char stringpool_str2342[sizeof("zgora.pl")];
- char stringpool_str2343[sizeof("samnanger.no")];
- char stringpool_str2344[sizeof("lib.ok.us")];
- char stringpool_str2345[sizeof("hof.no")];
- char stringpool_str2346[sizeof("co.gy")];
- char stringpool_str2347[sizeof("mincom.tn")];
- char stringpool_str2348[sizeof("kanra.gunma.jp")];
- char stringpool_str2349[sizeof("net.af")];
- char stringpool_str2350[sizeof("monmouth.museum")];
- char stringpool_str2351[sizeof("higashinaruse.akita.jp")];
- char stringpool_str2352[sizeof("akkeshi.hokkaido.jp")];
- char stringpool_str2353[sizeof("blogspot.ca")];
- char stringpool_str2354[sizeof("net.ve")];
- char stringpool_str2355[sizeof("saves-the-whales.com")];
- char stringpool_str2356[sizeof("gobiernoelectronico.ar")];
- char stringpool_str2357[sizeof("koshimizu.hokkaido.jp")];
- char stringpool_str2358[sizeof("kautokeino.no")];
- char stringpool_str2359[sizeof("net.vi")];
- char stringpool_str2360[sizeof("nsw.au")];
- char stringpool_str2361[sizeof("va.no")];
- char stringpool_str2362[sizeof("higashiizumo.shimane.jp")];
- char stringpool_str2363[sizeof("shimizu.hokkaido.jp")];
- char stringpool_str2364[sizeof("sakae.nagano.jp")];
- char stringpool_str2365[sizeof("akagi.shimane.jp")];
- char stringpool_str2366[sizeof("nome.pt")];
- char stringpool_str2367[sizeof("ggf.br")];
- char stringpool_str2368[sizeof("omaezaki.shizuoka.jp")];
- char stringpool_str2369[sizeof("hu.com")];
- char stringpool_str2370[sizeof("kawachinagano.osaka.jp")];
- char stringpool_str2371[sizeof("database.museum")];
- char stringpool_str2372[sizeof("net.vc")];
- char stringpool_str2373[sizeof("medizinhistorisches.museum")];
- char stringpool_str2374[sizeof("k12.or.us")];
- char stringpool_str2375[sizeof("from-mn.com")];
- char stringpool_str2376[sizeof("from-mt.com")];
- char stringpool_str2377[sizeof("from-de.com")];
- char stringpool_str2378[sizeof("from-or.com")];
- char stringpool_str2379[sizeof("from-in.com")];
- char stringpool_str2380[sizeof("sch.id")];
- char stringpool_str2381[sizeof("gratangen.no")];
- char stringpool_str2382[sizeof("skiptvet.no")];
- char stringpool_str2383[sizeof("blogspot.com.es")];
- char stringpool_str2384[sizeof("ny.us")];
- char stringpool_str2385[sizeof("niepce.museum")];
- char stringpool_str2386[sizeof("naumburg.museum")];
- char stringpool_str2387[sizeof("haebaru.okinawa.jp")];
- char stringpool_str2388[sizeof("from-ar.com")];
- char stringpool_str2389[sizeof("nes.akershus.no")];
- char stringpool_str2390[sizeof("manx.museum")];
- char stringpool_str2391[sizeof("blogspot.ch")];
- char stringpool_str2392[sizeof("oyer.no")];
- char stringpool_str2393[sizeof("lib.or.us")];
- char stringpool_str2394[sizeof("kyotanabe.kyoto.jp")];
- char stringpool_str2395[sizeof("from-ct.com")];
- char stringpool_str2396[sizeof("nara.jp")];
- char stringpool_str2397[sizeof("from-il.com")];
- char stringpool_str2398[sizeof("tenei.fukushima.jp")];
- char stringpool_str2399[sizeof("shimizu.shizuoka.jp")];
- char stringpool_str2400[sizeof("kyowa.akita.jp")];
- char stringpool_str2401[sizeof("kvanangen.no")];
- char stringpool_str2402[sizeof("from-ok.com")];
- char stringpool_str2403[sizeof("bizen.okayama.jp")];
- char stringpool_str2404[sizeof("from-al.com")];
- char stringpool_str2405[sizeof("net.th")];
- char stringpool_str2406[sizeof("delaware.museum")];
- char stringpool_str2407[sizeof("net.bh")];
- char stringpool_str2408[sizeof("city.sapporo.jp")];
- char stringpool_str2409[sizeof("shiriuchi.hokkaido.jp")];
- char stringpool_str2410[sizeof("oyamazaki.kyoto.jp")];
- char stringpool_str2411[sizeof("tm.ro")];
- char stringpool_str2412[sizeof("volgograd.ru")];
- char stringpool_str2413[sizeof("chukotka.ru")];
- char stringpool_str2414[sizeof("from-ak.com")];
- char stringpool_str2415[sizeof("net.vn")];
- char stringpool_str2416[sizeof("from-ut.com")];
- char stringpool_str2417[sizeof("net.sh")];
- char stringpool_str2418[sizeof("london.museum")];
- char stringpool_str2419[sizeof("hizen.saga.jp")];
- char stringpool_str2420[sizeof("knowsitall.info")];
- char stringpool_str2421[sizeof("k12.wv.us")];
- char stringpool_str2422[sizeof("air-surveillance.aero")];
- char stringpool_str2423[sizeof("miyoshi.tokushima.jp")];
- char stringpool_str2424[sizeof("from-tx.com")];
- char stringpool_str2425[sizeof("from-tn.com")];
- char stringpool_str2426[sizeof("hyuga.miyazaki.jp")];
- char stringpool_str2427[sizeof("zagan.pl")];
- char stringpool_str2428[sizeof("toyota.aichi.jp")];
- char stringpool_str2429[sizeof("blogspot.com.au")];
- char stringpool_str2430[sizeof("sabae.fukui.jp")];
- char stringpool_str2431[sizeof("togitsu.nagasaki.jp")];
- char stringpool_str2432[sizeof("campobasso.it")];
- char stringpool_str2433[sizeof("laakesvuemie.no")];
- char stringpool_str2434[sizeof("kamitsue.oita.jp")];
- char stringpool_str2435[sizeof("shika.ishikawa.jp")];
- char stringpool_str2436[sizeof("suita.osaka.jp")];
- char stringpool_str2437[sizeof("from-nv.com")];
- char stringpool_str2438[sizeof("from-nm.com")];
- char stringpool_str2439[sizeof("lib.wv.us")];
- char stringpool_str2440[sizeof("from-ne.com")];
- char stringpool_str2441[sizeof("nittedal.no")];
- char stringpool_str2442[sizeof("blogspot.com.ar")];
- char stringpool_str2443[sizeof("sch.ir")];
- char stringpool_str2444[sizeof("hm.no")];
- char stringpool_str2445[sizeof("from-ma.com")];
- char stringpool_str2446[sizeof("fukuchiyama.kyoto.jp")];
- char stringpool_str2447[sizeof("from-ia.com")];
- char stringpool_str2448[sizeof("higashikurume.tokyo.jp")];
- char stringpool_str2449[sizeof("from-ga.com")];
- char stringpool_str2450[sizeof("from-nj.com")];
- char stringpool_str2451[sizeof("forgot.her.name")];
- char stringpool_str2452[sizeof("lindesnes.no")];
- char stringpool_str2453[sizeof("okuizumo.shimane.jp")];
- char stringpool_str2454[sizeof("saiki.oita.jp")];
- char stringpool_str2455[sizeof("asahi.mie.jp")];
- char stringpool_str2456[sizeof("blogspot.com.br")];
- char stringpool_str2457[sizeof("higashiyamato.tokyo.jp")];
- char stringpool_str2458[sizeof("higashisumiyoshi.osaka.jp")];
- char stringpool_str2459[sizeof("folkebibl.no")];
- char stringpool_str2460[sizeof("k12.nv.us")];
- char stringpool_str2461[sizeof("chocolate.museum")];
- char stringpool_str2462[sizeof("shiwa.iwate.jp")];
- char stringpool_str2463[sizeof("from-ca.com")];
- char stringpool_str2464[sizeof("boston.museum")];
- char stringpool_str2465[sizeof("sanda.hyogo.jp")];
- char stringpool_str2466[sizeof("flatanger.no")];
- char stringpool_str2467[sizeof("from-md.com")];
- char stringpool_str2468[sizeof("from-id.com")];
- char stringpool_str2469[sizeof("nes.buskerud.no")];
- char stringpool_str2470[sizeof("ng")];
- char stringpool_str2471[sizeof("elvendrell.museum")];
- char stringpool_str2472[sizeof("scienceandindustry.museum")];
- char stringpool_str2473[sizeof("name.my")];
- char stringpool_str2474[sizeof("lib.nv.us")];
- char stringpool_str2475[sizeof("name.pr")];
- char stringpool_str2476[sizeof("from-ms.com")];
- char stringpool_str2477[sizeof("kyuragi.saga.jp")];
- char stringpool_str2478[sizeof("from-ks.com")];
- char stringpool_str2479[sizeof("artgallery.museum")];
- char stringpool_str2480[sizeof("onna.okinawa.jp")];
- char stringpool_str2481[sizeof("from-sd.com")];
- char stringpool_str2482[sizeof("sciencehistory.museum")];
- char stringpool_str2483[sizeof("tv.bo")];
- char stringpool_str2484[sizeof("sakawa.kochi.jp")];
- char stringpool_str2485[sizeof("shibata.miyagi.jp")];
- char stringpool_str2486[sizeof("nore-og-uvdal.no")];
- char stringpool_str2487[sizeof("ebina.kanagawa.jp")];
- char stringpool_str2488[sizeof("szex.hu")];
- char stringpool_str2489[sizeof("act.edu.au")];
- char stringpool_str2490[sizeof("dyndns-ip.com")];
- char stringpool_str2491[sizeof("oshino.yamanashi.jp")];
- char stringpool_str2492[sizeof("atami.shizuoka.jp")];
- char stringpool_str2493[sizeof("otsu.shiga.jp")];
- char stringpool_str2494[sizeof("cc.mt.us")];
- char stringpool_str2495[sizeof("forgot.his.name")];
- char stringpool_str2496[sizeof("cc.ga.us")];
- char stringpool_str2497[sizeof("cc.ma.us")];
- char stringpool_str2498[sizeof("kiyosu.aichi.jp")];
- char stringpool_str2499[sizeof("name.hr")];
- char stringpool_str2500[sizeof("edogawa.tokyo.jp")];
- char stringpool_str2501[sizeof("cc.ia.us")];
- char stringpool_str2502[sizeof("mashike.hokkaido.jp")];
- char stringpool_str2503[sizeof("cc.ct.us")];
- char stringpool_str2504[sizeof("net.nf")];
- char stringpool_str2505[sizeof("from-oh.com")];
- char stringpool_str2506[sizeof("cc.ca.us")];
- char stringpool_str2507[sizeof("cc.ms.us")];
- char stringpool_str2508[sizeof("cc.ut.us")];
- char stringpool_str2509[sizeof("sumita.iwate.jp")];
- char stringpool_str2510[sizeof("cc.ks.us")];
- char stringpool_str2511[sizeof("oiso.kanagawa.jp")];
- char stringpool_str2512[sizeof("jefferson.museum")];
- char stringpool_str2513[sizeof("katowice.pl")];
- char stringpool_str2514[sizeof("funabashi.chiba.jp")];
- char stringpool_str2515[sizeof("cartoonart.museum")];
- char stringpool_str2516[sizeof("froya.no")];
- char stringpool_str2517[sizeof("qc.ca")];
- char stringpool_str2518[sizeof("from-dc.com")];
- char stringpool_str2519[sizeof("oita.oita.jp")];
- char stringpool_str2520[sizeof("from-nd.com")];
- char stringpool_str2521[sizeof("hl.no")];
- char stringpool_str2522[sizeof("name.jo")];
- char stringpool_str2523[sizeof("shunan.yamaguchi.jp")];
- char stringpool_str2524[sizeof("tenri.nara.jp")];
- char stringpool_str2525[sizeof("tabuse.yamaguchi.jp")];
- char stringpool_str2526[sizeof("shiki.saitama.jp")];
- char stringpool_str2527[sizeof("from-sc.com")];
- char stringpool_str2528[sizeof("or.bi")];
- char stringpool_str2529[sizeof("cc.wa.us")];
- char stringpool_str2530[sizeof("ha.no")];
- char stringpool_str2531[sizeof("kosai.shizuoka.jp")];
- char stringpool_str2532[sizeof("sakaiminato.tottori.jp")];
- char stringpool_str2533[sizeof("cc.vt.us")];
- char stringpool_str2534[sizeof("orsta.no")];
- char stringpool_str2535[sizeof("city.sendai.jp")];
- char stringpool_str2536[sizeof("koori.fukushima.jp")];
- char stringpool_str2537[sizeof("cc.va.us")];
- char stringpool_str2538[sizeof("ookuwa.nagano.jp")];
- char stringpool_str2539[sizeof("olawa.pl")];
- char stringpool_str2540[sizeof("cc.tx.us")];
- char stringpool_str2541[sizeof("komae.tokyo.jp")];
- char stringpool_str2542[sizeof("cc.pa.us")];
- char stringpool_str2543[sizeof("countryestate.museum")];
- char stringpool_str2544[sizeof("kushimoto.wakayama.jp")];
- char stringpool_str2545[sizeof("hayashima.okayama.jp")];
- char stringpool_str2546[sizeof("mishima.shizuoka.jp")];
- char stringpool_str2547[sizeof("gobo.wakayama.jp")];
- char stringpool_str2548[sizeof("from-nh.com")];
- char stringpool_str2549[sizeof("cc.dc.us")];
- char stringpool_str2550[sizeof("skedsmokorset.no")];
- char stringpool_str2551[sizeof("harvestcelebration.museum")];
- char stringpool_str2552[sizeof("author.aero")];
- char stringpool_str2553[sizeof("hammerfest.no")];
- char stringpool_str2554[sizeof("naples.it")];
- char stringpool_str2555[sizeof("kagoshima.kagoshima.jp")];
- char stringpool_str2556[sizeof("from-nc.com")];
- char stringpool_str2557[sizeof("tado.mie.jp")];
- char stringpool_str2558[sizeof("toyone.aichi.jp")];
- char stringpool_str2559[sizeof("scienceandhistory.museum")];
- char stringpool_str2560[sizeof("kawai.nara.jp")];
- char stringpool_str2561[sizeof("cc.nj.us")];
- char stringpool_str2562[sizeof("cc.la.us")];
- char stringpool_str2563[sizeof("hitachiomiya.ibaraki.jp")];
- char stringpool_str2564[sizeof("ballangen.no")];
- char stringpool_str2565[sizeof("koza.wakayama.jp")];
- char stringpool_str2566[sizeof("miyoshi.hiroshima.jp")];
- char stringpool_str2567[sizeof("org.im")];
- char stringpool_str2568[sizeof("kashima.ibaraki.jp")];
- char stringpool_str2569[sizeof("mashiki.kumamoto.jp")];
- char stringpool_str2570[sizeof("cc.me.us")];
- char stringpool_str2571[sizeof("arakawa.tokyo.jp")];
- char stringpool_str2572[sizeof("cc.nc.us")];
- char stringpool_str2573[sizeof("org.is")];
- char stringpool_str2574[sizeof("noheji.aomori.jp")];
- char stringpool_str2575[sizeof("notteroy.no")];
- char stringpool_str2576[sizeof("toyota.yamaguchi.jp")];
- char stringpool_str2577[sizeof("oumu.hokkaido.jp")];
- char stringpool_str2578[sizeof("higashimurayama.tokyo.jp")];
- char stringpool_str2579[sizeof("from-mo.com")];
- char stringpool_str2580[sizeof("miura.kanagawa.jp")];
- char stringpool_str2581[sizeof("dlugoleka.pl")];
- char stringpool_str2582[sizeof("cc.as.us")];
- char stringpool_str2583[sizeof("k12.oh.us")];
- char stringpool_str2584[sizeof("cc.de.us")];
- char stringpool_str2585[sizeof("mifune.kumamoto.jp")];
- char stringpool_str2586[sizeof("higashiosaka.osaka.jp")];
- char stringpool_str2587[sizeof("belgorod.ru")];
- char stringpool_str2588[sizeof("stryn.no")];
- char stringpool_str2589[sizeof("blogspot.fr")];
- char stringpool_str2590[sizeof("azumino.nagano.jp")];
- char stringpool_str2591[sizeof("ayabe.kyoto.jp")];
- char stringpool_str2592[sizeof("hitachi.ibaraki.jp")];
- char stringpool_str2593[sizeof("vic.edu.au")];
- char stringpool_str2594[sizeof("tonosho.kagawa.jp")];
- char stringpool_str2595[sizeof("from-fl.com")];
- char stringpool_str2596[sizeof("langevag.no")];
- char stringpool_str2597[sizeof("kiho.mie.jp")];
- char stringpool_str2598[sizeof("dyndns-at-home.com")];
- char stringpool_str2599[sizeof("betainabox.com")];
- char stringpool_str2600[sizeof("lib.oh.us")];
- char stringpool_str2601[sizeof("at-band-camp.net")];
- char stringpool_str2602[sizeof("anamizu.ishikawa.jp")];
- char stringpool_str2603[sizeof("cc.mn.us")];
- char stringpool_str2604[sizeof("bielawa.pl")];
- char stringpool_str2605[sizeof("org.ir")];
- char stringpool_str2606[sizeof("org.in")];
- char stringpool_str2607[sizeof("cc.in.us")];
- char stringpool_str2608[sizeof("sakae.chiba.jp")];
- char stringpool_str2609[sizeof("taiki.hokkaido.jp")];
- char stringpool_str2610[sizeof("opole.pl")];
- char stringpool_str2611[sizeof("sells-for-u.com")];
- char stringpool_str2612[sizeof("berlevag.no")];
- char stringpool_str2613[sizeof("kashima.saga.jp")];
- char stringpool_str2614[sizeof("from-ky.com")];
- char stringpool_str2615[sizeof("from-pr.com")];
- char stringpool_str2616[sizeof("dyndns.info")];
- char stringpool_str2617[sizeof("joboji.iwate.jp")];
- char stringpool_str2618[sizeof("kushiro.hokkaido.jp")];
- char stringpool_str2619[sizeof("vicenza.it")];
- char stringpool_str2620[sizeof("cc.ne.us")];
- char stringpool_str2621[sizeof("nebraska.museum")];
- char stringpool_str2622[sizeof("noda.iwate.jp")];
- char stringpool_str2623[sizeof("midatlantic.museum")];
- char stringpool_str2624[sizeof("olbiatempio.it")];
- char stringpool_str2625[sizeof("blogspot.fi")];
- char stringpool_str2626[sizeof("nord-odal.no")];
- char stringpool_str2627[sizeof("medecin.fr")];
- char stringpool_str2628[sizeof("numata.gunma.jp")];
- char stringpool_str2629[sizeof("amami.kagoshima.jp")];
- char stringpool_str2630[sizeof("okutama.tokyo.jp")];
- char stringpool_str2631[sizeof("kushima.miyazaki.jp")];
- char stringpool_str2632[sizeof("bungoono.oita.jp")];
- char stringpool_str2633[sizeof("higashiomi.shiga.jp")];
- char stringpool_str2634[sizeof("cc.tn.us")];
- char stringpool_str2635[sizeof("mecon.ar")];
- char stringpool_str2636[sizeof("ryugasaki.ibaraki.jp")];
- char stringpool_str2637[sizeof("toba.mie.jp")];
- char stringpool_str2638[sizeof("etajima.hiroshima.jp")];
- char stringpool_str2639[sizeof("michigan.museum")];
- char stringpool_str2640[sizeof("florence.it")];
- char stringpool_str2641[sizeof("higashiyodogawa.osaka.jp")];
- char stringpool_str2642[sizeof("taki.mie.jp")];
- char stringpool_str2643[sizeof("nannestad.no")];
- char stringpool_str2644[sizeof("ozu.ehime.jp")];
- char stringpool_str2645[sizeof("from-pa.com")];
- char stringpool_str2646[sizeof("gov.hk")];
- char stringpool_str2647[sizeof("medical.museum")];
- char stringpool_str2648[sizeof("edu.hk")];
- char stringpool_str2649[sizeof("com.hk")];
- char stringpool_str2650[sizeof("hammarfeasta.no")];
- char stringpool_str2651[sizeof("homebuilt.aero")];
- char stringpool_str2652[sizeof("selfip.biz")];
- char stringpool_str2653[sizeof("from-mi.com")];
- char stringpool_str2654[sizeof("cc.az.us")];
- char stringpool_str2655[sizeof("yt")];
- char stringpool_str2656[sizeof("kanonji.kagawa.jp")];
- char stringpool_str2657[sizeof("mediocampidano.it")];
- char stringpool_str2658[sizeof("ye")];
- char stringpool_str2659[sizeof("rokunohe.aomori.jp")];
- char stringpool_str2660[sizeof("schoenbrunn.museum")];
- char stringpool_str2661[sizeof("jamison.museum")];
- char stringpool_str2662[sizeof("mallorca.museum")];
- char stringpool_str2663[sizeof("tenkawa.nara.jp")];
- char stringpool_str2664[sizeof("io")];
- char stringpool_str2665[sizeof("id")];
- char stringpool_str2666[sizeof("im")];
- char stringpool_str2667[sizeof("marketplace.aero")];
- char stringpool_str2668[sizeof("chihayaakasaka.osaka.jp")];
- char stringpool_str2669[sizeof("higashihiroshima.hiroshima.jp")];
- char stringpool_str2670[sizeof("tamba.hyogo.jp")];
- char stringpool_str2671[sizeof("co.st")];
- char stringpool_str2672[sizeof("ir")];
- char stringpool_str2673[sizeof("y.se")];
- char stringpool_str2674[sizeof("edu.ht")];
- char stringpool_str2675[sizeof("im.it")];
- char stringpool_str2676[sizeof("dellogliastra.it")];
- char stringpool_str2677[sizeof("com.ht")];
- char stringpool_str2678[sizeof("kanan.osaka.jp")];
- char stringpool_str2679[sizeof("narita.chiba.jp")];
- char stringpool_str2680[sizeof("it")];
- char stringpool_str2681[sizeof("archaeological.museum")];
- char stringpool_str2682[sizeof("goshiki.hyogo.jp")];
- char stringpool_str2683[sizeof("dyn-o-saur.com")];
- char stringpool_str2684[sizeof("edu.hn")];
- char stringpool_str2685[sizeof("austevoll.no")];
- char stringpool_str2686[sizeof("go.th")];
- char stringpool_str2687[sizeof("is")];
- char stringpool_str2688[sizeof("tokoname.aichi.jp")];
- char stringpool_str2689[sizeof("com.hr")];
- char stringpool_str2690[sizeof("com.hn")];
- char stringpool_str2691[sizeof("co.th")];
- char stringpool_str2692[sizeof("ie")];
- char stringpool_str2693[sizeof("city.kitakyushu.jp")];
- char stringpool_str2694[sizeof("from-ri.com")];
- char stringpool_str2695[sizeof("omaha.museum")];
- char stringpool_str2696[sizeof("id.us")];
- char stringpool_str2697[sizeof("maintenance.aero")];
- char stringpool_str2698[sizeof("cc.wv.us")];
- char stringpool_str2699[sizeof("aizubange.fukushima.jp")];
- char stringpool_str2700[sizeof("is.it")];
- char stringpool_str2701[sizeof("bergbau.museum")];
- char stringpool_str2702[sizeof("fribourg.museum")];
- char stringpool_str2703[sizeof("sex.hu")];
- char stringpool_str2704[sizeof("akabira.hokkaido.jp")];
- char stringpool_str2705[sizeof("clinton.museum")];
- char stringpool_str2706[sizeof("asahi.toyama.jp")];
- char stringpool_str2707[sizeof("art.ht")];
- char stringpool_str2708[sizeof("nomi.ishikawa.jp")];
- char stringpool_str2709[sizeof("tsukiyono.gunma.jp")];
- char stringpool_str2710[sizeof("i.se")];
- char stringpool_str2711[sizeof("osaka.jp")];
- char stringpool_str2712[sizeof("lucca.it")];
- char stringpool_str2713[sizeof("vibovalentia.it")];
- char stringpool_str2714[sizeof("net.im")];
- char stringpool_str2715[sizeof("net.id")];
- char stringpool_str2716[sizeof("noto.ishikawa.jp")];
- char stringpool_str2717[sizeof("konan.shiga.jp")];
- char stringpool_str2718[sizeof("botanicgarden.museum")];
- char stringpool_str2719[sizeof("naruto.tokushima.jp")];
- char stringpool_str2720[sizeof("oga.akita.jp")];
- char stringpool_str2721[sizeof("nose.osaka.jp")];
- char stringpool_str2722[sizeof("in")];
- char stringpool_str2723[sizeof("net.is")];
- char stringpool_str2724[sizeof("cc.nv.us")];
- char stringpool_str2725[sizeof("arakawa.saitama.jp")];
- char stringpool_str2726[sizeof("coldwar.museum")];
- char stringpool_str2727[sizeof("birdart.museum")];
- char stringpool_str2728[sizeof("boleslawiec.pl")];
- char stringpool_str2729[sizeof("y.bg")];
- char stringpool_str2730[sizeof("nysa.pl")];
- char stringpool_str2731[sizeof("denmark.museum")];
- char stringpool_str2732[sizeof("asso.dz")];
- char stringpool_str2733[sizeof("rishiri.hokkaido.jp")];
- char stringpool_str2734[sizeof("med.ht")];
- char stringpool_str2735[sizeof("bibai.hokkaido.jp")];
- char stringpool_str2736[sizeof("nawras.om")];
- char stringpool_str2737[sizeof("tsuyama.okayama.jp")];
- char stringpool_str2738[sizeof("il")];
- char stringpool_str2739[sizeof("fineart.museum")];
- char stringpool_str2740[sizeof("int")];
- char stringpool_str2741[sizeof("s3-website-us-east-1.amazonaws.com")];
- char stringpool_str2742[sizeof("in.ua")];
- char stringpool_str2743[sizeof("hagi.yamaguchi.jp")];
- char stringpool_str2744[sizeof("int.bo")];
- char stringpool_str2745[sizeof("gangaviika.no")];
- char stringpool_str2746[sizeof("noda.chiba.jp")];
- char stringpool_str2747[sizeof("int.az")];
- char stringpool_str2748[sizeof("nord-fron.no")];
- char stringpool_str2749[sizeof("store.bb")];
- char stringpool_str2750[sizeof("in.us")];
- char stringpool_str2751[sizeof("ohtawara.tochigi.jp")];
- char stringpool_str2752[sizeof("magazine.aero")];
- char stringpool_str2753[sizeof("volyn.ua")];
- char stringpool_str2754[sizeof("idrett.no")];
- char stringpool_str2755[sizeof("vibo-valentia.it")];
- char stringpool_str2756[sizeof("frosta.no")];
- char stringpool_str2757[sizeof("org.sy")];
- char stringpool_str2758[sizeof("convent.museum")];
- char stringpool_str2759[sizeof("hamatonbetsu.hokkaido.jp")];
- char stringpool_str2760[sizeof("opoczno.pl")];
- char stringpool_str2761[sizeof("net.ir")];
- char stringpool_str2762[sizeof("net.in")];
- char stringpool_str2763[sizeof("i.bg")];
- char stringpool_str2764[sizeof("muosat.no")];
- char stringpool_str2765[sizeof("otoineppu.hokkaido.jp")];
- char stringpool_str2766[sizeof("il.us")];
- char stringpool_str2767[sizeof("dyndns-at-work.com")];
- char stringpool_str2768[sizeof("yk.ca")];
- char stringpool_str2769[sizeof("artanddesign.museum")];
- char stringpool_str2770[sizeof("kiwa.mie.jp")];
- char stringpool_str2771[sizeof("york.museum")];
- char stringpool_str2772[sizeof("ostre-toten.no")];
- char stringpool_str2773[sizeof("mi.th")];
- char stringpool_str2774[sizeof("co.sz")];
- char stringpool_str2775[sizeof("ia.us")];
- char stringpool_str2776[sizeof("ind.tn")];
- char stringpool_str2777[sizeof("rel.ht")];
- char stringpool_str2778[sizeof("ind.br")];
- char stringpool_str2779[sizeof("gob.hn")];
- char stringpool_str2780[sizeof("numata.hokkaido.jp")];
- char stringpool_str2781[sizeof("int.co")];
- char stringpool_str2782[sizeof("komforb.se")];
- char stringpool_str2783[sizeof("int.tt")];
- char stringpool_str2784[sizeof("int.ci")];
- char stringpool_str2785[sizeof("medio-campidano.it")];
- char stringpool_str2786[sizeof("nativeamerican.museum")];
- char stringpool_str2787[sizeof("higashimatsuyama.saitama.jp")];
- char stringpool_str2788[sizeof("koya.wakayama.jp")];
- char stringpool_str2789[sizeof("za.com")];
- char stringpool_str2790[sizeof("onga.fukuoka.jp")];
- char stringpool_str2791[sizeof("in.na")];
- char stringpool_str2792[sizeof("fukui.fukui.jp")];
- char stringpool_str2793[sizeof("media.aero")];
- char stringpool_str2794[sizeof("theater.museum")];
- char stringpool_str2795[sizeof("logistics.aero")];
- char stringpool_str2796[sizeof("hashimoto.wakayama.jp")];
- char stringpool_str2797[sizeof("achi.nagano.jp")];
- char stringpool_str2798[sizeof("jobs")];
- char stringpool_str2799[sizeof("ws")];
- char stringpool_str2800[sizeof("defense.tn")];
- char stringpool_str2801[sizeof("tm.se")];
- char stringpool_str2802[sizeof("sande.xn--mre-og-romsdal-qqb.no")];
- char stringpool_str2803[sizeof("imb.br")];
- char stringpool_str2804[sizeof("saotome.st")];
- char stringpool_str2805[sizeof("wv.us")];
- char stringpool_str2806[sizeof("arts.nf")];
- char stringpool_str2807[sizeof("s3-website-sa-east-1.amazonaws.com")];
- char stringpool_str2808[sizeof("crotone.it")];
- char stringpool_str2809[sizeof("lebtimnetz.de")];
- char stringpool_str2810[sizeof("nara.nara.jp")];
- char stringpool_str2811[sizeof("arts.museum")];
- char stringpool_str2812[sizeof("dyndns-home.com")];
- char stringpool_str2813[sizeof("hioki.kagoshima.jp")];
- char stringpool_str2814[sizeof("omuta.fukuoka.jp")];
- char stringpool_str2815[sizeof("narvik.no")];
- char stringpool_str2816[sizeof("int.tj")];
- char stringpool_str2817[sizeof("aguni.okinawa.jp")];
- char stringpool_str2818[sizeof("village.museum")];
- char stringpool_str2819[sizeof("nagasaki.jp")];
- char stringpool_str2820[sizeof("lecce.it")];
- char stringpool_str2821[sizeof("hoylandet.no")];
- char stringpool_str2822[sizeof("w.se")];
- char stringpool_str2823[sizeof("sibenik.museum")];
- char stringpool_str2824[sizeof("higashine.yamagata.jp")];
- char stringpool_str2825[sizeof("hitachinaka.ibaraki.jp")];
- char stringpool_str2826[sizeof("yn.cn")];
- char stringpool_str2827[sizeof("com.fr")];
- char stringpool_str2828[sizeof("mil.hn")];
- char stringpool_str2829[sizeof("sorfold.no")];
- char stringpool_str2830[sizeof("cremona.it")];
- char stringpool_str2831[sizeof("sagae.yamagata.jp")];
- char stringpool_str2832[sizeof("shari.hokkaido.jp")];
- char stringpool_str2833[sizeof("fujishiro.ibaraki.jp")];
- char stringpool_str2834[sizeof("axis.museum")];
- char stringpool_str2835[sizeof("bd.se")];
- char stringpool_str2836[sizeof("asahi.nagano.jp")];
- char stringpool_str2837[sizeof("mobi.tz")];
- char stringpool_str2838[sizeof("ternopil.ua")];
- char stringpool_str2839[sizeof("blogspot.co.nz")];
- char stringpool_str2840[sizeof("akrehamn.no")];
- char stringpool_str2841[sizeof("novosibirsk.ru")];
- char stringpool_str2842[sizeof("brussels.museum")];
- char stringpool_str2843[sizeof("kids.museum")];
- char stringpool_str2844[sizeof("numazu.shizuoka.jp")];
- char stringpool_str2845[sizeof("suisse.museum")];
- char stringpool_str2846[sizeof("stjohn.museum")];
- char stringpool_str2847[sizeof("kids.us")];
- char stringpool_str2848[sizeof("lib.hi.us")];
- char stringpool_str2849[sizeof("iron.museum")];
- char stringpool_str2850[sizeof("go.dyndns.org")];
- char stringpool_str2851[sizeof("jobs.tt")];
- char stringpool_str2852[sizeof("wi.us")];
- char stringpool_str2853[sizeof("toyoake.aichi.jp")];
- char stringpool_str2854[sizeof("s3-website-us-west-1.amazonaws.com")];
- char stringpool_str2855[sizeof("grosseto.it")];
- char stringpool_str2856[sizeof("shimoichi.nara.jp")];
- char stringpool_str2857[sizeof("dyndns-work.com")];
- char stringpool_str2858[sizeof("hirono.iwate.jp")];
- char stringpool_str2859[sizeof("finland.museum")];
- char stringpool_str2860[sizeof("intl.tn")];
- char stringpool_str2861[sizeof("shitara.aichi.jp")];
- char stringpool_str2862[sizeof("ws.na")];
- char stringpool_str2863[sizeof("shinshiro.aichi.jp")];
- char stringpool_str2864[sizeof("campidano-medio.it")];
- char stringpool_str2865[sizeof("farmers.museum")];
- char stringpool_str2866[sizeof("kalmykia.ru")];
- char stringpool_str2867[sizeof("iraq.museum")];
- char stringpool_str2868[sizeof("w.bg")];
- char stringpool_str2869[sizeof("artdeco.museum")];
- char stringpool_str2870[sizeof("doshi.yamanashi.jp")];
- char stringpool_str2871[sizeof("technology.museum")];
- char stringpool_str2872[sizeof("blogspot.co.at")];
- char stringpool_str2873[sizeof("aizuwakamatsu.fukushima.jp")];
- char stringpool_str2874[sizeof("motoyama.kochi.jp")];
- char stringpool_str2875[sizeof("city.nagoya.jp")];
- char stringpool_str2876[sizeof("wa.us")];
- char stringpool_str2877[sizeof("tateyama.toyama.jp")];
- char stringpool_str2878[sizeof("oi.kanagawa.jp")];
- char stringpool_str2879[sizeof("naka.ibaraki.jp")];
- char stringpool_str2880[sizeof("osakasayama.osaka.jp")];
- char stringpool_str2881[sizeof("tobishima.aichi.jp")];
- char stringpool_str2882[sizeof("motosu.gifu.jp")];
- char stringpool_str2883[sizeof("eidsberg.no")];
- char stringpool_str2884[sizeof("vinnytsia.ua")];
- char stringpool_str2885[sizeof("indian.museum")];
- char stringpool_str2886[sizeof("chicago.museum")];
- char stringpool_str2887[sizeof("from-hi.com")];
- char stringpool_str2888[sizeof("omitama.ibaraki.jp")];
- char stringpool_str2889[sizeof("blogspot.co.uk")];
- char stringpool_str2890[sizeof("santafe.museum")];
- char stringpool_str2891[sizeof("moroyama.saitama.jp")];
- char stringpool_str2892[sizeof("blogspot.co.il")];
- char stringpool_str2893[sizeof("kamchatka.ru")];
- char stringpool_str2894[sizeof("kutno.pl")];
- char stringpool_str2895[sizeof("nantan.kyoto.jp")];
- char stringpool_str2896[sizeof("sakai.fukui.jp")];
- char stringpool_str2897[sizeof("honai.ehime.jp")];
- char stringpool_str2898[sizeof("otama.fukushima.jp")];
- char stringpool_str2899[sizeof("higashi.okinawa.jp")];
- char stringpool_str2900[sizeof("handson.museum")];
- char stringpool_str2901[sizeof("nuernberg.museum")];
- char stringpool_str2902[sizeof("fh.se")];
- char stringpool_str2903[sizeof("arts.co")];
- char stringpool_str2904[sizeof("songfest.om")];
- char stringpool_str2905[sizeof("atlanta.museum")];
- char stringpool_str2906[sizeof("net.sy")];
- char stringpool_str2907[sizeof("ip6.arpa")];
- char stringpool_str2908[sizeof("web.co")];
- char stringpool_str2909[sizeof("higashikagura.hokkaido.jp")];
- char stringpool_str2910[sizeof("seihi.nagasaki.jp")];
- char stringpool_str2911[sizeof("glas.museum")];
- char stringpool_str2912[sizeof("horonobe.hokkaido.jp")];
- char stringpool_str2913[sizeof("tonsberg.no")];
- char stringpool_str2914[sizeof("okuma.fukushima.jp")];
- char stringpool_str2915[sizeof("grajewo.pl")];
- char stringpool_str2916[sizeof("higashiyama.kyoto.jp")];
- char stringpool_str2917[sizeof("niigata.jp")];
- char stringpool_str2918[sizeof("bialystok.pl")];
- char stringpool_str2919[sizeof("askvoll.no")];
- char stringpool_str2920[sizeof("neues.museum")];
- char stringpool_str2921[sizeof("here-for-more.info")];
- char stringpool_str2922[sizeof("sveio.no")];
- char stringpool_str2923[sizeof("kristiansund.no")];
- char stringpool_str2924[sizeof("corporation.museum")];
- char stringpool_str2925[sizeof("kai.yamanashi.jp")];
- char stringpool_str2926[sizeof("iq")];
- char stringpool_str2927[sizeof("dyndns-wiki.com")];
- char stringpool_str2928[sizeof("takinoue.hokkaido.jp")];
- char stringpool_str2929[sizeof("radio.br")];
- char stringpool_str2930[sizeof("arts.ro")];
- char stringpool_str2931[sizeof("lans.museum")];
- char stringpool_str2932[sizeof("imageandsound.museum")];
- char stringpool_str2933[sizeof("fudai.iwate.jp")];
- char stringpool_str2934[sizeof("shakotan.hokkaido.jp")];
- char stringpool_str2935[sizeof("rankoshi.hokkaido.jp")];
- char stringpool_str2936[sizeof("id.lv")];
- char stringpool_str2937[sizeof("traniandriabarletta.it")];
- char stringpool_str2938[sizeof("narviika.no")];
- char stringpool_str2939[sizeof("voronezh.ru")];
- char stringpool_str2940[sizeof("in.rs")];
- char stringpool_str2941[sizeof("ballooning.aero")];
- char stringpool_str2942[sizeof("versailles.museum")];
- char stringpool_str2943[sizeof("higashiagatsuma.gunma.jp")];
- char stringpool_str2944[sizeof("web.tj")];
- char stringpool_str2945[sizeof("i.ph")];
- char stringpool_str2946[sizeof("gateway.museum")];
- char stringpool_str2947[sizeof("notaires.km")];
- char stringpool_str2948[sizeof("selfip.info")];
- char stringpool_str2949[sizeof("ethnology.museum")];
- char stringpool_str2950[sizeof("onomichi.hiroshima.jp")];
- char stringpool_str2951[sizeof("nagano.jp")];
- char stringpool_str2952[sizeof("kaminokawa.tochigi.jp")];
- char stringpool_str2953[sizeof("flight.aero")];
- char stringpool_str2954[sizeof("moriyoshi.akita.jp")];
- char stringpool_str2955[sizeof("otake.hiroshima.jp")];
- char stringpool_str2956[sizeof("flesberg.no")];
- char stringpool_str2957[sizeof("moss.no")];
- char stringpool_str2958[sizeof("stathelle.no")];
- char stringpool_str2959[sizeof("takanabe.miyazaki.jp")];
- char stringpool_str2960[sizeof("moriya.ibaraki.jp")];
- char stringpool_str2961[sizeof("safety.aero")];
- char stringpool_str2962[sizeof("wiki.br")];
- char stringpool_str2963[sizeof("okawa.fukuoka.jp")];
- char stringpool_str2964[sizeof("dyndns-mail.com")];
- char stringpool_str2965[sizeof("astronomy.museum")];
- char stringpool_str2966[sizeof("fukuoka.jp")];
- char stringpool_str2967[sizeof("tsuga.tochigi.jp")];
- char stringpool_str2968[sizeof("gifu.gifu.jp")];
- char stringpool_str2969[sizeof("int.vn")];
- char stringpool_str2970[sizeof("niikappu.hokkaido.jp")];
- char stringpool_str2971[sizeof("shiroi.chiba.jp")];
- char stringpool_str2972[sizeof("mosjoen.no")];
- char stringpool_str2973[sizeof("nesna.no")];
- char stringpool_str2974[sizeof("balsan.it")];
- char stringpool_str2975[sizeof("naha.okinawa.jp")];
- char stringpool_str2976[sizeof("karasuyama.tochigi.jp")];
- char stringpool_str2977[sizeof("s3-website-us-west-2.amazonaws.com")];
- char stringpool_str2978[sizeof("airport.aero")];
- char stringpool_str2979[sizeof("gonohe.aomori.jp")];
- char stringpool_str2980[sizeof("eidsvoll.no")];
- char stringpool_str2981[sizeof("alabama.museum")];
- char stringpool_str2982[sizeof("kuriyama.hokkaido.jp")];
- char stringpool_str2983[sizeof("shirakawa.gifu.jp")];
- char stringpool_str2984[sizeof("shirakawa.fukushima.jp")];
- char stringpool_str2985[sizeof("karmoy.no")];
- char stringpool_str2986[sizeof("kepno.pl")];
- char stringpool_str2987[sizeof("omi.niigata.jp")];
- char stringpool_str2988[sizeof("historichouses.museum")];
- char stringpool_str2989[sizeof("miyawaka.fukuoka.jp")];
- char stringpool_str2990[sizeof("rovno.ua")];
- char stringpool_str2991[sizeof("uz")];
- char stringpool_str2992[sizeof("kristiansand.no")];
- char stringpool_str2993[sizeof("manchester.museum")];
- char stringpool_str2994[sizeof("gov.do")];
- char stringpool_str2995[sizeof("gov.dm")];
- char stringpool_str2996[sizeof("southcarolina.museum")];
- char stringpool_str2997[sizeof("edu.do")];
- char stringpool_str2998[sizeof("edu.dm")];
- char stringpool_str2999[sizeof("com.do")];
- char stringpool_str3000[sizeof("com.dm")];
- char stringpool_str3001[sizeof("com.de")];
- char stringpool_str3002[sizeof("gov.dz")];
- char stringpool_str3003[sizeof("edu.dz")];
- char stringpool_str3004[sizeof("nagasu.kumamoto.jp")];
- char stringpool_str3005[sizeof("cc.mi.us")];
- char stringpool_str3006[sizeof("com.dz")];
- char stringpool_str3007[sizeof("go.id")];
- char stringpool_str3008[sizeof("co.id")];
- char stringpool_str3009[sizeof("ud.it")];
- char stringpool_str3010[sizeof("dynathome.net")];
- char stringpool_str3011[sizeof("taiji.wakayama.jp")];
- char stringpool_str3012[sizeof("k12.fl.us")];
- char stringpool_str3013[sizeof("halloffame.museum")];
- char stringpool_str3014[sizeof("voss.no")];
- char stringpool_str3015[sizeof("kosei.shiga.jp")];
- char stringpool_str3016[sizeof("nord-aurdal.no")];
- char stringpool_str3017[sizeof("uz.ua")];
- char stringpool_str3018[sizeof("us")];
- char stringpool_str3019[sizeof("obanazawa.yamagata.jp")];
- char stringpool_str3020[sizeof("kishiwada.osaka.jp")];
- char stringpool_str3021[sizeof("historical.museum")];
- char stringpool_str3022[sizeof("art.do")];
- char stringpool_str3023[sizeof("s3-website-ap-southeast-1.amazonaws.com")];
- char stringpool_str3024[sizeof("lib.fl.us")];
- char stringpool_str3025[sizeof("art.dz")];
- char stringpool_str3026[sizeof("wy.us")];
- char stringpool_str3027[sizeof("kasai.hyogo.jp")];
- char stringpool_str3028[sizeof("shimotsuma.ibaraki.jp")];
- char stringpool_str3029[sizeof("wroc.pl")];
- char stringpool_str3030[sizeof("cc.wi.us")];
- char stringpool_str3031[sizeof("kumiyama.kyoto.jp")];
- char stringpool_str3032[sizeof("u.se")];
- char stringpool_str3033[sizeof("reggio-calabria.it")];
- char stringpool_str3034[sizeof("ut.us")];
- char stringpool_str3035[sizeof("indianmarket.museum")];
- char stringpool_str3036[sizeof("cc.vi.us")];
- char stringpool_str3037[sizeof("forli-cesena.it")];
- char stringpool_str3038[sizeof("railway.museum")];
- char stringpool_str3039[sizeof("nsw.edu.au")];
- char stringpool_str3040[sizeof("tamayu.shimane.jp")];
- char stringpool_str3041[sizeof("hekinan.aichi.jp")];
- char stringpool_str3042[sizeof("kashiwara.osaka.jp")];
- char stringpool_str3043[sizeof("sandoy.no")];
- char stringpool_str3044[sizeof("bomlo.no")];
- char stringpool_str3045[sizeof("fukaya.saitama.jp")];
- char stringpool_str3046[sizeof("illustration.museum")];
- char stringpool_str3047[sizeof("asahi.chiba.jp")];
- char stringpool_str3048[sizeof("video.hu")];
- char stringpool_str3049[sizeof("arkhangelsk.ru")];
- char stringpool_str3050[sizeof("higashimatsushima.miyagi.jp")];
- char stringpool_str3051[sizeof("bunkyo.tokyo.jp")];
- char stringpool_str3052[sizeof("starostwo.gov.pl")];
- char stringpool_str3053[sizeof("bo.nordland.no")];
- char stringpool_str3054[sizeof("is-a-nurse.com")];
- char stringpool_str3055[sizeof("s3-website-ap-northeast-1.amazonaws.com")];
- char stringpool_str3056[sizeof("sld.do")];
- char stringpool_str3057[sizeof("asahi.yamagata.jp")];
- char stringpool_str3058[sizeof("sor-fron.no")];
- char stringpool_str3059[sizeof("tranoy.no")];
- char stringpool_str3060[sizeof("ua")];
- char stringpool_str3061[sizeof("hobby-site.com")];
- char stringpool_str3062[sizeof("org.tw")];
- char stringpool_str3063[sizeof("web.ve")];
- char stringpool_str3064[sizeof("org.bw")];
- char stringpool_str3065[sizeof("isla.pr")];
- char stringpool_str3066[sizeof("happou.akita.jp")];
- char stringpool_str3067[sizeof("us.na")];
- char stringpool_str3068[sizeof("england.museum")];
- char stringpool_str3069[sizeof("andriatranibarletta.it")];
- char stringpool_str3070[sizeof("gob.do")];
- char stringpool_str3071[sizeof("u.bg")];
- char stringpool_str3072[sizeof("gallery.museum")];
- char stringpool_str3073[sizeof("yono.saitama.jp")];
- char stringpool_str3074[sizeof("vardo.no")];
- char stringpool_str3075[sizeof("shimokawa.hokkaido.jp")];
- char stringpool_str3076[sizeof("tarnobrzeg.pl")];
- char stringpool_str3077[sizeof("tomiya.miyagi.jp")];
- char stringpool_str3078[sizeof("nasu.tochigi.jp")];
- char stringpool_str3079[sizeof("yaroslavl.ru")];
- char stringpool_str3080[sizeof("finnoy.no")];
- char stringpool_str3081[sizeof("hemsedal.no")];
- char stringpool_str3082[sizeof("rodoy.no")];
- char stringpool_str3083[sizeof("dyndns-free.com")];
- char stringpool_str3084[sizeof("nago.okinawa.jp")];
- char stringpool_str3085[sizeof("uk")];
- char stringpool_str3086[sizeof("nakano.tokyo.jp")];
- char stringpool_str3087[sizeof("massacarrara.it")];
- char stringpool_str3088[sizeof("org.cw")];
- char stringpool_str3089[sizeof("sejny.pl")];
- char stringpool_str3090[sizeof("hadsel.no")];
- char stringpool_str3091[sizeof("hitoyoshi.kumamoto.jp")];
- char stringpool_str3092[sizeof("com.ro")];
- char stringpool_str3093[sizeof("com.re")];
- char stringpool_str3094[sizeof("go.kr")];
- char stringpool_str3095[sizeof("co.kr")];
- char stringpool_str3096[sizeof("seljord.no")];
- char stringpool_str3097[sizeof("co.ir")];
- char stringpool_str3098[sizeof("tynset.no")];
- char stringpool_str3099[sizeof("go.cr")];
- char stringpool_str3100[sizeof("ed.cr")];
- char stringpool_str3101[sizeof("gov.rs")];
- char stringpool_str3102[sizeof("co.cr")];
- char stringpool_str3103[sizeof("edu.rs")];
- char stringpool_str3104[sizeof("shinanomachi.nagano.jp")];
- char stringpool_str3105[sizeof("dnsdojo.net")];
- char stringpool_str3106[sizeof("is-a-llama.com")];
- char stringpool_str3107[sizeof("nagatoro.saitama.jp")];
- char stringpool_str3108[sizeof("yokkaichi.mie.jp")];
- char stringpool_str3109[sizeof("nakano.nagano.jp")];
- char stringpool_str3110[sizeof("naie.hokkaido.jp")];
- char stringpool_str3111[sizeof("annefrank.museum")];
- char stringpool_str3112[sizeof("cuneo.it")];
- char stringpool_str3113[sizeof("yazu.tottori.jp")];
- char stringpool_str3114[sizeof("es.kr")];
- char stringpool_str3115[sizeof("california.museum")];
- char stringpool_str3116[sizeof("averoy.no")];
- char stringpool_str3117[sizeof("luroy.no")];
- char stringpool_str3118[sizeof("fukuyama.hiroshima.jp")];
- char stringpool_str3119[sizeof("mil.do")];
- char stringpool_str3120[sizeof("sakai.osaka.jp")];
- char stringpool_str3121[sizeof("re.kr")];
- char stringpool_str3122[sizeof("nagiso.nagano.jp")];
- char stringpool_str3123[sizeof("gov.ru")];
- char stringpool_str3124[sizeof("ae.org")];
- char stringpool_str3125[sizeof("fermo.it")];
- char stringpool_str3126[sizeof("edu.ru")];
- char stringpool_str3127[sizeof("com.ru")];
- char stringpool_str3128[sizeof("farmequipment.museum")];
- char stringpool_str3129[sizeof("andoy.no")];
- char stringpool_str3130[sizeof("shimosuwa.nagano.jp")];
- char stringpool_str3131[sizeof("moriyama.shiga.jp")];
- char stringpool_str3132[sizeof("tm.fr")];
- char stringpool_str3133[sizeof("nakanojo.gunma.jp")];
- char stringpool_str3134[sizeof("hatoyama.saitama.jp")];
- char stringpool_str3135[sizeof("univ.sn")];
- char stringpool_str3136[sizeof("nakasatsunai.hokkaido.jp")];
- char stringpool_str3137[sizeof("nagi.okayama.jp")];
- char stringpool_str3138[sizeof("niki.hokkaido.jp")];
- char stringpool_str3139[sizeof("yamato.kumamoto.jp")];
- char stringpool_str3140[sizeof("rishirifuji.hokkaido.jp")];
- char stringpool_str3141[sizeof("kawai.iwate.jp")];
- char stringpool_str3142[sizeof("stv.ru")];
- char stringpool_str3143[sizeof("uvic.museum")];
- char stringpool_str3144[sizeof("city.yokohama.jp")];
- char stringpool_str3145[sizeof("s3-website-ap-southeast-2.amazonaws.com")];
- char stringpool_str3146[sizeof("tottori.jp")];
- char stringpool_str3147[sizeof("gov.mo")];
- char stringpool_str3148[sizeof("gov.me")];
- char stringpool_str3149[sizeof("ms.kr")];
- char stringpool_str3150[sizeof("edu.mo")];
- char stringpool_str3151[sizeof("edu.me")];
- char stringpool_str3152[sizeof("gov.mk")];
- char stringpool_str3153[sizeof("edu.mk")];
- char stringpool_str3154[sizeof("com.mo")];
- char stringpool_str3155[sizeof("miasta.pl")];
- char stringpool_str3156[sizeof("com.mk")];
- char stringpool_str3157[sizeof("gov.mg")];
- char stringpool_str3158[sizeof("edu.mg")];
- char stringpool_str3159[sizeof("radoy.no")];
- char stringpool_str3160[sizeof("com.mg")];
- char stringpool_str3161[sizeof("co.im")];
- char stringpool_str3162[sizeof("gov.ma")];
- char stringpool_str3163[sizeof("kms.ru")];
- char stringpool_str3164[sizeof("tom.ru")];
- char stringpool_str3165[sizeof("www.ck")];
- char stringpool_str3166[sizeof("nedre-eiker.no")];
- char stringpool_str3167[sizeof("web.nf")];
- char stringpool_str3168[sizeof("s3-website-us-gov-west-1.amazonaws.com")];
- char stringpool_str3169[sizeof("ozora.hokkaido.jp")];
- char stringpool_str3170[sizeof("morioka.iwate.jp")];
- char stringpool_str3171[sizeof("uri.arpa")];
- char stringpool_str3172[sizeof("k12.de.us")];
- char stringpool_str3173[sizeof("mitoyo.kagawa.jp")];
- char stringpool_str3174[sizeof("reggio-emilia.it")];
- char stringpool_str3175[sizeof("kounosu.saitama.jp")];
- char stringpool_str3176[sizeof("money.museum")];
- char stringpool_str3177[sizeof("seirou.niigata.jp")];
- char stringpool_str3178[sizeof("urn.arpa")];
- char stringpool_str3179[sizeof("osakikamijima.hiroshima.jp")];
- char stringpool_str3180[sizeof("cc.hi.us")];
- char stringpool_str3181[sizeof("kawanabe.kagoshima.jp")];
- char stringpool_str3182[sizeof("kouyama.kagoshima.jp")];
- char stringpool_str3183[sizeof("honefoss.no")];
- char stringpool_str3184[sizeof("gov.mu")];
- char stringpool_str3185[sizeof("rnd.ru")];
- char stringpool_str3186[sizeof("snz.ru")];
- char stringpool_str3187[sizeof("lib.de.us")];
- char stringpool_str3188[sizeof("com.mu")];
- char stringpool_str3189[sizeof("sa.cr")];
- char stringpool_str3190[sizeof("nirasaki.yamanashi.jp")];
- char stringpool_str3191[sizeof("k12.dc.us")];
- char stringpool_str3192[sizeof("uba.ar")];
- char stringpool_str3193[sizeof("otsuchi.iwate.jp")];
- char stringpool_str3194[sizeof("station.museum")];
- char stringpool_str3195[sizeof("kamioka.akita.jp")];
- char stringpool_str3196[sizeof("sapporo.jp")];
- char stringpool_str3197[sizeof("tm.km")];
- char stringpool_str3198[sizeof("misconfused.org")];
- char stringpool_str3199[sizeof("gov.iq")];
- char stringpool_str3200[sizeof("edu.iq")];
- char stringpool_str3201[sizeof("hakui.ishikawa.jp")];
- char stringpool_str3202[sizeof("gov.mr")];
- char stringpool_str3203[sizeof("gov.mn")];
- char stringpool_str3204[sizeof("com.iq")];
- char stringpool_str3205[sizeof("edu.mn")];
- char stringpool_str3206[sizeof("meloy.no")];
- char stringpool_str3207[sizeof("lib.dc.us")];
- char stringpool_str3208[sizeof("co.tm")];
- char stringpool_str3209[sizeof("fi.cr")];
- char stringpool_str3210[sizeof("ginan.gifu.jp")];
- char stringpool_str3211[sizeof("unbi.ba")];
- char stringpool_str3212[sizeof("archaeology.museum")];
- char stringpool_str3213[sizeof("kui.hiroshima.jp")];
- char stringpool_str3214[sizeof("yuki.ibaraki.jp")];
- char stringpool_str3215[sizeof("bahcavuotna.no")];
- char stringpool_str3216[sizeof("yokote.akita.jp")];
- char stringpool_str3217[sizeof("narusawa.yamanashi.jp")];
- char stringpool_str3218[sizeof("masoy.no")];
- char stringpool_str3219[sizeof("sa.edu.au")];
- char stringpool_str3220[sizeof("cc.ri.us")];
- char stringpool_str3221[sizeof("tochio.niigata.jp")];
- char stringpool_str3222[sizeof("gov.ml")];
- char stringpool_str3223[sizeof("edu.ml")];
- char stringpool_str3224[sizeof("askoy.no")];
- char stringpool_str3225[sizeof("floro.no")];
- char stringpool_str3226[sizeof("com.ml")];
- char stringpool_str3227[sizeof("takayama.nagano.jp")];
- char stringpool_str3228[sizeof("malatvuopmi.no")];
- char stringpool_str3229[sizeof("textile.museum")];
- char stringpool_str3230[sizeof("uy")];
- char stringpool_str3231[sizeof("teledata.mz")];
- char stringpool_str3232[sizeof("hachioji.tokyo.jp")];
- char stringpool_str3233[sizeof("net.tw")];
- char stringpool_str3234[sizeof("ivgu.no")];
- char stringpool_str3235[sizeof("chichibu.saitama.jp")];
- char stringpool_str3236[sizeof("higashikawa.hokkaido.jp")];
- char stringpool_str3237[sizeof("unsa.ba")];
- char stringpool_str3238[sizeof("massa-carrara.it")];
- char stringpool_str3239[sizeof("zhitomir.ua")];
- char stringpool_str3240[sizeof("tadaoka.osaka.jp")];
- char stringpool_str3241[sizeof("yorkshire.museum")];
- char stringpool_str3242[sizeof("toyotsu.fukuoka.jp")];
- char stringpool_str3243[sizeof("tottori.tottori.jp")];
- char stringpool_str3244[sizeof("nc")];
- char stringpool_str3245[sizeof("ina.nagano.jp")];
- char stringpool_str3246[sizeof("kameoka.kyoto.jp")];
- char stringpool_str3247[sizeof("khv.ru")];
- char stringpool_str3248[sizeof("indianapolis.museum")];
- char stringpool_str3249[sizeof("arboretum.museum")];
- char stringpool_str3250[sizeof("shimonita.gunma.jp")];
- char stringpool_str3251[sizeof("stjordal.no")];
- char stringpool_str3252[sizeof("memorial.museum")];
- char stringpool_str3253[sizeof("varoy.no")];
- char stringpool_str3254[sizeof("e-burg.ru")];
- char stringpool_str3255[sizeof("jar.ru")];
- char stringpool_str3256[sizeof("judaica.museum")];
- char stringpool_str3257[sizeof("bir.ru")];
- char stringpool_str3258[sizeof("net.cw")];
- char stringpool_str3259[sizeof("takayama.gunma.jp")];
- char stringpool_str3260[sizeof("my.id")];
- char stringpool_str3261[sizeof("orskog.no")];
- char stringpool_str3262[sizeof("kemerovo.ru")];
- char stringpool_str3263[sizeof("kunstunddesign.museum")];
- char stringpool_str3264[sizeof("zoological.museum")];
- char stringpool_str3265[sizeof("kunstsammlung.museum")];
- char stringpool_str3266[sizeof("tachikawa.tokyo.jp")];
- char stringpool_str3267[sizeof("shikokuchuo.ehime.jp")];
- char stringpool_str3268[sizeof("nc.us")];
- char stringpool_str3269[sizeof("isen.kagoshima.jp")];
- char stringpool_str3270[sizeof("int.is")];
- char stringpool_str3271[sizeof("kostroma.ru")];
- char stringpool_str3272[sizeof("yokoze.saitama.jp")];
- char stringpool_str3273[sizeof("chelyabinsk.ru")];
- char stringpool_str3274[sizeof("mil.ru")];
- char stringpool_str3275[sizeof("uk.net")];
- char stringpool_str3276[sizeof("soundandvision.museum")];
- char stringpool_str3277[sizeof("foundation.museum")];
- char stringpool_str3278[sizeof("fukushima.fukushima.jp")];
- char stringpool_str3279[sizeof("vrn.ru")];
- char stringpool_str3280[sizeof("shichinohe.aomori.jp")];
- char stringpool_str3281[sizeof("naka.hiroshima.jp")];
- char stringpool_str3282[sizeof("ogawa.saitama.jp")];
- char stringpool_str3283[sizeof("kitahata.saga.jp")];
- char stringpool_str3284[sizeof("malbork.pl")];
- char stringpool_str3285[sizeof("louvre.museum")];
- char stringpool_str3286[sizeof("sango.nara.jp")];
- char stringpool_str3287[sizeof("msk.ru")];
- char stringpool_str3288[sizeof("aerobatic.aero")];
- char stringpool_str3289[sizeof("flanders.museum")];
- char stringpool_str3290[sizeof("ind.in")];
- char stringpool_str3291[sizeof("k12.ri.us")];
- char stringpool_str3292[sizeof("tsk.ru")];
- char stringpool_str3293[sizeof("adachi.tokyo.jp")];
- char stringpool_str3294[sizeof("istmein.de")];
- char stringpool_str3295[sizeof("mizuho.tokyo.jp")];
- char stringpool_str3296[sizeof("obama.fukui.jp")];
- char stringpool_str3297[sizeof("shiroishi.saga.jp")];
- char stringpool_str3298[sizeof("obira.hokkaido.jp")];
- char stringpool_str3299[sizeof("kasuya.fukuoka.jp")];
- char stringpool_str3300[sizeof("mil.mg")];
- char stringpool_str3301[sizeof("kawahara.tottori.jp")];
- char stringpool_str3302[sizeof("matera.it")];
- char stringpool_str3303[sizeof("nogi.tochigi.jp")];
- char stringpool_str3304[sizeof("children.museum")];
- char stringpool_str3305[sizeof("modern.museum")];
- char stringpool_str3306[sizeof("lib.ri.us")];
- char stringpool_str3307[sizeof("chosei.chiba.jp")];
- char stringpool_str3308[sizeof("broadcast.museum")];
- char stringpool_str3309[sizeof("ug")];
- char stringpool_str3310[sizeof("niihama.ehime.jp")];
- char stringpool_str3311[sizeof("honjyo.akita.jp")];
- char stringpool_str3312[sizeof("irkutsk.ru")];
- char stringpool_str3313[sizeof("jolster.no")];
- char stringpool_str3314[sizeof("bungotakada.oita.jp")];
- char stringpool_str3315[sizeof("ashiya.hyogo.jp")];
- char stringpool_str3316[sizeof("luzern.museum")];
- char stringpool_str3317[sizeof("spb.ru")];
- char stringpool_str3318[sizeof("ashiya.fukuoka.jp")];
- char stringpool_str3319[sizeof("kanoya.kagoshima.jp")];
- char stringpool_str3320[sizeof("takko.aomori.jp")];
- char stringpool_str3321[sizeof("hiraya.nagano.jp")];
- char stringpool_str3322[sizeof("awaji.hyogo.jp")];
- char stringpool_str3323[sizeof("nagawa.nagano.jp")];
- char stringpool_str3324[sizeof("samara.ru")];
- char stringpool_str3325[sizeof("niigata.niigata.jp")];
- char stringpool_str3326[sizeof("otobe.hokkaido.jp")];
- char stringpool_str3327[sizeof("montreal.museum")];
- char stringpool_str3328[sizeof("cmw.ru")];
- char stringpool_str3329[sizeof("automotive.museum")];
- char stringpool_str3330[sizeof("aomori.jp")];
- char stringpool_str3331[sizeof("childrens.museum")];
- char stringpool_str3332[sizeof("canada.museum")];
- char stringpool_str3333[sizeof("asuke.aichi.jp")];
- char stringpool_str3334[sizeof("ingatlan.hu")];
- char stringpool_str3335[sizeof("building.museum")];
- char stringpool_str3336[sizeof("ol.no")];
- char stringpool_str3337[sizeof("british.museum")];
- char stringpool_str3338[sizeof("obama.nagasaki.jp")];
- char stringpool_str3339[sizeof("kasaoka.okayama.jp")];
- char stringpool_str3340[sizeof("mil.iq")];
- char stringpool_str3341[sizeof("brindisi.it")];
- char stringpool_str3342[sizeof("nagano.nagano.jp")];
- char stringpool_str3343[sizeof("nic.tr")];
- char stringpool_str3344[sizeof("russia.museum")];
- char stringpool_str3345[sizeof("nakanoto.ishikawa.jp")];
- char stringpool_str3346[sizeof("tomioka.gunma.jp")];
- char stringpool_str3347[sizeof("nic.ar")];
- char stringpool_str3348[sizeof("k12.mo.us")];
- char stringpool_str3349[sizeof("k12.me.us")];
- char stringpool_str3350[sizeof("k12.md.us")];
- char stringpool_str3351[sizeof("czest.pl")];
- char stringpool_str3352[sizeof("machida.tokyo.jp")];
- char stringpool_str3353[sizeof("k12.mi.us")];
- char stringpool_str3354[sizeof("hs.kr")];
- char stringpool_str3355[sizeof("australia.museum")];
- char stringpool_str3356[sizeof("naganohara.gunma.jp")];
- char stringpool_str3357[sizeof("omihachiman.shiga.jp")];
- char stringpool_str3358[sizeof("aircraft.aero")];
- char stringpool_str3359[sizeof("kongsvinger.no")];
- char stringpool_str3360[sizeof("nagasaki.nagasaki.jp")];
- char stringpool_str3361[sizeof("k12.ma.us")];
- char stringpool_str3362[sizeof("kudoyama.wakayama.jp")];
- char stringpool_str3363[sizeof("k12.ms.us")];
- char stringpool_str3364[sizeof("higashikagawa.kagawa.jp")];
- char stringpool_str3365[sizeof("yame.fukuoka.jp")];
- char stringpool_str3366[sizeof("lib.mo.us")];
- char stringpool_str3367[sizeof("lib.me.us")];
- char stringpool_str3368[sizeof("lib.md.us")];
- char stringpool_str3369[sizeof("kofu.yamanashi.jp")];
- char stringpool_str3370[sizeof("lib.mi.us")];
- char stringpool_str3371[sizeof("kyoto.jp")];
- char stringpool_str3372[sizeof("mochizuki.nagano.jp")];
- char stringpool_str3373[sizeof("tanohata.iwate.jp")];
- char stringpool_str3374[sizeof("chitose.hokkaido.jp")];
- char stringpool_str3375[sizeof("arteducation.museum")];
- char stringpool_str3376[sizeof("carrier.museum")];
- char stringpool_str3377[sizeof("dnsdojo.org")];
- char stringpool_str3378[sizeof("forsand.no")];
- char stringpool_str3379[sizeof("tosashimizu.kochi.jp")];
- char stringpool_str3380[sizeof("lib.ma.us")];
- char stringpool_str3381[sizeof("tjeldsund.no")];
- char stringpool_str3382[sizeof("dielddanuorri.no")];
- char stringpool_str3383[sizeof("lib.ms.us")];
- char stringpool_str3384[sizeof("yakutia.ru")];
- char stringpool_str3385[sizeof("miners.museum")];
- char stringpool_str3386[sizeof("yekaterinburg.ru")];
- char stringpool_str3387[sizeof("nic.tj")];
- char stringpool_str3388[sizeof("columbus.museum")];
- char stringpool_str3389[sizeof("kicks-ass.net")];
- char stringpool_str3390[sizeof("gets-it.net")];
- char stringpool_str3391[sizeof("tochigi.jp")];
- char stringpool_str3392[sizeof("utah.museum")];
- char stringpool_str3393[sizeof("teramo.it")];
- char stringpool_str3394[sizeof("iki.nagasaki.jp")];
- char stringpool_str3395[sizeof("zhytomyr.ua")];
- char stringpool_str3396[sizeof("badaddja.no")];
- char stringpool_str3397[sizeof("fujioka.gunma.jp")];
- char stringpool_str3398[sizeof("elburg.museum")];
- char stringpool_str3399[sizeof("k12.mt.us")];
- char stringpool_str3400[sizeof("am.br")];
- char stringpool_str3401[sizeof("miyoshi.aichi.jp")];
- char stringpool_str3402[sizeof("wakasa.tottori.jp")];
- char stringpool_str3403[sizeof("shimoda.shizuoka.jp")];
- char stringpool_str3404[sizeof("moscow.museum")];
- char stringpool_str3405[sizeof("city.kobe.jp")];
- char stringpool_str3406[sizeof("vestre-toten.no")];
- char stringpool_str3407[sizeof("hattfjelldal.no")];
- char stringpool_str3408[sizeof("dyroy.no")];
- char stringpool_str3409[sizeof("k12.mn.us")];
- char stringpool_str3410[sizeof("odate.akita.jp")];
- char stringpool_str3411[sizeof("nogata.fukuoka.jp")];
- char stringpool_str3412[sizeof("cinema.museum")];
- char stringpool_str3413[sizeof("lib.mt.us")];
- char stringpool_str3414[sizeof("federation.aero")];
- char stringpool_str3415[sizeof("yamanashi.jp")];
- char stringpool_str3416[sizeof("from-az.net")];
- char stringpool_str3417[sizeof("kochi.jp")];
- char stringpool_str3418[sizeof("brescia.it")];
- char stringpool_str3419[sizeof("warabi.saitama.jp")];
- char stringpool_str3420[sizeof("kobayashi.miyazaki.jp")];
- char stringpool_str3421[sizeof("oregon.museum")];
- char stringpool_str3422[sizeof("hachinohe.aomori.jp")];
- char stringpool_str3423[sizeof("omura.nagasaki.jp")];
- char stringpool_str3424[sizeof("lib.mn.us")];
- char stringpool_str3425[sizeof("rifu.miyagi.jp")];
- char stringpool_str3426[sizeof("beiarn.no")];
- char stringpool_str3427[sizeof("sannohe.aomori.jp")];
- char stringpool_str3428[sizeof("iveland.no")];
- char stringpool_str3429[sizeof("higashiura.aichi.jp")];
- char stringpool_str3430[sizeof("shimokitayama.nara.jp")];
- char stringpool_str3431[sizeof("uda.nara.jp")];
- char stringpool_str3432[sizeof("aomori.aomori.jp")];
- char stringpool_str3433[sizeof("semboku.akita.jp")];
- char stringpool_str3434[sizeof("stavropol.ru")];
- char stringpool_str3435[sizeof("czeladz.pl")];
- char stringpool_str3436[sizeof("web.id")];
- char stringpool_str3437[sizeof("tv.br")];
- char stringpool_str3438[sizeof("does-it.net")];
- char stringpool_str3439[sizeof("ullensaker.no")];
- char stringpool_str3440[sizeof("mansions.museum")];
- char stringpool_str3441[sizeof("namie.fukushima.jp")];
- char stringpool_str3442[sizeof("railroad.museum")];
- char stringpool_str3443[sizeof("romsa.no")];
- char stringpool_str3444[sizeof("chita.aichi.jp")];
- char stringpool_str3445[sizeof("ueno.gunma.jp")];
- char stringpool_str3446[sizeof("beardu.no")];
- char stringpool_str3447[sizeof("fm.br")];
- char stringpool_str3448[sizeof("bauern.museum")];
- char stringpool_str3449[sizeof("usarts.museum")];
- char stringpool_str3450[sizeof("touch.museum")];
- char stringpool_str3451[sizeof("storfjord.no")];
- char stringpool_str3452[sizeof("nakijin.okinawa.jp")];
- char stringpool_str3453[sizeof("takahama.aichi.jp")];
- char stringpool_str3454[sizeof("sakuho.nagano.jp")];
- char stringpool_str3455[sizeof("aichi.jp")];
- char stringpool_str3456[sizeof("florida.museum")];
- char stringpool_str3457[sizeof("gs.st.no")];
- char stringpool_str3458[sizeof("takaharu.miyazaki.jp")];
- char stringpool_str3459[sizeof("repbody.aero")];
- char stringpool_str3460[sizeof("co.mu")];
- char stringpool_str3461[sizeof("catering.aero")];
- char stringpool_str3462[sizeof("daisen.akita.jp")];
- char stringpool_str3463[sizeof("com.uz")];
- char stringpool_str3464[sizeof("com.ug")];
- char stringpool_str3465[sizeof("yonabaru.okinawa.jp")];
- char stringpool_str3466[sizeof("gov.ua")];
- char stringpool_str3467[sizeof("edu.ua")];
- char stringpool_str3468[sizeof("kg.kr")];
- char stringpool_str3469[sizeof("com.ua")];
- char stringpool_str3470[sizeof("fuossko.no")];
- char stringpool_str3471[sizeof("from-wv.com")];
- char stringpool_str3472[sizeof("odawara.kanagawa.jp")];
- char stringpool_str3473[sizeof("kanie.aichi.jp")];
- char stringpool_str3474[sizeof("is-a-candidate.org")];
- char stringpool_str3475[sizeof("beeldengeluid.museum")];
- char stringpool_str3476[sizeof("trust.museum")];
- char stringpool_str3477[sizeof("iizuna.nagano.jp")];
- char stringpool_str3478[sizeof("cloudfront.net")];
- char stringpool_str3479[sizeof("karpacz.pl")];
- char stringpool_str3480[sizeof("ochi.kochi.jp")];
- char stringpool_str3481[sizeof("gjerdrum.no")];
- char stringpool_str3482[sizeof("mod.uk")];
- char stringpool_str3483[sizeof("iwatsuki.saitama.jp")];
- char stringpool_str3484[sizeof("kin.okinawa.jp")];
- char stringpool_str3485[sizeof("alessandria.it")];
- char stringpool_str3486[sizeof("higashitsuno.kochi.jp")];
- char stringpool_str3487[sizeof("rzeszow.pl")];
- char stringpool_str3488[sizeof("kunst.museum")];
- char stringpool_str3489[sizeof("anthro.museum")];
- char stringpool_str3490[sizeof("yasu.shiga.jp")];
- char stringpool_str3491[sizeof("tatarstan.ru")];
- char stringpool_str3492[sizeof("rissa.no")];
- char stringpool_str3493[sizeof("hinohara.tokyo.jp")];
- char stringpool_str3494[sizeof("rochester.museum")];
- char stringpool_str3495[sizeof("yamatotakada.nara.jp")];
- char stringpool_str3496[sizeof("sciencecenter.museum")];
- char stringpool_str3497[sizeof("is-very-evil.org")];
- char stringpool_str3498[sizeof("ayagawa.kagawa.jp")];
- char stringpool_str3499[sizeof("hobby-site.org")];
- char stringpool_str3500[sizeof("erimo.hokkaido.jp")];
- char stringpool_str3501[sizeof("owani.aomori.jp")];
- char stringpool_str3502[sizeof("kotohira.kagawa.jp")];
- char stringpool_str3503[sizeof("from-wa.com")];
- char stringpool_str3504[sizeof("ilawa.pl")];
- char stringpool_str3505[sizeof("exchange.aero")];
- char stringpool_str3506[sizeof("kumamoto.jp")];
- char stringpool_str3507[sizeof("otaki.saitama.jp")];
- char stringpool_str3508[sizeof("museum")];
- char stringpool_str3509[sizeof("entertainment.aero")];
- char stringpool_str3510[sizeof("ogawa.nagano.jp")];
- char stringpool_str3511[sizeof("takehara.hiroshima.jp")];
- char stringpool_str3512[sizeof("gs.ah.no")];
- char stringpool_str3513[sizeof("konan.aichi.jp")];
- char stringpool_str3514[sizeof("s3-fips-us-gov-west-1.amazonaws.com")];
- char stringpool_str3515[sizeof("pm")];
- char stringpool_str3516[sizeof("sasayama.hyogo.jp")];
- char stringpool_str3517[sizeof("itoman.okinawa.jp")];
- char stringpool_str3518[sizeof("sciencecenters.museum")];
- char stringpool_str3519[sizeof("ohira.miyagi.jp")];
- char stringpool_str3520[sizeof("kitashiobara.fukushima.jp")];
- char stringpool_str3521[sizeof("izhevsk.ru")];
- char stringpool_str3522[sizeof("fed.us")];
- char stringpool_str3523[sizeof("kitayama.wakayama.jp")];
- char stringpool_str3524[sizeof("kouhoku.saga.jp")];
- char stringpool_str3525[sizeof("trondheim.no")];
- char stringpool_str3526[sizeof("pr")];
- char stringpool_str3527[sizeof("pro")];
- char stringpool_str3528[sizeof("iwanai.hokkaido.jp")];
- char stringpool_str3529[sizeof("po.it")];
- char stringpool_str3530[sizeof("pv.it")];
- char stringpool_str3531[sizeof("pu.it")];
- char stringpool_str3532[sizeof("pd.it")];
- char stringpool_str3533[sizeof("malselv.no")];
- char stringpool_str3534[sizeof("jet.uk")];
- char stringpool_str3535[sizeof("museum.no")];
- char stringpool_str3536[sizeof("pz.it")];
- char stringpool_str3537[sizeof("shiroishi.miyagi.jp")];
- char stringpool_str3538[sizeof("surgut.ru")];
- char stringpool_str3539[sizeof("hongo.hiroshima.jp")];
- char stringpool_str3540[sizeof("leirfjord.no")];
- char stringpool_str3541[sizeof("gov.sx")];
- char stringpool_str3542[sizeof("vestre-slidre.no")];
- char stringpool_str3543[sizeof("encyclopedic.museum")];
- char stringpool_str3544[sizeof("pt")];
- char stringpool_str3545[sizeof("pro.az")];
- char stringpool_str3546[sizeof("carbonia-iglesias.it")];
- char stringpool_str3547[sizeof("pr.it")];
- char stringpool_str3548[sizeof("brasil.museum")];
- char stringpool_str3549[sizeof("ps")];
- char stringpool_str3550[sizeof("workshop.museum")];
- char stringpool_str3551[sizeof("toyooka.hyogo.jp")];
- char stringpool_str3552[sizeof("usantiques.museum")];
- char stringpool_str3553[sizeof("pe")];
- char stringpool_str3554[sizeof("school.na")];
- char stringpool_str3555[sizeof("hyogo.jp")];
- char stringpool_str3556[sizeof("takaoka.toyama.jp")];
- char stringpool_str3557[sizeof("pt.it")];
- char stringpool_str3558[sizeof("museum.tt")];
- char stringpool_str3559[sizeof("nf")];
- char stringpool_str3560[sizeof("pe.it")];
- char stringpool_str3561[sizeof("ogawara.miyagi.jp")];
- char stringpool_str3562[sizeof("kamifurano.hokkaido.jp")];
- char stringpool_str3563[sizeof("pr.us")];
- char stringpool_str3564[sizeof("raisa.no")];
- char stringpool_str3565[sizeof("pe.ca")];
- char stringpool_str3566[sizeof("p.se")];
- char stringpool_str3567[sizeof("gov.cx")];
- char stringpool_str3568[sizeof("snasa.no")];
- char stringpool_str3569[sizeof("cbg.ru")];
- char stringpool_str3570[sizeof("gs.of.no")];
- char stringpool_str3571[sizeof("nf.ca")];
- char stringpool_str3572[sizeof("fortmissoula.museum")];
- char stringpool_str3573[sizeof("yoro.gifu.jp")];
- char stringpool_str3574[sizeof("school.museum")];
- char stringpool_str3575[sizeof("per.sg")];
- char stringpool_str3576[sizeof("pro.tt")];
- char stringpool_str3577[sizeof("stjordalshalsen.no")];
- char stringpool_str3578[sizeof("yawata.kyoto.jp")];
- char stringpool_str3579[sizeof("trysil.no")];
- char stringpool_str3580[sizeof("takahagi.ibaraki.jp")];
- char stringpool_str3581[sizeof("pn")];
- char stringpool_str3582[sizeof("galsa.no")];
- char stringpool_str3583[sizeof("iwaizumi.iwate.jp")];
- char stringpool_str3584[sizeof("takayama.gifu.jp")];
- char stringpool_str3585[sizeof("zushi.kanagawa.jp")];
- char stringpool_str3586[sizeof("olbia-tempio.it")];
- char stringpool_str3587[sizeof("frosinone.it")];
- char stringpool_str3588[sizeof("pro.br")];
- char stringpool_str3589[sizeof("pi.it")];
- char stringpool_str3590[sizeof("glass.museum")];
- char stringpool_str3591[sizeof("yuzawa.niigata.jp")];
- char stringpool_str3592[sizeof("usenet.pl")];
- char stringpool_str3593[sizeof("pn.it")];
- char stringpool_str3594[sizeof("kuchinotsu.nagasaki.jp")];
- char stringpool_str3595[sizeof("tarui.gifu.jp")];
- char stringpool_str3596[sizeof("museum.mv")];
- char stringpool_str3597[sizeof("izu.shizuoka.jp")];
- char stringpool_str3598[sizeof("post")];
- char stringpool_str3599[sizeof("pl")];
- char stringpool_str3600[sizeof("airguard.museum")];
- char stringpool_str3601[sizeof("midori.gunma.jp")];
- char stringpool_str3602[sizeof("sarufutsu.hokkaido.jp")];
- char stringpool_str3603[sizeof("tgory.pl")];
- char stringpool_str3604[sizeof("tabayama.yamanashi.jp")];
- char stringpool_str3605[sizeof("motorcycle.museum")];
- char stringpool_str3606[sizeof("harstad.no")];
- char stringpool_str3607[sizeof("pa")];
- char stringpool_str3608[sizeof("ito.shizuoka.jp")];
- char stringpool_str3609[sizeof("gs.vf.no")];
- char stringpool_str3610[sizeof("neat-url.com")];
- char stringpool_str3611[sizeof("oguni.kumamoto.jp")];
- char stringpool_str3612[sizeof("kuroiso.tochigi.jp")];
- char stringpool_str3613[sizeof("computer.museum")];
- char stringpool_str3614[sizeof("nonoichi.ishikawa.jp")];
- char stringpool_str3615[sizeof("pl.ua")];
- char stringpool_str3616[sizeof("okayama.jp")];
- char stringpool_str3617[sizeof("pa.it")];
- char stringpool_str3618[sizeof("fukudomi.saga.jp")];
- char stringpool_str3619[sizeof("handa.aichi.jp")];
- char stringpool_str3620[sizeof("leksvik.no")];
- char stringpool_str3621[sizeof("square.museum")];
- char stringpool_str3622[sizeof("p.bg")];
- char stringpool_str3623[sizeof("nyny.museum")];
- char stringpool_str3624[sizeof("sumida.tokyo.jp")];
- char stringpool_str3625[sizeof("austrheim.no")];
- char stringpool_str3626[sizeof("dni.us")];
- char stringpool_str3627[sizeof("wake.okayama.jp")];
- char stringpool_str3628[sizeof("lebork.pl")];
- char stringpool_str3629[sizeof("wakkanai.hokkaido.jp")];
- char stringpool_str3630[sizeof("engerdal.no")];
- char stringpool_str3631[sizeof("masuda.shimane.jp")];
- char stringpool_str3632[sizeof("heroy.nordland.no")];
- char stringpool_str3633[sizeof("pa.us")];
- char stringpool_str3634[sizeof("itabashi.tokyo.jp")];
- char stringpool_str3635[sizeof("game-server.cc")];
- char stringpool_str3636[sizeof("pub.sa")];
- char stringpool_str3637[sizeof("oyabe.toyama.jp")];
- char stringpool_str3638[sizeof("sa.au")];
- char stringpool_str3639[sizeof("ph")];
- char stringpool_str3640[sizeof("schlesisches.museum")];
- char stringpool_str3641[sizeof("fukuchi.fukuoka.jp")];
- char stringpool_str3642[sizeof("murayama.yamagata.jp")];
- char stringpool_str3643[sizeof("pk")];
- char stringpool_str3644[sizeof("yalta.ua")];
- char stringpool_str3645[sizeof("algard.no")];
- char stringpool_str3646[sizeof("priv.me")];
- char stringpool_str3647[sizeof("toride.ibaraki.jp")];
- char stringpool_str3648[sizeof("tsuno.miyazaki.jp")];
- char stringpool_str3649[sizeof("sf.no")];
- char stringpool_str3650[sizeof("sells-for-less.com")];
- char stringpool_str3651[sizeof("okinawa.jp")];
- char stringpool_str3652[sizeof("towada.aomori.jp")];
- char stringpool_str3653[sizeof("yamato.fukushima.jp")];
- char stringpool_str3654[sizeof("pro.ec")];
- char stringpool_str3655[sizeof("pp.ua")];
- char stringpool_str3656[sizeof("psi.br")];
- char stringpool_str3657[sizeof("priv.at")];
- char stringpool_str3658[sizeof("circus.museum")];
- char stringpool_str3659[sizeof("homeftp.net")];
- char stringpool_str3660[sizeof("sassari.it")];
- char stringpool_str3661[sizeof("funahashi.toyama.jp")];
- char stringpool_str3662[sizeof("is-a-linux-user.org")];
- char stringpool_str3663[sizeof("nishihara.kumamoto.jp")];
- char stringpool_str3664[sizeof("kaneyama.yamagata.jp")];
- char stringpool_str3665[sizeof("co.hu")];
- char stringpool_str3666[sizeof("izumiotsu.osaka.jp")];
- char stringpool_str3667[sizeof("ogata.akita.jp")];
- char stringpool_str3668[sizeof("shijonawate.osaka.jp")];
- char stringpool_str3669[sizeof("iitate.fukushima.jp")];
- char stringpool_str3670[sizeof("glogow.pl")];
- char stringpool_str3671[sizeof("aquarium.museum")];
- char stringpool_str3672[sizeof("og.ao")];
- char stringpool_str3673[sizeof("yuzhno-sakhalinsk.ru")];
- char stringpool_str3674[sizeof("sue.fukuoka.jp")];
- char stringpool_str3675[sizeof("etnedal.no")];
- char stringpool_str3676[sizeof("isernia.it")];
- char stringpool_str3677[sizeof("helsinki.museum")];
- char stringpool_str3678[sizeof("pro.na")];
- char stringpool_str3679[sizeof("yamashina.kyoto.jp")];
- char stringpool_str3680[sizeof("midori.chiba.jp")];
- char stringpool_str3681[sizeof("kinko.kagoshima.jp")];
- char stringpool_str3682[sizeof("yamato.kanagawa.jp")];
- char stringpool_str3683[sizeof("arendal.no")];
- char stringpool_str3684[sizeof("pri.ee")];
- char stringpool_str3685[sizeof("perm.ru")];
- char stringpool_str3686[sizeof("hjelmeland.no")];
- char stringpool_str3687[sizeof("columbia.museum")];
- char stringpool_str3688[sizeof("k12.ut.us")];
- char stringpool_str3689[sizeof("nishiarita.saga.jp")];
- char stringpool_str3690[sizeof("usui.fukuoka.jp")];
- char stringpool_str3691[sizeof("krakow.pl")];
- char stringpool_str3692[sizeof("urausu.hokkaido.jp")];
- char stringpool_str3693[sizeof("tm.hu")];
- char stringpool_str3694[sizeof("wakasa.fukui.jp")];
- char stringpool_str3695[sizeof("ath.cx")];
- char stringpool_str3696[sizeof("ushistory.museum")];
- char stringpool_str3697[sizeof("ooshika.nagano.jp")];
- char stringpool_str3698[sizeof("from-wy.com")];
- char stringpool_str3699[sizeof("gojome.akita.jp")];
- char stringpool_str3700[sizeof("izumisano.osaka.jp")];
- char stringpool_str3701[sizeof("chesapeakebay.museum")];
- char stringpool_str3702[sizeof("saito.miyazaki.jp")];
- char stringpool_str3703[sizeof("lib.ut.us")];
- char stringpool_str3704[sizeof("katori.chiba.jp")];
- char stringpool_str3705[sizeof("sunndal.no")];
- char stringpool_str3706[sizeof("upow.gov.pl")];
- char stringpool_str3707[sizeof("jaworzno.pl")];
- char stringpool_str3708[sizeof("higashichichibu.saitama.jp")];
- char stringpool_str3709[sizeof("ohda.shimane.jp")];
- char stringpool_str3710[sizeof("no.com")];
- char stringpool_str3711[sizeof("cultural.museum")];
- char stringpool_str3712[sizeof("wales.museum")];
- char stringpool_str3713[sizeof("pisa.it")];
- char stringpool_str3714[sizeof("ebino.miyazaki.jp")];
- char stringpool_str3715[sizeof("arezzo.it")];
- char stringpool_str3716[sizeof("software.aero")];
- char stringpool_str3717[sizeof("urbino-pesaro.it")];
- char stringpool_str3718[sizeof("pw")];
- char stringpool_str3719[sizeof("kutchan.hokkaido.jp")];
- char stringpool_str3720[sizeof("fujimi.saitama.jp")];
- char stringpool_str3721[sizeof("blogspot.cf")];
- char stringpool_str3722[sizeof("k12.tx.us")];
- char stringpool_str3723[sizeof("graz.museum")];
- char stringpool_str3724[sizeof("oe.yamagata.jp")];
- char stringpool_str3725[sizeof("ustka.pl")];
- char stringpool_str3726[sizeof("cambridge.museum")];
- char stringpool_str3727[sizeof("vf.no")];
- char stringpool_str3728[sizeof("midtre-gauldal.no")];
- char stringpool_str3729[sizeof("dyndns-server.com")];
- char stringpool_str3730[sizeof("oceanographique.museum")];
- char stringpool_str3731[sizeof("yamatokoriyama.nara.jp")];
- char stringpool_str3732[sizeof("hiroo.hokkaido.jp")];
- char stringpool_str3733[sizeof("lib.tx.us")];
- char stringpool_str3734[sizeof("otaki.nagano.jp")];
- char stringpool_str3735[sizeof("rockart.museum")];
- char stringpool_str3736[sizeof("eigersund.no")];
- char stringpool_str3737[sizeof("university.museum")];
- char stringpool_str3738[sizeof("nishimera.miyazaki.jp")];
- char stringpool_str3739[sizeof("from-wi.com")];
- char stringpool_str3740[sizeof("keisen.fukuoka.jp")];
- char stringpool_str3741[sizeof("house.museum")];
- char stringpool_str3742[sizeof("aizumi.tokushima.jp")];
- char stringpool_str3743[sizeof("yamanakako.yamanashi.jp")];
- char stringpool_str3744[sizeof("nanae.hokkaido.jp")];
- char stringpool_str3745[sizeof("sakado.saitama.jp")];
- char stringpool_str3746[sizeof("kaisei.kanagawa.jp")];
- char stringpool_str3747[sizeof("sokndal.no")];
- char stringpool_str3748[sizeof("kuzumaki.iwate.jp")];
- char stringpool_str3749[sizeof("ebiz.tw")];
- char stringpool_str3750[sizeof("portal.museum")];
- char stringpool_str3751[sizeof("yamazoe.nara.jp")];
- char stringpool_str3752[sizeof("coloradoplateau.museum")];
- char stringpool_str3753[sizeof("ullensvang.no")];
- char stringpool_str3754[sizeof("vladivostok.ru")];
- char stringpool_str3755[sizeof("za.org")];
- char stringpool_str3756[sizeof("hanno.saitama.jp")];
- char stringpool_str3757[sizeof("komoro.nagano.jp")];
- char stringpool_str3758[sizeof("idv.tw")];
- char stringpool_str3759[sizeof("myoko.niigata.jp")];
- char stringpool_str3760[sizeof("py")];
- char stringpool_str3761[sizeof("pilots.museum")];
- char stringpool_str3762[sizeof("washingtondc.museum")];
- char stringpool_str3763[sizeof("scientist.aero")];
- char stringpool_str3764[sizeof("folldal.no")];
- char stringpool_str3765[sizeof("kasahara.gifu.jp")];
- char stringpool_str3766[sizeof("bajddar.no")];
- char stringpool_str3767[sizeof("shimoji.okinawa.jp")];
- char stringpool_str3768[sizeof("nt.no")];
- char stringpool_str3769[sizeof("saltdal.no")];
- char stringpool_str3770[sizeof("github.io")];
- char stringpool_str3771[sizeof("prof.pr")];
- char stringpool_str3772[sizeof("linz.museum")];
- char stringpool_str3773[sizeof("hachijo.tokyo.jp")];
- char stringpool_str3774[sizeof("kumamoto.kumamoto.jp")];
- char stringpool_str3775[sizeof("atsuma.hokkaido.jp")];
- char stringpool_str3776[sizeof("warmia.pl")];
- char stringpool_str3777[sizeof("museum.mw")];
- char stringpool_str3778[sizeof("hofu.yamaguchi.jp")];
- char stringpool_str3779[sizeof("iida.nagano.jp")];
- char stringpool_str3780[sizeof("toyama.jp")];
- char stringpool_str3781[sizeof("name.vn")];
- char stringpool_str3782[sizeof("fujimino.saitama.jp")];
- char stringpool_str3783[sizeof("chino.nagano.jp")];
- char stringpool_str3784[sizeof("yomitan.okinawa.jp")];
- char stringpool_str3785[sizeof("pro.vn")];
- char stringpool_str3786[sizeof("sakahogi.gifu.jp")];
- char stringpool_str3787[sizeof("seiro.niigata.jp")];
- char stringpool_str3788[sizeof("leitungsen.de")];
- char stringpool_str3789[sizeof("or.th")];
- char stringpool_str3790[sizeof("port.fr")];
- char stringpool_str3791[sizeof("is-very-good.org")];
- char stringpool_str3792[sizeof("williamsburg.museum")];
- char stringpool_str3793[sizeof("kitahiroshima.hokkaido.jp")];
- char stringpool_str3794[sizeof("melhus.no")];
- char stringpool_str3795[sizeof("ostroleka.pl")];
- char stringpool_str3796[sizeof("elverum.no")];
- char stringpool_str3797[sizeof("inawashiro.fukushima.jp")];
- char stringpool_str3798[sizeof("sakura.chiba.jp")];
- char stringpool_str3799[sizeof("ashoro.hokkaido.jp")];
- char stringpool_str3800[sizeof("takahashi.okayama.jp")];
- char stringpool_str3801[sizeof("halsa.no")];
- char stringpool_str3802[sizeof("obihiro.hokkaido.jp")];
- char stringpool_str3803[sizeof("hasuda.saitama.jp")];
- char stringpool_str3804[sizeof("anpachi.gifu.jp")];
- char stringpool_str3805[sizeof("tajiri.osaka.jp")];
- char stringpool_str3806[sizeof("kadoma.osaka.jp")];
- char stringpool_str3807[sizeof("svizzera.museum")];
- char stringpool_str3808[sizeof("openair.museum")];
- char stringpool_str3809[sizeof("osaki.miyagi.jp")];
- char stringpool_str3810[sizeof("tomari.hokkaido.jp")];
- char stringpool_str3811[sizeof("labour.museum")];
- char stringpool_str3812[sizeof("yokawa.hyogo.jp")];
- char stringpool_str3813[sizeof("mobara.chiba.jp")];
- char stringpool_str3814[sizeof("yamanouchi.nagano.jp")];
- char stringpool_str3815[sizeof("mihama.mie.jp")];
- char stringpool_str3816[sizeof("saroma.hokkaido.jp")];
- char stringpool_str3817[sizeof("pp.az")];
- char stringpool_str3818[sizeof("brumunddal.no")];
- char stringpool_str3819[sizeof("s3-us-west-2.amazonaws.com")];
- char stringpool_str3820[sizeof("nozawaonsen.nagano.jp")];
- char stringpool_str3821[sizeof("nl.no")];
- char stringpool_str3822[sizeof("stordal.no")];
- char stringpool_str3823[sizeof("ikoma.nara.jp")];
- char stringpool_str3824[sizeof("gov.km")];
- char stringpool_str3825[sizeof("edu.km")];
- char stringpool_str3826[sizeof("gov.ki")];
- char stringpool_str3827[sizeof("com.km")];
- char stringpool_str3828[sizeof("gov.kz")];
- char stringpool_str3829[sizeof("edu.ki")];
- char stringpool_str3830[sizeof("edu.kz")];
- char stringpool_str3831[sizeof("gov.kg")];
- char stringpool_str3832[sizeof("com.ki")];
- char stringpool_str3833[sizeof("edu.kg")];
- char stringpool_str3834[sizeof("com.kz")];
- char stringpool_str3835[sizeof("com.kg")];
- char stringpool_str3836[sizeof("imakane.hokkaido.jp")];
- char stringpool_str3837[sizeof("krasnoyarsk.ru")];
- char stringpool_str3838[sizeof("is-a-bruinsfan.org")];
- char stringpool_str3839[sizeof("namdalseid.no")];
- char stringpool_str3840[sizeof("ac.th")];
- char stringpool_str3841[sizeof("gaivuotna.no")];
- char stringpool_str3842[sizeof("plants.museum")];
- char stringpool_str3843[sizeof("childrensgarden.museum")];
- char stringpool_str3844[sizeof("pg")];
- char stringpool_str3845[sizeof("eiheiji.fukui.jp")];
- char stringpool_str3846[sizeof("tokai.ibaraki.jp")];
- char stringpool_str3847[sizeof("blogdns.net")];
- char stringpool_str3848[sizeof("ogori.fukuoka.jp")];
- char stringpool_str3849[sizeof("okegawa.saitama.jp")];
- char stringpool_str3850[sizeof("salzburg.museum")];
- char stringpool_str3851[sizeof("stokke.no")];
- char stringpool_str3852[sizeof("sanjo.niigata.jp")];
- char stringpool_str3853[sizeof("kimitsu.chiba.jp")];
- char stringpool_str3854[sizeof("pg.it")];
- char stringpool_str3855[sizeof("southwest.museum")];
- char stringpool_str3856[sizeof("ina.saitama.jp")];
- char stringpool_str3857[sizeof("ass.km")];
- char stringpool_str3858[sizeof("tsu.mie.jp")];
- char stringpool_str3859[sizeof("priv.no")];
- char stringpool_str3860[sizeof("morimachi.shizuoka.jp")];
- char stringpool_str3861[sizeof("priv.pl")];
- char stringpool_str3862[sizeof("gov.kn")];
- char stringpool_str3863[sizeof("edu.kn")];
- char stringpool_str3864[sizeof("bruxelles.museum")];
- char stringpool_str3865[sizeof("honjo.saitama.jp")];
- char stringpool_str3866[sizeof("kitamoto.saitama.jp")];
- char stringpool_str3867[sizeof("drammen.no")];
- char stringpool_str3868[sizeof("per.nf")];
- char stringpool_str3869[sizeof("traeumtgerade.de")];
- char stringpool_str3870[sizeof("nic.im")];
- char stringpool_str3871[sizeof("nishinoshima.shimane.jp")];
- char stringpool_str3872[sizeof("environment.museum")];
- char stringpool_str3873[sizeof("padova.it")];
- char stringpool_str3874[sizeof("sa.gov.au")];
- char stringpool_str3875[sizeof("mishima.fukushima.jp")];
- char stringpool_str3876[sizeof("przeworsk.pl")];
- char stringpool_str3877[sizeof("luxembourg.museum")];
- char stringpool_str3878[sizeof("fujimi.nagano.jp")];
- char stringpool_str3879[sizeof("caserta.it")];
- char stringpool_str3880[sizeof("hamada.shimane.jp")];
- char stringpool_str3881[sizeof("workinggroup.aero")];
- char stringpool_str3882[sizeof("minamata.kumamoto.jp")];
- char stringpool_str3883[sizeof("uslivinghistory.museum")];
- char stringpool_str3884[sizeof("science.museum")];
- char stringpool_str3885[sizeof("iyo.ehime.jp")];
- char stringpool_str3886[sizeof("homeftp.org")];
- char stringpool_str3887[sizeof("mashiko.tochigi.jp")];
- char stringpool_str3888[sizeof("ogimi.okinawa.jp")];
- char stringpool_str3889[sizeof("kitami.hokkaido.jp")];
- char stringpool_str3890[sizeof("sondre-land.no")];
- char stringpool_str3891[sizeof("odessa.ua")];
- char stringpool_str3892[sizeof("bihoro.hokkaido.jp")];
- char stringpool_str3893[sizeof("sakai.ibaraki.jp")];
- char stringpool_str3894[sizeof("asahi.ibaraki.jp")];
- char stringpool_str3895[sizeof("iruma.saitama.jp")];
- char stringpool_str3896[sizeof("fredrikstad.no")];
- char stringpool_str3897[sizeof("minamiise.mie.jp")];
- char stringpool_str3898[sizeof("minami.tokushima.jp")];
- char stringpool_str3899[sizeof("mihara.hiroshima.jp")];
- char stringpool_str3900[sizeof("os.hordaland.no")];
- char stringpool_str3901[sizeof("lyngdal.no")];
- char stringpool_str3902[sizeof("takamori.kumamoto.jp")];
- char stringpool_str3903[sizeof("yabu.hyogo.jp")];
- char stringpool_str3904[sizeof("ham-radio-op.net")];
- char stringpool_str3905[sizeof("palace.museum")];
- char stringpool_str3906[sizeof("ac.se")];
- char stringpool_str3907[sizeof("wada.nagano.jp")];
- char stringpool_str3908[sizeof("nishikatsura.yamanashi.jp")];
- char stringpool_str3909[sizeof("gs.mr.no")];
- char stringpool_str3910[sizeof("nic.in")];
- char stringpool_str3911[sizeof("ac.sz")];
- char stringpool_str3912[sizeof("plantation.museum")];
- char stringpool_str3913[sizeof("kisofukushima.nagano.jp")];
- char stringpool_str3914[sizeof("publ.pt")];
- char stringpool_str3915[sizeof("hinode.tokyo.jp")];
- char stringpool_str3916[sizeof("saijo.ehime.jp")];
- char stringpool_str3917[sizeof("manno.kagawa.jp")];
- char stringpool_str3918[sizeof("gov.my")];
- char stringpool_str3919[sizeof("ryazan.ru")];
- char stringpool_str3920[sizeof("priv.hu")];
- char stringpool_str3921[sizeof("edu.my")];
- char stringpool_str3922[sizeof("national.museum")];
- char stringpool_str3923[sizeof("from-vt.com")];
- char stringpool_str3924[sizeof("com.my")];
- char stringpool_str3925[sizeof("mihama.chiba.jp")];
- char stringpool_str3926[sizeof("abiko.chiba.jp")];
- char stringpool_str3927[sizeof("radom.pl")];
- char stringpool_str3928[sizeof("kakuda.miyagi.jp")];
- char stringpool_str3929[sizeof("nt.ro")];
- char stringpool_str3930[sizeof("anthropology.museum")];
- char stringpool_str3931[sizeof("yashio.saitama.jp")];
- char stringpool_str3932[sizeof("palana.ru")];
- char stringpool_str3933[sizeof("tawaramoto.nara.jp")];
- char stringpool_str3934[sizeof("kazimierz-dolny.pl")];
- char stringpool_str3935[sizeof("control.aero")];
- char stringpool_str3936[sizeof("monzabrianza.it")];
- char stringpool_str3937[sizeof("miyama.mie.jp")];
- char stringpool_str3938[sizeof("yamanashi.yamanashi.jp")];
- char stringpool_str3939[sizeof("tendo.yamagata.jp")];
- char stringpool_str3940[sizeof("messina.it")];
- char stringpool_str3941[sizeof("biz.ki")];
- char stringpool_str3942[sizeof("yokosuka.kanagawa.jp")];
- char stringpool_str3943[sizeof("ibaraki.jp")];
- char stringpool_str3944[sizeof("nishihara.okinawa.jp")];
- char stringpool_str3945[sizeof("otari.nagano.jp")];
- char stringpool_str3946[sizeof("yoka.hyogo.jp")];
- char stringpool_str3947[sizeof("okayama.okayama.jp")];
- char stringpool_str3948[sizeof("agano.niigata.jp")];
- char stringpool_str3949[sizeof("dazaifu.fukuoka.jp")];
- char stringpool_str3950[sizeof("tonami.toyama.jp")];
- char stringpool_str3951[sizeof("sondrio.it")];
- char stringpool_str3952[sizeof("pordenone.it")];
- char stringpool_str3953[sizeof("stalowa-wola.pl")];
- char stringpool_str3954[sizeof("navuotna.no")];
- char stringpool_str3955[sizeof("aland.fi")];
- char stringpool_str3956[sizeof("otaki.chiba.jp")];
- char stringpool_str3957[sizeof("kuromatsunai.hokkaido.jp")];
- char stringpool_str3958[sizeof("gs.tr.no")];
- char stringpool_str3959[sizeof("histoire.museum")];
- char stringpool_str3960[sizeof("field.museum")];
- char stringpool_str3961[sizeof("asago.hyogo.jp")];
- char stringpool_str3962[sizeof("s3-us-west-1.amazonaws.com")];
- char stringpool_str3963[sizeof("aisai.aichi.jp")];
- char stringpool_str3964[sizeof("risor.no")];
- char stringpool_str3965[sizeof("geometre-expert.fr")];
- char stringpool_str3966[sizeof("sorum.no")];
- char stringpool_str3967[sizeof("mil.km")];
- char stringpool_str3968[sizeof("marumori.miyagi.jp")];
- char stringpool_str3969[sizeof("kasama.ibaraki.jp")];
- char stringpool_str3970[sizeof("gs.fm.no")];
- char stringpool_str3971[sizeof("mil.kz")];
- char stringpool_str3972[sizeof("sogndal.no")];
- char stringpool_str3973[sizeof("mil.kg")];
- char stringpool_str3974[sizeof("gov.lk")];
- char stringpool_str3975[sizeof("edu.lk")];
- char stringpool_str3976[sizeof("minami.kyoto.jp")];
- char stringpool_str3977[sizeof("shichikashuku.miyagi.jp")];
- char stringpool_str3978[sizeof("com.lk")];
- char stringpool_str3979[sizeof("nishiawakura.okayama.jp")];
- char stringpool_str3980[sizeof("on-the-web.tv")];
- char stringpool_str3981[sizeof("bl.uk")];
- char stringpool_str3982[sizeof("from-va.com")];
- char stringpool_str3983[sizeof("gov.la")];
- char stringpool_str3984[sizeof("edu.la")];
- char stringpool_str3985[sizeof("com.la")];
- char stringpool_str3986[sizeof("co.cl")];
- char stringpool_str3987[sizeof("yoshikawa.saitama.jp")];
- char stringpool_str3988[sizeof("bellevue.museum")];
- char stringpool_str3989[sizeof("gov.lc")];
- char stringpool_str3990[sizeof("edu.lc")];
- char stringpool_str3991[sizeof("fujiyoshida.yamanashi.jp")];
- char stringpool_str3992[sizeof("com.lc")];
- char stringpool_str3993[sizeof("modum.no")];
- char stringpool_str3994[sizeof("pila.pl")];
- char stringpool_str3995[sizeof("poznan.pl")];
- char stringpool_str3996[sizeof("gov.lb")];
- char stringpool_str3997[sizeof("edu.lb")];
- char stringpool_str3998[sizeof("oristano.it")];
- char stringpool_str3999[sizeof("karikatur.museum")];
- char stringpool_str4000[sizeof("com.lb")];
- char stringpool_str4001[sizeof("amber.museum")];
- char stringpool_str4002[sizeof("yugawa.fukushima.jp")];
- char stringpool_str4003[sizeof("ppg.br")];
- char stringpool_str4004[sizeof("yonezawa.yamagata.jp")];
- char stringpool_str4005[sizeof("fukumitsu.toyama.jp")];
- char stringpool_str4006[sizeof("minamiboso.chiba.jp")];
- char stringpool_str4007[sizeof("gov.lt")];
- char stringpool_str4008[sizeof("livorno.it")];
- char stringpool_str4009[sizeof("forum.hu")];
- char stringpool_str4010[sizeof("mil.kr")];
- char stringpool_str4011[sizeof("kariya.aichi.jp")];
- char stringpool_str4012[sizeof("gs.tm.no")];
- char stringpool_str4013[sizeof("stord.no")];
- char stringpool_str4014[sizeof("gov.lr")];
- char stringpool_str4015[sizeof("edu.lr")];
- char stringpool_str4016[sizeof("mulhouse.museum")];
- char stringpool_str4017[sizeof("iwate.jp")];
- char stringpool_str4018[sizeof("com.lr")];
- char stringpool_str4019[sizeof("naamesjevuemie.no")];
- char stringpool_str4020[sizeof("co.pl")];
- char stringpool_str4021[sizeof("shimodate.ibaraki.jp")];
- char stringpool_str4022[sizeof("takamori.nagano.jp")];
- char stringpool_str4023[sizeof("doomdns.org")];
- char stringpool_str4024[sizeof("ltd.lk")];
- char stringpool_str4025[sizeof("omiya.saitama.jp")];
- char stringpool_str4026[sizeof("architecture.museum")];
- char stringpool_str4027[sizeof("k12.ks.us")];
- char stringpool_str4028[sizeof("cci.fr")];
- char stringpool_str4029[sizeof("ulsan.kr")];
- char stringpool_str4030[sizeof("entomology.museum")];
- char stringpool_str4031[sizeof("uhren.museum")];
- char stringpool_str4032[sizeof("co.nl")];
- char stringpool_str4033[sizeof("mihama.wakayama.jp")];
- char stringpool_str4034[sizeof("nishi.fukuoka.jp")];
- char stringpool_str4035[sizeof("hikimi.shimane.jp")];
- char stringpool_str4036[sizeof("society.museum")];
- char stringpool_str4037[sizeof("hamura.tokyo.jp")];
- char stringpool_str4038[sizeof("hamamatsu.shizuoka.jp")];
- char stringpool_str4039[sizeof("tokai.aichi.jp")];
- char stringpool_str4040[sizeof("lib.ks.us")];
- char stringpool_str4041[sizeof("aarborte.no")];
- char stringpool_str4042[sizeof("oishida.yamagata.jp")];
- char stringpool_str4043[sizeof("computerhistory.museum")];
- char stringpool_str4044[sizeof("asker.no")];
- char stringpool_str4045[sizeof("cc.mo.us")];
- char stringpool_str4046[sizeof("tamamura.gunma.jp")];
- char stringpool_str4047[sizeof("veterinaire.km")];
- char stringpool_str4048[sizeof("getmyip.com")];
- char stringpool_str4049[sizeof("yoshioka.gunma.jp")];
- char stringpool_str4050[sizeof("uozu.toyama.jp")];
- char stringpool_str4051[sizeof("gov.kp")];
- char stringpool_str4052[sizeof("edu.kp")];
- char stringpool_str4053[sizeof("haboro.hokkaido.jp")];
- char stringpool_str4054[sizeof("cc.co.us")];
- char stringpool_str4055[sizeof("com.kp")];
- char stringpool_str4056[sizeof("oamishirasato.chiba.jp")];
- char stringpool_str4057[sizeof("monzaebrianza.it")];
- char stringpool_str4058[sizeof("tm.pl")];
- char stringpool_str4059[sizeof("noshiro.akita.jp")];
- char stringpool_str4060[sizeof("qc.com")];
- char stringpool_str4061[sizeof("miyada.nagano.jp")];
- char stringpool_str4062[sizeof("magadan.ru")];
- char stringpool_str4063[sizeof("so.gov.pl")];
- char stringpool_str4064[sizeof("sayama.saitama.jp")];
- char stringpool_str4065[sizeof("izena.okinawa.jp")];
- char stringpool_str4066[sizeof("abeno.osaka.jp")];
- char stringpool_str4067[sizeof("sr.gov.pl")];
- char stringpool_str4068[sizeof("viterbo.it")];
- char stringpool_str4069[sizeof("chijiwa.nagasaki.jp")];
- char stringpool_str4070[sizeof("doesntexist.org")];
- char stringpool_str4071[sizeof("org.hk")];
- char stringpool_str4072[sizeof("kommune.no")];
- char stringpool_str4073[sizeof("oregontrail.museum")];
- char stringpool_str4074[sizeof("kurume.fukuoka.jp")];
- char stringpool_str4075[sizeof("community.museum")];
- char stringpool_str4076[sizeof("mil.my")];
- char stringpool_str4077[sizeof("monza-brianza.it")];
- char stringpool_str4078[sizeof("kunimi.fukushima.jp")];
- char stringpool_str4079[sizeof("grp.lk")];
- char stringpool_str4080[sizeof("mihama.fukui.jp")];
- char stringpool_str4081[sizeof("askim.no")];
- char stringpool_str4082[sizeof("steam.museum")];
- char stringpool_str4083[sizeof("salerno.it")];
- char stringpool_str4084[sizeof("heroy.more-og-romsdal.no")];
- char stringpool_str4085[sizeof("nishikawa.yamagata.jp")];
- char stringpool_str4086[sizeof("ishinomaki.miyagi.jp")];
- char stringpool_str4087[sizeof("starachowice.pl")];
- char stringpool_str4088[sizeof("s3-us-gov-west-1.amazonaws.com")];
- char stringpool_str4089[sizeof("labor.museum")];
- char stringpool_str4090[sizeof("taito.tokyo.jp")];
- char stringpool_str4091[sizeof("yoita.niigata.jp")];
- char stringpool_str4092[sizeof("academy.museum")];
- char stringpool_str4093[sizeof("philately.museum")];
- char stringpool_str4094[sizeof("otago.museum")];
- char stringpool_str4095[sizeof("chiropractic.museum")];
- char stringpool_str4096[sizeof("is-very-bad.org")];
- char stringpool_str4097[sizeof("ueda.nagano.jp")];
- char stringpool_str4098[sizeof("org.hu")];
- char stringpool_str4099[sizeof("ako.hyogo.jp")];
- char stringpool_str4100[sizeof("bv.nl")];
- char stringpool_str4101[sizeof("kitadaito.okinawa.jp")];
- char stringpool_str4102[sizeof("salem.museum")];
- char stringpool_str4103[sizeof("leasing.aero")];
- char stringpool_str4104[sizeof("blogdns.org")];
- char stringpool_str4105[sizeof("org.ht")];
- char stringpool_str4106[sizeof("meguro.tokyo.jp")];
- char stringpool_str4107[sizeof("sortland.no")];
- char stringpool_str4108[sizeof("hashima.gifu.jp")];
- char stringpool_str4109[sizeof("org.hn")];
- char stringpool_str4110[sizeof("barum.no")];
- char stringpool_str4111[sizeof("okinoshima.shimane.jp")];
- char stringpool_str4112[sizeof("takahata.yamagata.jp")];
- char stringpool_str4113[sizeof("ritto.shiga.jp")];
- char stringpool_str4114[sizeof("shacknet.nu")];
- char stringpool_str4115[sizeof("powiat.pl")];
- char stringpool_str4116[sizeof("settlers.museum")];
- char stringpool_str4117[sizeof("tambov.ru")];
- char stringpool_str4118[sizeof("or.id")];
- char stringpool_str4119[sizeof("communication.museum")];
- char stringpool_str4120[sizeof("if.ua")];
- char stringpool_str4121[sizeof("daito.osaka.jp")];
- char stringpool_str4122[sizeof("mordovia.ru")];
- char stringpool_str4123[sizeof("tohnosho.chiba.jp")];
- char stringpool_str4124[sizeof("herad.no")];
- char stringpool_str4125[sizeof("kashiwazaki.niigata.jp")];
- char stringpool_str4126[sizeof("sayama.osaka.jp")];
- char stringpool_str4127[sizeof("togura.nagano.jp")];
- char stringpool_str4128[sizeof("grandrapids.museum")];
- char stringpool_str4129[sizeof("jinsekikogen.hiroshima.jp")];
- char stringpool_str4130[sizeof("ikeda.hokkaido.jp")];
- char stringpool_str4131[sizeof("higashi.fukuoka.jp")];
- char stringpool_str4132[sizeof("communications.museum")];
- char stringpool_str4133[sizeof("okinawa.okinawa.jp")];
- char stringpool_str4134[sizeof("yokaichiba.chiba.jp")];
- char stringpool_str4135[sizeof("discovery.museum")];
- char stringpool_str4136[sizeof("echizen.fukui.jp")];
- char stringpool_str4137[sizeof("udine.it")];
- char stringpool_str4138[sizeof("aya.miyazaki.jp")];
- char stringpool_str4139[sizeof("philadelphia.museum")];
- char stringpool_str4140[sizeof("toyama.toyama.jp")];
- char stringpool_str4141[sizeof("ambulance.museum")];
- char stringpool_str4142[sizeof("tateyama.chiba.jp")];
- char stringpool_str4143[sizeof("topology.museum")];
- char stringpool_str4144[sizeof("historisches.museum")];
- char stringpool_str4145[sizeof("is-a-student.com")];
- char stringpool_str4146[sizeof("kameyama.mie.jp")];
- char stringpool_str4147[sizeof("congresodelalengua3.ar")];
- char stringpool_str4148[sizeof("info")];
- char stringpool_str4149[sizeof("simple-url.com")];
- char stringpool_str4150[sizeof("gs.hm.no")];
- char stringpool_str4151[sizeof("uryu.hokkaido.jp")];
- char stringpool_str4152[sizeof("tra.kp")];
- char stringpool_str4153[sizeof("ranzan.saitama.jp")];
- char stringpool_str4154[sizeof("historisch.museum")];
- char stringpool_str4155[sizeof("rep.kp")];
- char stringpool_str4156[sizeof("k12.la.us")];
- char stringpool_str4157[sizeof("hanamaki.iwate.jp")];
- char stringpool_str4158[sizeof("info.mv")];
- char stringpool_str4159[sizeof("ac.id")];
- char stringpool_str4160[sizeof("shimofusa.chiba.jp")];
- char stringpool_str4161[sizeof("edu.pe")];
- char stringpool_str4162[sizeof("gov.pk")];
- char stringpool_str4163[sizeof("lib.la.us")];
- char stringpool_str4164[sizeof("edu.pk")];
- char stringpool_str4165[sizeof("com.pe")];
- char stringpool_str4166[sizeof("info.at")];
- char stringpool_str4167[sizeof("com.pk")];
- char stringpool_str4168[sizeof("gov.ge")];
- char stringpool_str4169[sizeof("edu.ge")];
- char stringpool_str4170[sizeof("bytom.pl")];
- char stringpool_str4171[sizeof("inabe.mie.jp")];
- char stringpool_str4172[sizeof("gov.gi")];
- char stringpool_str4173[sizeof("ojiya.niigata.jp")];
- char stringpool_str4174[sizeof("com.ge")];
- char stringpool_str4175[sizeof("edu.gi")];
- char stringpool_str4176[sizeof("co.gg")];
- char stringpool_str4177[sizeof("gov.gg")];
- char stringpool_str4178[sizeof("hurum.no")];
- char stringpool_str4179[sizeof("com.gi")];
- char stringpool_str4180[sizeof("nakhodka.ru")];
- char stringpool_str4181[sizeof("edu.pa")];
- char stringpool_str4182[sizeof("xxx")];
- char stringpool_str4183[sizeof("cechire.com")];
- char stringpool_str4184[sizeof("com.pa")];
- char stringpool_str4185[sizeof("gov.ps")];
- char stringpool_str4186[sizeof("edu.ps")];
- char stringpool_str4187[sizeof("com.ps")];
- char stringpool_str4188[sizeof("minamiizu.shizuoka.jp")];
- char stringpool_str4189[sizeof("ibaraki.osaka.jp")];
- char stringpool_str4190[sizeof("go.ug")];
- char stringpool_str4191[sizeof("suzuka.mie.jp")];
- char stringpool_str4192[sizeof("saigawa.fukuoka.jp")];
- char stringpool_str4193[sizeof("co.ug")];
- char stringpool_str4194[sizeof("nakatombetsu.hokkaido.jp")];
- char stringpool_str4195[sizeof("chiyoda.tokyo.jp")];
- char stringpool_str4196[sizeof("newhampshire.museum")];
- char stringpool_str4197[sizeof("moseushi.hokkaido.jp")];
- char stringpool_str4198[sizeof("gos.pk")];
- char stringpool_str4199[sizeof("honjo.akita.jp")];
- char stringpool_str4200[sizeof("homedns.org")];
- char stringpool_str4201[sizeof("tarama.okinawa.jp")];
- char stringpool_str4202[sizeof("is-a-caterer.com")];
- char stringpool_str4203[sizeof("ostroda.pl")];
- char stringpool_str4204[sizeof("mragowo.pl")];
- char stringpool_str4205[sizeof("inf.br")];
- char stringpool_str4206[sizeof("higashi.fukushima.jp")];
- char stringpool_str4207[sizeof("raholt.no")];
- char stringpool_str4208[sizeof("aso.kumamoto.jp")];
- char stringpool_str4209[sizeof("googlecode.com")];
- char stringpool_str4210[sizeof("info.tn")];
- char stringpool_str4211[sizeof("edu.uy")];
- char stringpool_str4212[sizeof("info.tt")];
- char stringpool_str4213[sizeof("com.uy")];
- char stringpool_str4214[sizeof("dnsdojo.com")];
- char stringpool_str4215[sizeof("muroran.hokkaido.jp")];
- char stringpool_str4216[sizeof("hachirogata.akita.jp")];
- char stringpool_str4217[sizeof("mod.gi")];
- char stringpool_str4218[sizeof("gov.pt")];
- char stringpool_str4219[sizeof("wf")];
- char stringpool_str4220[sizeof("edu.pt")];
- char stringpool_str4221[sizeof("com.pt")];
- char stringpool_str4222[sizeof("x.se")];
- char stringpool_str4223[sizeof("is-a-cpa.com")];
- char stringpool_str4224[sizeof("imabari.ehime.jp")];
- char stringpool_str4225[sizeof("edu.gt")];
- char stringpool_str4226[sizeof("is-a-knight.org")];
- char stringpool_str4227[sizeof("info.nr")];
- char stringpool_str4228[sizeof("com.gt")];
- char stringpool_str4229[sizeof("tm.mg")];
- char stringpool_str4230[sizeof("info.bb")];
- char stringpool_str4231[sizeof("gov.pr")];
- char stringpool_str4232[sizeof("gov.pn")];
- char stringpool_str4233[sizeof("gov.rw")];
- char stringpool_str4234[sizeof("edu.pr")];
- char stringpool_str4235[sizeof("inf.cu")];
- char stringpool_str4236[sizeof("edu.pn")];
- char stringpool_str4237[sizeof("edu.rw")];
- char stringpool_str4238[sizeof("castle.museum")];
- char stringpool_str4239[sizeof("com.pr")];
- char stringpool_str4240[sizeof("shirosato.ibaraki.jp")];
- char stringpool_str4241[sizeof("com.rw")];
- char stringpool_str4242[sizeof("gov.gr")];
- char stringpool_str4243[sizeof("gov.gn")];
- char stringpool_str4244[sizeof("edu.gr")];
- char stringpool_str4245[sizeof("edu.gn")];
- char stringpool_str4246[sizeof("abu.yamaguchi.jp")];
- char stringpool_str4247[sizeof("com.gr")];
- char stringpool_str4248[sizeof("com.gn")];
- char stringpool_str4249[sizeof("dyndns-pics.com")];
- char stringpool_str4250[sizeof("overhalla.no")];
- char stringpool_str4251[sizeof("gon.pk")];
- char stringpool_str4252[sizeof("cyber.museum")];
- char stringpool_str4253[sizeof("iwata.shizuoka.jp")];
- char stringpool_str4254[sizeof("ltd.gi")];
- char stringpool_str4255[sizeof("or.kr")];
- char stringpool_str4256[sizeof("avellino.it")];
- char stringpool_str4257[sizeof("gov.pl")];
- char stringpool_str4258[sizeof("net.hk")];
- char stringpool_str4259[sizeof("asakawa.fukushima.jp")];
- char stringpool_str4260[sizeof("edu.pl")];
- char stringpool_str4261[sizeof("aizumisato.fukushima.jp")];
- char stringpool_str4262[sizeof("info.au")];
- char stringpool_str4263[sizeof("monza-e-della-brianza.it")];
- char stringpool_str4264[sizeof("com.pl")];
- char stringpool_str4265[sizeof("pescara.it")];
- char stringpool_str4266[sizeof("med.pa")];
- char stringpool_str4267[sizeof("sakuragawa.ibaraki.jp")];
- char stringpool_str4268[sizeof("or.cr")];
- char stringpool_str4269[sizeof("chikusei.ibaraki.jp")];
- char stringpool_str4270[sizeof("is-an-actress.com")];
- char stringpool_str4271[sizeof("cc.ky.us")];
- char stringpool_str4272[sizeof("nakaniikawa.toyama.jp")];
- char stringpool_str4273[sizeof("is-a-guru.com")];
- char stringpool_str4274[sizeof("lomza.pl")];
- char stringpool_str4275[sizeof("cieszyn.pl")];
- char stringpool_str4276[sizeof("rovigo.it")];
- char stringpool_str4277[sizeof("info.sd")];
- char stringpool_str4278[sizeof("horology.museum")];
- char stringpool_str4279[sizeof("hirado.nagasaki.jp")];
- char stringpool_str4280[sizeof("atm.pl")];
- char stringpool_str4281[sizeof("biella.it")];
- char stringpool_str4282[sizeof("sld.pa")];
- char stringpool_str4283[sizeof("ikeda.nagano.jp")];
- char stringpool_str4284[sizeof("gsm.pl")];
- char stringpool_str4285[sizeof("sos.pl")];
- char stringpool_str4286[sizeof("est.pr")];
- char stringpool_str4287[sizeof("miasa.nagano.jp")];
- char stringpool_str4288[sizeof("art.pl")];
- char stringpool_str4289[sizeof("gob.pe")];
- char stringpool_str4290[sizeof("sex.pl")];
- char stringpool_str4291[sizeof("gob.pk")];
- char stringpool_str4292[sizeof("is-an-artist.com")];
- char stringpool_str4293[sizeof("miharu.fukushima.jp")];
- char stringpool_str4294[sizeof("info.na")];
- char stringpool_str4295[sizeof("x.bg")];
- char stringpool_str4296[sizeof("microlight.aero")];
- char stringpool_str4297[sizeof("aisho.shiga.jp")];
- char stringpool_str4298[sizeof("paroch.k12.ma.us")];
- char stringpool_str4299[sizeof("info.nf")];
- char stringpool_str4300[sizeof("s3-website-eu-west-1.amazonaws.com")];
- char stringpool_str4301[sizeof("gob.pa")];
- char stringpool_str4302[sizeof("net.ht")];
- char stringpool_str4303[sizeof("minami.fukuoka.jp")];
- char stringpool_str4304[sizeof("cc.wy.us")];
- char stringpool_str4305[sizeof("abo.pa")];
- char stringpool_str4306[sizeof("oguni.yamagata.jp")];
- char stringpool_str4307[sizeof("minamifurano.hokkaido.jp")];
- char stringpool_str4308[sizeof("gov.mw")];
- char stringpool_str4309[sizeof("pittsburgh.museum")];
- char stringpool_str4310[sizeof("info.la")];
- char stringpool_str4311[sizeof("edu.mw")];
- char stringpool_str4312[sizeof("gop.pk")];
- char stringpool_str4313[sizeof("iide.yamagata.jp")];
- char stringpool_str4314[sizeof("com.mw")];
- char stringpool_str4315[sizeof("net.hn")];
- char stringpool_str4316[sizeof("info.ec")];
- char stringpool_str4317[sizeof("co.ag")];
- char stringpool_str4318[sizeof("dyndns-blog.com")];
- char stringpool_str4319[sizeof("aid.pl")];
- char stringpool_str4320[sizeof("yuza.yamagata.jp")];
- char stringpool_str4321[sizeof("med.pl")];
- char stringpool_str4322[sizeof("gok.pk")];
- char stringpool_str4323[sizeof("hamar.no")];
- char stringpool_str4324[sizeof("sc.kr")];
- char stringpool_str4325[sizeof("ac.kr")];
- char stringpool_str4326[sizeof("gub.uy")];
- char stringpool_str4327[sizeof("ac.ir")];
- char stringpool_str4328[sizeof("kotoura.tottori.jp")];
- char stringpool_str4329[sizeof("ina.ibaraki.jp")];
- char stringpool_str4330[sizeof("ac.cr")];
- char stringpool_str4331[sizeof("iwamizawa.hokkaido.jp")];
- char stringpool_str4332[sizeof("seaport.museum")];
- char stringpool_str4333[sizeof("hamaroy.no")];
- char stringpool_str4334[sizeof("notaires.fr")];
- char stringpool_str4335[sizeof("cc.ny.us")];
- char stringpool_str4336[sizeof("skanland.no")];
- char stringpool_str4337[sizeof("freemasonry.museum")];
- char stringpool_str4338[sizeof("potenza.it")];
- char stringpool_str4339[sizeof("civilisation.museum")];
- char stringpool_str4340[sizeof("koryo.nara.jp")];
- char stringpool_str4341[sizeof("fam.pk")];
- char stringpool_str4342[sizeof("gob.gt")];
- char stringpool_str4343[sizeof("shirako.chiba.jp")];
- char stringpool_str4344[sizeof("biz.pk")];
- char stringpool_str4345[sizeof("embroidery.museum")];
- char stringpool_str4346[sizeof("minamiaiki.nagano.jp")];
- char stringpool_str4347[sizeof("bashkiria.ru")];
- char stringpool_str4348[sizeof("lecco.it")];
- char stringpool_str4349[sizeof("lincoln.museum")];
- char stringpool_str4350[sizeof("onagawa.miyagi.jp")];
- char stringpool_str4351[sizeof("amusement.aero")];
- char stringpool_str4352[sizeof("hirara.okinawa.jp")];
- char stringpool_str4353[sizeof("rec.ro")];
- char stringpool_str4354[sizeof("gda.pl")];
- char stringpool_str4355[sizeof("minamimaki.nagano.jp")];
- char stringpool_str4356[sizeof("chiryu.aichi.jp")];
- char stringpool_str4357[sizeof("yugawara.kanagawa.jp")];
- char stringpool_str4358[sizeof("shioya.tochigi.jp")];
- char stringpool_str4359[sizeof("merseine.nu")];
- char stringpool_str4360[sizeof("ikata.ehime.jp")];
- char stringpool_str4361[sizeof("vyatka.ru")];
- char stringpool_str4362[sizeof("aquila.it")];
- char stringpool_str4363[sizeof("xz.cn")];
- char stringpool_str4364[sizeof("thruhere.net")];
- char stringpool_str4365[sizeof("daegu.kr")];
- char stringpool_str4366[sizeof("mil.pe")];
- char stringpool_str4367[sizeof("mil.ge")];
- char stringpool_str4368[sizeof("rel.pl")];
- char stringpool_str4369[sizeof("ikeda.fukui.jp")];
- char stringpool_str4370[sizeof("agrar.hu")];
- char stringpool_str4371[sizeof("tokyo.jp")];
- char stringpool_str4372[sizeof("ono.fukui.jp")];
- char stringpool_str4373[sizeof("homeunix.net")];
- char stringpool_str4374[sizeof("philadelphiaarea.museum")];
- char stringpool_str4375[sizeof("ac.pr")];
- char stringpool_str4376[sizeof("uruma.okinawa.jp")];
- char stringpool_str4377[sizeof("geisei.kochi.jp")];
- char stringpool_str4378[sizeof("nagato.yamaguchi.jp")];
- char stringpool_str4379[sizeof("oyama.tochigi.jp")];
- char stringpool_str4380[sizeof("stockholm.museum")];
- char stringpool_str4381[sizeof("cherkasy.ua")];
- char stringpool_str4382[sizeof("dnsalias.net")];
- char stringpool_str4383[sizeof("name.az")];
- char stringpool_str4384[sizeof("gotemba.shizuoka.jp")];
- char stringpool_str4385[sizeof("niimi.okayama.jp")];
- char stringpool_str4386[sizeof("frankfurt.museum")];
- char stringpool_str4387[sizeof("nishiokoppe.hokkaido.jp")];
- char stringpool_str4388[sizeof("ac.im")];
- char stringpool_str4389[sizeof("xj.cn")];
- char stringpool_str4390[sizeof("biz.pr")];
- char stringpool_str4391[sizeof("vevelstad.no")];
- char stringpool_str4392[sizeof("stange.no")];
- char stringpool_str4393[sizeof("urawa.saitama.jp")];
- char stringpool_str4394[sizeof("koriyama.fukushima.jp")];
- char stringpool_str4395[sizeof("haram.no")];
- char stringpool_str4396[sizeof("ofunato.iwate.jp")];
- char stringpool_str4397[sizeof("mazury.pl")];
- char stringpool_str4398[sizeof("mil.uy")];
- char stringpool_str4399[sizeof("harima.hyogo.jp")];
- char stringpool_str4400[sizeof("shimotsuke.tochigi.jp")];
- char stringpool_str4401[sizeof("choyo.kumamoto.jp")];
- char stringpool_str4402[sizeof("setouchi.okayama.jp")];
- char stringpool_str4403[sizeof("biz.pl")];
- char stringpool_str4404[sizeof("mil.gt")];
- char stringpool_str4405[sizeof("it.ao")];
- char stringpool_str4406[sizeof("soo.kagoshima.jp")];
- char stringpool_str4407[sizeof("for-our.info")];
- char stringpool_str4408[sizeof("narashino.chiba.jp")];
- char stringpool_str4409[sizeof("mil.rw")];
- char stringpool_str4410[sizeof("is-an-entertainer.com")];
- char stringpool_str4411[sizeof("googleapis.com")];
- char stringpool_str4412[sizeof("public.museum")];
- char stringpool_str4413[sizeof("homeunix.org")];
- char stringpool_str4414[sizeof("edu.pf")];
- char stringpool_str4415[sizeof("okaya.nagano.jp")];
- char stringpool_str4416[sizeof("kawara.fukuoka.jp")];
- char stringpool_str4417[sizeof("com.pf")];
- char stringpool_str4418[sizeof("mamurogawa.yamagata.jp")];
- char stringpool_str4419[sizeof("k12.pa.us")];
- char stringpool_str4420[sizeof("tsukui.kanagawa.jp")];
- char stringpool_str4421[sizeof("mil.pl")];
- char stringpool_str4422[sizeof("info.co")];
- char stringpool_str4423[sizeof("dnsalias.org")];
- char stringpool_str4424[sizeof("k12.ga.us")];
- char stringpool_str4425[sizeof("name.qa")];
- char stringpool_str4426[sizeof("yoshida.saitama.jp")];
- char stringpool_str4427[sizeof("nichinan.tottori.jp")];
- char stringpool_str4428[sizeof("swinoujscie.pl")];
- char stringpool_str4429[sizeof("tamaki.mie.jp")];
- char stringpool_str4430[sizeof("nom.fr")];
- char stringpool_str4431[sizeof("tokamachi.niigata.jp")];
- char stringpool_str4432[sizeof("kaluga.ru")];
- char stringpool_str4433[sizeof("lib.pa.us")];
- char stringpool_str4434[sizeof("cargo.aero")];
- char stringpool_str4435[sizeof("lib.ga.us")];
- char stringpool_str4436[sizeof("ohira.tochigi.jp")];
- char stringpool_str4437[sizeof("sykkylven.no")];
- char stringpool_str4438[sizeof("paris.museum")];
- char stringpool_str4439[sizeof("belau.pw")];
- char stringpool_str4440[sizeof("info.pr")];
- char stringpool_str4441[sizeof("omasvuotna.no")];
- char stringpool_str4442[sizeof("biz.mw")];
- char stringpool_str4443[sizeof("bjerkreim.no")];
- char stringpool_str4444[sizeof("bardu.no")];
- char stringpool_str4445[sizeof("k12.gu.us")];
- char stringpool_str4446[sizeof("unnan.shimane.jp")];
- char stringpool_str4447[sizeof("edu.gp")];
- char stringpool_str4448[sizeof("kozaki.chiba.jp")];
- char stringpool_str4449[sizeof("artsandcrafts.museum")];
- char stringpool_str4450[sizeof("com.gp")];
- char stringpool_str4451[sizeof("ono.fukushima.jp")];
- char stringpool_str4452[sizeof("info.ro")];
- char stringpool_str4453[sizeof("info.pl")];
- char stringpool_str4454[sizeof("elk.pl")];
- char stringpool_str4455[sizeof("naustdal.no")];
- char stringpool_str4456[sizeof("bamble.no")];
- char stringpool_str4457[sizeof("nesset.no")];
- char stringpool_str4458[sizeof("birthplace.museum")];
- char stringpool_str4459[sizeof("k12.pr.us")];
- char stringpool_str4460[sizeof("ibaraki.ibaraki.jp")];
- char stringpool_str4461[sizeof("minamiyamashiro.kyoto.jp")];
- char stringpool_str4462[sizeof("info.pk")];
- char stringpool_str4463[sizeof("lib.gu.us")];
- char stringpool_str4464[sizeof("info.ht")];
- char stringpool_str4465[sizeof("asakuchi.okayama.jp")];
- char stringpool_str4466[sizeof("omotego.fukushima.jp")];
- char stringpool_str4467[sizeof("gov.ph")];
- char stringpool_str4468[sizeof("minamitane.kagoshima.jp")];
- char stringpool_str4469[sizeof("edu.ph")];
- char stringpool_str4470[sizeof("go.jp")];
- char stringpool_str4471[sizeof("hanamigawa.chiba.jp")];
- char stringpool_str4472[sizeof("ed.jp")];
- char stringpool_str4473[sizeof("com.ph")];
- char stringpool_str4474[sizeof("co.jp")];
- char stringpool_str4475[sizeof("gov.gh")];
- char stringpool_str4476[sizeof("edu.gh")];
- char stringpool_str4477[sizeof("ad.jp")];
- char stringpool_str4478[sizeof("kobierzyce.pl")];
- char stringpool_str4479[sizeof("annaka.gunma.jp")];
- char stringpool_str4480[sizeof("detroit.museum")];
- char stringpool_str4481[sizeof("lib.pr.us")];
- char stringpool_str4482[sizeof("com.gh")];
- char stringpool_str4483[sizeof("kamikoani.akita.jp")];
- char stringpool_str4484[sizeof("telekommunikation.museum")];
- char stringpool_str4485[sizeof("dontexist.org")];
- char stringpool_str4486[sizeof("yorii.saitama.jp")];
- char stringpool_str4487[sizeof("geology.museum")];
- char stringpool_str4488[sizeof("gr.jp")];
- char stringpool_str4489[sizeof("ohi.fukui.jp")];
- char stringpool_str4490[sizeof("higashishirakawa.gifu.jp")];
- char stringpool_str4491[sizeof("is-a-green.com")];
- char stringpool_str4492[sizeof("ikawa.akita.jp")];
- char stringpool_str4493[sizeof("embaixada.st")];
- char stringpool_str4494[sizeof("org.do")];
- char stringpool_str4495[sizeof("org.dm")];
- char stringpool_str4496[sizeof("amakusa.kumamoto.jp")];
- char stringpool_str4497[sizeof("design.museum")];
- char stringpool_str4498[sizeof("org.dz")];
- char stringpool_str4499[sizeof("kosaka.akita.jp")];
- char stringpool_str4500[sizeof("kembuchi.hokkaido.jp")];
- char stringpool_str4501[sizeof("ichiba.tokushima.jp")];
- char stringpool_str4502[sizeof("is-uberleet.com")];
- char stringpool_str4503[sizeof("szkola.pl")];
- char stringpool_str4504[sizeof("omachi.nagano.jp")];
- char stringpool_str4505[sizeof("info.ki")];
- char stringpool_str4506[sizeof("stuff-4-sale.us")];
- char stringpool_str4507[sizeof("podhale.pl")];
- char stringpool_str4508[sizeof("grozny.ru")];
- char stringpool_str4509[sizeof("sakurai.nara.jp")];
- char stringpool_str4510[sizeof("snillfjord.no")];
- char stringpool_str4511[sizeof("lahppi.no")];
- char stringpool_str4512[sizeof("tagami.niigata.jp")];
- char stringpool_str4513[sizeof("design.aero")];
- char stringpool_str4514[sizeof("civilaviation.aero")];
- char stringpool_str4515[sizeof("is-found.org")];
- char stringpool_str4516[sizeof("ukiha.fukuoka.jp")];
- char stringpool_str4517[sizeof("hasami.nagasaki.jp")];
- char stringpool_str4518[sizeof("endofinternet.net")];
- char stringpool_str4519[sizeof("jur.pro")];
- char stringpool_str4520[sizeof("miyama.fukuoka.jp")];
- char stringpool_str4521[sizeof("med.pro")];
- char stringpool_str4522[sizeof("zgorzelec.pl")];
- char stringpool_str4523[sizeof("itayanagi.aomori.jp")];
- char stringpool_str4524[sizeof("loyalist.museum")];
- char stringpool_str4525[sizeof("info.hu")];
- char stringpool_str4526[sizeof("kawaminami.miyazaki.jp")];
- char stringpool_str4527[sizeof("bolzano.it")];
- char stringpool_str4528[sizeof("minamiuonuma.niigata.jp")];
- char stringpool_str4529[sizeof("is-a-painter.com")];
- char stringpool_str4530[sizeof("kaneyama.fukushima.jp")];
- char stringpool_str4531[sizeof("is-into-anime.com")];
- char stringpool_str4532[sizeof("xn--j1amh")];
- char stringpool_str4533[sizeof("kamikawa.saitama.jp")];
- char stringpool_str4534[sizeof("xn--wgbl6a")];
- char stringpool_str4535[sizeof("minamiminowa.nagano.jp")];
- char stringpool_str4536[sizeof("hasama.oita.jp")];
- char stringpool_str4537[sizeof("okagaki.fukuoka.jp")];
- char stringpool_str4538[sizeof("fussa.tokyo.jp")];
- char stringpool_str4539[sizeof("tsurugashima.saitama.jp")];
- char stringpool_str4540[sizeof("kartuzy.pl")];
- char stringpool_str4541[sizeof("yoshino.nara.jp")];
- char stringpool_str4542[sizeof("nissedal.no")];
- char stringpool_str4543[sizeof("belluno.it")];
- char stringpool_str4544[sizeof("mazowsze.pl")];
- char stringpool_str4545[sizeof("aki.kochi.jp")];
- char stringpool_str4546[sizeof("ena.gifu.jp")];
- char stringpool_str4547[sizeof("nishio.aichi.jp")];
- char stringpool_str4548[sizeof("xn--nnx388a")];
- char stringpool_str4549[sizeof("xn--asky-ira.no")];
- char stringpool_str4550[sizeof("kagamino.okayama.jp")];
- char stringpool_str4551[sizeof("tsuchiura.ibaraki.jp")];
- char stringpool_str4552[sizeof("newjersey.museum")];
- char stringpool_str4553[sizeof("mantova.it")];
- char stringpool_str4554[sizeof("heguri.nara.jp")];
- char stringpool_str4555[sizeof("takamatsu.kagawa.jp")];
- char stringpool_str4556[sizeof("spjelkavik.no")];
- char stringpool_str4557[sizeof("aknoluokta.no")];
- char stringpool_str4558[sizeof("fujikawa.shizuoka.jp")];
- char stringpool_str4559[sizeof("yoshida.shizuoka.jp")];
- char stringpool_str4560[sizeof("xn--skjk-soa.no")];
- char stringpool_str4561[sizeof("nakatane.kagoshima.jp")];
- char stringpool_str4562[sizeof("gs.bu.no")];
- char stringpool_str4563[sizeof("missoula.museum")];
- char stringpool_str4564[sizeof("planetarium.museum")];
- char stringpool_str4565[sizeof("is-a-socialist.com")];
- char stringpool_str4566[sizeof("id.ly")];
- char stringpool_str4567[sizeof("kitakami.iwate.jp")];
- char stringpool_str4568[sizeof("nagoya.jp")];
- char stringpool_str4569[sizeof("shinonsen.hyogo.jp")];
- char stringpool_str4570[sizeof("minoh.osaka.jp")];
- char stringpool_str4571[sizeof("karumai.iwate.jp")];
- char stringpool_str4572[sizeof("is-leet.com")];
- char stringpool_str4573[sizeof("pskov.ru")];
- char stringpool_str4574[sizeof("is-a-rockstar.com")];
- char stringpool_str4575[sizeof("off.ai")];
- char stringpool_str4576[sizeof("meraker.no")];
- char stringpool_str4577[sizeof("cc.oh.us")];
- char stringpool_str4578[sizeof("andria-barletta-trani.it")];
- char stringpool_str4579[sizeof("oyodo.nara.jp")];
- char stringpool_str4580[sizeof("kasumigaura.ibaraki.jp")];
- char stringpool_str4581[sizeof("nationalheritage.museum")];
- char stringpool_str4582[sizeof("xn--trgstad-r1a.no")];
- char stringpool_str4583[sizeof("misaki.osaka.jp")];
- char stringpool_str4584[sizeof("iwade.wakayama.jp")];
- char stringpool_str4585[sizeof("pavia.it")];
- char stringpool_str4586[sizeof("chikushino.fukuoka.jp")];
- char stringpool_str4587[sizeof("org.ro")];
- char stringpool_str4588[sizeof("monza.it")];
- char stringpool_str4589[sizeof("dynalias.net")];
- char stringpool_str4590[sizeof("turek.pl")];
- char stringpool_str4591[sizeof("suzaka.nagano.jp")];
- char stringpool_str4592[sizeof("parma.it")];
- char stringpool_str4593[sizeof("macerata.it")];
- char stringpool_str4594[sizeof("mil.ph")];
- char stringpool_str4595[sizeof("padua.it")];
- char stringpool_str4596[sizeof("or.mu")];
- char stringpool_str4597[sizeof("mil.gh")];
- char stringpool_str4598[sizeof("tsukumi.oita.jp")];
- char stringpool_str4599[sizeof("homelinux.org")];
- char stringpool_str4600[sizeof("org.rs")];
- char stringpool_str4601[sizeof("kafjord.no")];
- char stringpool_str4602[sizeof("xn--brum-voa.no")];
- char stringpool_str4603[sizeof("bar.pro")];
- char stringpool_str4604[sizeof("chiyoda.gunma.jp")];
- char stringpool_str4605[sizeof("agrigento.it")];
- char stringpool_str4606[sizeof("gov.ky")];
- char stringpool_str4607[sizeof("tachiarai.fukuoka.jp")];
- char stringpool_str4608[sizeof("edu.ky")];
- char stringpool_str4609[sizeof("bedzin.pl")];
- char stringpool_str4610[sizeof("com.ky")];
- char stringpool_str4611[sizeof("kitakata.miyazaki.jp")];
- char stringpool_str4612[sizeof("xn--snes-poa.no")];
- char stringpool_str4613[sizeof("ikeda.osaka.jp")];
- char stringpool_str4614[sizeof("historicalsociety.museum")];
- char stringpool_str4615[sizeof("xn--andy-ira.no")];
- char stringpool_str4616[sizeof("owariasahi.aichi.jp")];
- char stringpool_str4617[sizeof("cpa.pro")];
- char stringpool_str4618[sizeof("org.ru")];
- char stringpool_str4619[sizeof("selbu.no")];
- char stringpool_str4620[sizeof("xn--slat-5na.no")];
- char stringpool_str4621[sizeof("ogawa.ibaraki.jp")];
- char stringpool_str4622[sizeof("kamikawa.hokkaido.jp")];
- char stringpool_str4623[sizeof("kawakami.nara.jp")];
- char stringpool_str4624[sizeof("oceanographic.museum")];
- char stringpool_str4625[sizeof("okawa.kochi.jp")];
- char stringpool_str4626[sizeof("cc.nh.us")];
- char stringpool_str4627[sizeof("kunohe.iwate.jp")];
- char stringpool_str4628[sizeof("cherkassy.ua")];
- char stringpool_str4629[sizeof("dynalias.org")];
- char stringpool_str4630[sizeof("odesa.ua")];
- char stringpool_str4631[sizeof("sande.vestfold.no")];
- char stringpool_str4632[sizeof("shibukawa.gunma.jp")];
- char stringpool_str4633[sizeof("cc.sc.us")];
- char stringpool_str4634[sizeof("yoshimi.saitama.jp")];
- char stringpool_str4635[sizeof("net.do")];
- char stringpool_str4636[sizeof("net.dm")];
- char stringpool_str4637[sizeof("chungbuk.kr")];
- char stringpool_str4638[sizeof("decorativearts.museum")];
- char stringpool_str4639[sizeof("chungnam.kr")];
- char stringpool_str4640[sizeof("net.dz")];
- char stringpool_str4641[sizeof("org.mo")];
- char stringpool_str4642[sizeof("org.me")];
- char stringpool_str4643[sizeof("org.mk")];
- char stringpool_str4644[sizeof("isehara.kanagawa.jp")];
- char stringpool_str4645[sizeof("minamisanriku.miyagi.jp")];
- char stringpool_str4646[sizeof("org.mg")];
- char stringpool_str4647[sizeof("afjord.no")];
- char stringpool_str4648[sizeof("xn--snase-nra.no")];
- char stringpool_str4649[sizeof("mitaka.tokyo.jp")];
- char stringpool_str4650[sizeof("yura.wakayama.jp")];
- char stringpool_str4651[sizeof("kahoku.yamagata.jp")];
- char stringpool_str4652[sizeof("org.ma")];
- char stringpool_str4653[sizeof("ac.mu")];
- char stringpool_str4654[sizeof("us.com")];
- char stringpool_str4655[sizeof("ibara.okayama.jp")];
- char stringpool_str4656[sizeof("xn--bievt-0qa.no")];
- char stringpool_str4657[sizeof("xn--stjrdal-s1a.no")];
- char stringpool_str4658[sizeof("fukuroi.shizuoka.jp")];
- char stringpool_str4659[sizeof("minakami.gunma.jp")];
- char stringpool_str4660[sizeof("sanok.pl")];
- char stringpool_str4661[sizeof("naklo.pl")];
- char stringpool_str4662[sizeof("onojo.fukuoka.jp")];
- char stringpool_str4663[sizeof("xn--bdddj-mrabd.no")];
- char stringpool_str4664[sizeof("ujitawara.kyoto.jp")];
- char stringpool_str4665[sizeof("xn--snsa-roa.no")];
- char stringpool_str4666[sizeof("xn--smla-hra.no")];
- char stringpool_str4667[sizeof("misugi.mie.jp")];
- char stringpool_str4668[sizeof("tychy.pl")];
- char stringpool_str4669[sizeof("karelia.ru")];
- char stringpool_str4670[sizeof("org.mu")];
- char stringpool_str4671[sizeof("toyohashi.aichi.jp")];
- char stringpool_str4672[sizeof("sanfrancisco.museum")];
- char stringpool_str4673[sizeof("minamioguni.kumamoto.jp")];
- char stringpool_str4674[sizeof("hisayama.fukuoka.jp")];
- char stringpool_str4675[sizeof("notodden.no")];
- char stringpool_str4676[sizeof("iwaki.fukushima.jp")];
- char stringpool_str4677[sizeof("yusui.kagoshima.jp")];
- char stringpool_str4678[sizeof("toyokawa.aichi.jp")];
- char stringpool_str4679[sizeof("klabu.no")];
- char stringpool_str4680[sizeof("inami.toyama.jp")];
- char stringpool_str4681[sizeof("izumi.kagoshima.jp")];
- char stringpool_str4682[sizeof("org.iq")];
- char stringpool_str4683[sizeof("nichinan.miyazaki.jp")];
- char stringpool_str4684[sizeof("brandywinevalley.museum")];
- char stringpool_str4685[sizeof("xn--seral-lra.no")];
- char stringpool_str4686[sizeof("org.mn")];
- char stringpool_str4687[sizeof("modalen.no")];
- char stringpool_str4688[sizeof("oz.au")];
- char stringpool_str4689[sizeof("s3-sa-east-1.amazonaws.com")];
- char stringpool_str4690[sizeof("nakai.kanagawa.jp")];
- char stringpool_str4691[sizeof("hidaka.saitama.jp")];
- char stringpool_str4692[sizeof("omanmobile.om")];
- char stringpool_str4693[sizeof("furukawa.miyagi.jp")];
- char stringpool_str4694[sizeof("kolobrzeg.pl")];
- char stringpool_str4695[sizeof("org.ml")];
- char stringpool_str4696[sizeof("clock.museum")];
- char stringpool_str4697[sizeof("zgrad.ru")];
- char stringpool_str4698[sizeof("writesthisblog.com")];
- char stringpool_str4699[sizeof("nesodden.no")];
- char stringpool_str4700[sizeof("teaches-yoga.com")];
- char stringpool_str4701[sizeof("tsukuba.ibaraki.jp")];
- char stringpool_str4702[sizeof("est-mon-blogueur.com")];
- char stringpool_str4703[sizeof("is-a-conservative.com")];
- char stringpool_str4704[sizeof("guovdageaidnu.no")];
- char stringpool_str4705[sizeof("khmelnitskiy.ua")];
- char stringpool_str4706[sizeof("xn--xkc2dl3a5ee0h")];
- char stringpool_str4707[sizeof("tsuruta.aomori.jp")];
- char stringpool_str4708[sizeof("bydgoszcz.pl")];
- char stringpool_str4709[sizeof("kanagawa.jp")];
- char stringpool_str4710[sizeof("rahkkeravju.no")];
- char stringpool_str4711[sizeof("trustee.museum")];
- char stringpool_str4712[sizeof("is-an-actor.com")];
- char stringpool_str4713[sizeof("flekkefjord.no")];
- char stringpool_str4714[sizeof("xn--vard-jra.no")];
- char stringpool_str4715[sizeof("cymru.museum")];
- char stringpool_str4716[sizeof("nom.ro")];
- char stringpool_str4717[sizeof("nom.re")];
- char stringpool_str4718[sizeof("nishi.osaka.jp")];
- char stringpool_str4719[sizeof("shingo.aomori.jp")];
- char stringpool_str4720[sizeof("stargard.pl")];
- char stringpool_str4721[sizeof("pc.it")];
- char stringpool_str4722[sizeof("siellak.no")];
- char stringpool_str4723[sizeof("zao.miyagi.jp")];
- char stringpool_str4724[sizeof("shinyoshitomi.fukuoka.jp")];
- char stringpool_str4725[sizeof("history.museum")];
- char stringpool_str4726[sizeof("is-a-bulls-fan.com")];
- char stringpool_str4727[sizeof("uk.com")];
- char stringpool_str4728[sizeof("zamami.okinawa.jp")];
- char stringpool_str4729[sizeof("xn--sknit-yqa.no")];
- char stringpool_str4730[sizeof("endofinternet.org")];
- char stringpool_str4731[sizeof("hirakata.osaka.jp")];
- char stringpool_str4732[sizeof("gs.svalbard.no")];
- char stringpool_str4733[sizeof("ne.kr")];
- char stringpool_str4734[sizeof("law.pro")];
- char stringpool_str4735[sizeof("seoul.kr")];
- char stringpool_str4736[sizeof("xn--troms-zua.no")];
- char stringpool_str4737[sizeof("giessen.museum")];
- char stringpool_str4738[sizeof("nov.ru")];
- char stringpool_str4739[sizeof("kiyama.saga.jp")];
- char stringpool_str4740[sizeof("science-fiction.museum")];
- char stringpool_str4741[sizeof("sch.uk")];
- char stringpool_str4742[sizeof("takikawa.hokkaido.jp")];
- char stringpool_str4743[sizeof("gov.ly")];
- char stringpool_str4744[sizeof("edu.ly")];
- char stringpool_str4745[sizeof("com.ly")];
- char stringpool_str4746[sizeof("ashikaga.tochigi.jp")];
- char stringpool_str4747[sizeof("oizumi.gunma.jp")];
- char stringpool_str4748[sizeof("seiyo.ehime.jp")];
- char stringpool_str4749[sizeof("oketo.hokkaido.jp")];
- char stringpool_str4750[sizeof("isleofman.museum")];
- char stringpool_str4751[sizeof("habikino.osaka.jp")];
- char stringpool_str4752[sizeof("kawakami.nagano.jp")];
- char stringpool_str4753[sizeof("nt.edu.au")];
- char stringpool_str4754[sizeof("songdalen.no")];
- char stringpool_str4755[sizeof("xn--trna-woa.no")];
- char stringpool_str4756[sizeof("of.no")];
- char stringpool_str4757[sizeof("sakaki.nagano.jp")];
- char stringpool_str4758[sizeof("sanuki.kagawa.jp")];
- char stringpool_str4759[sizeof("takahama.fukui.jp")];
- char stringpool_str4760[sizeof("gov.mv")];
- char stringpool_str4761[sizeof("edu.mv")];
- char stringpool_str4762[sizeof("burghof.museum")];
- char stringpool_str4763[sizeof("toyako.hokkaido.jp")];
- char stringpool_str4764[sizeof("com.mv")];
- char stringpool_str4765[sizeof("namsskogan.no")];
- char stringpool_str4766[sizeof("hidaka.hokkaido.jp")];
- char stringpool_str4767[sizeof("xn--vads-jra.no")];
- char stringpool_str4768[sizeof("brussel.museum")];
- char stringpool_str4769[sizeof("siedlce.pl")];
- char stringpool_str4770[sizeof("nom.mg")];
- char stringpool_str4771[sizeof("drangedal.no")];
- char stringpool_str4772[sizeof("iglesias-carbonia.it")];
- char stringpool_str4773[sizeof("joshkar-ola.ru")];
- char stringpool_str4774[sizeof("unzen.nagasaki.jp")];
- char stringpool_str4775[sizeof("kamikitayama.nara.jp")];
- char stringpool_str4776[sizeof("naroy.no")];
- char stringpool_str4777[sizeof("news.hu")];
- char stringpool_str4778[sizeof("tsuiki.fukuoka.jp")];
- char stringpool_str4779[sizeof("idv.hk")];
- char stringpool_str4780[sizeof("art.museum")];
- char stringpool_str4781[sizeof("ryuoh.shiga.jp")];
- char stringpool_str4782[sizeof("psc.br")];
- char stringpool_str4783[sizeof("oto.fukuoka.jp")];
- char stringpool_str4784[sizeof("net.ru")];
- char stringpool_str4785[sizeof("inatsuki.fukuoka.jp")];
- char stringpool_str4786[sizeof("murakami.niigata.jp")];
- char stringpool_str4787[sizeof("iwate.iwate.jp")];
- char stringpool_str4788[sizeof("nishiwaki.hyogo.jp")];
- char stringpool_str4789[sizeof("sakyo.kyoto.jp")];
- char stringpool_str4790[sizeof("yufu.oita.jp")];
- char stringpool_str4791[sizeof("is-a-personaltrainer.com")];
- char stringpool_str4792[sizeof("gs.ol.no")];
- char stringpool_str4793[sizeof("stuff-4-sale.org")];
- char stringpool_str4794[sizeof("hidaka.wakayama.jp")];
- char stringpool_str4795[sizeof("larsson.museum")];
- char stringpool_str4796[sizeof("k12.ky.us")];
- char stringpool_str4797[sizeof("oystre-slidre.no")];
- char stringpool_str4798[sizeof("tomakomai.hokkaido.jp")];
- char stringpool_str4799[sizeof("gyokuto.kumamoto.jp")];
- char stringpool_str4800[sizeof("kosuge.yamanashi.jp")];
- char stringpool_str4801[sizeof("incheon.kr")];
- char stringpool_str4802[sizeof("med.ly")];
- char stringpool_str4803[sizeof("usuki.oita.jp")];
- char stringpool_str4804[sizeof("net.mo")];
- char stringpool_str4805[sizeof("net.me")];
- char stringpool_str4806[sizeof("net.mk")];
- char stringpool_str4807[sizeof("lib.ky.us")];
- char stringpool_str4808[sizeof("xn--berlevg-jxa.no")];
- char stringpool_str4809[sizeof("is-a-techie.com")];
- char stringpool_str4810[sizeof("steigen.no")];
- char stringpool_str4811[sizeof("xn--sr-aurdal-l8a.no")];
- char stringpool_str4812[sizeof("ayase.kanagawa.jp")];
- char stringpool_str4813[sizeof("bristol.museum")];
- char stringpool_str4814[sizeof("and.museum")];
- char stringpool_str4815[sizeof("is-a-doctor.com")];
- char stringpool_str4816[sizeof("lg.jp")];
- char stringpool_str4817[sizeof("net.ma")];
- char stringpool_str4818[sizeof("air.museum")];
- char stringpool_str4819[sizeof("xn--zf0avx.hk")];
- char stringpool_str4820[sizeof("indiana.museum")];
- char stringpool_str4821[sizeof("xn--vrggt-xqad.no")];
- char stringpool_str4822[sizeof("xn--j6w193g")];
- char stringpool_str4823[sizeof("eng.pro")];
- char stringpool_str4824[sizeof("ddr.museum")];
- char stringpool_str4825[sizeof("mjondalen.no")];
- char stringpool_str4826[sizeof("yashiro.hyogo.jp")];
- char stringpool_str4827[sizeof("gamagori.aichi.jp")];
- char stringpool_str4828[sizeof("tokuyama.yamaguchi.jp")];
- char stringpool_str4829[sizeof("yao.osaka.jp")];
- char stringpool_str4830[sizeof("kahoku.ishikawa.jp")];
- char stringpool_str4831[sizeof("minamidaito.okinawa.jp")];
- char stringpool_str4832[sizeof("xn--55qx5d.cn")];
- char stringpool_str4833[sizeof("sukumo.kochi.jp")];
- char stringpool_str4834[sizeof("net.mu")];
- char stringpool_str4835[sizeof("is-a-geek.org")];
- char stringpool_str4836[sizeof("pyatigorsk.ru")];
- char stringpool_str4837[sizeof("tonaki.okinawa.jp")];
- char stringpool_str4838[sizeof("government.aero")];
- char stringpool_str4839[sizeof("kharkov.ua")];
- char stringpool_str4840[sizeof("kharkiv.ua")];
- char stringpool_str4841[sizeof("net.iq")];
- char stringpool_str4842[sizeof("gs.nl.no")];
- char stringpool_str4843[sizeof("rotorcraft.aero")];
- char stringpool_str4844[sizeof("miyagi.jp")];
- char stringpool_str4845[sizeof("bus.museum")];
- char stringpool_str4846[sizeof("daigo.ibaraki.jp")];
- char stringpool_str4847[sizeof("yahaba.iwate.jp")];
- char stringpool_str4848[sizeof("nkz.ru")];
- char stringpool_str4849[sizeof("akiruno.tokyo.jp")];
- char stringpool_str4850[sizeof("skjak.no")];
- char stringpool_str4851[sizeof("is-a-hard-worker.com")];
- char stringpool_str4852[sizeof("net.ml")];
- char stringpool_str4853[sizeof("mad.museum")];
- char stringpool_str4854[sizeof("chikuhoku.nagano.jp")];
- char stringpool_str4855[sizeof("plc.co.im")];
- char stringpool_str4856[sizeof("ac.ru")];
- char stringpool_str4857[sizeof("xn--s-1fa.no")];
- char stringpool_str4858[sizeof("usdecorativearts.museum")];
- char stringpool_str4859[sizeof("uy.com")];
- char stringpool_str4860[sizeof("xn--smna-gra.no")];
- char stringpool_str4861[sizeof("nsk.ru")];
- char stringpool_str4862[sizeof("gloppen.no")];
- char stringpool_str4863[sizeof("readmyblog.org")];
- char stringpool_str4864[sizeof("in.th")];
- char stringpool_str4865[sizeof("khmelnytskyi.ua")];
- char stringpool_str4866[sizeof("doomdns.com")];
- char stringpool_str4867[sizeof("ardal.no")];
- char stringpool_str4868[sizeof("misaki.okayama.jp")];
- char stringpool_str4869[sizeof("ichinomiya.chiba.jp")];
- char stringpool_str4870[sizeof("nagai.yamagata.jp")];
- char stringpool_str4871[sizeof("sekikawa.niigata.jp")];
- char stringpool_str4872[sizeof("izunokuni.shizuoka.jp")];
- char stringpool_str4873[sizeof("barrell-of-knowledge.info")];
- char stringpool_str4874[sizeof("novara.it")];
- char stringpool_str4875[sizeof("katagami.akita.jp")];
- char stringpool_str4876[sizeof("kitagata.saga.jp")];
- char stringpool_str4877[sizeof("can.museum")];
- char stringpool_str4878[sizeof("ulan-ude.ru")];
- char stringpool_str4879[sizeof("bando.ibaraki.jp")];
- char stringpool_str4880[sizeof("inami.wakayama.jp")];
- char stringpool_str4881[sizeof("biz.mv")];
- char stringpool_str4882[sizeof("jamal.ru")];
- char stringpool_str4883[sizeof("toyoura.hokkaido.jp")];
- char stringpool_str4884[sizeof("xn--bmlo-gra.no")];
- char stringpool_str4885[sizeof("nuoro.it")];
- char stringpool_str4886[sizeof("moriguchi.osaka.jp")];
- char stringpool_str4887[sizeof("oseto.nagasaki.jp")];
- char stringpool_str4888[sizeof("xn--b-5ga.nordland.no")];
- char stringpool_str4889[sizeof("horokanai.hokkaido.jp")];
- char stringpool_str4890[sizeof("aerodrome.aero")];
- char stringpool_str4891[sizeof("nalchik.ru")];
- char stringpool_str4892[sizeof("mil.mv")];
- char stringpool_str4893[sizeof("chikuma.nagano.jp")];
- char stringpool_str4894[sizeof("beppu.oita.jp")];
- char stringpool_str4895[sizeof("yamatsuri.fukushima.jp")];
- char stringpool_str4896[sizeof("ski.museum")];
- char stringpool_str4897[sizeof("kitagawa.kochi.jp")];
- char stringpool_str4898[sizeof("palmsprings.museum")];
- char stringpool_str4899[sizeof("for-more.biz")];
- char stringpool_str4900[sizeof("nishinomiya.hyogo.jp")];
- char stringpool_str4901[sizeof("xn--tn0ag.hk")];
- char stringpool_str4902[sizeof("tas.gov.au")];
- char stringpool_str4903[sizeof("org.uz")];
- char stringpool_str4904[sizeof("tokigawa.saitama.jp")];
- char stringpool_str4905[sizeof("oarai.ibaraki.jp")];
- char stringpool_str4906[sizeof("org.ug")];
- char stringpool_str4907[sizeof("oki.fukuoka.jp")];
- char stringpool_str4908[sizeof("doesntexist.com")];
- char stringpool_str4909[sizeof("nishitosa.kochi.jp")];
- char stringpool_str4910[sizeof("is-a-blogger.com")];
- char stringpool_str4911[sizeof("org.ua")];
- char stringpool_str4912[sizeof("minokamo.gifu.jp")];
- char stringpool_str4913[sizeof("vologda.ru")];
- char stringpool_str4914[sizeof("pulawy.pl")];
- char stringpool_str4915[sizeof("kadogawa.miyazaki.jp")];
- char stringpool_str4916[sizeof("mykolaiv.ua")];
- char stringpool_str4917[sizeof("nature.museum")];
- char stringpool_str4918[sizeof("badajoz.museum")];
- char stringpool_str4919[sizeof("usa.oita.jp")];
- char stringpool_str4920[sizeof("isumi.chiba.jp")];
- char stringpool_str4921[sizeof("tsuruoka.yamagata.jp")];
- char stringpool_str4922[sizeof("malopolska.pl")];
- char stringpool_str4923[sizeof("xn--55qx5d.hk")];
- char stringpool_str4924[sizeof("xn--btsfjord-9za.no")];
- char stringpool_str4925[sizeof("fjell.no")];
- char stringpool_str4926[sizeof("is-a-hunter.com")];
- char stringpool_str4927[sizeof("xn--srum-gra.no")];
- char stringpool_str4928[sizeof("cc.md.us")];
- char stringpool_str4929[sizeof("torahime.shiga.jp")];
- char stringpool_str4930[sizeof("ogano.saitama.jp")];
- char stringpool_str4931[sizeof("fujikawa.yamanashi.jp")];
- char stringpool_str4932[sizeof("cc.id.us")];
- char stringpool_str4933[sizeof("varggat.no")];
- char stringpool_str4934[sizeof("minamiawaji.hyogo.jp")];
- char stringpool_str4935[sizeof("mihara.kochi.jp")];
- char stringpool_str4936[sizeof("basel.museum")];
- char stringpool_str4937[sizeof("shimogo.fukushima.jp")];
- char stringpool_str4938[sizeof("casadelamoneda.museum")];
- char stringpool_str4939[sizeof("nasushiobara.tochigi.jp")];
- char stringpool_str4940[sizeof("xn--sandy-yua.no")];
- char stringpool_str4941[sizeof("webhop.net")];
- char stringpool_str4942[sizeof("blogdns.com")];
- char stringpool_str4943[sizeof("xn--zf0ao64a.tw")];
- char stringpool_str4944[sizeof("gov.py")];
- char stringpool_str4945[sizeof("edu.py")];
- char stringpool_str4946[sizeof("office-on-the.net")];
- char stringpool_str4947[sizeof("barrel-of-knowledge.info")];
- char stringpool_str4948[sizeof("com.py")];
- char stringpool_str4949[sizeof("nikaho.akita.jp")];
- char stringpool_str4950[sizeof("isteingeek.de")];
- char stringpool_str4951[sizeof("com.gy")];
- char stringpool_str4952[sizeof("airtraffic.aero")];
- char stringpool_str4953[sizeof("shell.museum")];
- char stringpool_str4954[sizeof("xn--bjddar-pta.no")];
- char stringpool_str4955[sizeof("urbinopesaro.it")];
- char stringpool_str4956[sizeof("xn--vgan-qoa.no")];
- char stringpool_str4957[sizeof("is-a-lawyer.com")];
- char stringpool_str4958[sizeof("oygarden.no")];
- char stringpool_str4959[sizeof("ivano-frankivsk.ua")];
- char stringpool_str4960[sizeof("kunigami.okinawa.jp")];
- char stringpool_str4961[sizeof("gs.hl.no")];
- char stringpool_str4962[sizeof("kagamiishi.fukushima.jp")];
- char stringpool_str4963[sizeof("imari.saga.jp")];
- char stringpool_str4964[sizeof("kamikawa.hyogo.jp")];
- char stringpool_str4965[sizeof("kitaura.miyazaki.jp")];
- char stringpool_str4966[sizeof("omachi.saga.jp")];
- char stringpool_str4967[sizeof("zoology.museum")];
- char stringpool_str4968[sizeof("family.museum")];
- char stringpool_str4969[sizeof("ogaki.gifu.jp")];
- char stringpool_str4970[sizeof("works.aero")];
- char stringpool_str4971[sizeof("hotel.tz")];
- char stringpool_str4972[sizeof("western.museum")];
- char stringpool_str4973[sizeof("xn--sr-odal-q1a.no")];
- char stringpool_str4974[sizeof("cc.nd.us")];
- char stringpool_str4975[sizeof("pf")];
- char stringpool_str4976[sizeof("kikugawa.shizuoka.jp")];
- char stringpool_str4977[sizeof("hotel.lk")];
- char stringpool_str4978[sizeof("bologna.it")];
- char stringpool_str4979[sizeof("tsuno.kochi.jp")];
- char stringpool_str4980[sizeof("culturalcenter.museum")];
- char stringpool_str4981[sizeof("environmentalconservation.museum")];
- char stringpool_str4982[sizeof("nango.fukushima.jp")];
- char stringpool_str4983[sizeof("xn--trany-yua.no")];
- char stringpool_str4984[sizeof("kitagawa.miyazaki.jp")];
- char stringpool_str4985[sizeof("gs.rl.no")];
- char stringpool_str4986[sizeof("nishikata.tochigi.jp")];
- char stringpool_str4987[sizeof("shingu.wakayama.jp")];
- char stringpool_str4988[sizeof("izumi.osaka.jp")];
- char stringpool_str4989[sizeof("hotel.hu")];
- char stringpool_str4990[sizeof("xn--bhcavuotna-s4a.no")];
- char stringpool_str4991[sizeof("ouchi.saga.jp")];
- char stringpool_str4992[sizeof("xn--sandnessjen-ogb.no")];
- char stringpool_str4993[sizeof("xn--io0a7i.cn")];
- char stringpool_str4994[sizeof("bjarkoy.no")];
- char stringpool_str4995[sizeof("uwajima.ehime.jp")];
- char stringpool_str4996[sizeof("xn--vgsy-qoa0j.no")];
- char stringpool_str4997[sizeof("kakegawa.shizuoka.jp")];
- char stringpool_str4998[sizeof("yoshinogari.saga.jp")];
- char stringpool_str4999[sizeof("kinokawa.wakayama.jp")];
- char stringpool_str5000[sizeof("oshima.tokyo.jp")];
- char stringpool_str5001[sizeof("carboniaiglesias.it")];
- char stringpool_str5002[sizeof("sunagawa.hokkaido.jp")];
- char stringpool_str5003[sizeof("nagaokakyo.kyoto.jp")];
- char stringpool_str5004[sizeof("minami-alps.yamanashi.jp")];
- char stringpool_str5005[sizeof("grong.no")];
- char stringpool_str5006[sizeof("tahara.aichi.jp")];
- char stringpool_str5007[sizeof("sagamihara.kanagawa.jp")];
- char stringpool_str5008[sizeof("north.museum")];
- char stringpool_str5009[sizeof("lavagis.no")];
- char stringpool_str5010[sizeof("yawatahama.ehime.jp")];
- char stringpool_str5011[sizeof("nanmoku.gunma.jp")];
- char stringpool_str5012[sizeof("ohkura.yamagata.jp")];
- char stringpool_str5013[sizeof("inagawa.hyogo.jp")];
- char stringpool_str5014[sizeof("cc.or.us")];
- char stringpool_str5015[sizeof("kumagaya.saitama.jp")];
- char stringpool_str5016[sizeof("kawakita.ishikawa.jp")];
- char stringpool_str5017[sizeof("xn--ciqpn.hk")];
- char stringpool_str5018[sizeof("inzai.chiba.jp")];
- char stringpool_str5019[sizeof("dreamhosters.com")];
- char stringpool_str5020[sizeof("uzhgorod.ua")];
- char stringpool_str5021[sizeof("mihama.aichi.jp")];
- char stringpool_str5022[sizeof("yaotsu.gifu.jp")];
- char stringpool_str5023[sizeof("xn--xkc2al3hye2a")];
- char stringpool_str5024[sizeof("itami.hyogo.jp")];
- char stringpool_str5025[sizeof("hobol.no")];
- char stringpool_str5026[sizeof("miyake.nara.jp")];
- char stringpool_str5027[sizeof("iki.fi")];
- char stringpool_str5028[sizeof("sklep.pl")];
- char stringpool_str5029[sizeof("tochigi.tochigi.jp")];
- char stringpool_str5030[sizeof("osteroy.no")];
- char stringpool_str5031[sizeof("is-a-patsfan.org")];
- char stringpool_str5032[sizeof("yokohama.jp")];
- char stringpool_str5033[sizeof("net.uz")];
- char stringpool_str5034[sizeof("wakayama.jp")];
- char stringpool_str5035[sizeof("net.ua")];
- char stringpool_str5036[sizeof("xn--bearalvhki-y4a.no")];
- char stringpool_str5037[sizeof("shiogama.miyagi.jp")];
- char stringpool_str5038[sizeof("furudono.fukushima.jp")];
- char stringpool_str5039[sizeof("spy.museum")];
- char stringpool_str5040[sizeof("kurogi.fukuoka.jp")];
- char stringpool_str5041[sizeof("mil.py")];
- char stringpool_str5042[sizeof("cc.pr.us")];
- char stringpool_str5043[sizeof("parachuting.aero")];
- char stringpool_str5044[sizeof("kanzaki.saga.jp")];
- char stringpool_str5045[sizeof("nobeoka.miyazaki.jp")];
- char stringpool_str5046[sizeof("nacion.ar")];
- char stringpool_str5047[sizeof("setagaya.tokyo.jp")];
- char stringpool_str5048[sizeof("skjervoy.no")];
- char stringpool_str5049[sizeof("klepp.no")];
- char stringpool_str5050[sizeof("atsugi.kanagawa.jp")];
- char stringpool_str5051[sizeof("air-traffic-control.aero")];
- char stringpool_str5052[sizeof("inagi.tokyo.jp")];
- char stringpool_str5053[sizeof("nsn.us")];
- char stringpool_str5054[sizeof("xn--io0a7i.hk")];
- char stringpool_str5055[sizeof("nls.uk")];
- char stringpool_str5056[sizeof("miyako.fukuoka.jp")];
- char stringpool_str5057[sizeof("nel.uk")];
- char stringpool_str5058[sizeof("fukagawa.hokkaido.jp")];
- char stringpool_str5059[sizeof("samukawa.kanagawa.jp")];
- char stringpool_str5060[sizeof("championship.aero")];
- char stringpool_str5061[sizeof("vefsn.no")];
- char stringpool_str5062[sizeof("tydal.no")];
- char stringpool_str5063[sizeof("aogaki.hyogo.jp")];
- char stringpool_str5064[sizeof("xn--sr-fron-q1a.no")];
- char stringpool_str5065[sizeof("ariake.saga.jp")];
- char stringpool_str5066[sizeof("kanegasaki.iwate.jp")];
- char stringpool_str5067[sizeof("kamimine.saga.jp")];
- char stringpool_str5068[sizeof("takagi.nagano.jp")];
- char stringpool_str5069[sizeof("cc.ar.us")];
- char stringpool_str5070[sizeof("assedic.fr")];
- char stringpool_str5071[sizeof("is-very-sweet.org")];
- char stringpool_str5072[sizeof("nt.au")];
- char stringpool_str5073[sizeof("soc.lk")];
- char stringpool_str5074[sizeof("fuefuki.yamanashi.jp")];
- char stringpool_str5075[sizeof("kitakyushu.jp")];
- char stringpool_str5076[sizeof("cc.nm.us")];
- char stringpool_str5077[sizeof("ono.hyogo.jp")];
- char stringpool_str5078[sizeof("nanporo.hokkaido.jp")];
- char stringpool_str5079[sizeof("sakura.tochigi.jp")];
- char stringpool_str5080[sizeof("kanuma.tochigi.jp")];
- char stringpool_str5081[sizeof("xn--bod-2na.no")];
- char stringpool_str5082[sizeof("of.by")];
- char stringpool_str5083[sizeof("miyakonojo.miyazaki.jp")];
- char stringpool_str5084[sizeof("mizumaki.fukuoka.jp")];
- char stringpool_str5085[sizeof("nesseby.no")];
- char stringpool_str5086[sizeof("nesoddtangen.no")];
- char stringpool_str5087[sizeof("is-a-photographer.com")];
- char stringpool_str5088[sizeof("is-a-player.com")];
- char stringpool_str5089[sizeof("tv.sd")];
- char stringpool_str5090[sizeof("principe.st")];
- char stringpool_str5091[sizeof("kasuga.hyogo.jp")];
- char stringpool_str5092[sizeof("ushuaia.museum")];
- char stringpool_str5093[sizeof("koshu.yamanashi.jp")];
- char stringpool_str5094[sizeof("kasuga.fukuoka.jp")];
- char stringpool_str5095[sizeof("dnepropetrovsk.ua")];
- char stringpool_str5096[sizeof("nanto.toyama.jp")];
- char stringpool_str5097[sizeof("skydiving.aero")];
- char stringpool_str5098[sizeof("ikeda.gifu.jp")];
- char stringpool_str5099[sizeof("yaita.tochigi.jp")];
- char stringpool_str5100[sizeof("izumozaki.niigata.jp")];
- char stringpool_str5101[sizeof("isahaya.nagasaki.jp")];
- char stringpool_str5102[sizeof("norddal.no")];
- char stringpool_str5103[sizeof("timekeeping.museum")];
- char stringpool_str5104[sizeof("ostrowwlkp.pl")];
- char stringpool_str5105[sizeof("xn--bhccavuotna-k7a.no")];
- char stringpool_str5106[sizeof("vadso.no")];
- char stringpool_str5107[sizeof("nuremberg.museum")];
- char stringpool_str5108[sizeof("kamakura.kanagawa.jp")];
- char stringpool_str5109[sizeof("worse-than.tv")];
- char stringpool_str5110[sizeof("leangaviika.no")];
- char stringpool_str5111[sizeof("uchinomi.kagawa.jp")];
- char stringpool_str5112[sizeof("dnipropetrovsk.ua")];
- char stringpool_str5113[sizeof("kagami.kochi.jp")];
- char stringpool_str5114[sizeof("kochi.kochi.jp")];
- char stringpool_str5115[sizeof("suwalki.pl")];
- char stringpool_str5116[sizeof("kopervik.no")];
- char stringpool_str5117[sizeof("iheya.okinawa.jp")];
- char stringpool_str5118[sizeof("iris.arpa")];
- char stringpool_str5119[sizeof("togakushi.nagano.jp")];
- char stringpool_str5120[sizeof("freight.aero")];
- char stringpool_str5121[sizeof("kamigori.hyogo.jp")];
- char stringpool_str5122[sizeof("is-lost.org")];
- char stringpool_str5123[sizeof("jessheim.no")];
- char stringpool_str5124[sizeof("tomigusuku.okinawa.jp")];
- char stringpool_str5125[sizeof("sanagochi.tokushima.jp")];
- char stringpool_str5126[sizeof("nishiaizu.fukushima.jp")];
- char stringpool_str5127[sizeof("buyshouses.net")];
- char stringpool_str5128[sizeof("tozsde.hu")];
- char stringpool_str5129[sizeof("tsuru.yamanashi.jp")];
- char stringpool_str5130[sizeof("jan-mayen.no")];
- char stringpool_str5131[sizeof("minamiashigara.kanagawa.jp")];
- char stringpool_str5132[sizeof("hatogaya.saitama.jp")];
- char stringpool_str5133[sizeof("nordreisa.no")];
- char stringpool_str5134[sizeof("museumcenter.museum")];
- char stringpool_str5135[sizeof("xn--czrw28b.tw")];
- char stringpool_str5136[sizeof("rhcloud.com")];
- char stringpool_str5137[sizeof("xn--vg-yiab.no")];
- char stringpool_str5138[sizeof("civilwar.museum")];
- char stringpool_str5139[sizeof("sch.lk")];
- char stringpool_str5140[sizeof("nachikatsuura.wakayama.jp")];
- char stringpool_str5141[sizeof("szczecin.pl")];
- char stringpool_str5142[sizeof("kawaguchi.saitama.jp")];
- char stringpool_str5143[sizeof("yusuhara.kochi.jp")];
- char stringpool_str5144[sizeof("id.ir")];
- char stringpool_str5145[sizeof("gwangju.kr")];
- char stringpool_str5146[sizeof("scotland.museum")];
- char stringpool_str5147[sizeof("myphotos.cc")];
- char stringpool_str5148[sizeof("yurihonjo.akita.jp")];
- char stringpool_str5149[sizeof("org.km")];
- char stringpool_str5150[sizeof("maryland.museum")];
- char stringpool_str5151[sizeof("org.ki")];
- char stringpool_str5152[sizeof("org.kz")];
- char stringpool_str5153[sizeof("org.kg")];
- char stringpool_str5154[sizeof("nemuro.hokkaido.jp")];
- char stringpool_str5155[sizeof("nakadomari.aomori.jp")];
- char stringpool_str5156[sizeof("takanezawa.tochigi.jp")];
- char stringpool_str5157[sizeof("urakawa.hokkaido.jp")];
- char stringpool_str5158[sizeof("kitagata.gifu.jp")];
- char stringpool_str5159[sizeof("xn--stjrdalshalsen-sqb.no")];
- char stringpool_str5160[sizeof("shingu.hyogo.jp")];
- char stringpool_str5161[sizeof("xn--aurskog-hland-jnb.no")];
- char stringpool_str5162[sizeof("dyndns-office.com")];
- char stringpool_str5163[sizeof("ozu.kumamoto.jp")];
- char stringpool_str5164[sizeof("shingu.fukuoka.jp")];
- char stringpool_str5165[sizeof("nabari.mie.jp")];
- char stringpool_str5166[sizeof("pb.ao")];
- char stringpool_str5167[sizeof("tsurugi.ishikawa.jp")];
- char stringpool_str5168[sizeof("xn--vler-qoa.hedmark.no")];
- char stringpool_str5169[sizeof("nagaoka.niigata.jp")];
- char stringpool_str5170[sizeof("or.ug")];
- char stringpool_str5171[sizeof("org.kn")];
- char stringpool_str5172[sizeof("tsushima.aichi.jp")];
- char stringpool_str5173[sizeof("xn--vestvgy-ixa6o.no")];
- char stringpool_str5174[sizeof("uchinada.ishikawa.jp")];
- char stringpool_str5175[sizeof("castres.museum")];
- char stringpool_str5176[sizeof("hokuryu.hokkaido.jp")];
- char stringpool_str5177[sizeof("chofu.tokyo.jp")];
- char stringpool_str5178[sizeof("hikari.yamaguchi.jp")];
- char stringpool_str5179[sizeof("kiyokawa.kanagawa.jp")];
- char stringpool_str5180[sizeof("yoichi.hokkaido.jp")];
- char stringpool_str5181[sizeof("nowaruda.pl")];
- char stringpool_str5182[sizeof("izumo.shimane.jp")];
- char stringpool_str5183[sizeof("webhop.org")];
- char stringpool_str5184[sizeof("choshi.chiba.jp")];
- char stringpool_str5185[sizeof("its.me")];
- char stringpool_str5186[sizeof("izumizaki.fukushima.jp")];
- char stringpool_str5187[sizeof("int.ru")];
- char stringpool_str5188[sizeof("web.do")];
- char stringpool_str5189[sizeof("dontexist.com")];
- char stringpool_str5190[sizeof("kasamatsu.gifu.jp")];
- char stringpool_str5191[sizeof("naturalhistory.museum")];
- char stringpool_str5192[sizeof("nakayama.yamagata.jp")];
- char stringpool_str5193[sizeof("utsunomiya.tochigi.jp")];
- char stringpool_str5194[sizeof("missile.museum")];
- char stringpool_str5195[sizeof("mansion.museum")];
- char stringpool_str5196[sizeof("sc.ug")];
- char stringpool_str5197[sizeof("ac.ug")];
- char stringpool_str5198[sizeof("other.nf")];
- char stringpool_str5199[sizeof("osoyro.no")];
- char stringpool_str5200[sizeof("nakatsugawa.gifu.jp")];
- char stringpool_str5201[sizeof("cc.gu.us")];
- char stringpool_str5202[sizeof("org.my")];
- char stringpool_str5203[sizeof("kozagawa.wakayama.jp")];
- char stringpool_str5204[sizeof("warszawa.pl")];
- char stringpool_str5205[sizeof("naturbruksgymn.se")];
- char stringpool_str5206[sizeof("sec.ps")];
- char stringpool_str5207[sizeof("obuse.nagano.jp")];
- char stringpool_str5208[sizeof("olecko.pl")];
- char stringpool_str5209[sizeof("hichiso.gifu.jp")];
- char stringpool_str5210[sizeof("nerima.tokyo.jp")];
- char stringpool_str5211[sizeof("nt.gov.au")];
- char stringpool_str5212[sizeof("nanjo.okinawa.jp")];
- char stringpool_str5213[sizeof("veterinaire.fr")];
- char stringpool_str5214[sizeof("xn--wcvs22d.hk")];
- char stringpool_str5215[sizeof("is-a-democrat.com")];
- char stringpool_str5216[sizeof("shimonoseki.yamaguchi.jp")];
- char stringpool_str5217[sizeof("nom.km")];
- char stringpool_str5218[sizeof("naturalhistorymuseum.museum")];
- char stringpool_str5219[sizeof("esashi.hokkaido.jp")];
- char stringpool_str5220[sizeof("ac.ng")];
- char stringpool_str5221[sizeof("union.aero")];
- char stringpool_str5222[sizeof("ogose.saitama.jp")];
- char stringpool_str5223[sizeof("hakodate.hokkaido.jp")];
- char stringpool_str5224[sizeof("org.lk")];
- char stringpool_str5225[sizeof("brand.se")];
- char stringpool_str5226[sizeof("org.la")];
- char stringpool_str5227[sizeof("nawrastelecom.om")];
- char stringpool_str5228[sizeof("nordre-land.no")];
- char stringpool_str5229[sizeof("vegarshei.no")];
- char stringpool_str5230[sizeof("org.ls")];
- char stringpool_str5231[sizeof("kakogawa.hyogo.jp")];
- char stringpool_str5232[sizeof("org.lc")];
- char stringpool_str5233[sizeof("org.lb")];
- char stringpool_str5234[sizeof("net.ki")];
- char stringpool_str5235[sizeof("net.kz")];
- char stringpool_str5236[sizeof("net.kg")];
- char stringpool_str5237[sizeof("xn--nry-yla5g.no")];
- char stringpool_str5238[sizeof("shinkamigoto.nagasaki.jp")];
- char stringpool_str5239[sizeof("vossevangen.no")];
- char stringpool_str5240[sizeof("iz.hr")];
- char stringpool_str5241[sizeof("taishi.osaka.jp")];
- char stringpool_str5242[sizeof("iwama.ibaraki.jp")];
- char stringpool_str5243[sizeof("shibuya.tokyo.jp")];
- char stringpool_str5244[sizeof("chikuzen.fukuoka.jp")];
- char stringpool_str5245[sizeof("org.lr")];
- char stringpool_str5246[sizeof("sch.gg")];
- char stringpool_str5247[sizeof("akishima.tokyo.jp")];
- char stringpool_str5248[sizeof("xn--tysvr-vra.no")];
- char stringpool_str5249[sizeof("wa.edu.au")];
- char stringpool_str5250[sizeof("susaki.kochi.jp")];
- char stringpool_str5251[sizeof("skierva.no")];
- char stringpool_str5252[sizeof("xn--bjarky-fya.no")];
- char stringpool_str5253[sizeof("homeunix.com")];
- char stringpool_str5254[sizeof("net.kn")];
- char stringpool_str5255[sizeof("hayakawa.yamanashi.jp")];
- char stringpool_str5256[sizeof("dnsalias.com")];
- char stringpool_str5257[sizeof("wakuya.miyagi.jp")];
- char stringpool_str5258[sizeof("yamanobe.yamagata.jp")];
- char stringpool_str5259[sizeof("org.kp")];
- char stringpool_str5260[sizeof("homelinux.com")];
- char stringpool_str5261[sizeof("is-an-accountant.com")];
- char stringpool_str5262[sizeof("nagahama.shiga.jp")];
- char stringpool_str5263[sizeof("abashiri.hokkaido.jp")];
- char stringpool_str5264[sizeof("is-into-cars.com")];
- char stringpool_str5265[sizeof("kawagoe.saitama.jp")];
- char stringpool_str5266[sizeof("kudamatsu.yamaguchi.jp")];
- char stringpool_str5267[sizeof("batsfjord.no")];
- char stringpool_str5268[sizeof("omanpost.om")];
- char stringpool_str5269[sizeof("xn--45brj9c")];
- char stringpool_str5270[sizeof("natori.miyagi.jp")];
- char stringpool_str5271[sizeof("is-a-teacher.com")];
- char stringpool_str5272[sizeof("costume.museum")];
- char stringpool_str5273[sizeof("is-a-anarchist.com")];
- char stringpool_str5274[sizeof("podlasie.pl")];
- char stringpool_str5275[sizeof("xn--s9brj9c")];
- char stringpool_str5276[sizeof("is-by.us")];
- char stringpool_str5277[sizeof("xn--vry-yla5g.no")];
- char stringpool_str5278[sizeof("komaki.aichi.jp")];
- char stringpool_str5279[sizeof("vagsoy.no")];
- char stringpool_str5280[sizeof("coastaldefence.museum")];
- char stringpool_str5281[sizeof("onjuku.chiba.jp")];
- char stringpool_str5282[sizeof("ibestad.no")];
- char stringpool_str5283[sizeof("nishiizu.shizuoka.jp")];
- char stringpool_str5284[sizeof("otsuki.yamanashi.jp")];
- char stringpool_str5285[sizeof("kujukuri.chiba.jp")];
- char stringpool_str5286[sizeof("or.jp")];
- char stringpool_str5287[sizeof("is-a-musician.com")];
- char stringpool_str5288[sizeof("net.my")];
- char stringpool_str5289[sizeof("hirogawa.wakayama.jp")];
- char stringpool_str5290[sizeof("nakamura.kochi.jp")];
- char stringpool_str5291[sizeof("gov.lv")];
- char stringpool_str5292[sizeof("youth.museum")];
- char stringpool_str5293[sizeof("edu.lv")];
- char stringpool_str5294[sizeof("is-an-anarchist.com")];
- char stringpool_str5295[sizeof("com.lv")];
- char stringpool_str5296[sizeof("funagata.yamagata.jp")];
- char stringpool_str5297[sizeof("kawamata.fukushima.jp")];
- char stringpool_str5298[sizeof("balsfjord.no")];
- char stringpool_str5299[sizeof("ujiie.tochigi.jp")];
- char stringpool_str5300[sizeof("is-into-cartoons.com")];
- char stringpool_str5301[sizeof("nayoro.hokkaido.jp")];
- char stringpool_str5302[sizeof("nishigo.fukushima.jp")];
- char stringpool_str5303[sizeof("is-a-landscaper.com")];
- char stringpool_str5304[sizeof("tajimi.gifu.jp")];
- char stringpool_str5305[sizeof("net.lk")];
- char stringpool_str5306[sizeof("net.la")];
- char stringpool_str5307[sizeof("is-certified.com")];
- char stringpool_str5308[sizeof("oppegard.no")];
- char stringpool_str5309[sizeof("qld.gov.au")];
- char stringpool_str5310[sizeof("ac.jp")];
- char stringpool_str5311[sizeof("shishikui.tokushima.jp")];
- char stringpool_str5312[sizeof("net.lc")];
- char stringpool_str5313[sizeof("tsushima.nagasaki.jp")];
- char stringpool_str5314[sizeof("culture.museum")];
- char stringpool_str5315[sizeof("windmill.museum")];
- char stringpool_str5316[sizeof("sakegawa.yamagata.jp")];
- char stringpool_str5317[sizeof("dontexist.net")];
- char stringpool_str5318[sizeof("net.lb")];
- char stringpool_str5319[sizeof("xn--wgbh1c")];
- char stringpool_str5320[sizeof("yasuoka.nagano.jp")];
- char stringpool_str5321[sizeof("itano.tokushima.jp")];
- char stringpool_str5322[sizeof("whaling.museum")];
- char stringpool_str5323[sizeof("asn.lv")];
- char stringpool_str5324[sizeof("us.org")];
- char stringpool_str5325[sizeof("org.pe")];
- char stringpool_str5326[sizeof("otofuke.hokkaido.jp")];
- char stringpool_str5327[sizeof("org.pk")];
- char stringpool_str5328[sizeof("net.lr")];
- char stringpool_str5329[sizeof("udm.ru")];
- char stringpool_str5330[sizeof("org.ge")];
- char stringpool_str5331[sizeof("org.gi")];
- char stringpool_str5332[sizeof("nishinoomote.kagoshima.jp")];
- char stringpool_str5333[sizeof("org.gg")];
- char stringpool_str5334[sizeof("org.pa")];
- char stringpool_str5335[sizeof("org.ps")];
- char stringpool_str5336[sizeof("nanao.ishikawa.jp")];
- char stringpool_str5337[sizeof("ambulance.aero")];
- char stringpool_str5338[sizeof("virtuel.museum")];
- char stringpool_str5339[sizeof("marylhurst.museum")];
- char stringpool_str5340[sizeof("virtual.museum")];
- char stringpool_str5341[sizeof("bialowieza.pl")];
- char stringpool_str5342[sizeof("org.uy")];
- char stringpool_str5343[sizeof("oguchi.aichi.jp")];
- char stringpool_str5344[sizeof("utsira.no")];
- char stringpool_str5345[sizeof("org.pt")];
- char stringpool_str5346[sizeof("aca.pro")];
- char stringpool_str5347[sizeof("org.gt")];
- char stringpool_str5348[sizeof("org.pr")];
- char stringpool_str5349[sizeof("org.pn")];
- char stringpool_str5350[sizeof("hembygdsforbund.museum")];
- char stringpool_str5351[sizeof("pro.ht")];
- char stringpool_str5352[sizeof("org.gr")];
- char stringpool_str5353[sizeof("org.gn")];
- char stringpool_str5354[sizeof("promocion.ar")];
- char stringpool_str5355[sizeof("nagara.chiba.jp")];
- char stringpool_str5356[sizeof("is-a-liberal.com")];
- char stringpool_str5357[sizeof("settlement.museum")];
- char stringpool_str5358[sizeof("org.pl")];
- char stringpool_str5359[sizeof("aeroport.fr")];
- char stringpool_str5360[sizeof("id.au")];
- char stringpool_str5361[sizeof("elasticbeanstalk.com")];
- char stringpool_str5362[sizeof("chirurgiens-dentistes.fr")];
- char stringpool_str5363[sizeof("isa.us")];
- char stringpool_str5364[sizeof("mil.lv")];
- char stringpool_str5365[sizeof("udono.mie.jp")];
- char stringpool_str5366[sizeof("namerikawa.toyama.jp")];
- char stringpool_str5367[sizeof("gs.sf.no")];
- char stringpool_str5368[sizeof("dynalias.com")];
- char stringpool_str5369[sizeof("xn--blt-elab.no")];
- char stringpool_str5370[sizeof("bieszczady.pl")];
- char stringpool_str5371[sizeof("xn--slt-elab.no")];
- char stringpool_str5372[sizeof("est-le-patron.com")];
- char stringpool_str5373[sizeof("hidaka.kochi.jp")];
- char stringpool_str5374[sizeof("kumakogen.ehime.jp")];
- char stringpool_str5375[sizeof("org.mw")];
- char stringpool_str5376[sizeof("pol.ht")];
- char stringpool_str5377[sizeof("baghdad.museum")];
- char stringpool_str5378[sizeof("is-a-geek.com")];
- char stringpool_str5379[sizeof("newmexico.museum")];
- char stringpool_str5380[sizeof("xn--bidr-5nac.no")];
- char stringpool_str5381[sizeof("kashiwa.chiba.jp")];
- char stringpool_str5382[sizeof("homelinux.net")];
- char stringpool_str5383[sizeof("www.ro")];
- char stringpool_str5384[sizeof("cc.ok.us")];
- char stringpool_str5385[sizeof("huissier-justice.fr")];
- char stringpool_str5386[sizeof("isshiki.aichi.jp")];
- char stringpool_str5387[sizeof("info.vn")];
- char stringpool_str5388[sizeof("info.ve")];
- char stringpool_str5389[sizeof("nom.pe")];
- char stringpool_str5390[sizeof("presse.ci")];
- char stringpool_str5391[sizeof("phoenix.museum")];
- char stringpool_str5392[sizeof("gjesdal.no")];
- char stringpool_str5393[sizeof("nom.pa")];
- char stringpool_str5394[sizeof("is-a-soxfan.org")];
- char stringpool_str5395[sizeof("norfolk.museum")];
- char stringpool_str5396[sizeof("porsangu.no")];
- char stringpool_str5397[sizeof("nordkapp.no")];
- char stringpool_str5398[sizeof("nieruchomosci.pl")];
- char stringpool_str5399[sizeof("kawagoe.mie.jp")];
- char stringpool_str5400[sizeof("valer.ostfold.no")];
- char stringpool_str5401[sizeof("presse.km")];
- char stringpool_str5402[sizeof("napoli.it")];
- char stringpool_str5403[sizeof("taishi.hyogo.jp")];
- char stringpool_str5404[sizeof("consulado.st")];
- char stringpool_str5405[sizeof("gausdal.no")];
- char stringpool_str5406[sizeof("net.pe")];
- char stringpool_str5407[sizeof("ne.ug")];
- char stringpool_str5408[sizeof("net.pk")];
- char stringpool_str5409[sizeof("kakamigahara.gifu.jp")];
- char stringpool_str5410[sizeof("net.ge")];
- char stringpool_str5411[sizeof("oxford.museum")];
- char stringpool_str5412[sizeof("net.gg")];
- char stringpool_str5413[sizeof("net.pa")];
- char stringpool_str5414[sizeof("net.ps")];
- char stringpool_str5415[sizeof("undersea.museum")];
- char stringpool_str5416[sizeof("iglesiascarbonia.it")];
- char stringpool_str5417[sizeof("akashi.hyogo.jp")];
- char stringpool_str5418[sizeof("nom.pl")];
- char stringpool_str5419[sizeof("org.pf")];
- char stringpool_str5420[sizeof("prd.fr")];
- char stringpool_str5421[sizeof("net.uy")];
- char stringpool_str5422[sizeof("net.pt")];
- char stringpool_str5423[sizeof("pilot.aero")];
- char stringpool_str5424[sizeof("net.gt")];
- char stringpool_str5425[sizeof("schokoladen.museum")];
- char stringpool_str5426[sizeof("presse.ml")];
- char stringpool_str5427[sizeof("net.pr")];
- char stringpool_str5428[sizeof("net.pn")];
- char stringpool_str5429[sizeof("net.rw")];
- char stringpool_str5430[sizeof("net.gr")];
- char stringpool_str5431[sizeof("net.gn")];
- char stringpool_str5432[sizeof("ora.gunma.jp")];
- char stringpool_str5433[sizeof("cc.ak.us")];
- char stringpool_str5434[sizeof("poltava.ua")];
- char stringpool_str5435[sizeof("nishiazai.shiga.jp")];
- char stringpool_str5436[sizeof("pp.se")];
- char stringpool_str5437[sizeof("ota.gunma.jp")];
- char stringpool_str5438[sizeof("net.pl")];
- char stringpool_str5439[sizeof("org.gp")];
- char stringpool_str5440[sizeof("pistoia.it")];
- char stringpool_str5441[sizeof("xn--sr-varanger-ggb.no")];
- char stringpool_str5442[sizeof("valer.hedmark.no")];
- char stringpool_str5443[sizeof("kasukabe.saitama.jp")];
- char stringpool_str5444[sizeof("org.ph")];
- char stringpool_str5445[sizeof("is-a-republican.com")];
- char stringpool_str5446[sizeof("wa.au")];
- char stringpool_str5447[sizeof("org.gh")];
- char stringpool_str5448[sizeof("project.museum")];
- char stringpool_str5449[sizeof("marburg.museum")];
- char stringpool_str5450[sizeof("ngo.lk")];
- char stringpool_str5451[sizeof("yamada.toyama.jp")];
- char stringpool_str5452[sizeof("wakayama.wakayama.jp")];
- char stringpool_str5453[sizeof("is-a-libertarian.com")];
- char stringpool_str5454[sizeof("issmarterthanyou.com")];
- char stringpool_str5455[sizeof("is-a-nascarfan.com")];
- char stringpool_str5456[sizeof("oskol.ru")];
- char stringpool_str5457[sizeof("parliament.uk")];
- char stringpool_str5458[sizeof("localhistory.museum")];
- char stringpool_str5459[sizeof("net.mw")];
- char stringpool_str5460[sizeof("cc.fl.us")];
- char stringpool_str5461[sizeof("namikata.ehime.jp")];
- char stringpool_str5462[sizeof("inuyama.aichi.jp")];
- char stringpool_str5463[sizeof("gemological.museum")];
- char stringpool_str5464[sizeof("xn--brnnysund-m8ac.no")];
- char stringpool_str5465[sizeof("cc.il.us")];
- char stringpool_str5466[sizeof("nankoku.kochi.jp")];
- char stringpool_str5467[sizeof("museumvereniging.museum")];
- char stringpool_str5468[sizeof("xn--node")];
- char stringpool_str5469[sizeof("is-a-therapist.com")];
- char stringpool_str5470[sizeof("scrapper-site.net")];
- char stringpool_str5471[sizeof("nakama.fukuoka.jp")];
- char stringpool_str5472[sizeof("sodegaura.chiba.jp")];
- char stringpool_str5473[sizeof("yanaizu.fukushima.jp")];
- char stringpool_str5474[sizeof("namsos.no")];
- char stringpool_str5475[sizeof("hanggliding.aero")];
- char stringpool_str5476[sizeof("tcm.museum")];
- char stringpool_str5477[sizeof("munakata.fukuoka.jp")];
- char stringpool_str5478[sizeof("yakumo.shimane.jp")];
- char stringpool_str5479[sizeof("act.gov.au")];
- char stringpool_str5480[sizeof("consultant.aero")];
- char stringpool_str5481[sizeof("bifuka.hokkaido.jp")];
- char stringpool_str5482[sizeof("xn--nmesjevuemie-tcba.no")];
- char stringpool_str5483[sizeof("xn--sndre-land-0cb.no")];
- char stringpool_str5484[sizeof("is-a-designer.com")];
- char stringpool_str5485[sizeof("ise.mie.jp")];
- char stringpool_str5486[sizeof("xn--vegrshei-c0a.no")];
- char stringpool_str5487[sizeof("imperia.it")];
- char stringpool_str5488[sizeof("nikolaev.ua")];
- char stringpool_str5489[sizeof("is-a-geek.net")];
- char stringpool_str5490[sizeof("vaksdal.no")];
- char stringpool_str5491[sizeof("newport.museum")];
- char stringpool_str5492[sizeof("cc.al.us")];
- char stringpool_str5493[sizeof("okoppe.hokkaido.jp")];
- char stringpool_str5494[sizeof("xn--sknland-fxa.no")];
- char stringpool_str5495[sizeof("fuchu.hiroshima.jp")];
- char stringpool_str5496[sizeof("ichinomiya.aichi.jp")];
- char stringpool_str5497[sizeof("kitakata.fukushima.jp")];
- char stringpool_str5498[sizeof("xn--comunicaes-v6a2o.museum")];
- char stringpool_str5499[sizeof("xn--jlster-bya.no")];
- char stringpool_str5500[sizeof("sch.ly")];
- char stringpool_str5501[sizeof("kamogawa.chiba.jp")];
- char stringpool_str5502[sizeof("oryol.ru")];
- char stringpool_str5503[sizeof("udmurtia.ru")];
- char stringpool_str5504[sizeof("is-gone.com")];
- char stringpool_str5505[sizeof("yakumo.hokkaido.jp")];
- char stringpool_str5506[sizeof("net.gp")];
- char stringpool_str5507[sizeof("ne.jp")];
- char stringpool_str5508[sizeof("equipment.aero")];
- char stringpool_str5509[sizeof("iijima.nagano.jp")];
- char stringpool_str5510[sizeof("ogasawara.tokyo.jp")];
- char stringpool_str5511[sizeof("preservation.museum")];
- char stringpool_str5512[sizeof("org.ky")];
- char stringpool_str5513[sizeof("suifu.ibaraki.jp")];
- char stringpool_str5514[sizeof("nagareyama.chiba.jp")];
- char stringpool_str5515[sizeof("is-an-engineer.com")];
- char stringpool_str5516[sizeof("judygarland.museum")];
- char stringpool_str5517[sizeof("net.ph")];
- char stringpool_str5518[sizeof("tsuruga.fukui.jp")];
- char stringpool_str5519[sizeof("is-with-theband.com")];
- char stringpool_str5520[sizeof("schweiz.museum")];
- char stringpool_str5521[sizeof("omigawa.chiba.jp")];
- char stringpool_str5522[sizeof("navigation.aero")];
- char stringpool_str5523[sizeof("presse.fr")];
- char stringpool_str5524[sizeof("paleo.museum")];
- char stringpool_str5525[sizeof("hamburg.museum")];
- char stringpool_str5526[sizeof("xn--brnny-wuac.no")];
- char stringpool_str5527[sizeof("xn--tjme-hra.no")];
- char stringpool_str5528[sizeof("kiryu.gunma.jp")];
- char stringpool_str5529[sizeof("pol.dz")];
- char stringpool_str5530[sizeof("piacenza.it")];
- char stringpool_str5531[sizeof("vic.gov.au")];
- char stringpool_str5532[sizeof("nyuzen.toyama.jp")];
- char stringpool_str5533[sizeof("xn--o3cw4h")];
- char stringpool_str5534[sizeof("interactive.museum")];
- char stringpool_str5535[sizeof("in-addr.arpa")];
- char stringpool_str5536[sizeof("motegi.tochigi.jp")];
- char stringpool_str5537[sizeof("nakamichi.yamanashi.jp")];
- char stringpool_str5538[sizeof("tamakawa.fukushima.jp")];
- char stringpool_str5539[sizeof("hirokawa.fukuoka.jp")];
- char stringpool_str5540[sizeof("is-a-celticsfan.org")];
- char stringpool_str5541[sizeof("xn--9dbhblg6di.museum")];
- char stringpool_str5542[sizeof("kawaue.gifu.jp")];
- char stringpool_str5543[sizeof("fauske.no")];
- char stringpool_str5544[sizeof("usgarden.museum")];
- char stringpool_str5545[sizeof("xn--srfold-bya.no")];
- char stringpool_str5546[sizeof("matsusaka.mie.jp")];
- char stringpool_str5547[sizeof("inderoy.no")];
- char stringpool_str5548[sizeof("wassamu.hokkaido.jp")];
- char stringpool_str5549[sizeof("norilsk.ru")];
- char stringpool_str5550[sizeof("ichinohe.iwate.jp")];
- char stringpool_str5551[sizeof("is-into-games.com")];
- char stringpool_str5552[sizeof("tarumizu.kagoshima.jp")];
- char stringpool_str5553[sizeof("wa.gov.au")];
- char stringpool_str5554[sizeof("boldlygoingnowhere.org")];
- char stringpool_str5555[sizeof("webhop.biz")];
- char stringpool_str5556[sizeof("xn--skjervy-v1a.no")];
- char stringpool_str5557[sizeof("pruszkow.pl")];
- char stringpool_str5558[sizeof("tomika.gifu.jp")];
- char stringpool_str5559[sizeof("ngo.pl")];
- char stringpool_str5560[sizeof("hanyu.saitama.jp")];
- char stringpool_str5561[sizeof("pe.kr")];
- char stringpool_str5562[sizeof("oshima.yamaguchi.jp")];
- char stringpool_str5563[sizeof("shiso.hyogo.jp")];
- char stringpool_str5564[sizeof("olsztyn.pl")];
- char stringpool_str5565[sizeof("wolomin.pl")];
- char stringpool_str5566[sizeof("uenohara.yamanashi.jp")];
- char stringpool_str5567[sizeof("is-very-nice.org")];
- char stringpool_str5568[sizeof("yamada.fukuoka.jp")];
- char stringpool_str5569[sizeof("miyako.iwate.jp")];
- char stringpool_str5570[sizeof("xn--jrpeland-54a.no")];
- char stringpool_str5571[sizeof("is-a-financialadvisor.com")];
- char stringpool_str5572[sizeof("umi.fukuoka.jp")];
- char stringpool_str5573[sizeof("ptz.ru")];
- char stringpool_str5574[sizeof("int.lk")];
- char stringpool_str5575[sizeof("utazas.hu")];
- char stringpool_str5576[sizeof("fuchu.toyama.jp")];
- char stringpool_str5577[sizeof("org.ly")];
- char stringpool_str5578[sizeof("edu.mx")];
- char stringpool_str5579[sizeof("xn--skierv-uta.no")];
- char stringpool_str5580[sizeof("int.la")];
- char stringpool_str5581[sizeof("com.mx")];
- char stringpool_str5582[sizeof("ikusaka.nagano.jp")];
- char stringpool_str5583[sizeof("yawara.ibaraki.jp")];
- char stringpool_str5584[sizeof("matsue.shimane.jp")];
- char stringpool_str5585[sizeof("prd.mg")];
- char stringpool_str5586[sizeof("tokorozawa.saitama.jp")];
- char stringpool_str5587[sizeof("org.mv")];
- char stringpool_str5588[sizeof("yamamoto.miyagi.jp")];
- char stringpool_str5589[sizeof("net.ky")];
- char stringpool_str5590[sizeof("chikugo.fukuoka.jp")];
- char stringpool_str5591[sizeof("nyc.mn")];
- char stringpool_str5592[sizeof("otaru.hokkaido.jp")];
- char stringpool_str5593[sizeof("prato.it")];
- char stringpool_str5594[sizeof("is-a-bookkeeper.com")];
- char stringpool_str5595[sizeof("lajolla.museum")];
- char stringpool_str5596[sizeof("shisui.chiba.jp")];
- char stringpool_str5597[sizeof("walbrzych.pl")];
- char stringpool_str5598[sizeof("ninohe.iwate.jp")];
- char stringpool_str5599[sizeof("ichinoseki.iwate.jp")];
- char stringpool_str5600[sizeof("emergency.aero")];
- char stringpool_str5601[sizeof("alaska.museum")];
- char stringpool_str5602[sizeof("modelling.aero")];
- char stringpool_str5603[sizeof("xn--sgne-gra.no")];
- char stringpool_str5604[sizeof("consulting.aero")];
- char stringpool_str5605[sizeof("ninomiya.kanagawa.jp")];
- char stringpool_str5606[sizeof("nikko.tochigi.jp")];
- char stringpool_str5607[sizeof("wielun.pl")];
- char stringpool_str5608[sizeof("nic.uk")];
- char stringpool_str5609[sizeof("yuu.yamaguchi.jp")];
- char stringpool_str5610[sizeof("komagane.nagano.jp")];
- char stringpool_str5611[sizeof("isesaki.gunma.jp")];
- char stringpool_str5612[sizeof("gob.mx")];
- char stringpool_str5613[sizeof("chikujo.fukuoka.jp")];
- char stringpool_str5614[sizeof("yaese.okinawa.jp")];
- char stringpool_str5615[sizeof("is-a-chef.org")];
- char stringpool_str5616[sizeof("watari.miyagi.jp")];
- char stringpool_str5617[sizeof("mitake.gifu.jp")];
- char stringpool_str5618[sizeof("xn--b-5ga.telemark.no")];
- char stringpool_str5619[sizeof("matsubara.osaka.jp")];
- char stringpool_str5620[sizeof("kamagaya.chiba.jp")];
- char stringpool_str5621[sizeof("sasaguri.fukuoka.jp")];
- char stringpool_str5622[sizeof("katsuragi.nara.jp")];
- char stringpool_str5623[sizeof("sologne.museum")];
- char stringpool_str5624[sizeof("nosegawa.nara.jp")];
- char stringpool_str5625[sizeof("wajima.ishikawa.jp")];
- char stringpool_str5626[sizeof("kommunalforbund.se")];
- char stringpool_str5627[sizeof("trolley.museum")];
- char stringpool_str5628[sizeof("yachimata.chiba.jp")];
- char stringpool_str5629[sizeof("pomorskie.pl")];
- char stringpool_str5630[sizeof("sosnowiec.pl")];
- char stringpool_str5631[sizeof("matsuzaki.shizuoka.jp")];
- char stringpool_str5632[sizeof("info.az")];
- char stringpool_str5633[sizeof("xn--tnsberg-q1a.no")];
- char stringpool_str5634[sizeof("web.lk")];
- char stringpool_str5635[sizeof("xn--srreisa-q1a.no")];
- char stringpool_str5636[sizeof("samegawa.fukushima.jp")];
- char stringpool_str5637[sizeof("ngo.ph")];
- char stringpool_str5638[sizeof("pasadena.museum")];
- char stringpool_str5639[sizeof("iiyama.nagano.jp")];
- char stringpool_str5640[sizeof("midsund.no")];
- char stringpool_str5641[sizeof("fetsund.no")];
- char stringpool_str5642[sizeof("aurskog-holand.no")];
- char stringpool_str5643[sizeof("sekigahara.gifu.jp")];
- char stringpool_str5644[sizeof("net.ly")];
- char stringpool_str5645[sizeof("jfk.museum")];
- char stringpool_str5646[sizeof("info.tz")];
- char stringpool_str5647[sizeof("alesund.no")];
- char stringpool_str5648[sizeof("ishikawa.jp")];
- char stringpool_str5649[sizeof("zaporizhzhia.ua")];
- char stringpool_str5650[sizeof("net.mv")];
- char stringpool_str5651[sizeof("civilization.museum")];
- char stringpool_str5652[sizeof("yuasa.wakayama.jp")];
- char stringpool_str5653[sizeof("photography.museum")];
- char stringpool_str5654[sizeof("lucerne.museum")];
- char stringpool_str5655[sizeof("farsund.no")];
- char stringpool_str5656[sizeof("org.py")];
- char stringpool_str5657[sizeof("unjarga.no")];
- char stringpool_str5658[sizeof("group.aero")];
- char stringpool_str5659[sizeof("zachpomor.pl")];
- char stringpool_str5660[sizeof("mitou.yamaguchi.jp")];
- char stringpool_str5661[sizeof("xn--od0alg.cn")];
- char stringpool_str5662[sizeof("matsubushi.saitama.jp")];
- char stringpool_str5663[sizeof("watchandclock.museum")];
- char stringpool_str5664[sizeof("accident-investigation.aero")];
- char stringpool_str5665[sizeof("xn--ygbi2ammx")];
- char stringpool_str5666[sizeof("wallonie.museum")];
- char stringpool_str5667[sizeof("wegrow.pl")];
- char stringpool_str5668[sizeof("ind.gt")];
- char stringpool_str5669[sizeof("int.pt")];
- char stringpool_str5670[sizeof("xn--yfro4i67o")];
- char stringpool_str5671[sizeof("ibigawa.gifu.jp")];
- char stringpool_str5672[sizeof("xn--vre-eiker-k8a.no")];
- char stringpool_str5673[sizeof("namegawa.saitama.jp")];
- char stringpool_str5674[sizeof("parti.se")];
- char stringpool_str5675[sizeof("endoftheinternet.org")];
- char stringpool_str5676[sizeof("int.rw")];
- char stringpool_str5677[sizeof("xn--aroport-bya.ci")];
- char stringpool_str5678[sizeof("xn--ystre-slidre-ujb.no")];
- char stringpool_str5679[sizeof("niiza.saitama.jp")];
- char stringpool_str5680[sizeof("chikuho.fukuoka.jp")];
- char stringpool_str5681[sizeof("webhop.info")];
- char stringpool_str5682[sizeof("nanbu.tottori.jp")];
- char stringpool_str5683[sizeof("xn--ygarden-p1a.no")];
- char stringpool_str5684[sizeof("sukagawa.fukushima.jp")];
- char stringpool_str5685[sizeof("xn--osyro-wua.no")];
- char stringpool_str5686[sizeof("press.ma")];
- char stringpool_str5687[sizeof("georgia.museum")];
- char stringpool_str5688[sizeof("uonuma.niigata.jp")];
- char stringpool_str5689[sizeof("press.museum")];
- char stringpool_str5690[sizeof("tanagura.fukushima.jp")];
- char stringpool_str5691[sizeof("int.mw")];
- char stringpool_str5692[sizeof("yokoshibahikari.chiba.jp")];
- char stringpool_str5693[sizeof("pesaro-urbino.it")];
- char stringpool_str5694[sizeof("mitsue.nara.jp")];
- char stringpool_str5695[sizeof("naval.museum")];
- char stringpool_str5696[sizeof("nahari.kochi.jp")];
- char stringpool_str5697[sizeof("xn--avery-yua.no")];
- char stringpool_str5698[sizeof("xn--od0alg.hk")];
- char stringpool_str5699[sizeof("katsushika.tokyo.jp")];
- char stringpool_str5700[sizeof("otsuki.kochi.jp")];
- char stringpool_str5701[sizeof("jewelry.museum")];
- char stringpool_str5702[sizeof("nrw.museum")];
- char stringpool_str5703[sizeof("takarazuka.hyogo.jp")];
- char stringpool_str5704[sizeof("matsuura.nagasaki.jp")];
- char stringpool_str5705[sizeof("romskog.no")];
- char stringpool_str5706[sizeof("ino.kochi.jp")];
- char stringpool_str5707[sizeof("panama.museum")];
- char stringpool_str5708[sizeof("web.pk")];
- char stringpool_str5709[sizeof("um.gov.pl")];
- char stringpool_str5710[sizeof("namegata.ibaraki.jp")];
- char stringpool_str5711[sizeof("isa-hockeynut.com")];
- char stringpool_str5712[sizeof("xn--eveni-0qa01ga.no")];
- char stringpool_str5713[sizeof("marugame.kagawa.jp")];
- char stringpool_str5714[sizeof("is-saved.org")];
- char stringpool_str5715[sizeof("experts-comptables.fr")];
- char stringpool_str5716[sizeof("paderborn.museum")];
- char stringpool_str5717[sizeof("net.py")];
- char stringpool_str5718[sizeof("net.gy")];
- char stringpool_str5719[sizeof("komvux.se")];
- char stringpool_str5720[sizeof("zakopane.pl")];
- char stringpool_str5721[sizeof("torsken.no")];
- char stringpool_str5722[sizeof("isa-geek.net")];
- char stringpool_str5723[sizeof("matsukawa.nagano.jp")];
- char stringpool_str5724[sizeof("eidskog.no")];
- char stringpool_str5725[sizeof("ontario.museum")];
- char stringpool_str5726[sizeof("fujikawaguchiko.yamanashi.jp")];
- char stringpool_str5727[sizeof("makurazaki.kagoshima.jp")];
- char stringpool_str5728[sizeof("isa.kagoshima.jp")];
- char stringpool_str5729[sizeof("isa-geek.org")];
- char stringpool_str5730[sizeof("ascolipiceno.it")];
- char stringpool_str5731[sizeof("xn--hobl-ira.no")];
- char stringpool_str5732[sizeof("notogawa.shiga.jp")];
- char stringpool_str5733[sizeof("kasugai.aichi.jp")];
- char stringpool_str5734[sizeof("fuchu.tokyo.jp")];
- char stringpool_str5735[sizeof("mutsu.aomori.jp")];
- char stringpool_str5736[sizeof("matsumoto.nagano.jp")];
- char stringpool_str5737[sizeof("nanyo.yamagata.jp")];
- char stringpool_str5738[sizeof("umaji.kochi.jp")];
- char stringpool_str5739[sizeof("nakagawa.tokushima.jp")];
- char stringpool_str5740[sizeof("konskowola.pl")];
- char stringpool_str5741[sizeof("kursk.ru")];
- char stringpool_str5742[sizeof("ivanovo.ru")];
- char stringpool_str5743[sizeof("presidio.museum")];
- char stringpool_str5744[sizeof("ishikari.hokkaido.jp")];
- char stringpool_str5745[sizeof("yachiyo.ibaraki.jp")];
- char stringpool_str5746[sizeof("tomsk.ru")];
- char stringpool_str5747[sizeof("nakagawa.nagano.jp")];
- char stringpool_str5748[sizeof("westfalen.museum")];
- char stringpool_str5749[sizeof("gotsu.shimane.jp")];
- char stringpool_str5750[sizeof("uto.kumamoto.jp")];
- char stringpool_str5751[sizeof("wajiki.tokushima.jp")];
- char stringpool_str5752[sizeof("neyagawa.osaka.jp")];
- char stringpool_str5753[sizeof("yamagata.jp")];
- char stringpool_str5754[sizeof("pesarourbino.it")];
- char stringpool_str5755[sizeof("xn--nvuotna-hwa.no")];
- char stringpool_str5756[sizeof("matsushige.tokushima.jp")];
- char stringpool_str5757[sizeof("production.aero")];
- char stringpool_str5758[sizeof("ing.pa")];
- char stringpool_str5759[sizeof("polkowice.pl")];
- char stringpool_str5760[sizeof("xn--90a3ac")];
- char stringpool_str5761[sizeof("nakagawa.hokkaido.jp")];
- char stringpool_str5762[sizeof("uw.gov.pl")];
- char stringpool_str5763[sizeof("ube.yamaguchi.jp")];
- char stringpool_str5764[sizeof("wazuka.kyoto.jp")];
- char stringpool_str5765[sizeof("wodzislaw.pl")];
- char stringpool_str5766[sizeof("yasuda.kochi.jp")];
- char stringpool_str5767[sizeof("xn--vler-qoa.xn--stfold-9xa.no")];
- char stringpool_str5768[sizeof("mitsuke.niigata.jp")];
- char stringpool_str5769[sizeof("niyodogawa.kochi.jp")];
- char stringpool_str5770[sizeof("pharmacy.museum")];
- char stringpool_str5771[sizeof("waw.pl")];
- char stringpool_str5772[sizeof("zaporizhzhe.ua")];
- char stringpool_str5773[sizeof("xn--yer-zna.no")];
- char stringpool_str5774[sizeof("ascoli-piceno.it")];
- char stringpool_str5775[sizeof("yasaka.nagano.jp")];
- char stringpool_str5776[sizeof("xn--holtlen-hxa.no")];
- char stringpool_str5777[sizeof("xn--fl-zia.no")];
- char stringpool_str5778[sizeof("yonago.tottori.jp")];
- char stringpool_str5779[sizeof("naturhistorisches.museum")];
- char stringpool_str5780[sizeof("pp.ru")];
- char stringpool_str5781[sizeof("in-the-band.net")];
- char stringpool_str5782[sizeof("xn--fiqs8s")];
- char stringpool_str5783[sizeof("slask.pl")];
- char stringpool_str5784[sizeof("xn--hpmir-xqa.no")];
- char stringpool_str5785[sizeof("pomorze.pl")];
- char stringpool_str5786[sizeof("szczytno.pl")];
- char stringpool_str5787[sizeof("wanouchi.gifu.jp")];
- char stringpool_str5788[sizeof("inf.mk")];
- char stringpool_str5789[sizeof("matsumoto.kagoshima.jp")];
- char stringpool_str5790[sizeof("historyofscience.museum")];
- char stringpool_str5791[sizeof("yosemite.museum")];
- char stringpool_str5792[sizeof("minamiechizen.fukui.jp")];
- char stringpool_str5793[sizeof("uki.kumamoto.jp")];
- char stringpool_str5794[sizeof("lutsk.ua")];
- char stringpool_str5795[sizeof("yamaga.kumamoto.jp")];
- char stringpool_str5796[sizeof("matsuno.ehime.jp")];
- char stringpool_str5797[sizeof("prd.km")];
- char stringpool_str5798[sizeof("xn--fiqz9s")];
- char stringpool_str5799[sizeof("monzaedellabrianza.it")];
- char stringpool_str5800[sizeof("xn--hery-ira.nordland.no")];
- char stringpool_str5801[sizeof("shizuoka.jp")];
- char stringpool_str5802[sizeof("pisz.pl")];
- char stringpool_str5803[sizeof("satsumasendai.kagoshima.jp")];
- char stringpool_str5804[sizeof("matsushima.miyagi.jp")];
- char stringpool_str5805[sizeof("yahiko.niigata.jp")];
- char stringpool_str5806[sizeof("ug.gov.pl")];
- char stringpool_str5807[sizeof("yasugi.shimane.jp")];
- char stringpool_str5808[sizeof("itako.ibaraki.jp")];
- char stringpool_str5809[sizeof("xn--3e0b707e")];
- char stringpool_str5810[sizeof("s3-eu-west-1.amazonaws.com")];
- char stringpool_str5811[sizeof("ishikawa.okinawa.jp")];
- char stringpool_str5812[sizeof("iizuka.fukuoka.jp")];
- char stringpool_str5813[sizeof("ikaruga.nara.jp")];
- char stringpool_str5814[sizeof("insurance.aero")];
- char stringpool_str5815[sizeof("yukuhashi.fukuoka.jp")];
- char stringpool_str5816[sizeof("matsuyama.ehime.jp")];
- char stringpool_str5817[sizeof("itakura.gunma.jp")];
- char stringpool_str5818[sizeof("katsuragi.wakayama.jp")];
- char stringpool_str5819[sizeof("yamal.ru")];
- char stringpool_str5820[sizeof("vanylven.no")];
- char stringpool_str5821[sizeof("yabuki.fukushima.jp")];
- char stringpool_str5822[sizeof("nanbu.yamanashi.jp")];
- char stringpool_str5823[sizeof("xn--h-2fa.no")];
- char stringpool_str5824[sizeof("int.mv")];
- char stringpool_str5825[sizeof("yatomi.aichi.jp")];
- char stringpool_str5826[sizeof("wroclaw.pl")];
- char stringpool_str5827[sizeof("xn--flor-jra.no")];
- char stringpool_str5828[sizeof("wlocl.pl")];
- char stringpool_str5829[sizeof("xn--mgb2ddes")];
- char stringpool_str5830[sizeof("xn--frna-woa.no")];
- char stringpool_str5831[sizeof("org.lv")];
- char stringpool_str5832[sizeof("yamaguchi.jp")];
- char stringpool_str5833[sizeof("nationalfirearms.museum")];
- char stringpool_str5834[sizeof("per.la")];
- char stringpool_str5835[sizeof("chippubetsu.hokkaido.jp")];
- char stringpool_str5836[sizeof("xn--od0aq3b.hk")];
- char stringpool_str5837[sizeof("s3.amazonaws.com")];
- char stringpool_str5838[sizeof("xn--fjord-lra.no")];
- char stringpool_str5839[sizeof("kisarazu.chiba.jp")];
- char stringpool_str5840[sizeof("palermo.it")];
- char stringpool_str5841[sizeof("tatsuno.hyogo.jp")];
- char stringpool_str5842[sizeof("nakagusuku.okinawa.jp")];
- char stringpool_str5843[sizeof("ushiku.ibaraki.jp")];
- char stringpool_str5844[sizeof("watarai.mie.jp")];
- char stringpool_str5845[sizeof("xn--hcesuolo-7ya35b.no")];
- char stringpool_str5846[sizeof("cc.sd.us")];
- char stringpool_str5847[sizeof("yamagata.nagano.jp")];
- char stringpool_str5848[sizeof("war.museum")];
- char stringpool_str5849[sizeof("national-library-scotland.uk")];
- char stringpool_str5850[sizeof("po.gov.pl")];
- char stringpool_str5851[sizeof("uchihara.ibaraki.jp")];
- char stringpool_str5852[sizeof("newyork.museum")];
- char stringpool_str5853[sizeof("otoyo.kochi.jp")];
- char stringpool_str5854[sizeof("portland.museum")];
- char stringpool_str5855[sizeof("xn--rland-uua.no")];
- char stringpool_str5856[sizeof("okazaki.aichi.jp")];
- char stringpool_str5857[sizeof("xn--frya-hra.no")];
- char stringpool_str5858[sizeof("pa.gov.pl")];
- char stringpool_str5859[sizeof("xn--mely-ira.no")];
- char stringpool_str5860[sizeof("pharmacien.fr")];
- char stringpool_str5861[sizeof("xn--finny-yua.no")];
- char stringpool_str5862[sizeof("xn--rady-ira.no")];
- char stringpool_str5863[sizeof("ulvik.no")];
- char stringpool_str5864[sizeof("yamagata.ibaraki.jp")];
- char stringpool_str5865[sizeof("net.lv")];
- char stringpool_str5866[sizeof("xn--rdal-poa.no")];
- char stringpool_str5867[sizeof("xn--risr-ira.no")];
- char stringpool_str5868[sizeof("yonaguni.okinawa.jp")];
- char stringpool_str5869[sizeof("kouzushima.tokyo.jp")];
- char stringpool_str5870[sizeof("is-not-certified.com")];
- char stringpool_str5871[sizeof("ishigaki.okinawa.jp")];
- char stringpool_str5872[sizeof("tatsuno.nagano.jp")];
- char stringpool_str5873[sizeof("is-a-chef.com")];
- char stringpool_str5874[sizeof("xn--hnefoss-q1a.no")];
- char stringpool_str5875[sizeof("shizuoka.shizuoka.jp")];
- char stringpool_str5876[sizeof("yamada.iwate.jp")];
- char stringpool_str5877[sizeof("pvt.ge")];
- char stringpool_str5878[sizeof("xn--stre-toten-zcb.no")];
- char stringpool_str5879[sizeof("futsu.nagasaki.jp")];
- char stringpool_str5880[sizeof("xn--mk0axi.hk")];
- char stringpool_str5881[sizeof("xn--merker-kua.no")];
- char stringpool_str5882[sizeof("accident-prevention.aero")];
- char stringpool_str5883[sizeof("kihoku.ehime.jp")];
- char stringpool_str5884[sizeof("itoigawa.niigata.jp")];
- char stringpool_str5885[sizeof("xn--risa-5na.no")];
- char stringpool_str5886[sizeof("pro.pr")];
- char stringpool_str5887[sizeof("ide.kyoto.jp")];
- char stringpool_str5888[sizeof("prochowice.pl")];
- char stringpool_str5889[sizeof("plo.ps")];
- char stringpool_str5890[sizeof("yamakita.kanagawa.jp")];
- char stringpool_str5891[sizeof("masaki.ehime.jp")];
- char stringpool_str5892[sizeof("naoshima.kagawa.jp")];
- char stringpool_str5893[sizeof("xn--rennesy-v1a.no")];
- char stringpool_str5894[sizeof("ulm.museum")];
- char stringpool_str5895[sizeof("penza.ru")];
- char stringpool_str5896[sizeof("ine.kyoto.jp")];
- char stringpool_str5897[sizeof("xn--mgbaam7a8h")];
- char stringpool_str5898[sizeof("usa.museum")];
- char stringpool_str5899[sizeof("xn--muost-0qa.no")];
- char stringpool_str5900[sizeof("mutsuzawa.chiba.jp")];
- char stringpool_str5901[sizeof("porsanger.no")];
- char stringpool_str5902[sizeof("xn--mjndalen-64a.no")];
- char stringpool_str5903[sizeof("naturalsciences.museum")];
- char stringpool_str5904[sizeof("xn--drbak-wua.no")];
- char stringpool_str5905[sizeof("iwanuma.miyagi.jp")];
- char stringpool_str5906[sizeof("xn--indery-fya.no")];
- char stringpool_str5907[sizeof("xn--dnna-gra.no")];
- char stringpool_str5908[sizeof("taishin.fukushima.jp")];
- char stringpool_str5909[sizeof("matsuda.kanagawa.jp")];
- char stringpool_str5910[sizeof("noboribetsu.hokkaido.jp")];
- char stringpool_str5911[sizeof("yamagata.gifu.jp")];
- char stringpool_str5912[sizeof("katsuura.chiba.jp")];
- char stringpool_str5913[sizeof("yakage.okayama.jp")];
- char stringpool_str5914[sizeof("pharmaciens.km")];
- char stringpool_str5915[sizeof("is-a-chef.net")];
- char stringpool_str5916[sizeof("plaza.museum")];
- char stringpool_str5917[sizeof("xn--msy-ula0h.no")];
- char stringpool_str5918[sizeof("pvt.k12.ma.us")];
- char stringpool_str5919[sizeof("xn--hylandet-54a.no")];
- char stringpool_str5920[sizeof("scrapping.cc")];
- char stringpool_str5921[sizeof("xn--uc0atv.hk")];
- char stringpool_str5922[sizeof("xn--rskog-uua.no")];
- char stringpool_str5923[sizeof("urayasu.chiba.jp")];
- char stringpool_str5924[sizeof("kaszuby.pl")];
- char stringpool_str5925[sizeof("xn--rholt-mra.no")];
- char stringpool_str5926[sizeof("xn--uc0atv.tw")];
- char stringpool_str5927[sizeof("xn--mlatvuopmi-s4a.no")];
- char stringpool_str5928[sizeof("xn--mgba3a4fra")];
- char stringpool_str5929[sizeof("kaizuka.osaka.jp")];
- char stringpool_str5930[sizeof("xn--mgba3a4f16a")];
- char stringpool_str5931[sizeof("irc.pl")];
- char stringpool_str5932[sizeof("xn--rst-0na.no")];
- char stringpool_str5933[sizeof("watch-and-clock.museum")];
- char stringpool_str5934[sizeof("xn--rde-ula.no")];
- char stringpool_str5935[sizeof("xn--mgba3a4fra.ir")];
- char stringpool_str5936[sizeof("xn--mgba3a4f16a.ir")];
- char stringpool_str5937[sizeof("ostrowiec.pl")];
- char stringpool_str5938[sizeof("xn--rros-gra.no")];
- char stringpool_str5939[sizeof("xn--h2brj9c")];
- char stringpool_str5940[sizeof("chizu.tottori.jp")];
- char stringpool_str5941[sizeof("org.mx")];
- char stringpool_str5942[sizeof("urasoe.okinawa.jp")];
- char stringpool_str5943[sizeof("xn--mgb9awbf")];
- char stringpool_str5944[sizeof("xn--mot-tla.no")];
- char stringpool_str5945[sizeof("yamagata.yamagata.jp")];
- char stringpool_str5946[sizeof("uscountryestate.museum")];
- char stringpool_str5947[sizeof("uji.kyoto.jp")];
- char stringpool_str5948[sizeof("xn--mgbayh7gpa")];
- char stringpool_str5949[sizeof("portlligat.museum")];
- char stringpool_str5950[sizeof("inashiki.ibaraki.jp")];
- char stringpool_str5951[sizeof("oharu.aichi.jp")];
- char stringpool_str5952[sizeof("maizuru.kyoto.jp")];
- char stringpool_str5953[sizeof("isa-geek.com")];
- char stringpool_str5954[sizeof("xn--nttery-byae.no")];
- char stringpool_str5955[sizeof("xn--dyry-ira.no")];
- char stringpool_str5956[sizeof("nyc.museum")];
- char stringpool_str5957[sizeof("ichihara.chiba.jp")];
- char stringpool_str5958[sizeof("xn--rlingen-mxa.no")];
- char stringpool_str5959[sizeof("matsumae.hokkaido.jp")];
- char stringpool_str5960[sizeof("pro.mv")];
- char stringpool_str5961[sizeof("iamallama.com")];
- char stringpool_str5962[sizeof("net.mx")];
- char stringpool_str5963[sizeof("xn--kprw13d")];
- char stringpool_str5964[sizeof("xn--kpry57d")];
- char stringpool_str5965[sizeof("nagakute.aichi.jp")];
- char stringpool_str5966[sizeof("s3-ap-northeast-1.amazonaws.com")];
- char stringpool_str5967[sizeof("pubol.museum")];
- char stringpool_str5968[sizeof("usculture.museum")];
- char stringpool_str5969[sizeof("perugia.it")];
- char stringpool_str5970[sizeof("xn--unjrga-rta.no")];
- char stringpool_str5971[sizeof("xn--davvenjrga-y4a.no")];
- char stringpool_str5972[sizeof("shizukuishi.iwate.jp")];
- char stringpool_str5973[sizeof("s3-ap-southeast-1.amazonaws.com")];
- char stringpool_str5974[sizeof("press.aero")];
- char stringpool_str5975[sizeof("press.se")];
- char stringpool_str5976[sizeof("wildlife.museum")];
- char stringpool_str5977[sizeof("xn--hery-ira.xn--mre-og-romsdal-qqb.no")];
- char stringpool_str5978[sizeof("xn--krehamn-dxa.no")];
- char stringpool_str5979[sizeof("xn--hyanger-q1a.no")];
- char stringpool_str5980[sizeof("xn--lury-ira.no")];
- char stringpool_str5981[sizeof("xn--mli-tla.no")];
- char stringpool_str5982[sizeof("posts-and-telecommunications.museum")];
- char stringpool_str5983[sizeof("perso.tn")];
- char stringpool_str5984[sizeof("iwakura.aichi.jp")];
- char stringpool_str5985[sizeof("pippu.hokkaido.jp")];
- char stringpool_str5986[sizeof("nakagyo.kyoto.jp")];
- char stringpool_str5987[sizeof("xn--p1ai")];
- char stringpool_str5988[sizeof("xn--klbu-woa.no")];
- char stringpool_str5989[sizeof("xn--hbmer-xqa.no")];
- char stringpool_str5990[sizeof("wloclawek.pl")];
- char stringpool_str5991[sizeof("xn--linds-pra.no")];
- char stringpool_str5992[sizeof("nakagawa.fukuoka.jp")];
- char stringpool_str5993[sizeof("s3-ap-southeast-2.amazonaws.com")];
- char stringpool_str5994[sizeof("xn--lesund-hua.no")];
- char stringpool_str5995[sizeof("perso.sn")];
- char stringpool_str5996[sizeof("xn--kfjord-iua.no")];
- char stringpool_str5997[sizeof("xn--fpcrj9c3d")];
- char stringpool_str5998[sizeof("perso.ht")];
- char stringpool_str5999[sizeof("xn--krdsherad-m8a.no")];
- char stringpool_str6000[sizeof("xn--clchc0ea0b2g2a9gcd")];
- char stringpool_str6001[sizeof("xn--oppegrd-ixa.no")];
- char stringpool_str6002[sizeof("xn--pgbs0dh")];
- char stringpool_str6003[sizeof("ishikawa.fukushima.jp")];
- char stringpool_str6004[sizeof("xn--hgebostad-g3a.no")];
- char stringpool_str6005[sizeof("utashinai.hokkaido.jp")];
- char stringpool_str6006[sizeof("xn--lrenskog-54a.no")];
- char stringpool_str6007[sizeof("xn--lrdal-sra.no")];
- char stringpool_str6008[sizeof("xn--54b7fta0cc")];
- char stringpool_str6009[sizeof("pc.pl")];
- char stringpool_str6010[sizeof("appspot.com")];
- char stringpool_str6011[sizeof("iwafune.tochigi.jp")];
- char stringpool_str6012[sizeof("yatsushiro.kumamoto.jp")];
- char stringpool_str6013[sizeof("yotsukaido.chiba.jp")];
- char stringpool_str6014[sizeof("xn--lten-gra.no")];
- char stringpool_str6015[sizeof("is-a-cubicle-slave.com")];
- char stringpool_str6016[sizeof("xn--karmy-yua.no")];
- char stringpool_str6017[sizeof("xn--gls-elac.no")];
- char stringpool_str6018[sizeof("ichikawa.hyogo.jp")];
- char stringpool_str6019[sizeof("xn--l-1fa.no")];
- char stringpool_str6020[sizeof("xn--krager-gya.no")];
- char stringpool_str6021[sizeof("xn--koluokta-7ya57h.no")];
- char stringpool_str6022[sizeof("xn--ostery-fya.no")];
- char stringpool_str6023[sizeof("xn--mgbbh1a71e")];
- char stringpool_str6024[sizeof("xn--uc0ay4a.hk")];
- char stringpool_str6025[sizeof("xn--langevg-jxa.no")];
- char stringpool_str6026[sizeof("hatsukaichi.hiroshima.jp")];
- char stringpool_str6027[sizeof("katsuyama.fukui.jp")];
- char stringpool_str6028[sizeof("ichikawamisato.yamanashi.jp")];
- char stringpool_str6029[sizeof("xn--h1aegh.museum")];
- char stringpool_str6030[sizeof("xn--gmqw5a.hk")];
- char stringpool_str6031[sizeof("nisshin.aichi.jp")];
- char stringpool_str6032[sizeof("xn--rdy-0nab.no")];
- char stringpool_str6033[sizeof("xn--lhppi-xqa.no")];
- char stringpool_str6034[sizeof("natuurwetenschappen.museum")];
- char stringpool_str6035[sizeof("xn--givuotna-8ya.no")];
- char stringpool_str6036[sizeof("xn--gjvik-wua.no")];
- char stringpool_str6037[sizeof("yanagawa.fukuoka.jp")];
- char stringpool_str6038[sizeof("xn--leagaviika-52b.no")];
- char stringpool_str6039[sizeof("xn--krjohka-hwab49j.no")];
- char stringpool_str6040[sizeof("xn--frde-gra.no")];
- char stringpool_str6041[sizeof("xn--rsta-fra.no")];
- char stringpool_str6042[sizeof("xn--gildeskl-g0a.no")];
- char stringpool_str6043[sizeof("xn--mgbc0a9azcg")];
- char stringpool_str6044[sizeof("xn--lcvr32d.hk")];
- char stringpool_str6045[sizeof("xn--mgberp4a5d4ar")];
- char stringpool_str6046[sizeof("la-spezia.it")];
- char stringpool_str6047[sizeof("xn--mlselv-iua.no")];
- char stringpool_str6048[sizeof("xn--moreke-jua.no")];
- char stringpool_str6049[sizeof("paragliding.aero")];
- char stringpool_str6050[sizeof("podzone.net")];
- char stringpool_str6051[sizeof("yachiyo.chiba.jp")];
- char stringpool_str6052[sizeof("xn--ldingen-q1a.no")];
- char stringpool_str6053[sizeof("xn--mgbqly7cvafr")];
- char stringpool_str6054[sizeof("xn--lns-qla.museum")];
- char stringpool_str6055[sizeof("yatsuka.shimane.jp")];
- char stringpool_str6056[sizeof("iwakuni.yamaguchi.jp")];
- char stringpool_str6057[sizeof("xn--rmskog-bya.no")];
- char stringpool_str6058[sizeof("xn--rhkkervju-01af.no")];
- char stringpool_str6059[sizeof("xn--gmq050i.hk")];
- char stringpool_str6060[sizeof("xn--ggaviika-8ya47h.no")];
- char stringpool_str6061[sizeof("plc.ly")];
- char stringpool_str6062[sizeof("inazawa.aichi.jp")];
- char stringpool_str6063[sizeof("ichikawa.chiba.jp")];
- char stringpool_str6064[sizeof("xn--fzc2c9e2c")];
- char stringpool_str6065[sizeof("xn--mtta-vrjjat-k7af.no")];
- char stringpool_str6066[sizeof("passenger-association.aero")];
- char stringpool_str6067[sizeof("ureshino.mie.jp")];
- char stringpool_str6068[sizeof("xn--mgberp4a5d4a87g")];
- char stringpool_str6069[sizeof("xn--mosjen-eya.no")];
- char stringpool_str6070[sizeof("podzone.org")];
- char stringpool_str6071[sizeof("xn--correios-e-telecomunicaes-ghc29a.museum")];
- char stringpool_str6072[sizeof("xn--ogbpf8fl")];
- char stringpool_str6073[sizeof("xn--loabt-0qa.no")];
- char stringpool_str6074[sizeof("matsudo.chiba.jp")];
- char stringpool_str6075[sizeof("xn--lgbbat1ad8j")];
- char stringpool_str6076[sizeof("pacific.museum")];
- char stringpool_str6077[sizeof("xn--lgrd-poac.no")];
- char stringpool_str6078[sizeof("xn--ksnes-uua.no")];
- char stringpool_str6079[sizeof("xn--gecrj9c")];
- char stringpool_str6080[sizeof("xn--ryken-vua.no")];
- char stringpool_str6081[sizeof("intelligence.museum")];
- char stringpool_str6082[sizeof("xn--hmmrfeasta-s4ac.no")];
- char stringpool_str6083[sizeof("xn--kvfjord-nxa.no")];
- char stringpool_str6084[sizeof("xn--ryrvik-bya.no")];
- char stringpool_str6085[sizeof("xn--lt-liac.no")];
- char stringpool_str6086[sizeof("newspaper.museum")];
- char stringpool_str6087[sizeof("porsgrunn.no")];
- char stringpool_str6088[sizeof("is-slick.com")];
- char stringpool_str6089[sizeof("xn--laheadju-7ya.no")];
- char stringpool_str6090[sizeof("ichikai.tochigi.jp")];
- char stringpool_str6091[sizeof("xn--mgbtf8fl")];
- char stringpool_str6092[sizeof("xn--kvnangen-k0a.no")];
- char stringpool_str6093[sizeof("xn--kranghke-b0a.no")];
- char stringpool_str6094[sizeof("yaizu.shizuoka.jp")];
- char stringpool_str6095[sizeof("imizu.toyama.jp")];
- char stringpool_str6096[sizeof("xn--mgbqly7c0a67fbc")];
- char stringpool_str6097[sizeof("xn--porsgu-sta26f.no")];
- char stringpool_str6098[sizeof("xn--mxtq1m.hk")];
- char stringpool_str6099[sizeof("unazuki.toyama.jp")];
- char stringpool_str6100[sizeof("xn--kvitsy-fya.no")];
- char stringpool_str6101[sizeof("utazu.kagawa.jp")];
- char stringpool_str6102[sizeof("uchiko.ehime.jp")];
+ char stringpool_str204[sizeof("gov.bb")];
+ char stringpool_str205[sizeof("esp.br")];
+ char stringpool_str206[sizeof("best")];
+ char stringpool_str207[sizeof("estate")];
+ char stringpool_str208[sizeof("ci")];
+ char stringpool_str209[sizeof("edu.bb")];
+ char stringpool_str210[sizeof("gov.iq")];
+ char stringpool_str211[sizeof("gov.is")];
+ char stringpool_str212[sizeof("gov.ir")];
+ char stringpool_str213[sizeof("adv.br")];
+ char stringpool_str214[sizeof("edu.iq")];
+ char stringpool_str215[sizeof("edu.is")];
+ char stringpool_str216[sizeof("com.bb")];
+ char stringpool_str217[sizeof("adm.br")];
+ char stringpool_str218[sizeof("mo")];
+ char stringpool_str219[sizeof("com.iq")];
+ char stringpool_str220[sizeof("com.is")];
+ char stringpool_str221[sizeof("md")];
+ char stringpool_str222[sizeof("com.io")];
+ char stringpool_str223[sizeof("mz")];
+ char stringpool_str224[sizeof("gift")];
+ char stringpool_str225[sizeof("bb")];
+ char stringpool_str226[sizeof("com.im")];
+ char stringpool_str227[sizeof("int.tj")];
+ char stringpool_str228[sizeof("beer")];
+ char stringpool_str229[sizeof("com.na")];
+ char stringpool_str230[sizeof("ai")];
+ char stringpool_str231[sizeof("z.bg")];
+ char stringpool_str232[sizeof("art.br")];
+ char stringpool_str233[sizeof("ms")];
+ char stringpool_str234[sizeof("country")];
+ char stringpool_str235[sizeof("fot.br")];
+ char stringpool_str236[sizeof("mr")];
+ char stringpool_str237[sizeof("info.pr")];
+ char stringpool_str238[sizeof("z.se")];
+ char stringpool_str239[sizeof("gov.nc.tr")];
+ char stringpool_str240[sizeof("moe")];
+ char stringpool_str241[sizeof("gov.rw")];
+ char stringpool_str242[sizeof("edu.rw")];
+ char stringpool_str243[sizeof("bi")];
+ char stringpool_str244[sizeof("fst.br")];
+ char stringpool_str245[sizeof("fet.no")];
+ char stringpool_str246[sizeof("ml")];
+ char stringpool_str247[sizeof("int.la")];
+ char stringpool_str248[sizeof("fi")];
+ char stringpool_str249[sizeof("com.rw")];
+ char stringpool_str250[sizeof("center")];
+ char stringpool_str251[sizeof("asso.dz")];
+ char stringpool_str252[sizeof("gotdns.com")];
+ char stringpool_str253[sizeof("gov.qa")];
+ char stringpool_str254[sizeof("edu.qa")];
+ char stringpool_str255[sizeof("info.bb")];
+ char stringpool_str256[sizeof("fla.no")];
+ char stringpool_str257[sizeof("info.az")];
+ char stringpool_str258[sizeof("gy")];
+ char stringpool_str259[sizeof("gifu.jp")];
+ char stringpool_str260[sizeof("gov.ie")];
+ char stringpool_str261[sizeof("com.qa")];
+ char stringpool_str262[sizeof("info.pk")];
+ char stringpool_str263[sizeof("cy")];
+ char stringpool_str264[sizeof("int.bo")];
+ char stringpool_str265[sizeof("mu")];
+ char stringpool_str266[sizeof("cnt.br")];
+ char stringpool_str267[sizeof("blog.br")];
+ char stringpool_str268[sizeof("inf.br")];
+ char stringpool_str269[sizeof("flog.br")];
+ char stringpool_str270[sizeof("c.la")];
+ char stringpool_str271[sizeof("assn.lk")];
+ char stringpool_str272[sizeof("int.is")];
+ char stringpool_str273[sizeof("m.bg")];
+ char stringpool_str274[sizeof("uz")];
+ char stringpool_str275[sizeof("mn")];
+ char stringpool_str276[sizeof("m.se")];
+ char stringpool_str277[sizeof("by")];
+ char stringpool_str278[sizeof("gov.ba")];
+ char stringpool_str279[sizeof("gov.jo")];
+ char stringpool_str280[sizeof("edu.ba")];
+ char stringpool_str281[sizeof("us")];
+ char stringpool_str282[sizeof("edu.jo")];
+ char stringpool_str283[sizeof("fosnes.no")];
+ char stringpool_str284[sizeof("com.ba")];
+ char stringpool_str285[sizeof("com.jo")];
+ char stringpool_str286[sizeof("coffee")];
+ char stringpool_str287[sizeof("gm")];
+ char stringpool_str288[sizeof("im")];
+ char stringpool_str289[sizeof("hm")];
+ char stringpool_str290[sizeof("me")];
+ char stringpool_str291[sizeof("firm.ro")];
+ char stringpool_str292[sizeof("cm")];
+ char stringpool_str293[sizeof("int.rw")];
+ char stringpool_str294[sizeof("hemnes.no")];
+ char stringpool_str295[sizeof("gov.mr")];
+ char stringpool_str296[sizeof("gov.mo")];
+ char stringpool_str297[sizeof("edu.mo")];
+ char stringpool_str298[sizeof("com.mo")];
+ char stringpool_str299[sizeof("firm.co")];
+ char stringpool_str300[sizeof("mq")];
+ char stringpool_str301[sizeof("g12.br")];
+ char stringpool_str302[sizeof("fed.us")];
+ char stringpool_str303[sizeof("mt")];
+ char stringpool_str304[sizeof("moda")];
+ char stringpool_str305[sizeof("am")];
+ char stringpool_str306[sizeof("bj")];
+ char stringpool_str307[sizeof("meet")];
+ char stringpool_str308[sizeof("fj")];
+ char stringpool_str309[sizeof("gov.tw")];
+ char stringpool_str310[sizeof("menu")];
+ char stringpool_str311[sizeof("gov.mk")];
+ char stringpool_str312[sizeof("blogspot.no")];
+ char stringpool_str313[sizeof("idv.tw")];
+ char stringpool_str314[sizeof("edu.tw")];
+ char stringpool_str315[sizeof("gol.no")];
+ char stringpool_str316[sizeof("edu.mk")];
+ char stringpool_str317[sizeof("hol.no")];
+ char stringpool_str318[sizeof("blogspot.cz")];
+ char stringpool_str319[sizeof("com.tw")];
+ char stringpool_str320[sizeof("com.mk")];
+ char stringpool_str321[sizeof("bm")];
+ char stringpool_str322[sizeof("blogspot.ro")];
+ char stringpool_str323[sizeof("fm")];
+ char stringpool_str324[sizeof("gov.ml")];
+ char stringpool_str325[sizeof("bid")];
+ char stringpool_str326[sizeof("u.bg")];
+ char stringpool_str327[sizeof("edu.ml")];
+ char stringpool_str328[sizeof("com.ml")];
+ char stringpool_str329[sizeof("gov.me")];
+ char stringpool_str330[sizeof("ato.br")];
+ char stringpool_str331[sizeof("u.se")];
+ char stringpool_str332[sizeof("edu.me")];
+ char stringpool_str333[sizeof("blogspot.nl")];
+ char stringpool_str334[sizeof("gdansk.pl")];
+ char stringpool_str335[sizeof("ind.br")];
+ char stringpool_str336[sizeof("cim.br")];
+ char stringpool_str337[sizeof("eng.br")];
+ char stringpool_str338[sizeof("info.mv")];
+ char stringpool_str339[sizeof("algard.no")];
+ char stringpool_str340[sizeof("museum")];
+ char stringpool_str341[sizeof("aip.ee")];
+ char stringpool_str342[sizeof("cng.br")];
+ char stringpool_str343[sizeof("blogspot.kr")];
+ char stringpool_str344[sizeof("fin.ec")];
+ char stringpool_str345[sizeof("ga")];
+ char stringpool_str346[sizeof("codespot.com")];
+ char stringpool_str347[sizeof("blogspot.td")];
+ char stringpool_str348[sizeof("isla.pr")];
+ char stringpool_str349[sizeof("haus")];
+ char stringpool_str350[sizeof("ca")];
+ char stringpool_str351[sizeof("qa")];
+ char stringpool_str352[sizeof("cat")];
+ char stringpool_str353[sizeof("gov.as")];
+ char stringpool_str354[sizeof("cab")];
+ char stringpool_str355[sizeof("gob.ar")];
+ char stringpool_str356[sizeof("edu.ar")];
+ char stringpool_str357[sizeof("eid.no")];
+ char stringpool_str358[sizeof("com.ar")];
+ char stringpool_str359[sizeof("mod.uk")];
+ char stringpool_str360[sizeof("uno")];
+ char stringpool_str361[sizeof("frosta.no")];
+ char stringpool_str362[sizeof("gov.ac")];
+ char stringpool_str363[sizeof("aero.mv")];
+ char stringpool_str364[sizeof("edu.ac")];
+ char stringpool_str365[sizeof("com.ac")];
+ char stringpool_str366[sizeof("fie.ee")];
+ char stringpool_str367[sizeof("blogspot.com")];
+ char stringpool_str368[sizeof("fnd.br")];
+ char stringpool_str369[sizeof("edu.bi")];
+ char stringpool_str370[sizeof("gp")];
+ char stringpool_str371[sizeof("gov.ma")];
+ char stringpool_str372[sizeof("ba")];
+ char stringpool_str373[sizeof("inf.mk")];
+ char stringpool_str374[sizeof("cards")];
+ char stringpool_str375[sizeof("bar")];
+ char stringpool_str376[sizeof("com.bi")];
+ char stringpool_str377[sizeof("blogspot.mr")];
+ char stringpool_str378[sizeof("museum.no")];
+ char stringpool_str379[sizeof("gov.ps")];
+ char stringpool_str380[sizeof("gov.pr")];
+ char stringpool_str381[sizeof("gov.al")];
+ char stringpool_str382[sizeof("med.om")];
+ char stringpool_str383[sizeof("edu.ps")];
+ char stringpool_str384[sizeof("edu.pr")];
+ char stringpool_str385[sizeof("asso.bj")];
+ char stringpool_str386[sizeof("edu.al")];
+ char stringpool_str387[sizeof("biz")];
+ char stringpool_str388[sizeof("casa")];
+ char stringpool_str389[sizeof("com.ps")];
+ char stringpool_str390[sizeof("com.pr")];
+ char stringpool_str391[sizeof("qsl.br")];
+ char stringpool_str392[sizeof("com.al")];
+ char stringpool_str393[sizeof("gov.ae")];
+ char stringpool_str394[sizeof("zm")];
+ char stringpool_str395[sizeof("est.pr")];
+ char stringpool_str396[sizeof("blogspot.re")];
+ char stringpool_str397[sizeof("bio.br")];
+ char stringpool_str398[sizeof("my")];
+ char stringpool_str399[sizeof("unsa.ba")];
+ char stringpool_str400[sizeof("gov.pk")];
+ char stringpool_str401[sizeof("gob.pk")];
+ char stringpool_str402[sizeof("farm")];
+ char stringpool_str403[sizeof("edu.pk")];
+ char stringpool_str404[sizeof("gop.pk")];
+ char stringpool_str405[sizeof("cv")];
+ char stringpool_str406[sizeof("com.pk")];
+ char stringpool_str407[sizeof("club")];
+ char stringpool_str408[sizeof("conf.lv")];
+ char stringpool_str409[sizeof("zlg.br")];
+ char stringpool_str410[sizeof("homeip.net")];
+ char stringpool_str411[sizeof("int.ar")];
+ char stringpool_str412[sizeof("gov.pl")];
+ char stringpool_str413[sizeof("mus.br")];
+ char stringpool_str414[sizeof("imb.br")];
+ char stringpool_str415[sizeof("gov.vc")];
+ char stringpool_str416[sizeof("edu.pl")];
+ char stringpool_str417[sizeof("consulado.st")];
+ char stringpool_str418[sizeof("gon.pk")];
+ char stringpool_str419[sizeof("edu.vc")];
+ char stringpool_str420[sizeof("emp.br")];
+ char stringpool_str421[sizeof("i.ph")];
+ char stringpool_str422[sizeof("com.pl")];
+ char stringpool_str423[sizeof("gob.pe")];
+ char stringpool_str424[sizeof("com.vc")];
+ char stringpool_str425[sizeof("edu.pe")];
+ char stringpool_str426[sizeof("gsm.pl")];
+ char stringpool_str427[sizeof("com.pe")];
+ char stringpool_str428[sizeof("asia")];
+ char stringpool_str429[sizeof("gos.pk")];
+ char stringpool_str430[sizeof("globo")];
+ char stringpool_str431[sizeof("mm")];
+ char stringpool_str432[sizeof("gov.mw")];
+ char stringpool_str433[sizeof("career")];
+ char stringpool_str434[sizeof("gov.ve")];
+ char stringpool_str435[sizeof("edu.mw")];
+ char stringpool_str436[sizeof("art.pl")];
+ char stringpool_str437[sizeof("edu.ve")];
+ char stringpool_str438[sizeof("qpon")];
+ char stringpool_str439[sizeof("com.mw")];
+ char stringpool_str440[sizeof("com.ve")];
+ char stringpool_str441[sizeof("biz.nr")];
+ char stringpool_str442[sizeof("za")];
+ char stringpool_str443[sizeof("uy")];
+ char stringpool_str444[sizeof("its.me")];
+ char stringpool_str445[sizeof("amursk.ru")];
+ char stringpool_str446[sizeof("blogspot.de")];
+ char stringpool_str447[sizeof("glogow.pl")];
+ char stringpool_str448[sizeof("is-a-cpa.com")];
+ char stringpool_str449[sizeof("med.ec")];
+ char stringpool_str450[sizeof("camera")];
+ char stringpool_str451[sizeof("gob.pa")];
+ char stringpool_str452[sizeof("com.nf")];
+ char stringpool_str453[sizeof("edu.pa")];
+ char stringpool_str454[sizeof("blogspot.se")];
+ char stringpool_str455[sizeof("blogspot.com.es")];
+ char stringpool_str456[sizeof("gda.pl")];
+ char stringpool_str457[sizeof("hurdal.no")];
+ char stringpool_str458[sizeof("com.pa")];
+ char stringpool_str459[sizeof("build")];
+ char stringpool_str460[sizeof("alvdal.no")];
+ char stringpool_str461[sizeof("med.sa")];
+ char stringpool_str462[sizeof("asso.km")];
+ char stringpool_str463[sizeof("med.sd")];
+ char stringpool_str464[sizeof("biz.tj")];
+ char stringpool_str465[sizeof("habmer.no")];
+ char stringpool_str466[sizeof("blogspot.pt")];
+ char stringpool_str467[sizeof("futbol")];
+ char stringpool_str468[sizeof("blogspot.hu")];
+ char stringpool_str469[sizeof("fjaler.no")];
+ char stringpool_str470[sizeof("moscow")];
+ char stringpool_str471[sizeof("med.ee")];
+ char stringpool_str472[sizeof("ma")];
+ char stringpool_str473[sizeof("aseral.no")];
+ char stringpool_str474[sizeof("int.mw")];
+ char stringpool_str475[sizeof("blogspot.co.nz")];
+ char stringpool_str476[sizeof("x.bg")];
+ char stringpool_str477[sizeof("med.br")];
+ char stringpool_str478[sizeof("com.aw")];
+ char stringpool_str479[sizeof("museum.tt")];
+ char stringpool_str480[sizeof("x.se")];
+ char stringpool_str481[sizeof("far.br")];
+ char stringpool_str482[sizeof("gh")];
+ char stringpool_str483[sizeof("ch")];
+ char stringpool_str484[sizeof("asso.fr")];
+ char stringpool_str485[sizeof("atm.pl")];
+ char stringpool_str486[sizeof("quebec")];
+ char stringpool_str487[sizeof("blogspot.com.br")];
+ char stringpool_str488[sizeof("biz.bb")];
+ char stringpool_str489[sizeof("mp")];
+ char stringpool_str490[sizeof("gov.bf")];
+ char stringpool_str491[sizeof("bieszczady.pl")];
+ char stringpool_str492[sizeof("com.hr")];
+ char stringpool_str493[sizeof("guide")];
+ char stringpool_str494[sizeof("gal")];
+ char stringpool_str495[sizeof("bmd.br")];
+ char stringpool_str496[sizeof("ingatlan.hu")];
+ char stringpool_str497[sizeof("mil")];
+ char stringpool_str498[sizeof("events")];
+ char stringpool_str499[sizeof("gov.hk")];
+ char stringpool_str500[sizeof("com.ai")];
+ char stringpool_str501[sizeof("idv.hk")];
+ char stringpool_str502[sizeof("edu.hk")];
+ char stringpool_str503[sizeof("mil.do")];
+ char stringpool_str504[sizeof("firm.in")];
+ char stringpool_str505[sizeof("com.hk")];
+ char stringpool_str506[sizeof("eng.pro")];
+ char stringpool_str507[sizeof("bh")];
+ char stringpool_str508[sizeof("mv")];
+ char stringpool_str509[sizeof("hapmir.no")];
+ char stringpool_str510[sizeof("belgorod.ru")];
+ char stringpool_str511[sizeof("ua")];
+ char stringpool_str512[sizeof("e12.ve")];
+ char stringpool_str513[sizeof("hemsedal.no")];
+ char stringpool_str514[sizeof("mango")];
+ char stringpool_str515[sizeof("evenes.no")];
+ char stringpool_str516[sizeof("miami")];
+ char stringpool_str517[sizeof("engerdal.no")];
+ char stringpool_str518[sizeof("blogspot.in")];
+ char stringpool_str519[sizeof("hvaler.no")];
+ char stringpool_str520[sizeof("mielno.pl")];
+ char stringpool_str521[sizeof("hadsel.no")];
+ char stringpool_str522[sizeof("bronnoysund.no")];
+ char stringpool_str523[sizeof("blogspot.ie")];
+ char stringpool_str524[sizeof("blogspot.ca")];
+ char stringpool_str525[sizeof("com.vi")];
+ char stringpool_str526[sizeof("etc.br")];
+ char stringpool_str527[sizeof("broke-it.net")];
+ char stringpool_str528[sizeof("mil.no")];
+ char stringpool_str529[sizeof("mincom.tn")];
+ char stringpool_str530[sizeof("asso.re")];
+ char stringpool_str531[sizeof("blogspot.co.il")];
+ char stringpool_str532[sizeof("fhv.se")];
+ char stringpool_str533[sizeof("blogspot.it")];
+ char stringpool_str534[sizeof("mielec.pl")];
+ char stringpool_str535[sizeof("fish")];
+ char stringpool_str536[sizeof("e164.arpa")];
+ char stringpool_str537[sizeof("mie.jp")];
+ char stringpool_str538[sizeof("ing.pa")];
+ char stringpool_str539[sizeof("eti.br")];
+ char stringpool_str540[sizeof("biz.id")];
+ char stringpool_str541[sizeof("mat.br")];
+ char stringpool_str542[sizeof("bindal.no")];
+ char stringpool_str543[sizeof("mil.ec")];
+ char stringpool_str544[sizeof("mil.to")];
+ char stringpool_str545[sizeof("hareid.no")];
+ char stringpool_str546[sizeof("mil.tj")];
+ char stringpool_str547[sizeof("mil.tm")];
+ char stringpool_str548[sizeof("abo.pa")];
+ char stringpool_str549[sizeof("fyresdal.no")];
+ char stringpool_str550[sizeof("gallery")];
+ char stringpool_str551[sizeof("hk")];
+ char stringpool_str552[sizeof("builders")];
+ char stringpool_str553[sizeof("blogspot.cv")];
+ char stringpool_str554[sizeof("ck")];
+ char stringpool_str555[sizeof("fhs.no")];
+ char stringpool_str556[sizeof("gov.km")];
+ char stringpool_str557[sizeof("broker.aero")];
+ char stringpool_str558[sizeof("edu.km")];
+ char stringpool_str559[sizeof("aid.pl")];
+ char stringpool_str560[sizeof("com.km")];
+ char stringpool_str561[sizeof("meland.no")];
+ char stringpool_str562[sizeof("mil.br")];
+ char stringpool_str563[sizeof("mil.bo")];
+ char stringpool_str564[sizeof("mh")];
+ char stringpool_str565[sizeof("gaular.no")];
+ char stringpool_str566[sizeof("fk")];
+ char stringpool_str567[sizeof("isernia.it")];
+ char stringpool_str568[sizeof("mil.iq")];
+ char stringpool_str569[sizeof("gov.kp")];
+ char stringpool_str570[sizeof("ws")];
+ char stringpool_str571[sizeof("ullensaker.no")];
+ char stringpool_str572[sizeof("blogspot.com.ar")];
+ char stringpool_str573[sizeof("edu.kp")];
+ char stringpool_str574[sizeof("gov.af")];
+ char stringpool_str575[sizeof("com.kp")];
+ char stringpool_str576[sizeof("edu.af")];
+ char stringpool_str577[sizeof("com.af")];
+ char stringpool_str578[sizeof("biz.pr")];
+ char stringpool_str579[sizeof("biella.it")];
+ char stringpool_str580[sizeof("mil.rw")];
+ char stringpool_str581[sizeof("blogspot.com.au")];
+ char stringpool_str582[sizeof("med.pro")];
+ char stringpool_str583[sizeof("author.aero")];
+ char stringpool_str584[sizeof("bar.pro")];
+ char stringpool_str585[sizeof("ass.km")];
+ char stringpool_str586[sizeof("mil.qa")];
+ char stringpool_str587[sizeof("fuossko.no")];
+ char stringpool_str588[sizeof("fam.pk")];
+ char stringpool_str589[sizeof("edu.pf")];
+ char stringpool_str590[sizeof("biz.pk")];
+ char stringpool_str591[sizeof("com.pf")];
+ char stringpool_str592[sizeof("med.pl")];
+ char stringpool_str593[sizeof("fuel.aero")];
+ char stringpool_str594[sizeof("urn.arpa")];
+ char stringpool_str595[sizeof("w.bg")];
+ char stringpool_str596[sizeof("eidfjord.no")];
+ char stringpool_str597[sizeof("w.se")];
+ char stringpool_str598[sizeof("biz.pl")];
+ char stringpool_str599[sizeof("arendal.no")];
+ char stringpool_str600[sizeof("irc.pl")];
+ char stringpool_str601[sizeof("miasta.pl")];
+ char stringpool_str602[sizeof("mil.ba")];
+ char stringpool_str603[sizeof("mil.jo")];
+ char stringpool_str604[sizeof("web.do")];
+ char stringpool_str605[sizeof("biz.mw")];
+ char stringpool_str606[sizeof("blogspot.ch")];
+ char stringpool_str607[sizeof("fuettertdasnetz.de")];
+ char stringpool_str608[sizeof("googleapis.com")];
+ char stringpool_str609[sizeof("bronnoy.no")];
+ char stringpool_str610[sizeof("mil.id")];
+ char stringpool_str611[sizeof("inderoy.no")];
+ char stringpool_str612[sizeof("cpa.pro")];
+ char stringpool_str613[sizeof("museum.mv")];
+ char stringpool_str614[sizeof("blogspot.gr")];
+ char stringpool_str615[sizeof("etnedal.no")];
+ char stringpool_str616[sizeof("careers")];
+ char stringpool_str617[sizeof("med.pa")];
+ char stringpool_str618[sizeof("mil.tw")];
+ char stringpool_str619[sizeof("xyz")];
+ char stringpool_str620[sizeof("mk")];
+ char stringpool_str621[sizeof("web.lk")];
+ char stringpool_str622[sizeof("hjartdal.no")];
+ char stringpool_str623[sizeof("foggia.it")];
+ char stringpool_str624[sizeof("brussels.museum")];
+ char stringpool_str625[sizeof("marker.no")];
+ char stringpool_str626[sizeof("modena.it")];
+ char stringpool_str627[sizeof("bamble.no")];
+ char stringpool_str628[sizeof("ip6.arpa")];
+ char stringpool_str629[sizeof("ferrara.it")];
+ char stringpool_str630[sizeof("imperia.it")];
+ char stringpool_str631[sizeof("blogspot.co.at")];
+ char stringpool_str632[sizeof("flesberg.no")];
+ char stringpool_str633[sizeof("bergamo.it")];
+ char stringpool_str634[sizeof("aircraft.aero")];
+ char stringpool_str635[sizeof("mil.ar")];
+ char stringpool_str636[sizeof("gov.ki")];
+ char stringpool_str637[sizeof("edu.ki")];
+ char stringpool_str638[sizeof("hjelmeland.no")];
+ char stringpool_str639[sizeof("wed")];
+ char stringpool_str640[sizeof("mil.ac")];
+ char stringpool_str641[sizeof("com.ki")];
+ char stringpool_str642[sizeof("meldal.no")];
+ char stringpool_str643[sizeof("github.io")];
+ char stringpool_str644[sizeof("web.tj")];
+ char stringpool_str645[sizeof("black")];
+ char stringpool_str646[sizeof("uk")];
+ char stringpool_str647[sizeof("cheap")];
+ char stringpool_str648[sizeof("horology.museum")];
+ char stringpool_str649[sizeof("mil.al")];
+ char stringpool_str650[sizeof("wroc.pl")];
+ char stringpool_str651[sizeof("work")];
+ char stringpool_str652[sizeof("wien")];
+ char stringpool_str653[sizeof("mil.ae")];
+ char stringpool_str654[sizeof("caravan")];
+ char stringpool_str655[sizeof("works")];
+ char stringpool_str656[sizeof("eidsvoll.no")];
+ char stringpool_str657[sizeof("folldal.no")];
+ char stringpool_str658[sizeof("gjesdal.no")];
+ char stringpool_str659[sizeof("mil.pl")];
+ char stringpool_str660[sizeof("mandal.no")];
+ char stringpool_str661[sizeof("mil.vc")];
+ char stringpool_str662[sizeof("mail.pl")];
+ char stringpool_str663[sizeof("melhus.no")];
+ char stringpool_str664[sizeof("immobilien")];
+ char stringpool_str665[sizeof("mil.pe")];
+ char stringpool_str666[sizeof("cleaning")];
+ char stringpool_str667[sizeof("fredrikstad.no")];
+ char stringpool_str668[sizeof("asmatart.museum")];
+ char stringpool_str669[sizeof("hamaroy.no")];
+ char stringpool_str670[sizeof("catania.it")];
+ char stringpool_str671[sizeof("mil.ve")];
+ char stringpool_str672[sizeof("museum.om")];
+ char stringpool_str673[sizeof("genova.it")];
+ char stringpool_str674[sizeof("badaddja.no")];
+ char stringpool_str675[sizeof("iris.arpa")];
+ char stringpool_str676[sizeof("flanders.museum")];
+ char stringpool_str677[sizeof("creation.museum")];
+ char stringpool_str678[sizeof("milano.it")];
+ char stringpool_str679[sizeof("gausdal.no")];
+ char stringpool_str680[sizeof("ancona.it")];
+ char stringpool_str681[sizeof("matera.it")];
+ char stringpool_str682[sizeof("budapest")];
+ char stringpool_str683[sizeof("modalen.no")];
+ char stringpool_str684[sizeof("gotdns.org")];
+ char stringpool_str685[sizeof("blogspot.dk")];
+ char stringpool_str686[sizeof("eidsberg.no")];
+ char stringpool_str687[sizeof("aremark.no")];
+ char stringpool_str688[sizeof("club.aero")];
+ char stringpool_str689[sizeof("blogspot.sk")];
+ char stringpool_str690[sizeof("web.id")];
+ char stringpool_str691[sizeof("is-a-llama.com")];
+ char stringpool_str692[sizeof("izhevsk.ru")];
+ char stringpool_str693[sizeof("hita.oita.jp")];
+ char stringpool_str694[sizeof("benevento.it")];
+ char stringpool_str695[sizeof("wang")];
+ char stringpool_str696[sizeof("blogspot.hk")];
+ char stringpool_str697[sizeof("ibaraki.jp")];
+ char stringpool_str698[sizeof("holtalen.no")];
+ char stringpool_str699[sizeof("fauske.no")];
+ char stringpool_str700[sizeof("uri.arpa")];
+ char stringpool_str701[sizeof("masfjorden.no")];
+ char stringpool_str702[sizeof("airguard.museum")];
+ char stringpool_str703[sizeof("baidar.no")];
+ char stringpool_str704[sizeof("american.museum")];
+ char stringpool_str705[sizeof("blogspot.co.uk")];
+ char stringpool_str706[sizeof("montreal.museum")];
+ char stringpool_str707[sizeof("guitars")];
+ char stringpool_str708[sizeof("bargains")];
+ char stringpool_str709[sizeof("estate.museum")];
+ char stringpool_str710[sizeof("wtc")];
+ char stringpool_str711[sizeof("uzhgorod.ua")];
+ char stringpool_str712[sizeof("bydgoszcz.pl")];
+ char stringpool_str713[sizeof("web.pk")];
+ char stringpool_str714[sizeof("cartoonart.museum")];
+ char stringpool_str715[sizeof("caa.aero")];
+ char stringpool_str716[sizeof("kz")];
+ char stringpool_str717[sizeof("cloudfront.net")];
+ char stringpool_str718[sizeof("cultural.museum")];
+ char stringpool_str719[sizeof("center.museum")];
+ char stringpool_str720[sizeof("kr")];
+ char stringpool_str721[sizeof("catering")];
+ char stringpool_str722[sizeof("gov.ru")];
+ char stringpool_str723[sizeof("edu.ru")];
+ char stringpool_str724[sizeof("brunel.museum")];
+ char stringpool_str725[sizeof("com.ru")];
+ char stringpool_str726[sizeof("mil.kr")];
+ char stringpool_str727[sizeof("mil.km")];
+ char stringpool_str728[sizeof("web.ve")];
+ char stringpool_str729[sizeof("chtr.k12.ma.us")];
+ char stringpool_str730[sizeof("czeladz.pl")];
+ char stringpool_str731[sizeof("kobe.jp")];
+ char stringpool_str732[sizeof("kred")];
+ char stringpool_str733[sizeof("in-addr.arpa")];
+ char stringpool_str734[sizeof("k.bg")];
+ char stringpool_str735[sizeof("web.nf")];
+ char stringpool_str736[sizeof("kn")];
+ char stringpool_str737[sizeof("k.se")];
+ char stringpool_str738[sizeof("biz.ki")];
+ char stringpool_str739[sizeof("mragowo.pl")];
+ char stringpool_str740[sizeof("gw")];
+ char stringpool_str741[sizeof("cw")];
+ char stringpool_str742[sizeof("ke")];
+ char stringpool_str743[sizeof("gov.ws")];
+ char stringpool_str744[sizeof("int.ru")];
+ char stringpool_str745[sizeof("edu.ws")];
+ char stringpool_str746[sizeof("com.ws")];
+ char stringpool_str747[sizeof("wegrow.pl")];
+ char stringpool_str748[sizeof("gov.sg")];
+ char stringpool_str749[sizeof("aw")];
+ char stringpool_str750[sizeof("edu.sg")];
+ char stringpool_str751[sizeof("ascoli-piceno.it")];
+ char stringpool_str752[sizeof("com.sg")];
+ char stringpool_str753[sizeof("columbia.museum")];
+ char stringpool_str754[sizeof("erotica.hu")];
+ char stringpool_str755[sizeof("crafts.museum")];
+ char stringpool_str756[sizeof("gildeskal.no")];
+ char stringpool_str757[sizeof("krd")];
+ char stringpool_str758[sizeof("bw")];
+ char stringpool_str759[sizeof("erotika.hu")];
+ char stringpool_str760[sizeof("audnedaln.no")];
+ char stringpool_str761[sizeof("circus.museum")];
+ char stringpool_str762[sizeof("blogspot.jp")];
+ char stringpool_str763[sizeof("aomori.aomori.jp")];
+ char stringpool_str764[sizeof("brasil.museum")];
+ char stringpool_str765[sizeof("com.ug")];
+ char stringpool_str766[sizeof("guernsey.museum")];
+ char stringpool_str767[sizeof("aomori.jp")];
+ char stringpool_str768[sizeof("gov.ng")];
+ char stringpool_str769[sizeof("edu.ng")];
+ char stringpool_str770[sizeof("ki")];
+ char stringpool_str771[sizeof("com.ng")];
+ char stringpool_str772[sizeof("kim")];
+ char stringpool_str773[sizeof("grandrapids.museum")];
+ char stringpool_str774[sizeof("cagliari.it")];
+ char stringpool_str775[sizeof("fhsk.se")];
+ char stringpool_str776[sizeof("gov.eg")];
+ char stringpool_str777[sizeof("edu.eg")];
+ char stringpool_str778[sizeof("gjemnes.no")];
+ char stringpool_str779[sizeof("historical.museum")];
+ char stringpool_str780[sizeof("magadan.ru")];
+ char stringpool_str781[sizeof("com.eg")];
+ char stringpool_str782[sizeof("alessandria.it")];
+ char stringpool_str783[sizeof("asso.gp")];
+ char stringpool_str784[sizeof("crimea.ua")];
+ char stringpool_str785[sizeof("miners.museum")];
+ char stringpool_str786[sizeof("zw")];
+ char stringpool_str787[sizeof("memorial.museum")];
+ char stringpool_str788[sizeof("ky")];
+ char stringpool_str789[sizeof("webhop.net")];
+ char stringpool_str790[sizeof("meeres.museum")];
+ char stringpool_str791[sizeof("granvin.no")];
+ char stringpool_str792[sizeof("contemporary.museum")];
+ char stringpool_str793[sizeof("bir.ru")];
+ char stringpool_str794[sizeof("k12.ec")];
+ char stringpool_str795[sizeof("eun.eg")];
+ char stringpool_str796[sizeof("evenassi.no")];
+ char stringpool_str797[sizeof("baikal.ru")];
+ char stringpool_str798[sizeof("warszawa.pl")];
+ char stringpool_str799[sizeof("clothing")];
+ char stringpool_str800[sizeof("mw")];
+ char stringpool_str801[sizeof("km")];
+ char stringpool_str802[sizeof("cupcake.is")];
+ char stringpool_str803[sizeof("castle.museum")];
+ char stringpool_str804[sizeof("mobi")];
+ char stringpool_str805[sizeof("enebakk.no")];
+ char stringpool_str806[sizeof("gov.mu")];
+ char stringpool_str807[sizeof("beskidy.pl")];
+ char stringpool_str808[sizeof("udm.ru")];
+ char stringpool_str809[sizeof("com.mu")];
+ char stringpool_str810[sizeof("canada.museum")];
+ char stringpool_str811[sizeof("cbg.ru")];
+ char stringpool_str812[sizeof("hagebostad.no")];
+ char stringpool_str813[sizeof("usarts.museum")];
+ char stringpool_str814[sizeof("catering.aero")];
+ char stringpool_str815[sizeof("beardu.no")];
+ char stringpool_str816[sizeof("info.at")];
+ char stringpool_str817[sizeof("gorlice.pl")];
+ char stringpool_str818[sizeof("celtic.museum")];
+ char stringpool_str819[sizeof("altoadige.it")];
+ char stringpool_str820[sizeof("fundacio.museum")];
+ char stringpool_str821[sizeof("moscow.museum")];
+ char stringpool_str822[sizeof("warmia.pl")];
+ char stringpool_str823[sizeof("bielawa.pl")];
+ char stringpool_str824[sizeof("anthro.museum")];
+ char stringpool_str825[sizeof("moareke.no")];
+ char stringpool_str826[sizeof("avellino.it")];
+ char stringpool_str827[sizeof("massacarrara.it")];
+ char stringpool_str828[sizeof("como.it")];
+ char stringpool_str829[sizeof("fylkesbibl.no")];
+ char stringpool_str830[sizeof("gov.au")];
+ char stringpool_str831[sizeof("ise.mie.jp")];
+ char stringpool_str832[sizeof("broadcast.museum")];
+ char stringpool_str833[sizeof("edu.au")];
+ char stringpool_str834[sizeof("mansions.museum")];
+ char stringpool_str835[sizeof("com.au")];
+ char stringpool_str836[sizeof("quebec.museum")];
+ char stringpool_str837[sizeof("gov.mg")];
+ char stringpool_str838[sizeof("ullensvang.no")];
+ char stringpool_str839[sizeof("edu.mg")];
+ char stringpool_str840[sizeof("com.mg")];
+ char stringpool_str841[sizeof("muncie.museum")];
+ char stringpool_str842[sizeof("e-burg.ru")];
+ char stringpool_str843[sizeof("kp")];
+ char stringpool_str844[sizeof("baseball.museum")];
+ char stringpool_str845[sizeof("hinode.tokyo.jp")];
+ char stringpool_str846[sizeof("cinema.museum")];
+ char stringpool_str847[sizeof("asn.au")];
+ char stringpool_str848[sizeof("florist")];
+ char stringpool_str849[sizeof("andebu.no")];
+ char stringpool_str850[sizeof("enna.it")];
+ char stringpool_str851[sizeof("blogspot.tw")];
+ char stringpool_str852[sizeof("karasjok.no")];
+ char stringpool_str853[sizeof("meraker.no")];
+ char stringpool_str854[sizeof("capebreton.museum")];
+ char stringpool_str855[sizeof("com.ag")];
+ char stringpool_str856[sizeof("ina.ibaraki.jp")];
+ char stringpool_str857[sizeof("unbi.ba")];
+ char stringpool_str858[sizeof("berkeley.museum")];
+ char stringpool_str859[sizeof("maryland.museum")];
+ char stringpool_str860[sizeof("holiday")];
+ char stringpool_str861[sizeof("email")];
+ char stringpool_str862[sizeof("mini")];
+ char stringpool_str863[sizeof("malselv.no")];
+ char stringpool_str864[sizeof("hellas.museum")];
+ char stringpool_str865[sizeof("zaporizhzhe.ua")];
+ char stringpool_str866[sizeof("hirosaki.aomori.jp")];
+ char stringpool_str867[sizeof("usgarden.museum")];
+ char stringpool_str868[sizeof("chieti.it")];
+ char stringpool_str869[sizeof("better-than.tv")];
+ char stringpool_str870[sizeof("qld.au")];
+ char stringpool_str871[sizeof("carraramassa.it")];
+ char stringpool_str872[sizeof("figueres.museum")];
+ char stringpool_str873[sizeof("gonohe.aomori.jp")];
+ char stringpool_str874[sizeof("watch")];
+ char stringpool_str875[sizeof("chernovtsy.ua")];
+ char stringpool_str876[sizeof("aejrie.no")];
+ char stringpool_str877[sizeof("bjarkoy.no")];
+ char stringpool_str878[sizeof("forlicesena.it")];
+ char stringpool_str879[sizeof("brindisi.it")];
+ char stringpool_str880[sizeof("cesenaforli.it")];
+ char stringpool_str881[sizeof("foundation")];
+ char stringpool_str882[sizeof("meguro.tokyo.jp")];
+ char stringpool_str883[sizeof("museum.mw")];
+ char stringpool_str884[sizeof("kh")];
+ char stringpool_str885[sizeof("mosreg.ru")];
+ char stringpool_str886[sizeof("akrehamn.no")];
+ char stringpool_str887[sizeof("zaporizhzhia.ua")];
+ char stringpool_str888[sizeof("uda.nara.jp")];
+ char stringpool_str889[sizeof("undersea.museum")];
+ char stringpool_str890[sizeof("cruises")];
+ char stringpool_str891[sizeof("eisenbahn.museum")];
+ char stringpool_str892[sizeof("mil.ru")];
+ char stringpool_str893[sizeof("wroclaw.pl")];
+ char stringpool_str894[sizeof("eidskog.no")];
+ char stringpool_str895[sizeof("aviation.museum")];
+ char stringpool_str896[sizeof("k12.or.us")];
+ char stringpool_str897[sizeof("hamura.tokyo.jp")];
+ char stringpool_str898[sizeof("k12.dc.us")];
+ char stringpool_str899[sizeof("mifune.kumamoto.jp")];
+ char stringpool_str900[sizeof("minato.tokyo.jp")];
+ char stringpool_str901[sizeof("k12.ok.us")];
+ char stringpool_str902[sizeof("k12.sc.us")];
+ char stringpool_str903[sizeof("ballooning.aero")];
+ char stringpool_str904[sizeof("muroto.kochi.jp")];
+ char stringpool_str905[sizeof("ambulance.museum")];
+ char stringpool_str906[sizeof("elblag.pl")];
+ char stringpool_str907[sizeof("ina.saitama.jp")];
+ char stringpool_str908[sizeof("k12.de.us")];
+ char stringpool_str909[sizeof("utsira.no")];
+ char stringpool_str910[sizeof("assassination.museum")];
+ char stringpool_str911[sizeof("zhitomir.ua")];
+ char stringpool_str912[sizeof("americanart.museum")];
+ char stringpool_str913[sizeof("kostroma.ru")];
+ char stringpool_str914[sizeof("krakow.pl")];
+ char stringpool_str915[sizeof("k12.nj.us")];
+ char stringpool_str916[sizeof("k12.nm.us")];
+ char stringpool_str917[sizeof("incheon.kr")];
+ char stringpool_str918[sizeof("bunkyo.tokyo.jp")];
+ char stringpool_str919[sizeof("k12.nc.us")];
+ char stringpool_str920[sizeof("gorizia.it")];
+ char stringpool_str921[sizeof("engine.aero")];
+ char stringpool_str922[sizeof("contemporaryart.museum")];
+ char stringpool_str923[sizeof("carrara-massa.it")];
+ char stringpool_str924[sizeof("astrakhan.ru")];
+ char stringpool_str925[sizeof("k12.ne.us")];
+ char stringpool_str926[sizeof("crew.aero")];
+ char stringpool_str927[sizeof("alaska.museum")];
+ char stringpool_str928[sizeof("mil.ng")];
+ char stringpool_str929[sizeof("bearalvahki.no")];
+ char stringpool_str930[sizeof("heguri.nara.jp")];
+ char stringpool_str931[sizeof("k12.la.us")];
+ char stringpool_str932[sizeof("mitsue.nara.jp")];
+ char stringpool_str933[sizeof("usantiques.museum")];
+ char stringpool_str934[sizeof("misasa.tottori.jp")];
+ char stringpool_str935[sizeof("cheltenham.museum")];
+ char stringpool_str936[sizeof("consultant.aero")];
+ char stringpool_str937[sizeof("imageandsound.museum")];
+ char stringpool_str938[sizeof("epilepsy.museum")];
+ char stringpool_str939[sizeof("mil.eg")];
+ char stringpool_str940[sizeof("madrid.museum")];
+ char stringpool_str941[sizeof("aquila.it")];
+ char stringpool_str942[sizeof("gobo.wakayama.jp")];
+ char stringpool_str943[sizeof("malbork.pl")];
+ char stringpool_str944[sizeof("k12.vi")];
+ char stringpool_str945[sizeof("hinohara.tokyo.jp")];
+ char stringpool_str946[sizeof("k12.nd.us")];
+ char stringpool_str947[sizeof("blackfriday")];
+ char stringpool_str948[sizeof("gov.kg")];
+ char stringpool_str949[sizeof("ashoro.hokkaido.jp")];
+ char stringpool_str950[sizeof("building.museum")];
+ char stringpool_str951[sizeof("edu.kg")];
+ char stringpool_str952[sizeof("city.sendai.jp")];
+ char stringpool_str953[sizeof("com.kg")];
+ char stringpool_str954[sizeof("franziskaner.museum")];
+ char stringpool_str955[sizeof("kemerovo.ru")];
+ char stringpool_str956[sizeof("k12.il.us")];
+ char stringpool_str957[sizeof("casino.hu")];
+ char stringpool_str958[sizeof("mihara.kochi.jp")];
+ char stringpool_str959[sizeof("marine.ru")];
+ char stringpool_str960[sizeof("k12.ri.us")];
+ char stringpool_str961[sizeof("australia.museum")];
+ char stringpool_str962[sizeof("business")];
+ char stringpool_str963[sizeof("furano.hokkaido.jp")];
+ char stringpool_str964[sizeof("kragero.no")];
+ char stringpool_str965[sizeof("mobara.chiba.jp")];
+ char stringpool_str966[sizeof("k12.ms.us")];
+ char stringpool_str967[sizeof("k12.mo.us")];
+ char stringpool_str968[sizeof("k12.ia.us")];
+ char stringpool_str969[sizeof("k12.id.us")];
+ char stringpool_str970[sizeof("chocolate.museum")];
+ char stringpool_str971[sizeof("giehtavuoatna.no")];
+ char stringpool_str972[sizeof("americana.museum")];
+ char stringpool_str973[sizeof("maintenance.aero")];
+ char stringpool_str974[sizeof("baltimore.museum")];
+ char stringpool_str975[sizeof("k12.me.us")];
+ char stringpool_str976[sizeof("minnesota.museum")];
+ char stringpool_str977[sizeof("mil.mg")];
+ char stringpool_str978[sizeof("klodzko.pl")];
+ char stringpool_str979[sizeof("children.museum")];
+ char stringpool_str980[sizeof("flekkefjord.no")];
+ char stringpool_str981[sizeof("monticello.museum")];
+ char stringpool_str982[sizeof("k12.as.us")];
+ char stringpool_str983[sizeof("k12.ar.us")];
+ char stringpool_str984[sizeof("fuso.aichi.jp")];
+ char stringpool_str985[sizeof("certification.aero")];
+ char stringpool_str986[sizeof("bilbao.museum")];
+ char stringpool_str987[sizeof("college")];
+ char stringpool_str988[sizeof("historichouses.museum")];
+ char stringpool_str989[sizeof("championship.aero")];
+ char stringpool_str990[sizeof("bihoro.hokkaido.jp")];
+ char stringpool_str991[sizeof("grosseto.it")];
+ char stringpool_str992[sizeof("k12.ak.us")];
+ char stringpool_str993[sizeof("chernivtsi.ua")];
+ char stringpool_str994[sizeof("gyeonggi.kr")];
+ char stringpool_str995[sizeof("k12.ma.us")];
+ char stringpool_str996[sizeof("kitchen")];
+ char stringpool_str997[sizeof("k12.md.us")];
+ char stringpool_str998[sizeof("k12.pr.us")];
+ char stringpool_str999[sizeof("k12.al.us")];
+ char stringpool_str1000[sizeof("barcelona.museum")];
+ char stringpool_str1001[sizeof("ami.ibaraki.jp")];
+ char stringpool_str1002[sizeof("federation.aero")];
+ char stringpool_str1003[sizeof("kvafjord.no")];
+ char stringpool_str1004[sizeof("malopolska.pl")];
+ char stringpool_str1005[sizeof("karlsoy.no")];
+ char stringpool_str1006[sizeof("bungoono.oita.jp")];
+ char stringpool_str1007[sizeof("holmestrand.no")];
+ char stringpool_str1008[sizeof("mesaverde.museum")];
+ char stringpool_str1009[sizeof("microlight.aero")];
+ char stringpool_str1010[sizeof("americanantiques.museum")];
+ char stringpool_str1011[sizeof("webhop.org")];
+ char stringpool_str1012[sizeof("ethnology.museum")];
+ char stringpool_str1013[sizeof("ina.nagano.jp")];
+ char stringpool_str1014[sizeof("kusu.oita.jp")];
+ char stringpool_str1015[sizeof("beeldengeluid.museum")];
+ char stringpool_str1016[sizeof("elverum.no")];
+ char stringpool_str1017[sizeof("ibaraki.osaka.jp")];
+ char stringpool_str1018[sizeof("city.sapporo.jp")];
+ char stringpool_str1019[sizeof("haboro.hokkaido.jp")];
+ char stringpool_str1020[sizeof("chernigov.ua")];
+ char stringpool_str1021[sizeof("cx")];
+ char stringpool_str1022[sizeof("consulting")];
+ char stringpool_str1023[sizeof("kherson.ua")];
+ char stringpool_str1024[sizeof("aurskog-holand.no")];
+ char stringpool_str1025[sizeof("k12.pa.us")];
+ char stringpool_str1026[sizeof("kalmykia.ru")];
+ char stringpool_str1027[sizeof("gov.sh")];
+ char stringpool_str1028[sizeof("ax")];
+ char stringpool_str1029[sizeof("k12.mi.us")];
+ char stringpool_str1030[sizeof("com.sh")];
+ char stringpool_str1031[sizeof("foundation.museum")];
+ char stringpool_str1032[sizeof("k-uralsk.ru")];
+ char stringpool_str1033[sizeof("geisei.kochi.jp")];
+ char stringpool_str1034[sizeof("aknoluokta.no")];
+ char stringpool_str1035[sizeof("adachi.tokyo.jp")];
+ char stringpool_str1036[sizeof("chelyabinsk.ru")];
+ char stringpool_str1037[sizeof("andasuolo.no")];
+ char stringpool_str1038[sizeof("k12.va.us")];
+ char stringpool_str1039[sizeof("wolomin.pl")];
+ char stringpool_str1040[sizeof("windmill.museum")];
+ char stringpool_str1041[sizeof("manchester.museum")];
+ char stringpool_str1042[sizeof("matsusaka.mie.jp")];
+ char stringpool_str1043[sizeof("ink")];
+ char stringpool_str1044[sizeof("civilwar.museum")];
+ char stringpool_str1045[sizeof("fortmissoula.museum")];
+ char stringpool_str1046[sizeof("axa")];
+ char stringpool_str1047[sizeof("midtre-gauldal.no")];
+ char stringpool_str1048[sizeof("midori.gunma.jp")];
+ char stringpool_str1049[sizeof("elburg.museum")];
+ char stringpool_str1050[sizeof("kristiansand.no")];
+ char stringpool_str1051[sizeof("karelia.ru")];
+ char stringpool_str1052[sizeof("hiraya.nagano.jp")];
+ char stringpool_str1053[sizeof("missoula.museum")];
+ char stringpool_str1054[sizeof("filatelia.museum")];
+ char stringpool_str1055[sizeof("murata.miyagi.jp")];
+ char stringpool_str1056[sizeof("freemasonry.museum")];
+ char stringpool_str1057[sizeof("mizuho.tokyo.jp")];
+ char stringpool_str1058[sizeof("gov.bh")];
+ char stringpool_str1059[sizeof("engineer.aero")];
+ char stringpool_str1060[sizeof("edu.bh")];
+ char stringpool_str1061[sizeof("iizuna.nagano.jp")];
+ char stringpool_str1062[sizeof("motoyama.kochi.jp")];
+ char stringpool_str1063[sizeof("k12.vi.us")];
+ char stringpool_str1064[sizeof("com.bh")];
+ char stringpool_str1065[sizeof("atsuma.hokkaido.jp")];
+ char stringpool_str1066[sizeof("equipment")];
+ char stringpool_str1067[sizeof("collection.museum")];
+ char stringpool_str1068[sizeof("bajddar.no")];
+ char stringpool_str1069[sizeof("mx")];
+ char stringpool_str1070[sizeof("from.hr")];
+ char stringpool_str1071[sizeof("imabari.ehime.jp")];
+ char stringpool_str1072[sizeof("midori.chiba.jp")];
+ char stringpool_str1073[sizeof("cherkassy.ua")];
+ char stringpool_str1074[sizeof("izumisano.osaka.jp")];
+ char stringpool_str1075[sizeof("misato.miyagi.jp")];
+ char stringpool_str1076[sizeof("isleofman.museum")];
+ char stringpool_str1077[sizeof("konyvelo.hu")];
+ char stringpool_str1078[sizeof("minamiise.mie.jp")];
+ char stringpool_str1079[sizeof("info.au")];
+ char stringpool_str1080[sizeof("voto")];
+ char stringpool_str1081[sizeof("monash")];
+ char stringpool_str1082[sizeof("mitane.akita.jp")];
+ char stringpool_str1083[sizeof("bike")];
+ char stringpool_str1084[sizeof("hasama.oita.jp")];
+ char stringpool_str1085[sizeof("mitaka.tokyo.jp")];
+ char stringpool_str1086[sizeof("vote")];
+ char stringpool_str1087[sizeof("k12.ks.us")];
+ char stringpool_str1088[sizeof("is-found.org")];
+ char stringpool_str1089[sizeof("kw")];
+ char stringpool_str1090[sizeof("misato.akita.jp")];
+ char stringpool_str1091[sizeof("matta-varjjat.no")];
+ char stringpool_str1092[sizeof("vu")];
+ char stringpool_str1093[sizeof("conf.au")];
+ char stringpool_str1094[sizeof("minato.osaka.jp")];
+ char stringpool_str1095[sizeof("mihama.chiba.jp")];
+ char stringpool_str1096[sizeof("goshiki.hyogo.jp")];
+ char stringpool_str1097[sizeof("gotemba.shizuoka.jp")];
+ char stringpool_str1098[sizeof("hazu.aichi.jp")];
+ char stringpool_str1099[sizeof("v.bg")];
+ char stringpool_str1100[sizeof("vn")];
+ char stringpool_str1101[sizeof("consulting.aero")];
+ char stringpool_str1102[sizeof("mihama.aichi.jp")];
+ char stringpool_str1103[sizeof("cherkasy.ua")];
+ char stringpool_str1104[sizeof("mil.kg")];
+ char stringpool_str1105[sizeof("mito.ibaraki.jp")];
+ char stringpool_str1106[sizeof("ve")];
+ char stringpool_str1107[sizeof("edogawa.tokyo.jp")];
+ char stringpool_str1108[sizeof("hidaka.kochi.jp")];
+ char stringpool_str1109[sizeof("chernihiv.ua")];
+ char stringpool_str1110[sizeof("hyllestad.no")];
+ char stringpool_str1111[sizeof("inagawa.hyogo.jp")];
+ char stringpool_str1112[sizeof("cranbrook.museum")];
+ char stringpool_str1113[sizeof("urbino-pesaro.it")];
+ char stringpool_str1114[sizeof("annaka.gunma.jp")];
+ char stringpool_str1115[sizeof("krasnoyarsk.ru")];
+ char stringpool_str1116[sizeof("mari-el.ru")];
+ char stringpool_str1117[sizeof("fareast.ru")];
+ char stringpool_str1118[sizeof("hamada.shimane.jp")];
+ char stringpool_str1119[sizeof("andriabarlettatrani.it")];
+ char stringpool_str1120[sizeof("mo-i-rana.no")];
+ char stringpool_str1121[sizeof("miho.ibaraki.jp")];
+ char stringpool_str1122[sizeof("amur.ru")];
+ char stringpool_str1123[sizeof("karasjohka.no")];
+ char stringpool_str1124[sizeof("blogspot.mx")];
+ char stringpool_str1125[sizeof("kristiansund.no")];
+ char stringpool_str1126[sizeof("assisi.museum")];
+ char stringpool_str1127[sizeof("minami.kyoto.jp")];
+ char stringpool_str1128[sizeof("konskowola.pl")];
+ char stringpool_str1129[sizeof("finearts.museum")];
+ char stringpool_str1130[sizeof("humanities.museum")];
+ char stringpool_str1131[sizeof("vi")];
+ char stringpool_str1132[sizeof("gov.ph")];
+ char stringpool_str1133[sizeof("environment.museum")];
+ char stringpool_str1134[sizeof("edu.ph")];
+ char stringpool_str1135[sizeof("misato.shimane.jp")];
+ char stringpool_str1136[sizeof("com.ph")];
+ char stringpool_str1137[sizeof("zoological.museum")];
+ char stringpool_str1138[sizeof("chosei.chiba.jp")];
+ char stringpool_str1139[sizeof("kvitsoy.no")];
+ char stringpool_str1140[sizeof("gangwon.kr")];
+ char stringpool_str1141[sizeof("gok.pk")];
+ char stringpool_str1142[sizeof("biratori.hokkaido.jp")];
+ char stringpool_str1143[sizeof("andria-trani-barletta.it")];
+ char stringpool_str1144[sizeof("vlog.br")];
+ char stringpool_str1145[sizeof("gjerdrum.no")];
+ char stringpool_str1146[sizeof("minano.saitama.jp")];
+ char stringpool_str1147[sizeof("bjerkreim.no")];
+ char stringpool_str1148[sizeof("city.kitakyushu.jp")];
+ char stringpool_str1149[sizeof("vegas")];
+ char stringpool_str1150[sizeof("vdonsk.ru")];
+ char stringpool_str1151[sizeof("hiranai.aomori.jp")];
+ char stringpool_str1152[sizeof("furubira.hokkaido.jp")];
+ char stringpool_str1153[sizeof("aya.miyazaki.jp")];
+ char stringpool_str1154[sizeof("elk.pl")];
+ char stringpool_str1155[sizeof("vet.br")];
+ char stringpool_str1156[sizeof("hasuda.saitama.jp")];
+ char stringpool_str1157[sizeof("misato.saitama.jp")];
+ char stringpool_str1158[sizeof("esashi.hokkaido.jp")];
+ char stringpool_str1159[sizeof("karate.museum")];
+ char stringpool_str1160[sizeof("childrens.museum")];
+ char stringpool_str1161[sizeof("watarai.mie.jp")];
+ char stringpool_str1162[sizeof("hachioji.tokyo.jp")];
+ char stringpool_str1163[sizeof("geelvinck.museum")];
+ char stringpool_str1164[sizeof("kms.ru")];
+ char stringpool_str1165[sizeof("matsue.shimane.jp")];
+ char stringpool_str1166[sizeof("construction")];
+ char stringpool_str1167[sizeof("military.museum")];
+ char stringpool_str1168[sizeof("itabashi.tokyo.jp")];
+ char stringpool_str1169[sizeof("isen.kagoshima.jp")];
+ char stringpool_str1170[sizeof("arakawa.tokyo.jp")];
+ char stringpool_str1171[sizeof("va")];
+ char stringpool_str1172[sizeof("mobi.gp")];
+ char stringpool_str1173[sizeof("masuda.shimane.jp")];
+ char stringpool_str1174[sizeof("kautokeino.no")];
+ char stringpool_str1175[sizeof("macerata.it")];
+ char stringpool_str1176[sizeof("koenig.ru")];
+ char stringpool_str1177[sizeof("mil.sh")];
+ char stringpool_str1178[sizeof("mypets.ws")];
+ char stringpool_str1179[sizeof("chel.ru")];
+ char stringpool_str1180[sizeof("voronezh.ru")];
+ char stringpool_str1181[sizeof("fitjar.no")];
+ char stringpool_str1182[sizeof("asti.it")];
+ char stringpool_str1183[sizeof("misawa.aomori.jp")];
+ char stringpool_str1184[sizeof("kotoura.tottori.jp")];
+ char stringpool_str1185[sizeof("fukuoka.jp")];
+ char stringpool_str1186[sizeof("vennesla.no")];
+ char stringpool_str1187[sizeof("vladimir.ru")];
+ char stringpool_str1188[sizeof("chuo.chiba.jp")];
+ char stringpool_str1189[sizeof("isa.kagoshima.jp")];
+ char stringpool_str1190[sizeof("bifuka.hokkaido.jp")];
+ char stringpool_str1191[sizeof("mediocampidano.it")];
+ char stringpool_str1192[sizeof("bashkiria.ru")];
+ char stringpool_str1193[sizeof("kurobe.toyama.jp")];
+ char stringpool_str1194[sizeof("arakawa.saitama.jp")];
+ char stringpool_str1195[sizeof("hidaka.hokkaido.jp")];
+ char stringpool_str1196[sizeof("vestre-toten.no")];
+ char stringpool_str1197[sizeof("babia-gora.pl")];
+ char stringpool_str1198[sizeof("mihara.hiroshima.jp")];
+ char stringpool_str1199[sizeof("civilization.museum")];
+ char stringpool_str1200[sizeof("gyeongnam.kr")];
+ char stringpool_str1201[sizeof("khv.ru")];
+ char stringpool_str1202[sizeof("fuefuki.yamanashi.jp")];
+ char stringpool_str1203[sizeof("verdal.no")];
+ char stringpool_str1204[sizeof("genkai.saga.jp")];
+ char stringpool_str1205[sizeof("chuo.osaka.jp")];
+ char stringpool_str1206[sizeof("irkutsk.ru")];
+ char stringpool_str1207[sizeof("mimata.miyazaki.jp")];
+ char stringpool_str1208[sizeof("hamatama.saga.jp")];
+ char stringpool_str1209[sizeof("cadaques.museum")];
+ char stringpool_str1210[sizeof("chattanooga.museum")];
+ char stringpool_str1211[sizeof("aizumi.tokushima.jp")];
+ char stringpool_str1212[sizeof("minami.tokushima.jp")];
+ char stringpool_str1213[sizeof("viterbo.it")];
+ char stringpool_str1214[sizeof("usa.oita.jp")];
+ char stringpool_str1215[sizeof("futtsu.chiba.jp")];
+ char stringpool_str1216[sizeof("worse-than.tv")];
+ char stringpool_str1217[sizeof("british-library.uk")];
+ char stringpool_str1218[sizeof("britishcolumbia.museum")];
+ char stringpool_str1219[sizeof("choshi.chiba.jp")];
+ char stringpool_str1220[sizeof("archaeology.museum")];
+ char stringpool_str1221[sizeof("kuzbass.ru")];
+ char stringpool_str1222[sizeof("kharkov.ua")];
+ char stringpool_str1223[sizeof("kids.us")];
+ char stringpool_str1224[sizeof("kameoka.kyoto.jp")];
+ char stringpool_str1225[sizeof("vodka")];
+ char stringpool_str1226[sizeof("kvalsund.no")];
+ char stringpool_str1227[sizeof("komoro.nagano.jp")];
+ char stringpool_str1228[sizeof("kurotaki.nara.jp")];
+ char stringpool_str1229[sizeof("verona.it")];
+ char stringpool_str1230[sizeof("gliwice.pl")];
+ char stringpool_str1231[sizeof("kanmaki.nara.jp")];
+ char stringpool_str1232[sizeof("zachpomor.pl")];
+ char stringpool_str1233[sizeof("hashikami.aomori.jp")];
+ char stringpool_str1234[sizeof("minamiizu.shizuoka.jp")];
+ char stringpool_str1235[sizeof("eigersund.no")];
+ char stringpool_str1236[sizeof("venezia.it")];
+ char stringpool_str1237[sizeof("arts.museum")];
+ char stringpool_str1238[sizeof("matsubara.osaka.jp")];
+ char stringpool_str1239[sizeof("mishima.shizuoka.jp")];
+ char stringpool_str1240[sizeof("chiyoda.tokyo.jp")];
+ char stringpool_str1241[sizeof("villas")];
+ char stringpool_str1242[sizeof("mil.ph")];
+ char stringpool_str1243[sizeof("fortworth.museum")];
+ char stringpool_str1244[sizeof("k12.wa.us")];
+ char stringpool_str1245[sizeof("bari.it")];
+ char stringpool_str1246[sizeof("vinnica.ua")];
+ char stringpool_str1247[sizeof("coal.museum")];
+ char stringpool_str1248[sizeof("mosjoen.no")];
+ char stringpool_str1249[sizeof("michigan.museum")];
+ char stringpool_str1250[sizeof("kirovograd.ua")];
+ char stringpool_str1251[sizeof("kota.aichi.jp")];
+ char stringpool_str1252[sizeof("iraq.museum")];
+ char stringpool_str1253[sizeof("iron.museum")];
+ char stringpool_str1254[sizeof("bonn.museum")];
+ char stringpool_str1255[sizeof("glas.museum")];
+ char stringpool_str1256[sizeof("hachijo.tokyo.jp")];
+ char stringpool_str1257[sizeof("vestre-slidre.no")];
+ char stringpool_str1258[sizeof("watari.miyagi.jp")];
+ char stringpool_str1259[sizeof("moseushi.hokkaido.jp")];
+ char stringpool_str1260[sizeof("fribourg.museum")];
+ char stringpool_str1261[sizeof("ventures")];
+ char stringpool_str1262[sizeof("ebetsu.hokkaido.jp")];
+ char stringpool_str1263[sizeof("varese.it")];
+ char stringpool_str1264[sizeof("amakusa.kumamoto.jp")];
+ char stringpool_str1265[sizeof("frog.museum")];
+ char stringpool_str1266[sizeof("hidaka.saitama.jp")];
+ char stringpool_str1267[sizeof("archaeological.museum")];
+ char stringpool_str1268[sizeof("childrensgarden.museum")];
+ char stringpool_str1269[sizeof("arboretum.museum")];
+ char stringpool_str1270[sizeof("ariake.saga.jp")];
+ char stringpool_str1271[sizeof("iyo.ehime.jp")];
+ char stringpool_str1272[sizeof("kazo.saitama.jp")];
+ char stringpool_str1273[sizeof("budejju.no")];
+ char stringpool_str1274[sizeof("bern.museum")];
+ char stringpool_str1275[sizeof("ikaruga.nara.jp")];
+ char stringpool_str1276[sizeof("k12.wi.us")];
+ char stringpool_str1277[sizeof("assabu.hokkaido.jp")];
+ char stringpool_str1278[sizeof("kharkiv.ua")];
+ char stringpool_str1279[sizeof("moma.museum")];
+ char stringpool_str1280[sizeof("akishima.tokyo.jp")];
+ char stringpool_str1281[sizeof("evje-og-hornnes.no")];
+ char stringpool_str1282[sizeof("haugesund.no")];
+ char stringpool_str1283[sizeof("misaki.osaka.jp")];
+ char stringpool_str1284[sizeof("abashiri.hokkaido.jp")];
+ char stringpool_str1285[sizeof("mizusawa.iwate.jp")];
+ char stringpool_str1286[sizeof("aquarium.museum")];
+ char stringpool_str1287[sizeof("koza.wakayama.jp")];
+ char stringpool_str1288[sizeof("kashiba.nara.jp")];
+ char stringpool_str1289[sizeof("ujitawara.kyoto.jp")];
+ char stringpool_str1290[sizeof("no")];
+ char stringpool_str1291[sizeof("nz")];
+ char stringpool_str1292[sizeof("civilisation.museum")];
+ char stringpool_str1293[sizeof("hirado.nagasaki.jp")];
+ char stringpool_str1294[sizeof("nr")];
+ char stringpool_str1295[sizeof("gov.sx")];
+ char stringpool_str1296[sizeof("ishikawa.jp")];
+ char stringpool_str1297[sizeof("muroran.hokkaido.jp")];
+ char stringpool_str1298[sizeof("nom.ro")];
+ char stringpool_str1299[sizeof("nl")];
+ char stringpool_str1300[sizeof("kita.kyoto.jp")];
+ char stringpool_str1301[sizeof("hiroshima.jp")];
+ char stringpool_str1302[sizeof("iki.nagasaki.jp")];
+ char stringpool_str1303[sizeof("exeter.museum")];
+ char stringpool_str1304[sizeof("kira.aichi.jp")];
+ char stringpool_str1305[sizeof("nu")];
+ char stringpool_str1306[sizeof("anjo.aichi.jp")];
+ char stringpool_str1307[sizeof("moroyama.saitama.jp")];
+ char stringpool_str1308[sizeof("vercelli.it")];
+ char stringpool_str1309[sizeof("n.bg")];
+ char stringpool_str1310[sizeof("grajewo.pl")];
+ char stringpool_str1311[sizeof("nom.re")];
+ char stringpool_str1312[sizeof("n.se")];
+ char stringpool_str1313[sizeof("koganei.tokyo.jp")];
+ char stringpool_str1314[sizeof("kyotamba.kyoto.jp")];
+ char stringpool_str1315[sizeof("kuroishi.aomori.jp")];
+ char stringpool_str1316[sizeof("cody.museum")];
+ char stringpool_str1317[sizeof("nsn.us")];
+ char stringpool_str1318[sizeof("ne")];
+ char stringpool_str1319[sizeof("net")];
+ char stringpool_str1320[sizeof("urausu.hokkaido.jp")];
+ char stringpool_str1321[sizeof("kodaira.tokyo.jp")];
+ char stringpool_str1322[sizeof("net.do")];
+ char stringpool_str1323[sizeof("nom.es")];
+ char stringpool_str1324[sizeof("net.om")];
+ char stringpool_str1325[sizeof("net.dm")];
+ char stringpool_str1326[sizeof("net.so")];
+ char stringpool_str1327[sizeof("ivano-frankivsk.ua")];
+ char stringpool_str1328[sizeof("nom.tm")];
+ char stringpool_str1329[sizeof("net.sc")];
+ char stringpool_str1330[sizeof("net.lr")];
+ char stringpool_str1331[sizeof("net.sb")];
+ char stringpool_str1332[sizeof("minamiyamashiro.kyoto.jp")];
+ char stringpool_str1333[sizeof("qld.edu.au")];
+ char stringpool_str1334[sizeof("kviteseid.no")];
+ char stringpool_str1335[sizeof("net.lc")];
+ char stringpool_str1336[sizeof("kuju.oita.jp")];
+ char stringpool_str1337[sizeof("notteroy.no")];
+ char stringpool_str1338[sizeof("net.lb")];
+ char stringpool_str1339[sizeof("nls.uk")];
+ char stringpool_str1340[sizeof("net.lk")];
+ char stringpool_str1341[sizeof("net.sl")];
+ char stringpool_str1342[sizeof("not.br")];
+ char stringpool_str1343[sizeof("nom.br")];
+ char stringpool_str1344[sizeof("columbus.museum")];
+ char stringpool_str1345[sizeof("machida.tokyo.jp")];
+ char stringpool_str1346[sizeof("net.nr")];
+ char stringpool_str1347[sizeof("ni")];
+ char stringpool_str1348[sizeof("maritimo.museum")];
+ char stringpool_str1349[sizeof("civilaviation.aero")];
+ char stringpool_str1350[sizeof("unjarga.no")];
+ char stringpool_str1351[sizeof("koga.ibaraki.jp")];
+ char stringpool_str1352[sizeof("vacations")];
+ char stringpool_str1353[sizeof("copenhagen.museum")];
+ char stringpool_str1354[sizeof("minamiboso.chiba.jp")];
+ char stringpool_str1355[sizeof("mitsuke.niigata.jp")];
+ char stringpool_str1356[sizeof("farm.museum")];
+ char stringpool_str1357[sizeof("monmouth.museum")];
+ char stringpool_str1358[sizeof("net.ec")];
+ char stringpool_str1359[sizeof("katori.chiba.jp")];
+ char stringpool_str1360[sizeof("health.museum")];
+ char stringpool_str1361[sizeof("net.to")];
+ char stringpool_str1362[sizeof("net.tj")];
+ char stringpool_str1363[sizeof("net.tm")];
+ char stringpool_str1364[sizeof("kamo.kyoto.jp")];
+ char stringpool_str1365[sizeof("kizu.kyoto.jp")];
+ char stringpool_str1366[sizeof("net.sa")];
+ char stringpool_str1367[sizeof("net.sd")];
+ char stringpool_str1368[sizeof("bill.museum")];
+ char stringpool_str1369[sizeof("hatoyama.saitama.jp")];
+ char stringpool_str1370[sizeof("net.la")];
+ char stringpool_str1371[sizeof("arao.kumamoto.jp")];
+ char stringpool_str1372[sizeof("film.museum")];
+ char stringpool_str1373[sizeof("hanamaki.iwate.jp")];
+ char stringpool_str1374[sizeof("net.bs")];
+ char stringpool_str1375[sizeof("net.br")];
+ char stringpool_str1376[sizeof("net.bo")];
+ char stringpool_str1377[sizeof("net.ua")];
+ char stringpool_str1378[sizeof("net.bm")];
+ char stringpool_str1379[sizeof("bahn.museum")];
+ char stringpool_str1380[sizeof("net.bb")];
+ char stringpool_str1381[sizeof("ntr.br")];
+ char stringpool_str1382[sizeof("net.iq")];
+ char stringpool_str1383[sizeof("net.is")];
+ char stringpool_str1384[sizeof("net.ir")];
+ char stringpool_str1385[sizeof("buzz")];
+ char stringpool_str1386[sizeof("net.im")];
+ char stringpool_str1387[sizeof("minakami.gunma.jp")];
+ char stringpool_str1388[sizeof("inashiki.ibaraki.jp")];
+ char stringpool_str1389[sizeof("gob.mx")];
+ char stringpool_str1390[sizeof("edu.mx")];
+ char stringpool_str1391[sizeof("gojome.akita.jp")];
+ char stringpool_str1392[sizeof("com.mx")];
+ char stringpool_str1393[sizeof("maibara.shiga.jp")];
+ char stringpool_str1394[sizeof("gyeongbuk.kr")];
+ char stringpool_str1395[sizeof("cahcesuolo.no")];
+ char stringpool_str1396[sizeof("bialystok.pl")];
+ char stringpool_str1397[sizeof("kagami.kochi.jp")];
+ char stringpool_str1398[sizeof("net.rw")];
+ char stringpool_str1399[sizeof("warabi.saitama.jp")];
+ char stringpool_str1400[sizeof("kumenan.okayama.jp")];
+ char stringpool_str1401[sizeof("vyatka.ru")];
+ char stringpool_str1402[sizeof("net.qa")];
+ char stringpool_str1403[sizeof("asso.ht")];
+ char stringpool_str1404[sizeof("katsuragi.nara.jp")];
+ char stringpool_str1405[sizeof("info.ht")];
+ char stringpool_str1406[sizeof("minowa.nagano.jp")];
+ char stringpool_str1407[sizeof("katano.osaka.jp")];
+ char stringpool_str1408[sizeof("haibara.shizuoka.jp")];
+ char stringpool_str1409[sizeof("nysa.pl")];
+ char stringpool_str1410[sizeof("msk.ru")];
+ char stringpool_str1411[sizeof("na")];
+ char stringpool_str1412[sizeof("minamata.kumamoto.jp")];
+ char stringpool_str1413[sizeof("hiji.oita.jp")];
+ char stringpool_str1414[sizeof("net.ba")];
+ char stringpool_str1415[sizeof("net.jo")];
+ char stringpool_str1416[sizeof("williamsburg.museum")];
+ char stringpool_str1417[sizeof("neustar")];
+ char stringpool_str1418[sizeof("name")];
+ char stringpool_str1419[sizeof("mill.museum")];
+ char stringpool_str1420[sizeof("vestnes.no")];
+ char stringpool_str1421[sizeof("net.mo")];
+ char stringpool_str1422[sizeof("kasaoka.okayama.jp")];
+ char stringpool_str1423[sizeof("net.id")];
+ char stringpool_str1424[sizeof("uenohara.yamanashi.jp")];
+ char stringpool_str1425[sizeof("np")];
+ char stringpool_str1426[sizeof("nara.jp")];
+ char stringpool_str1427[sizeof("name.qa")];
+ char stringpool_str1428[sizeof("nel.uk")];
+ char stringpool_str1429[sizeof("net.tw")];
+ char stringpool_str1430[sizeof("net.mk")];
+ char stringpool_str1431[sizeof("net.je")];
+ char stringpool_str1432[sizeof("vrn.ru")];
+ char stringpool_str1433[sizeof("namsos.no")];
+ char stringpool_str1434[sizeof("name.jo")];
+ char stringpool_str1435[sizeof("kitami.hokkaido.jp")];
+ char stringpool_str1436[sizeof("bale.museum")];
+ char stringpool_str1437[sizeof("net.ml")];
+ char stringpool_str1438[sizeof("net.me")];
+ char stringpool_str1439[sizeof("arai.shizuoka.jp")];
+ char stringpool_str1440[sizeof("name.my")];
+ char stringpool_str1441[sizeof("nom.pl")];
+ char stringpool_str1442[sizeof("nom.pe")];
+ char stringpool_str1443[sizeof("kumano.hiroshima.jp")];
+ char stringpool_str1444[sizeof("net.ar")];
+ char stringpool_str1445[sizeof("net.ac")];
+ char stringpool_str1446[sizeof("wazuka.kyoto.jp")];
+ char stringpool_str1447[sizeof("name.mk")];
+ char stringpool_str1448[sizeof("nom.ad")];
+ char stringpool_str1449[sizeof("firm.ht")];
+ char stringpool_str1450[sizeof("name.pr")];
+ char stringpool_str1451[sizeof("net.ma")];
+ char stringpool_str1452[sizeof("arezzo.it")];
+ char stringpool_str1453[sizeof("kazuno.akita.jp")];
+ char stringpool_str1454[sizeof("net.ps")];
+ char stringpool_str1455[sizeof("net.pr")];
+ char stringpool_str1456[sizeof("net.al")];
+ char stringpool_str1457[sizeof("mashiki.kumamoto.jp")];
+ char stringpool_str1458[sizeof("net.ae")];
+ char stringpool_str1459[sizeof("name.az")];
+ char stringpool_str1460[sizeof("nom.pa")];
+ char stringpool_str1461[sizeof("net.pk")];
+ char stringpool_str1462[sizeof("iwanai.hokkaido.jp")];
+ char stringpool_str1463[sizeof("kita.osaka.jp")];
+ char stringpool_str1464[sizeof("barreau.bj")];
+ char stringpool_str1465[sizeof("net.pl")];
+ char stringpool_str1466[sizeof("net.vc")];
+ char stringpool_str1467[sizeof("net.pe")];
+ char stringpool_str1468[sizeof("kisarazu.chiba.jp")];
+ char stringpool_str1469[sizeof("kumatori.osaka.jp")];
+ char stringpool_str1470[sizeof("novara.it")];
+ char stringpool_str1471[sizeof("net.mw")];
+ char stringpool_str1472[sizeof("net.ve")];
+ char stringpool_str1473[sizeof("beauxarts.museum")];
+ char stringpool_str1474[sizeof("izumiotsu.osaka.jp")];
+ char stringpool_str1475[sizeof("funahashi.toyama.jp")];
+ char stringpool_str1476[sizeof("gg")];
+ char stringpool_str1477[sizeof("eg")];
+ char stringpool_str1478[sizeof("komaki.aichi.jp")];
+ char stringpool_str1479[sizeof("cg")];
+ char stringpool_str1480[sizeof("kunneppu.hokkaido.jp")];
+ char stringpool_str1481[sizeof("gov.gr")];
+ char stringpool_str1482[sizeof("kitaakita.akita.jp")];
+ char stringpool_str1483[sizeof("edu.gr")];
+ char stringpool_str1484[sizeof("net.nf")];
+ char stringpool_str1485[sizeof("com.gr")];
+ char stringpool_str1486[sizeof("net.pa")];
+ char stringpool_str1487[sizeof("hokksund.no")];
+ char stringpool_str1488[sizeof("khakassia.ru")];
+ char stringpool_str1489[sizeof("ag")];
+ char stringpool_str1490[sizeof("xxx")];
+ char stringpool_str1491[sizeof("ama.shimane.jp")];
+ char stringpool_str1492[sizeof("ggee")];
+ char stringpool_str1493[sizeof("gushikami.okinawa.jp")];
+ char stringpool_str1494[sizeof("bg")];
+ char stringpool_str1495[sizeof("vlaanderen.museum")];
+ char stringpool_str1496[sizeof("health.vn")];
+ char stringpool_str1497[sizeof("name.mv")];
+ char stringpool_str1498[sizeof("edu.gp")];
+ char stringpool_str1499[sizeof("gov.ge")];
+ char stringpool_str1500[sizeof("com.gp")];
+ char stringpool_str1501[sizeof("edu.ge")];
+ char stringpool_str1502[sizeof("freiburg.museum")];
+ char stringpool_str1503[sizeof("nic.uk")];
+ char stringpool_str1504[sizeof("com.ge")];
+ char stringpool_str1505[sizeof("utah.museum")];
+ char stringpool_str1506[sizeof("khabarovsk.ru")];
+ char stringpool_str1507[sizeof("hitoyoshi.kumamoto.jp")];
+ char stringpool_str1508[sizeof("workshop.museum")];
+ char stringpool_str1509[sizeof("urakawa.hokkaido.jp")];
+ char stringpool_str1510[sizeof("kai.yamanashi.jp")];
+ char stringpool_str1511[sizeof("agro.pl")];
+ char stringpool_str1512[sizeof("antiques.museum")];
+ char stringpool_str1513[sizeof("net.ai")];
+ char stringpool_str1514[sizeof("nic.tr")];
+ char stringpool_str1515[sizeof("nic.tj")];
+ char stringpool_str1516[sizeof("net.hk")];
+ char stringpool_str1517[sizeof("nittedal.no")];
+ char stringpool_str1518[sizeof("info.sd")];
+ char stringpool_str1519[sizeof("maebashi.gunma.jp")];
+ char stringpool_str1520[sizeof("name.eg")];
+ char stringpool_str1521[sizeof("notodden.no")];
+ char stringpool_str1522[sizeof("austrheim.no")];
+ char stringpool_str1523[sizeof("moriya.ibaraki.jp")];
+ char stringpool_str1524[sizeof("nissedal.no")];
+ char stringpool_str1525[sizeof("hasami.nagasaki.jp")];
+ char stringpool_str1526[sizeof("mining.museum")];
+ char stringpool_str1527[sizeof("nom.km")];
+ char stringpool_str1528[sizeof("kozaki.chiba.jp")];
+ char stringpool_str1529[sizeof("net.vi")];
+ char stringpool_str1530[sizeof("kosaka.akita.jp")];
+ char stringpool_str1531[sizeof("k12.oh.us")];
+ char stringpool_str1532[sizeof("ggf.br")];
+ char stringpool_str1533[sizeof("kraanghke.no")];
+ char stringpool_str1534[sizeof("kadoma.osaka.jp")];
+ char stringpool_str1535[sizeof("norddal.no")];
+ char stringpool_str1536[sizeof("agr.br")];
+ char stringpool_str1537[sizeof("mg")];
+ char stringpool_str1538[sizeof("mari.ru")];
+ char stringpool_str1539[sizeof("minamioguni.kumamoto.jp")];
+ char stringpool_str1540[sizeof("nagoya")];
+ char stringpool_str1541[sizeof("gov.gi")];
+ char stringpool_str1542[sizeof("versailles.museum")];
+ char stringpool_str1543[sizeof("edu.gi")];
+ char stringpool_str1544[sizeof("hirara.okinawa.jp")];
+ char stringpool_str1545[sizeof("com.gi")];
+ char stringpool_str1546[sizeof("k12.nh.us")];
+ char stringpool_str1547[sizeof("ro")];
+ char stringpool_str1548[sizeof("misaki.okayama.jp")];
+ char stringpool_str1549[sizeof("ginoza.okinawa.jp")];
+ char stringpool_str1550[sizeof("ug")];
+ char stringpool_str1551[sizeof("rs")];
+ char stringpool_str1552[sizeof("kagawa.jp")];
+ char stringpool_str1553[sizeof("nesodden.no")];
+ char stringpool_str1554[sizeof("vindafjord.no")];
+ char stringpool_str1555[sizeof("esan.hokkaido.jp")];
+ char stringpool_str1556[sizeof("net.af")];
+ char stringpool_str1557[sizeof("ru")];
+ char stringpool_str1558[sizeof("naples.it")];
+ char stringpool_str1559[sizeof("moriyoshi.akita.jp")];
+ char stringpool_str1560[sizeof("kitaaiki.nagano.jp")];
+ char stringpool_str1561[sizeof("naustdal.no")];
+ char stringpool_str1562[sizeof("chiryu.aichi.jp")];
+ char stringpool_str1563[sizeof("kasama.ibaraki.jp")];
+ char stringpool_str1564[sizeof("r.bg")];
+ char stringpool_str1565[sizeof("kannami.shizuoka.jp")];
+ char stringpool_str1566[sizeof("r.se")];
+ char stringpool_str1567[sizeof("blogspot.fr")];
+ char stringpool_str1568[sizeof("minami-alps.yamanashi.jp")];
+ char stringpool_str1569[sizeof("minobu.yamanashi.jp")];
+ char stringpool_str1570[sizeof("urasoe.okinawa.jp")];
+ char stringpool_str1571[sizeof("izu.shizuoka.jp")];
+ char stringpool_str1572[sizeof("nesseby.no")];
+ char stringpool_str1573[sizeof("kui.hiroshima.jp")];
+ char stringpool_str1574[sizeof("re")];
+ char stringpool_str1575[sizeof("akabira.hokkaido.jp")];
+ char stringpool_str1576[sizeof("aso.kumamoto.jp")];
+ char stringpool_str1577[sizeof("ren")];
+ char stringpool_str1578[sizeof("rodeo")];
+ char stringpool_str1579[sizeof("hokuto.hokkaido.jp")];
+ char stringpool_str1580[sizeof("kijo.miyazaki.jp")];
+ char stringpool_str1581[sizeof("city.kawasaki.jp")];
+ char stringpool_str1582[sizeof("rest")];
+ char stringpool_str1583[sizeof("ruhr")];
+ char stringpool_str1584[sizeof("nordre-land.no")];
+ char stringpool_str1585[sizeof("kumamoto.jp")];
+ char stringpool_str1586[sizeof("home.dyndns.org")];
+ char stringpool_str1587[sizeof("uvic.museum")];
+ char stringpool_str1588[sizeof("vantaa.museum")];
+ char stringpool_str1589[sizeof("kitaura.miyazaki.jp")];
+ char stringpool_str1590[sizeof("blogspot.sg")];
+ char stringpool_str1591[sizeof("nordkapp.no")];
+ char stringpool_str1592[sizeof("fuoisku.no")];
+ char stringpool_str1593[sizeof("red")];
+ char stringpool_str1594[sizeof("asakuchi.okayama.jp")];
+ char stringpool_str1595[sizeof("napoli.it")];
+ char stringpool_str1596[sizeof("net.ki")];
+ char stringpool_str1597[sizeof("blogspot.fi")];
+ char stringpool_str1598[sizeof("ito.shizuoka.jp")];
+ char stringpool_str1599[sizeof("utazas.hu")];
+ char stringpool_str1600[sizeof("hamamatsu.shizuoka.jp")];
+ char stringpool_str1601[sizeof("himeshima.oita.jp")];
+ char stringpool_str1602[sizeof("agents.aero")];
+ char stringpool_str1603[sizeof("farmequipment.museum")];
+ char stringpool_str1604[sizeof("chikusei.ibaraki.jp")];
+ char stringpool_str1605[sizeof("repair")];
+ char stringpool_str1606[sizeof("chitose.hokkaido.jp")];
+ char stringpool_str1607[sizeof("hadano.kanagawa.jp")];
+ char stringpool_str1608[sizeof("mod.gi")];
+ char stringpool_str1609[sizeof("rennesoy.no")];
+ char stringpool_str1610[sizeof("embaixada.st")];
+ char stringpool_str1611[sizeof("veterinaire.km")];
+ char stringpool_str1612[sizeof("wiki")];
+ char stringpool_str1613[sizeof("notaires.km")];
+ char stringpool_str1614[sizeof("ishikari.hokkaido.jp")];
+ char stringpool_str1615[sizeof("muko.kyoto.jp")];
+ char stringpool_str1616[sizeof("nordreisa.no")];
+ char stringpool_str1617[sizeof("mil.ge")];
+ char stringpool_str1618[sizeof("avoues.fr")];
+ char stringpool_str1619[sizeof("honjyo.akita.jp")];
+ char stringpool_str1620[sizeof("aeroport.fr")];
+ char stringpool_str1621[sizeof("hanamigawa.chiba.jp")];
+ char stringpool_str1622[sizeof("kamchatka.ru")];
+ char stringpool_str1623[sizeof("wiki.br")];
+ char stringpool_str1624[sizeof("vestvagoy.no")];
+ char stringpool_str1625[sizeof("higashikurume.tokyo.jp")];
+ char stringpool_str1626[sizeof("vic.au")];
+ char stringpool_str1627[sizeof("krodsherad.no")];
+ char stringpool_str1628[sizeof("uto.kumamoto.jp")];
+ char stringpool_str1629[sizeof("kamioka.akita.jp")];
+ char stringpool_str1630[sizeof("nov.ru")];
+ char stringpool_str1631[sizeof("kunisaki.oita.jp")];
+ char stringpool_str1632[sizeof("kitadaito.okinawa.jp")];
+ char stringpool_str1633[sizeof("mashike.hokkaido.jp")];
+ char stringpool_str1634[sizeof("mikasa.hokkaido.jp")];
+ char stringpool_str1635[sizeof("hirakata.osaka.jp")];
+ char stringpool_str1636[sizeof("rec.ro")];
+ char stringpool_str1637[sizeof("fukuroi.shizuoka.jp")];
+ char stringpool_str1638[sizeof("kids.museum")];
+ char stringpool_str1639[sizeof("info.hu")];
+ char stringpool_str1640[sizeof("namsskogan.no")];
+ char stringpool_str1641[sizeof("vevelstad.no")];
+ char stringpool_str1642[sizeof("upow.gov.pl")];
+ char stringpool_str1643[sizeof("ginowan.okinawa.jp")];
+ char stringpool_str1644[sizeof("kuzumaki.iwate.jp")];
+ char stringpool_str1645[sizeof("chichibu.saitama.jp")];
+ char stringpool_str1646[sizeof("net.ru")];
+ char stringpool_str1647[sizeof("nebraska.museum")];
+ char stringpool_str1648[sizeof("izunokuni.shizuoka.jp")];
+ char stringpool_str1649[sizeof("kumamoto.kumamoto.jp")];
+ char stringpool_str1650[sizeof("kami.miyagi.jp")];
+ char stringpool_str1651[sizeof("kembuchi.hokkaido.jp")];
+ char stringpool_str1652[sizeof("kosa.kumamoto.jp")];
+ char stringpool_str1653[sizeof("nome.pt")];
+ char stringpool_str1654[sizeof("kushima.miyazaki.jp")];
+ char stringpool_str1655[sizeof("network")];
+ char stringpool_str1656[sizeof("rocks")];
+ char stringpool_str1657[sizeof("hakuba.nagano.jp")];
+ char stringpool_str1658[sizeof("net.ws")];
+ char stringpool_str1659[sizeof("musashino.tokyo.jp")];
+ char stringpool_str1660[sizeof("rec.br")];
+ char stringpool_str1661[sizeof("rybnik.pl")];
+ char stringpool_str1662[sizeof("net.sg")];
+ char stringpool_str1663[sizeof("rindal.no")];
+ char stringpool_str1664[sizeof("is-a-candidate.org")];
+ char stringpool_str1665[sizeof("kami.kochi.jp")];
+ char stringpool_str1666[sizeof("nature.museum")];
+ char stringpool_str1667[sizeof("kumiyama.kyoto.jp")];
+ char stringpool_str1668[sizeof("zamami.okinawa.jp")];
+ char stringpool_str1669[sizeof("horokanai.hokkaido.jp")];
+ char stringpool_str1670[sizeof("gokase.miyazaki.jp")];
+ char stringpool_str1671[sizeof("volgograd.ru")];
+ char stringpool_str1672[sizeof("komi.ru")];
+ char stringpool_str1673[sizeof("bolt.hu")];
+ char stringpool_str1674[sizeof("kushiro.hokkaido.jp")];
+ char stringpool_str1675[sizeof("net.ng")];
+ char stringpool_str1676[sizeof("cesena-forli.it")];
+ char stringpool_str1677[sizeof("nes.akershus.no")];
+ char stringpool_str1678[sizeof("kashima.kumamoto.jp")];
+ char stringpool_str1679[sizeof("airtraffic.aero")];
+ char stringpool_str1680[sizeof("net.eg")];
+ char stringpool_str1681[sizeof("kishiwada.osaka.jp")];
+ char stringpool_str1682[sizeof("rel.pl")];
+ char stringpool_str1683[sizeof("uslivinghistory.museum")];
+ char stringpool_str1684[sizeof("hokuto.yamanashi.jp")];
+ char stringpool_str1685[sizeof("frankfurt.museum")];
+ char stringpool_str1686[sizeof("mykolaiv.ua")];
+ char stringpool_str1687[sizeof("ibestad.no")];
+ char stringpool_str1688[sizeof("wakasa.tottori.jp")];
+ char stringpool_str1689[sizeof("kagoshima.jp")];
+ char stringpool_str1690[sizeof("city.hu")];
+ char stringpool_str1691[sizeof("from-me.org")];
+ char stringpool_str1692[sizeof("kanoya.kagoshima.jp")];
+ char stringpool_str1693[sizeof("fukaya.saitama.jp")];
+ char stringpool_str1694[sizeof("nom.mg")];
+ char stringpool_str1695[sizeof("net.mu")];
+ char stringpool_str1696[sizeof("katsuura.chiba.jp")];
+ char stringpool_str1697[sizeof("kashiwara.osaka.jp")];
+ char stringpool_str1698[sizeof("fukudomi.saga.jp")];
+ char stringpool_str1699[sizeof("kariya.aichi.jp")];
+ char stringpool_str1700[sizeof("rzeszow.pl")];
+ char stringpool_str1701[sizeof("zama.kanagawa.jp")];
+ char stringpool_str1702[sizeof("novosibirsk.ru")];
+ char stringpool_str1703[sizeof("rep.kp")];
+ char stringpool_str1704[sizeof("noheji.aomori.jp")];
+ char stringpool_str1705[sizeof("hachirogata.akita.jp")];
+ char stringpool_str1706[sizeof("higashiyoshino.nara.jp")];
+ char stringpool_str1707[sizeof("nagano.jp")];
+ char stringpool_str1708[sizeof("vik.no")];
+ char stringpool_str1709[sizeof("katsushika.tokyo.jp")];
+ char stringpool_str1710[sizeof("wake.okayama.jp")];
+ char stringpool_str1711[sizeof("monzabrianza.it")];
+ char stringpool_str1712[sizeof("film.hu")];
+ char stringpool_str1713[sizeof("so")];
+ char stringpool_str1714[sizeof("sd")];
+ char stringpool_str1715[sizeof("sz")];
+ char stringpool_str1716[sizeof("nom.ag")];
+ char stringpool_str1717[sizeof("net.au")];
+ char stringpool_str1718[sizeof("sr")];
+ char stringpool_str1719[sizeof("aogashima.tokyo.jp")];
+ char stringpool_str1720[sizeof("nord-fron.no")];
+ char stringpool_str1721[sizeof("sl")];
+ char stringpool_str1722[sizeof("rentals")];
+ char stringpool_str1723[sizeof("iijima.nagano.jp")];
+ char stringpool_str1724[sizeof("kutchan.hokkaido.jp")];
+ char stringpool_str1725[sizeof("monza-brianza.it")];
+ char stringpool_str1726[sizeof("su")];
+ char stringpool_str1727[sizeof("matsuura.nagasaki.jp")];
+ char stringpool_str1728[sizeof("sohu")];
+ char stringpool_str1729[sizeof("fuji.shizuoka.jp")];
+ char stringpool_str1730[sizeof("higashiyamato.tokyo.jp")];
+ char stringpool_str1731[sizeof("harstad.no")];
+ char stringpool_str1732[sizeof("s.bg")];
+ char stringpool_str1733[sizeof("fujimi.nagano.jp")];
+ char stringpool_str1734[sizeof("sn")];
+ char stringpool_str1735[sizeof("viajes")];
+ char stringpool_str1736[sizeof("s.se")];
+ char stringpool_str1737[sizeof("rec.nf")];
+ char stringpool_str1738[sizeof("res.aero")];
+ char stringpool_str1739[sizeof("rich")];
+ char stringpool_str1740[sizeof("monzaebrianza.it")];
+ char stringpool_str1741[sizeof("se")];
+ char stringpool_str1742[sizeof("misato.wakayama.jp")];
+ char stringpool_str1743[sizeof("net.ag")];
+ char stringpool_str1744[sizeof("mitoyo.kagawa.jp")];
+ char stringpool_str1745[sizeof("st")];
+ char stringpool_str1746[sizeof("ragusa.it")];
+ char stringpool_str1747[sizeof("minamifurano.hokkaido.jp")];
+ char stringpool_str1748[sizeof("fujieda.shizuoka.jp")];
+ char stringpool_str1749[sizeof("kg")];
+ char stringpool_str1750[sizeof("vladikavkaz.ru")];
+ char stringpool_str1751[sizeof("sld.do")];
+ char stringpool_str1752[sizeof("higashiyama.kyoto.jp")];
+ char stringpool_str1753[sizeof("sb")];
+ char stringpool_str1754[sizeof("voting")];
+ char stringpool_str1755[sizeof("chuo.fukuoka.jp")];
+ char stringpool_str1756[sizeof("qld.gov.au")];
+ char stringpool_str1757[sizeof("agdenes.no")];
+ char stringpool_str1758[sizeof("si")];
+ char stringpool_str1759[sizeof("srv.br")];
+ char stringpool_str1760[sizeof("is-a-linux-user.org")];
+ char stringpool_str1761[sizeof("kin.okinawa.jp")];
+ char stringpool_str1762[sizeof("utashinai.hokkaido.jp")];
+ char stringpool_str1763[sizeof("entomology.museum")];
+ char stringpool_str1764[sizeof("kazimierz-dolny.pl")];
+ char stringpool_str1765[sizeof("morioka.iwate.jp")];
+ char stringpool_str1766[sizeof("rendalen.no")];
+ char stringpool_str1767[sizeof("ringerike.no")];
+ char stringpool_str1768[sizeof("kamaishi.iwate.jp")];
+ char stringpool_str1769[sizeof("sy")];
+ char stringpool_str1770[sizeof("nagoya.jp")];
+ char stringpool_str1771[sizeof("habikino.osaka.jp")];
+ char stringpool_str1772[sizeof("solar")];
+ char stringpool_str1773[sizeof("wakayama.jp")];
+ char stringpool_str1774[sizeof("snaase.no")];
+ char stringpool_str1775[sizeof("sm")];
+ char stringpool_str1776[sizeof("snoasa.no")];
+ char stringpool_str1777[sizeof("k12.tx.us")];
+ char stringpool_str1778[sizeof("slg.br")];
+ char stringpool_str1779[sizeof("numata.gunma.jp")];
+ char stringpool_str1780[sizeof("neat-url.com")];
+ char stringpool_str1781[sizeof("iwatsuki.saitama.jp")];
+ char stringpool_str1782[sizeof("nagasaki.jp")];
+ char stringpool_str1783[sizeof("kobayashi.miyazaki.jp")];
+ char stringpool_str1784[sizeof("norilsk.ru")];
+ char stringpool_str1785[sizeof("strand.no")];
+ char stringpool_str1786[sizeof("sa")];
+ char stringpool_str1787[sizeof("kitakami.iwate.jp")];
+ char stringpool_str1788[sizeof("sortland.no")];
+ char stringpool_str1789[sizeof("mihama.wakayama.jp")];
+ char stringpool_str1790[sizeof("nemuro.hokkaido.jp")];
+ char stringpool_str1791[sizeof("sel.no")];
+ char stringpool_str1792[sizeof("kvinnherad.no")];
+ char stringpool_str1793[sizeof("kokonoe.oita.jp")];
+ char stringpool_str1794[sizeof("motobu.okinawa.jp")];
+ char stringpool_str1795[sizeof("sv")];
+ char stringpool_str1796[sizeof("fujimi.saitama.jp")];
+ char stringpool_str1797[sizeof("nalchik.ru")];
+ char stringpool_str1798[sizeof("egersund.no")];
+ char stringpool_str1799[sizeof("nore-og-uvdal.no")];
+ char stringpool_str1800[sizeof("soc.lk")];
+ char stringpool_str1801[sizeof("is-lost.org")];
+ char stringpool_str1802[sizeof("hashimoto.wakayama.jp")];
+ char stringpool_str1803[sizeof("uwajima.ehime.jp")];
+ char stringpool_str1804[sizeof("ueno.gunma.jp")];
+ char stringpool_str1805[sizeof("net.kg")];
+ char stringpool_str1806[sizeof("solund.no")];
+ char stringpool_str1807[sizeof("rw")];
+ char stringpool_str1808[sizeof("kitahata.saga.jp")];
+ char stringpool_str1809[sizeof("sos.pl")];
+ char stringpool_str1810[sizeof("kuriyama.hokkaido.jp")];
+ char stringpool_str1811[sizeof("nkz.ru")];
+ char stringpool_str1812[sizeof("nagaokakyo.kyoto.jp")];
+ char stringpool_str1813[sizeof("a.prod.fastly.net")];
+ char stringpool_str1814[sizeof("higashinaruse.akita.jp")];
+ char stringpool_str1815[sizeof("saga.jp")];
+ char stringpool_str1816[sizeof("kamikoani.akita.jp")];
+ char stringpool_str1817[sizeof("nahari.kochi.jp")];
+ char stringpool_str1818[sizeof("aibetsu.hokkaido.jp")];
+ char stringpool_str1819[sizeof("fujisawa.iwate.jp")];
+ char stringpool_str1820[sizeof("numata.hokkaido.jp")];
+ char stringpool_str1821[sizeof("uki.kumamoto.jp")];
+ char stringpool_str1822[sizeof("koshimizu.hokkaido.jp")];
+ char stringpool_str1823[sizeof("zentsuji.kagawa.jp")];
+ char stringpool_str1824[sizeof("kasumigaura.ibaraki.jp")];
+ char stringpool_str1825[sizeof("fukuyama.hiroshima.jp")];
+ char stringpool_str1826[sizeof("russia.museum")];
+ char stringpool_str1827[sizeof("riik.ee")];
+ char stringpool_str1828[sizeof("webhop.info")];
+ char stringpool_str1829[sizeof("sh")];
+ char stringpool_str1830[sizeof("higashi.okinawa.jp")];
+ char stringpool_str1831[sizeof("rnd.ru")];
+ char stringpool_str1832[sizeof("sells-it.net")];
+ char stringpool_str1833[sizeof("samara.ru")];
+ char stringpool_str1834[sizeof("marnardal.no")];
+ char stringpool_str1835[sizeof("fukushima.jp")];
+ char stringpool_str1836[sizeof("solutions")];
+ char stringpool_str1837[sizeof("embetsu.hokkaido.jp")];
+ char stringpool_str1838[sizeof("biei.hokkaido.jp")];
+ char stringpool_str1839[sizeof("shoes")];
+ char stringpool_str1840[sizeof("sirdal.no")];
+ char stringpool_str1841[sizeof("sld.pa")];
+ char stringpool_str1842[sizeof("wakuya.miyagi.jp")];
+ char stringpool_str1843[sizeof("nes.buskerud.no")];
+ char stringpool_str1844[sizeof("kamiichi.toyama.jp")];
+ char stringpool_str1845[sizeof("kounosu.saitama.jp")];
+ char stringpool_str1846[sizeof("koshigaya.saitama.jp")];
+ char stringpool_str1847[sizeof("kagamino.okayama.jp")];
+ char stringpool_str1848[sizeof("railroad.museum")];
+ char stringpool_str1849[sizeof("karumai.iwate.jp")];
+ char stringpool_str1850[sizeof("sshn.se")];
+ char stringpool_str1851[sizeof("sondrio.it")];
+ char stringpool_str1852[sizeof("hidaka.wakayama.jp")];
+ char stringpool_str1853[sizeof("musashimurayama.tokyo.jp")];
+ char stringpool_str1854[sizeof("higashimurayama.tokyo.jp")];
+ char stringpool_str1855[sizeof("romskog.no")];
+ char stringpool_str1856[sizeof("sk")];
+ char stringpool_str1857[sizeof("roma.it")];
+ char stringpool_str1858[sizeof("kadena.okinawa.jp")];
+ char stringpool_str1859[sizeof("kusatsu.shiga.jp")];
+ char stringpool_str1860[sizeof("nagara.chiba.jp")];
+ char stringpool_str1861[sizeof("noshiro.akita.jp")];
+ char stringpool_str1862[sizeof("rome.it")];
+ char stringpool_str1863[sizeof("suldal.no")];
+ char stringpool_str1864[sizeof("kotohira.kagawa.jp")];
+ char stringpool_str1865[sizeof("singles")];
+ char stringpool_str1866[sizeof("sigdal.no")];
+ char stringpool_str1867[sizeof("kitamoto.saitama.jp")];
+ char stringpool_str1868[sizeof("naturalhistory.museum")];
+ char stringpool_str1869[sizeof("mihama.fukui.jp")];
+ char stringpool_str1870[sizeof("net.sh")];
+ char stringpool_str1871[sizeof("higashisumiyoshi.osaka.jp")];
+ char stringpool_str1872[sizeof("selfip.com")];
+ char stringpool_str1873[sizeof("kure.hiroshima.jp")];
+ char stringpool_str1874[sizeof("kunitomi.miyazaki.jp")];
+ char stringpool_str1875[sizeof("kanazawa.ishikawa.jp")];
+ char stringpool_str1876[sizeof("ushiku.ibaraki.jp")];
+ char stringpool_str1877[sizeof("systems")];
+ char stringpool_str1878[sizeof("saarland")];
+ char stringpool_str1879[sizeof("nagano.nagano.jp")];
+ char stringpool_str1880[sizeof("vaksdal.no")];
+ char stringpool_str1881[sizeof("mukawa.hokkaido.jp")];
+ char stringpool_str1882[sizeof("higashiizu.shizuoka.jp")];
+ char stringpool_str1883[sizeof("rubtsovsk.ru")];
+ char stringpool_str1884[sizeof("selfip.net")];
+ char stringpool_str1885[sizeof("noda.chiba.jp")];
+ char stringpool_str1886[sizeof("sunndal.no")];
+ char stringpool_str1887[sizeof("surnadal.no")];
+ char stringpool_str1888[sizeof("k12.ga.us")];
+ char stringpool_str1889[sizeof("net.th")];
+ char stringpool_str1890[sizeof("sec.ps")];
+ char stringpool_str1891[sizeof("axis.museum")];
+ char stringpool_str1892[sizeof("kaszuby.pl")];
+ char stringpool_str1893[sizeof("nesoddtangen.no")];
+ char stringpool_str1894[sizeof("sogndal.no")];
+ char stringpool_str1895[sizeof("kamikawa.hokkaido.jp")];
+ char stringpool_str1896[sizeof("net.bh")];
+ char stringpool_str1897[sizeof("svalbard.no")];
+ char stringpool_str1898[sizeof("marylhurst.museum")];
+ char stringpool_str1899[sizeof("stranda.no")];
+ char stringpool_str1900[sizeof("stordal.no")];
+ char stringpool_str1901[sizeof("kaluga.ru")];
+ char stringpool_str1902[sizeof("nannestad.no")];
+ char stringpool_str1903[sizeof("kakuda.miyagi.jp")];
+ char stringpool_str1904[sizeof("nose.osaka.jp")];
+ char stringpool_str1905[sizeof("natori.miyagi.jp")];
+ char stringpool_str1906[sizeof("etajima.hiroshima.jp")];
+ char stringpool_str1907[sizeof("savona.it")];
+ char stringpool_str1908[sizeof("sorreisa.no")];
+ char stringpool_str1909[sizeof("ena.gifu.jp")];
+ char stringpool_str1910[sizeof("godo.gifu.jp")];
+ char stringpool_str1911[sizeof("nishio.aichi.jp")];
+ char stringpool_str1912[sizeof("koga.fukuoka.jp")];
+ char stringpool_str1913[sizeof("sondre-land.no")];
+ char stringpool_str1914[sizeof("riodejaneiro.museum")];
+ char stringpool_str1915[sizeof("sauherad.no")];
+ char stringpool_str1916[sizeof("nieruchomosci.pl")];
+ char stringpool_str1917[sizeof("alaheadju.no")];
+ char stringpool_str1918[sizeof("groundhandling.aero")];
+ char stringpool_str1919[sizeof("anthropology.museum")];
+ char stringpool_str1920[sizeof("matsumoto.nagano.jp")];
+ char stringpool_str1921[sizeof("settlers.museum")];
+ char stringpool_str1922[sizeof("amsterdam.museum")];
+ char stringpool_str1923[sizeof("morotsuka.miyazaki.jp")];
+ char stringpool_str1924[sizeof("siellak.no")];
+ char stringpool_str1925[sizeof("higashiosaka.osaka.jp")];
+ char stringpool_str1926[sizeof("hikawa.shimane.jp")];
+ char stringpool_str1927[sizeof("gifu.gifu.jp")];
+ char stringpool_str1928[sizeof("isesaki.gunma.jp")];
+ char stringpool_str1929[sizeof("ryukyu")];
+ char stringpool_str1930[sizeof("higashiizumo.shimane.jp")];
+ char stringpool_str1931[sizeof("iglesias-carbonia.it")];
+ char stringpool_str1932[sizeof("itakura.gunma.jp")];
+ char stringpool_str1933[sizeof("naruto.tokushima.jp")];
+ char stringpool_str1934[sizeof("fujimino.saitama.jp")];
+ char stringpool_str1935[sizeof("name.hr")];
+ char stringpool_str1936[sizeof("niihama.ehime.jp")];
+ char stringpool_str1937[sizeof("rollag.no")];
+ char stringpool_str1938[sizeof("matsubushi.saitama.jp")];
+ char stringpool_str1939[sizeof("kitakata.miyazaki.jp")];
+ char stringpool_str1940[sizeof("unazuki.toyama.jp")];
+ char stringpool_str1941[sizeof("exhibition.museum")];
+ char stringpool_str1942[sizeof("hida.gifu.jp")];
+ char stringpool_str1943[sizeof("kurashiki.okayama.jp")];
+ char stringpool_str1944[sizeof("skodje.no")];
+ char stringpool_str1945[sizeof("net.ph")];
+ char stringpool_str1946[sizeof("maniwa.okayama.jp")];
+ char stringpool_str1947[sizeof("sassari.it")];
+ char stringpool_str1948[sizeof("fujiidera.osaka.jp")];
+ char stringpool_str1949[sizeof("y.bg")];
+ char stringpool_str1950[sizeof("y.se")];
+ char stringpool_str1951[sizeof("saotome.st")];
+ char stringpool_str1952[sizeof("kashihara.nara.jp")];
+ char stringpool_str1953[sizeof("ye")];
+ char stringpool_str1954[sizeof("stokke.no")];
+ char stringpool_str1955[sizeof("skanland.no")];
+ char stringpool_str1956[sizeof("ninja")];
+ char stringpool_str1957[sizeof("kaisei.kanagawa.jp")];
+ char stringpool_str1958[sizeof("yt")];
+ char stringpool_str1959[sizeof("ski.no")];
+ char stringpool_str1960[sizeof("fujikawa.yamanashi.jp")];
+ char stringpool_str1961[sizeof("usui.fukuoka.jp")];
+ char stringpool_str1962[sizeof("global.ssl.fastly.net")];
+ char stringpool_str1963[sizeof("mino.gifu.jp")];
+ char stringpool_str1964[sizeof("gov.gh")];
+ char stringpool_str1965[sizeof("edu.gh")];
+ char stringpool_str1966[sizeof("amagasaki.hyogo.jp")];
+ char stringpool_str1967[sizeof("ikusaka.nagano.jp")];
+ char stringpool_str1968[sizeof("com.gh")];
+ char stringpool_str1969[sizeof("square.museum")];
+ char stringpool_str1970[sizeof("kamikawa.saitama.jp")];
+ char stringpool_str1971[sizeof("kicks-ass.org")];
+ char stringpool_str1972[sizeof("rifu.miyagi.jp")];
+ char stringpool_str1973[sizeof("reviews")];
+ char stringpool_str1974[sizeof("reggioemilia.it")];
+ char stringpool_str1975[sizeof("kaho.fukuoka.jp")];
+ char stringpool_str1976[sizeof("suedtirol.it")];
+ char stringpool_str1977[sizeof("simbirsk.ru")];
+ char stringpool_str1978[sizeof("kamiamakusa.kumamoto.jp")];
+ char stringpool_str1979[sizeof("hotel.lk")];
+ char stringpool_str1980[sizeof("saratov.ru")];
+ char stringpool_str1981[sizeof("gamagori.aichi.jp")];
+ char stringpool_str1982[sizeof("kaga.ishikawa.jp")];
+ char stringpool_str1983[sizeof("uonuma.niigata.jp")];
+ char stringpool_str1984[sizeof("exposed")];
+ char stringpool_str1985[sizeof("saltdal.no")];
+ char stringpool_str1986[sizeof("kahoku.yamagata.jp")];
+ char stringpool_str1987[sizeof("fujikawa.shizuoka.jp")];
+ char stringpool_str1988[sizeof("nobeoka.miyazaki.jp")];
+ char stringpool_str1989[sizeof("kumejima.okinawa.jp")];
+ char stringpool_str1990[sizeof("stalbans.museum")];
+ char stringpool_str1991[sizeof("fujinomiya.shizuoka.jp")];
+ char stringpool_str1992[sizeof("haebaru.okinawa.jp")];
+ char stringpool_str1993[sizeof("rimini.it")];
+ char stringpool_str1994[sizeof("cuneo.it")];
+ char stringpool_str1995[sizeof("naumburg.museum")];
+ char stringpool_str1996[sizeof("ishikawa.okinawa.jp")];
+ char stringpool_str1997[sizeof("nagareyama.chiba.jp")];
+ char stringpool_str1998[sizeof("nord-aurdal.no")];
+ char stringpool_str1999[sizeof("kamisu.ibaraki.jp")];
+ char stringpool_str2000[sizeof("akaiwa.okayama.jp")];
+ char stringpool_str2001[sizeof("stv.ru")];
+ char stringpool_str2002[sizeof("furukawa.miyagi.jp")];
+ char stringpool_str2003[sizeof("skedsmo.no")];
+ char stringpool_str2004[sizeof("chikuma.nagano.jp")];
+ char stringpool_str2005[sizeof("aga.niigata.jp")];
+ char stringpool_str2006[sizeof("kushimoto.wakayama.jp")];
+ char stringpool_str2007[sizeof("vic.edu.au")];
+ char stringpool_str2008[sizeof("hikimi.shimane.jp")];
+ char stringpool_str2009[sizeof("kongsberg.no")];
+ char stringpool_str2010[sizeof("himeji.hyogo.jp")];
+ char stringpool_str2011[sizeof("aoste.it")];
+ char stringpool_str2012[sizeof("fermo.it")];
+ char stringpool_str2013[sizeof("hirono.fukushima.jp")];
+ char stringpool_str2014[sizeof("nagasu.kumamoto.jp")];
+ char stringpool_str2015[sizeof("vg")];
+ char stringpool_str2016[sizeof("naha.okinawa.jp")];
+ char stringpool_str2017[sizeof("marumori.miyagi.jp")];
+ char stringpool_str2018[sizeof("kitahiroshima.hokkaido.jp")];
+ char stringpool_str2019[sizeof("kuki.saitama.jp")];
+ char stringpool_str2020[sizeof("zao.miyagi.jp")];
+ char stringpool_str2021[sizeof("nagaoka.niigata.jp")];
+ char stringpool_str2022[sizeof("busan.kr")];
+ char stringpool_str2023[sizeof("gamo.shiga.jp")];
+ char stringpool_str2024[sizeof("naturalhistorymuseum.museum")];
+ char stringpool_str2025[sizeof("nago.okinawa.jp")];
+ char stringpool_str2026[sizeof("iitate.fukushima.jp")];
+ char stringpool_str2027[sizeof("sumy.ua")];
+ char stringpool_str2028[sizeof("nerima.tokyo.jp")];
+ char stringpool_str2029[sizeof("futaba.fukushima.jp")];
+ char stringpool_str2030[sizeof("sexy")];
+ char stringpool_str2031[sizeof("snz.ru")];
+ char stringpool_str2032[sizeof("sandnes.no")];
+ char stringpool_str2033[sizeof("narusawa.yamanashi.jp")];
+ char stringpool_str2034[sizeof("nirasaki.yamanashi.jp")];
+ char stringpool_str2035[sizeof("vgs.no")];
+ char stringpool_str2036[sizeof("sumoto.kumamoto.jp")];
+ char stringpool_str2037[sizeof("hirata.fukushima.jp")];
+ char stringpool_str2038[sizeof("bozen.it")];
+ char stringpool_str2039[sizeof("suisse.museum")];
+ char stringpool_str2040[sizeof("czest.pl")];
+ char stringpool_str2041[sizeof("mitake.gifu.jp")];
+ char stringpool_str2042[sizeof("siedlce.pl")];
+ char stringpool_str2043[sizeof("saitama.jp")];
+ char stringpool_str2044[sizeof("furudono.fukushima.jp")];
+ char stringpool_str2045[sizeof("wodzislaw.pl")];
+ char stringpool_str2046[sizeof("karikatur.museum")];
+ char stringpool_str2047[sizeof("selfip.org")];
+ char stringpool_str2048[sizeof("graz.museum")];
+ char stringpool_str2049[sizeof("spb.ru")];
+ char stringpool_str2050[sizeof("ashibetsu.hokkaido.jp")];
+ char stringpool_str2051[sizeof("ulsan.kr")];
+ char stringpool_str2052[sizeof("kimobetsu.hokkaido.jp")];
+ char stringpool_str2053[sizeof("aosta.it")];
+ char stringpool_str2054[sizeof("hakone.kanagawa.jp")];
+ char stringpool_str2055[sizeof("skoczow.pl")];
+ char stringpool_str2056[sizeof("sandefjord.no")];
+ char stringpool_str2057[sizeof("wassamu.hokkaido.jp")];
+ char stringpool_str2058[sizeof("mizunami.gifu.jp")];
+ char stringpool_str2059[sizeof("hobol.no")];
+ char stringpool_str2060[sizeof("fujisato.akita.jp")];
+ char stringpool_str2061[sizeof("snillfjord.no")];
+ char stringpool_str2062[sizeof("recreation.aero")];
+ char stringpool_str2063[sizeof("bomlo.no")];
+ char stringpool_str2064[sizeof("genoa.it")];
+ char stringpool_str2065[sizeof("kujukuri.chiba.jp")];
+ char stringpool_str2066[sizeof("svelvik.no")];
+ char stringpool_str2067[sizeof("greta.fr")];
+ char stringpool_str2068[sizeof("kunstsammlung.museum")];
+ char stringpool_str2069[sizeof("asnes.no")];
+ char stringpool_str2070[sizeof("stathelle.no")];
+ char stringpool_str2071[sizeof("fukumitsu.toyama.jp")];
+ char stringpool_str2072[sizeof("sex.pl")];
+ char stringpool_str2073[sizeof("herad.no")];
+ char stringpool_str2074[sizeof("cambridge.museum")];
+ char stringpool_str2075[sizeof("recipes")];
+ char stringpool_str2076[sizeof("aland.fi")];
+ char stringpool_str2077[sizeof("katsuragi.wakayama.jp")];
+ char stringpool_str2078[sizeof("nagatoro.saitama.jp")];
+ char stringpool_str2079[sizeof("6bone.pl")];
+ char stringpool_str2080[sizeof("mil.gh")];
+ char stringpool_str2081[sizeof("nagi.okayama.jp")];
+ char stringpool_str2082[sizeof("kuromatsunai.hokkaido.jp")];
+ char stringpool_str2083[sizeof("aogaki.hyogo.jp")];
+ char stringpool_str2084[sizeof("mikawa.yamagata.jp")];
+ char stringpool_str2085[sizeof("nakhodka.ru")];
+ char stringpool_str2086[sizeof("hisayama.fukuoka.jp")];
+ char stringpool_str2087[sizeof("floro.no")];
+ char stringpool_str2088[sizeof("forde.no")];
+ char stringpool_str2089[sizeof("wajiki.tokushima.jp")];
+ char stringpool_str2090[sizeof("kikonai.hokkaido.jp")];
+ char stringpool_str2091[sizeof("sendai.jp")];
+ char stringpool_str2092[sizeof("kahoku.ishikawa.jp")];
+ char stringpool_str2093[sizeof("naganohara.gunma.jp")];
+ char stringpool_str2094[sizeof("ardal.no")];
+ char stringpool_str2095[sizeof("sandnessjoen.no")];
+ char stringpool_str2096[sizeof("altai.ru")];
+ char stringpool_str2097[sizeof("chiyoda.gunma.jp")];
+ char stringpool_str2098[sizeof("hyogo.jp")];
+ char stringpool_str2099[sizeof("kanagawa.jp")];
+ char stringpool_str2100[sizeof("kvinesdal.no")];
+ char stringpool_str2101[sizeof("stjordal.no")];
+ char stringpool_str2102[sizeof("higashimatsuyama.saitama.jp")];
+ char stringpool_str2103[sizeof("hirokawa.fukuoka.jp")];
+ char stringpool_str2104[sizeof("frogn.no")];
+ char stringpool_str2105[sizeof("grane.no")];
+ char stringpool_str2106[sizeof("saga.saga.jp")];
+ char stringpool_str2107[sizeof("hemne.no")];
+ char stringpool_str2108[sizeof("sandiego.museum")];
+ char stringpool_str2109[sizeof("milan.it")];
+ char stringpool_str2110[sizeof("chungbuk.kr")];
+ char stringpool_str2111[sizeof("coloradoplateau.museum")];
+ char stringpool_str2112[sizeof("nsk.ru")];
+ char stringpool_str2113[sizeof("asahikawa.hokkaido.jp")];
+ char stringpool_str2114[sizeof("motosu.gifu.jp")];
+ char stringpool_str2115[sizeof("agrinet.tn")];
+ char stringpool_str2116[sizeof("mbone.pl")];
+ char stringpool_str2117[sizeof("nyny.museum")];
+ char stringpool_str2118[sizeof("mizumaki.fukuoka.jp")];
+ char stringpool_str2119[sizeof("santabarbara.museum")];
+ char stringpool_str2120[sizeof("k12.gu.us")];
+ char stringpool_str2121[sizeof("hurum.no")];
+ char stringpool_str2122[sizeof("hatogaya.saitama.jp")];
+ char stringpool_str2123[sizeof("gunma.jp")];
+ char stringpool_str2124[sizeof("nativeamerican.museum")];
+ char stringpool_str2125[sizeof("a.ssl.fastly.net")];
+ char stringpool_str2126[sizeof("kitagawa.kochi.jp")];
+ char stringpool_str2127[sizeof("bytom.pl")];
+ char stringpool_str2128[sizeof("fjell.no")];
+ char stringpool_str2129[sizeof("minami.fukuoka.jp")];
+ char stringpool_str2130[sizeof("b.ssl.fastly.net")];
+ char stringpool_str2131[sizeof("higashikagura.hokkaido.jp")];
+ char stringpool_str2132[sizeof("gulen.no")];
+ char stringpool_str2133[sizeof("narita.chiba.jp")];
+ char stringpool_str2134[sizeof("hamar.no")];
+ char stringpool_str2135[sizeof("kaizuka.osaka.jp")];
+ char stringpool_str2136[sizeof("niikappu.hokkaido.jp")];
+ char stringpool_str2137[sizeof("kudoyama.wakayama.jp")];
+ char stringpool_str2138[sizeof("udine.it")];
+ char stringpool_str2139[sizeof("kitayama.wakayama.jp")];
+ char stringpool_str2140[sizeof("csiro.au")];
+ char stringpool_str2141[sizeof("adult.ht")];
+ char stringpool_str2142[sizeof("nagiso.nagano.jp")];
+ char stringpool_str2143[sizeof("rahkkeravju.no")];
+ char stringpool_str2144[sizeof("bjugn.no")];
+ char stringpool_str2145[sizeof("andoy.no")];
+ char stringpool_str2146[sizeof("kamisato.saitama.jp")];
+ char stringpool_str2147[sizeof("yufu.oita.jp")];
+ char stringpool_str2148[sizeof("social")];
+ char stringpool_str2149[sizeof("higashihiroshima.hiroshima.jp")];
+ char stringpool_str2150[sizeof("bardu.no")];
+ char stringpool_str2151[sizeof("iwaizumi.iwate.jp")];
+ char stringpool_str2152[sizeof("zagan.pl")];
+ char stringpool_str2153[sizeof("soundandvision.museum")];
+ char stringpool_str2154[sizeof("net.mx")];
+ char stringpool_str2155[sizeof("ryokami.saitama.jp")];
+ char stringpool_str2156[sizeof("southcarolina.museum")];
+ char stringpool_str2157[sizeof("game-host.org")];
+ char stringpool_str2158[sizeof("stor-elvdal.no")];
+ char stringpool_str2159[sizeof("bandai.fukushima.jp")];
+ char stringpool_str2160[sizeof("reklam.hu")];
+ char stringpool_str2161[sizeof("flora.no")];
+ char stringpool_str2162[sizeof("nagawa.nagano.jp")];
+ char stringpool_str2163[sizeof("seto.aichi.jp")];
+ char stringpool_str2164[sizeof("homelinux.org")];
+ char stringpool_str2165[sizeof("surgeonshall.museum")];
+ char stringpool_str2166[sizeof("frana.no")];
+ char stringpool_str2167[sizeof("molde.no")];
+ char stringpool_str2168[sizeof("kinokawa.wakayama.jp")];
+ char stringpool_str2169[sizeof("giske.no")];
+ char stringpool_str2170[sizeof("fujiyoshida.yamanashi.jp")];
+ char stringpool_str2171[sizeof("saintlouis.museum")];
+ char stringpool_str2172[sizeof("gujo.gifu.jp")];
+ char stringpool_str2173[sizeof("murayama.yamagata.jp")];
+ char stringpool_str2174[sizeof("hitra.no")];
+ char stringpool_str2175[sizeof("modum.no")];
+ char stringpool_str2176[sizeof("kashima.saga.jp")];
+ char stringpool_str2177[sizeof("iwanuma.miyagi.jp")];
+ char stringpool_str2178[sizeof("haram.no")];
+ char stringpool_str2179[sizeof("minokamo.gifu.jp")];
+ char stringpool_str2180[sizeof("higashiyodogawa.osaka.jp")];
+ char stringpool_str2181[sizeof("shoo.okayama.jp")];
+ char stringpool_str2182[sizeof("froya.no")];
+ char stringpool_str2183[sizeof("ustka.pl")];
+ char stringpool_str2184[sizeof("iizuka.fukuoka.jp")];
+ char stringpool_str2185[sizeof("akashi.hyogo.jp")];
+ char stringpool_str2186[sizeof("rennebu.no")];
+ char stringpool_str2187[sizeof("barum.no")];
+ char stringpool_str2188[sizeof("sx")];
+ char stringpool_str2189[sizeof("yachts")];
+ char stringpool_str2190[sizeof("ng")];
+ char stringpool_str2191[sizeof("stpetersburg.museum")];
+ char stringpool_str2192[sizeof("hotel.hu")];
+ char stringpool_str2193[sizeof("vologda.ru")];
+ char stringpool_str2194[sizeof("roma.museum")];
+ char stringpool_str2195[sizeof("yao.osaka.jp")];
+ char stringpool_str2196[sizeof("wajima.ishikawa.jp")];
+ char stringpool_str2197[sizeof("koto.shiga.jp")];
+ char stringpool_str2198[sizeof("nagasaki.nagasaki.jp")];
+ char stringpool_str2199[sizeof("balat.no")];
+ char stringpool_str2200[sizeof("meloy.no")];
+ char stringpool_str2201[sizeof("hakusan.ishikawa.jp")];
+ char stringpool_str2202[sizeof("wlocl.pl")];
+ char stringpool_str2203[sizeof("ringebu.no")];
+ char stringpool_str2204[sizeof("kimino.wakayama.jp")];
+ char stringpool_str2205[sizeof("minamiaiki.nagano.jp")];
+ char stringpool_str2206[sizeof("ngo.lk")];
+ char stringpool_str2207[sizeof("net.gr")];
+ char stringpool_str2208[sizeof("sosa.chiba.jp")];
+ char stringpool_str2209[sizeof("nishiizu.shizuoka.jp")];
+ char stringpool_str2210[sizeof("heroy.nordland.no")];
+ char stringpool_str2211[sizeof("nakano.tokyo.jp")];
+ char stringpool_str2212[sizeof("santacruz.museum")];
+ char stringpool_str2213[sizeof("slattum.no")];
+ char stringpool_str2214[sizeof("masoy.no")];
+ char stringpool_str2215[sizeof("kamikitayama.nara.jp")];
+ char stringpool_str2216[sizeof("wanouchi.gifu.jp")];
+ char stringpool_str2217[sizeof("net.gp")];
+ char stringpool_str2218[sizeof("murakami.niigata.jp")];
+ char stringpool_str2219[sizeof("inatsuki.fukuoka.jp")];
+ char stringpool_str2220[sizeof("net.ge")];
+ char stringpool_str2221[sizeof("ashiya.hyogo.jp")];
+ char stringpool_str2222[sizeof("matsushima.miyagi.jp")];
+ char stringpool_str2223[sizeof("minamisanriku.miyagi.jp")];
+ char stringpool_str2224[sizeof("gmina.pl")];
+ char stringpool_str2225[sizeof("show.aero")];
+ char stringpool_str2226[sizeof("namerikawa.toyama.jp")];
+ char stringpool_str2227[sizeof("salangen.no")];
+ char stringpool_str2228[sizeof("matsumoto.kagoshima.jp")];
+ char stringpool_str2229[sizeof("susaki.kochi.jp")];
+ char stringpool_str2230[sizeof("galsa.no")];
+ char stringpool_str2231[sizeof("halsa.no")];
+ char stringpool_str2232[sizeof("hotel.tz")];
+ char stringpool_str2233[sizeof("kurate.fukuoka.jp")];
+ char stringpool_str2234[sizeof("forum.hu")];
+ char stringpool_str2235[sizeof("kanuma.tochigi.jp")];
+ char stringpool_str2236[sizeof("ehime.jp")];
+ char stringpool_str2237[sizeof("szkola.pl")];
+ char stringpool_str2238[sizeof("kouzushima.tokyo.jp")];
+ char stringpool_str2239[sizeof("saroma.hokkaido.jp")];
+ char stringpool_str2240[sizeof("games.hu")];
+ char stringpool_str2241[sizeof("alstahaug.no")];
+ char stringpool_str2242[sizeof("minamimaki.nagano.jp")];
+ char stringpool_str2243[sizeof("steiermark.museum")];
+ char stringpool_str2244[sizeof("numazu.shizuoka.jp")];
+ char stringpool_str2245[sizeof("aichi.jp")];
+ char stringpool_str2246[sizeof("stalowa-wola.pl")];
+ char stringpool_str2247[sizeof("yono.saitama.jp")];
+ char stringpool_str2248[sizeof("kamogawa.chiba.jp")];
+ char stringpool_str2249[sizeof("udono.mie.jp")];
+ char stringpool_str2250[sizeof("kurume.fukuoka.jp")];
+ char stringpool_str2251[sizeof("kamagaya.chiba.jp")];
+ char stringpool_str2252[sizeof("makinohara.shizuoka.jp")];
+ char stringpool_str2253[sizeof("southwest.museum")];
+ char stringpool_str2254[sizeof("kosuge.yamanashi.jp")];
+ char stringpool_str2255[sizeof("rankoshi.hokkaido.jp")];
+ char stringpool_str2256[sizeof("ngo.pl")];
+ char stringpool_str2257[sizeof("nishikatsura.yamanashi.jp")];
+ char stringpool_str2258[sizeof("komatsushima.tokushima.jp")];
+ char stringpool_str2259[sizeof("kutno.pl")];
+ char stringpool_str2260[sizeof("shinjo.nara.jp")];
+ char stringpool_str2261[sizeof("harima.hyogo.jp")];
+ char stringpool_str2262[sizeof("kasahara.gifu.jp")];
+ char stringpool_str2263[sizeof("miharu.fukushima.jp")];
+ char stringpool_str2264[sizeof("aikawa.kanagawa.jp")];
+ char stringpool_str2265[sizeof("shinto.gunma.jp")];
+ char stringpool_str2266[sizeof("kepno.pl")];
+ char stringpool_str2267[sizeof("gov.sy")];
+ char stringpool_str2268[sizeof("edu.sy")];
+ char stringpool_str2269[sizeof("com.sy")];
+ char stringpool_str2270[sizeof("sumida.tokyo.jp")];
+ char stringpool_str2271[sizeof("yamanashi.jp")];
+ char stringpool_str2272[sizeof("gov.ly")];
+ char stringpool_str2273[sizeof("ayabe.kyoto.jp")];
+ char stringpool_str2274[sizeof("edu.ly")];
+ char stringpool_str2275[sizeof("ashiya.fukuoka.jp")];
+ char stringpool_str2276[sizeof("com.ly")];
+ char stringpool_str2277[sizeof("kakinoki.shimane.jp")];
+ char stringpool_str2278[sizeof("edu.uy")];
+ char stringpool_str2279[sizeof("com.uy")];
+ char stringpool_str2280[sizeof("o.bg")];
+ char stringpool_str2281[sizeof("soo.kagoshima.jp")];
+ char stringpool_str2282[sizeof("o.se")];
+ char stringpool_str2283[sizeof("yamato.kumamoto.jp")];
+ char stringpool_str2284[sizeof("stjordalshalsen.no")];
+ char stringpool_str2285[sizeof("kumagaya.saitama.jp")];
+ char stringpool_str2286[sizeof("stuttgart.museum")];
+ char stringpool_str2287[sizeof("chita.ru")];
+ char stringpool_str2288[sizeof("gub.uy")];
+ char stringpool_str2289[sizeof("rishiri.hokkaido.jp")];
+ char stringpool_str2290[sizeof("hanawa.fukushima.jp")];
+ char stringpool_str2291[sizeof("org")];
+ char stringpool_str2292[sizeof("org.do")];
+ char stringpool_str2293[sizeof("org.om")];
+ char stringpool_str2294[sizeof("kamitonda.wakayama.jp")];
+ char stringpool_str2295[sizeof("org.dm")];
+ char stringpool_str2296[sizeof("suzaka.nagano.jp")];
+ char stringpool_str2297[sizeof("org.so")];
+ char stringpool_str2298[sizeof("org.rs")];
+ char stringpool_str2299[sizeof("org.ro")];
+ char stringpool_str2300[sizeof("kuban.ru")];
+ char stringpool_str2301[sizeof("gov.by")];
+ char stringpool_str2302[sizeof("ralingen.no")];
+ char stringpool_str2303[sizeof("org.sc")];
+ char stringpool_str2304[sizeof("org.ls")];
+ char stringpool_str2305[sizeof("org.lr")];
+ char stringpool_str2306[sizeof("org.sb")];
+ char stringpool_str2307[sizeof("com.by")];
+ char stringpool_str2308[sizeof("nakano.nagano.jp")];
+ char stringpool_str2309[sizeof("izumi.osaka.jp")];
+ char stringpool_str2310[sizeof("noto.ishikawa.jp")];
+ char stringpool_str2311[sizeof("org.lc")];
+ char stringpool_str2312[sizeof("org.lb")];
+ char stringpool_str2313[sizeof("soja.okayama.jp")];
+ char stringpool_str2314[sizeof("org.lk")];
+ char stringpool_str2315[sizeof("org.sl")];
+ char stringpool_str2316[sizeof("akita.jp")];
+ char stringpool_str2317[sizeof("shiroi.chiba.jp")];
+ char stringpool_str2318[sizeof("org.se")];
+ char stringpool_str2319[sizeof("inabe.mie.jp")];
+ char stringpool_str2320[sizeof("shisui.chiba.jp")];
+ char stringpool_str2321[sizeof("odo.br")];
+ char stringpool_str2322[sizeof("abeno.osaka.jp")];
+ char stringpool_str2323[sizeof("org.nr")];
+ char stringpool_str2324[sizeof("iwate.jp")];
+ char stringpool_str2325[sizeof("yamada.toyama.jp")];
+ char stringpool_str2326[sizeof("kokubunji.tokyo.jp")];
+ char stringpool_str2327[sizeof("oita.jp")];
+ char stringpool_str2328[sizeof("kitagawa.miyazaki.jp")];
+ char stringpool_str2329[sizeof("kyoto.jp")];
+ char stringpool_str2330[sizeof("org.es")];
+ char stringpool_str2331[sizeof("sokndal.no")];
+ char stringpool_str2332[sizeof("org.ec")];
+ char stringpool_str2333[sizeof("nakadomari.aomori.jp")];
+ char stringpool_str2334[sizeof("org.to")];
+ char stringpool_str2335[sizeof("org.tj")];
+ char stringpool_str2336[sizeof("org.tm")];
+ char stringpool_str2337[sizeof("org.sa")];
+ char stringpool_str2338[sizeof("org.sd")];
+ char stringpool_str2339[sizeof("kasuya.fukuoka.jp")];
+ char stringpool_str2340[sizeof("asahi.mie.jp")];
+ char stringpool_str2341[sizeof("vic.gov.au")];
+ char stringpool_str2342[sizeof("org.la")];
+ char stringpool_str2343[sizeof("org.ee")];
+ char stringpool_str2344[sizeof("yasuda.kochi.jp")];
+ char stringpool_str2345[sizeof("om")];
+ char stringpool_str2346[sizeof("izumo.shimane.jp")];
+ char stringpool_str2347[sizeof("gov.my")];
+ char stringpool_str2348[sizeof("edu.my")];
+ char stringpool_str2349[sizeof("org.bs")];
+ char stringpool_str2350[sizeof("org.br")];
+ char stringpool_str2351[sizeof("org.bo")];
+ char stringpool_str2352[sizeof("yura.wakayama.jp")];
+ char stringpool_str2353[sizeof("org.ua")];
+ char stringpool_str2354[sizeof("com.my")];
+ char stringpool_str2355[sizeof("org.bm")];
+ char stringpool_str2356[sizeof("sex.hu")];
+ char stringpool_str2357[sizeof("ashikaga.tochigi.jp")];
+ char stringpool_str2358[sizeof("onl")];
+ char stringpool_str2359[sizeof("gotsu.shimane.jp")];
+ char stringpool_str2360[sizeof("org.bb")];
+ char stringpool_str2361[sizeof("org.iq")];
+ char stringpool_str2362[sizeof("org.is")];
+ char stringpool_str2363[sizeof("org.ir")];
+ char stringpool_str2364[sizeof("osoyro.no")];
+ char stringpool_str2365[sizeof("org.im")];
+ char stringpool_str2366[sizeof("ilawa.pl")];
+ char stringpool_str2367[sizeof("org.na")];
+ char stringpool_str2368[sizeof("nishimera.miyazaki.jp")];
+ char stringpool_str2369[sizeof("finnoy.no")];
+ char stringpool_str2370[sizeof("yamazoe.nara.jp")];
+ char stringpool_str2371[sizeof("komatsu.ishikawa.jp")];
+ char stringpool_str2372[sizeof("org.qa")];
+ char stringpool_str2373[sizeof("maizuru.kyoto.jp")];
+ char stringpool_str2374[sizeof("fukusaki.hyogo.jp")];
+ char stringpool_str2375[sizeof("moriyama.shiga.jp")];
+ char stringpool_str2376[sizeof("notaires.fr")];
+ char stringpool_str2377[sizeof("honai.ehime.jp")];
+ char stringpool_str2378[sizeof("kyuragi.saga.jp")];
+ char stringpool_str2379[sizeof("org.ba")];
+ char stringpool_str2380[sizeof("gov.py")];
+ char stringpool_str2381[sizeof("org.jo")];
+ char stringpool_str2382[sizeof("edu.py")];
+ char stringpool_str2383[sizeof("com.py")];
+ char stringpool_str2384[sizeof("chiba.jp")];
+ char stringpool_str2385[sizeof("yatsuka.shimane.jp")];
+ char stringpool_str2386[sizeof("susono.shizuoka.jp")];
+ char stringpool_str2387[sizeof("org.mo")];
+ char stringpool_str2388[sizeof("naie.hokkaido.jp")];
+ char stringpool_str2389[sizeof("naka.ibaraki.jp")];
+ char stringpool_str2390[sizeof("med.ly")];
+ char stringpool_str2391[sizeof("saitama.saitama.jp")];
+ char stringpool_str2392[sizeof("org.tw")];
+ char stringpool_str2393[sizeof("org.mk")];
+ char stringpool_str2394[sizeof("zarow.pl")];
+ char stringpool_str2395[sizeof("hikone.shiga.jp")];
+ char stringpool_str2396[sizeof("ayagawa.kagawa.jp")];
+ char stringpool_str2397[sizeof("atsugi.kanagawa.jp")];
+ char stringpool_str2398[sizeof("org.je")];
+ char stringpool_str2399[sizeof("suginami.tokyo.jp")];
+ char stringpool_str2400[sizeof("munakata.fukuoka.jp")];
+ char stringpool_str2401[sizeof("org.ml")];
+ char stringpool_str2402[sizeof("org.me")];
+ char stringpool_str2403[sizeof("ovh")];
+ char stringpool_str2404[sizeof("akkeshi.hokkaido.jp")];
+ char stringpool_str2405[sizeof("nord-odal.no")];
+ char stringpool_str2406[sizeof("org.bw")];
+ char stringpool_str2407[sizeof("ainan.ehime.jp")];
+ char stringpool_str2408[sizeof("orland.no")];
+ char stringpool_str2409[sizeof("org.ar")];
+ char stringpool_str2410[sizeof("org.ac")];
+ char stringpool_str2411[sizeof("spjelkavik.no")];
+ char stringpool_str2412[sizeof("kadogawa.miyazaki.jp")];
+ char stringpool_str2413[sizeof("org.bi")];
+ char stringpool_str2414[sizeof("org.ma")];
+ char stringpool_str2415[sizeof("org.ps")];
+ char stringpool_str2416[sizeof("org.pr")];
+ char stringpool_str2417[sizeof("org.al")];
+ char stringpool_str2418[sizeof("colonialwilliamsburg.museum")];
+ char stringpool_str2419[sizeof("org.ae")];
+ char stringpool_str2420[sizeof("fujioka.gunma.jp")];
+ char stringpool_str2421[sizeof("org.pk")];
+ char stringpool_str2422[sizeof("mytis.ru")];
+ char stringpool_str2423[sizeof("shimoda.shizuoka.jp")];
+ char stringpool_str2424[sizeof("asago.hyogo.jp")];
+ char stringpool_str2425[sizeof("averoy.no")];
+ char stringpool_str2426[sizeof("org.pl")];
+ char stringpool_str2427[sizeof("ishikawa.fukushima.jp")];
+ char stringpool_str2428[sizeof("org.vc")];
+ char stringpool_str2429[sizeof("org.pe")];
+ char stringpool_str2430[sizeof("mutsu.aomori.jp")];
+ char stringpool_str2431[sizeof("kafjord.no")];
+ char stringpool_str2432[sizeof("yaroslavl.ru")];
+ char stringpool_str2433[sizeof("org.mw")];
+ char stringpool_str2434[sizeof("org.ve")];
+ char stringpool_str2435[sizeof("nikaho.akita.jp")];
+ char stringpool_str2436[sizeof("klabu.no")];
+ char stringpool_str2437[sizeof("mil.sy")];
+ char stringpool_str2438[sizeof("nishiokoppe.hokkaido.jp")];
+ char stringpool_str2439[sizeof("settsu.osaka.jp")];
+ char stringpool_str2440[sizeof("yusuhara.kochi.jp")];
+ char stringpool_str2441[sizeof("katagami.akita.jp")];
+ char stringpool_str2442[sizeof("kirov.ru")];
+ char stringpool_str2443[sizeof("org.pa")];
+ char stringpool_str2444[sizeof("bizen.okayama.jp")];
+ char stringpool_str2445[sizeof("usuki.oita.jp")];
+ char stringpool_str2446[sizeof("mil.uy")];
+ char stringpool_str2447[sizeof("kazan.ru")];
+ char stringpool_str2448[sizeof("matsuda.kanagawa.jp")];
+ char stringpool_str2449[sizeof("hokkaido.jp")];
+ char stringpool_str2450[sizeof("wakasa.fukui.jp")];
+ char stringpool_str2451[sizeof("ishinomaki.miyagi.jp")];
+ char stringpool_str2452[sizeof("nonoichi.ishikawa.jp")];
+ char stringpool_str2453[sizeof("unnan.shimane.jp")];
+ char stringpool_str2454[sizeof("media.pl")];
+ char stringpool_str2455[sizeof("shiksha")];
+ char stringpool_str2456[sizeof("kaneyama.fukushima.jp")];
+ char stringpool_str2457[sizeof("gwangju.kr")];
+ char stringpool_str2458[sizeof("osteroy.no")];
+ char stringpool_str2459[sizeof("org.ai")];
+ char stringpool_str2460[sizeof("org.hk")];
+ char stringpool_str2461[sizeof("gov.ky")];
+ char stringpool_str2462[sizeof("edu.ky")];
+ char stringpool_str2463[sizeof("semine.miyagi.jp")];
+ char stringpool_str2464[sizeof("com.ky")];
+ char stringpool_str2465[sizeof("nishiawakura.okayama.jp")];
+ char stringpool_str2466[sizeof("sakhalin.ru")];
+ char stringpool_str2467[sizeof("mil.by")];
+ char stringpool_str2468[sizeof("isehara.kanagawa.jp")];
+ char stringpool_str2469[sizeof("is-a-patsfan.org")];
+ char stringpool_str2470[sizeof("ibara.okayama.jp")];
+ char stringpool_str2471[sizeof("itami.hyogo.jp")];
+ char stringpool_str2472[sizeof("matsukawa.nagano.jp")];
+ char stringpool_str2473[sizeof("nakanojo.gunma.jp")];
+ char stringpool_str2474[sizeof("org.vi")];
+ char stringpool_str2475[sizeof("nikolaev.ua")];
+ char stringpool_str2476[sizeof("kaneyama.yamagata.jp")];
+ char stringpool_str2477[sizeof("kursk.ru")];
+ char stringpool_str2478[sizeof("naoshima.kagawa.jp")];
+ char stringpool_str2479[sizeof("aizumisato.fukushima.jp")];
+ char stringpool_str2480[sizeof("shimokitayama.nara.jp")];
+ char stringpool_str2481[sizeof("kamishihoro.hokkaido.jp")];
+ char stringpool_str2482[sizeof("fukagawa.hokkaido.jp")];
+ char stringpool_str2483[sizeof("ovre-eiker.no")];
+ char stringpool_str2484[sizeof("oppdal.no")];
+ char stringpool_str2485[sizeof("org.km")];
+ char stringpool_str2486[sizeof("yotsukaido.chiba.jp")];
+ char stringpool_str2487[sizeof("viking.museum")];
+ char stringpool_str2488[sizeof("shintoku.hokkaido.jp")];
+ char stringpool_str2489[sizeof("mil.my")];
+ char stringpool_str2490[sizeof("shimamoto.osaka.jp")];
+ char stringpool_str2491[sizeof("org.kp")];
+ char stringpool_str2492[sizeof("shimada.shizuoka.jp")];
+ char stringpool_str2493[sizeof("org.af")];
+ char stringpool_str2494[sizeof("shiojiri.nagano.jp")];
+ char stringpool_str2495[sizeof("ota.tokyo.jp")];
+ char stringpool_str2496[sizeof("minoh.osaka.jp")];
+ char stringpool_str2497[sizeof("fukushima.hokkaido.jp")];
+ char stringpool_str2498[sizeof("yatomi.aichi.jp")];
+ char stringpool_str2499[sizeof("mazury.pl")];
+ char stringpool_str2500[sizeof("iruma.saitama.jp")];
+ char stringpool_str2501[sizeof("net.gg")];
+ char stringpool_str2502[sizeof("kochi.jp")];
+ char stringpool_str2503[sizeof("mamurogawa.yamagata.jp")];
+ char stringpool_str2504[sizeof("org.pf")];
+ char stringpool_str2505[sizeof("oksnes.no")];
+ char stringpool_str2506[sizeof("kani.gifu.jp")];
+ char stringpool_str2507[sizeof("hanno.saitama.jp")];
+ char stringpool_str2508[sizeof("oystre-slidre.no")];
+ char stringpool_str2509[sizeof("gosen.niigata.jp")];
+ char stringpool_str2510[sizeof("odessa.ua")];
+ char stringpool_str2511[sizeof("mil.py")];
+ char stringpool_str2512[sizeof("otsuka")];
+ char stringpool_str2513[sizeof("ikoma.nara.jp")];
+ char stringpool_str2514[sizeof("yoshioka.gunma.jp")];
+ char stringpool_str2515[sizeof("ostroda.pl")];
+ char stringpool_str2516[sizeof("sasebo.nagasaki.jp")];
+ char stringpool_str2517[sizeof("minamiminowa.nagano.jp")];
+ char stringpool_str2518[sizeof("silk.museum")];
+ char stringpool_str2519[sizeof("ome.tokyo.jp")];
+ char stringpool_str2520[sizeof("higashikawa.hokkaido.jp")];
+ char stringpool_str2521[sizeof("varggat.no")];
+ char stringpool_str2522[sizeof("kashiwazaki.niigata.jp")];
+ char stringpool_str2523[sizeof("oygarden.no")];
+ char stringpool_str2524[sizeof("sugito.saitama.jp")];
+ char stringpool_str2525[sizeof("olecko.pl")];
+ char stringpool_str2526[sizeof("yoshimi.saitama.jp")];
+ char stringpool_str2527[sizeof("ikeda.osaka.jp")];
+ char stringpool_str2528[sizeof("org.ki")];
+ char stringpool_str2529[sizeof("minamidaito.okinawa.jp")];
+ char stringpool_str2530[sizeof("belau.pw")];
+ char stringpool_str2531[sizeof("kitagata.saga.jp")];
+ char stringpool_str2532[sizeof("soka.saitama.jp")];
+ char stringpool_str2533[sizeof("is-a-knight.org")];
+ char stringpool_str2534[sizeof("shinjuku.tokyo.jp")];
+ char stringpool_str2535[sizeof("cieszyn.pl")];
+ char stringpool_str2536[sizeof("hanyu.saitama.jp")];
+ char stringpool_str2537[sizeof("yoshida.saitama.jp")];
+ char stringpool_str2538[sizeof("oita.oita.jp")];
+ char stringpool_str2539[sizeof("ulvik.no")];
+ char stringpool_str2540[sizeof("yashiro.hyogo.jp")];
+ char stringpool_str2541[sizeof("chikuhoku.nagano.jp")];
+ char stringpool_str2542[sizeof("sg")];
+ char stringpool_str2543[sizeof("botany.museum")];
+ char stringpool_str2544[sizeof("kouhoku.saga.jp")];
+ char stringpool_str2545[sizeof("shonai.yamagata.jp")];
+ char stringpool_str2546[sizeof("sakurai.nara.jp")];
+ char stringpool_str2547[sizeof("shiraoka.saitama.jp")];
+ char stringpool_str2548[sizeof("hakata.fukuoka.jp")];
+ char stringpool_str2549[sizeof("nosegawa.nara.jp")];
+ char stringpool_str2550[sizeof("karatsu.saga.jp")];
+ char stringpool_str2551[sizeof("akita.akita.jp")];
+ char stringpool_str2552[sizeof("wakayama.wakayama.jp")];
+ char stringpool_str2553[sizeof("asaka.saitama.jp")];
+ char stringpool_str2554[sizeof("county.museum")];
+ char stringpool_str2555[sizeof("asker.no")];
+ char stringpool_str2556[sizeof("shimoji.okinawa.jp")];
+ char stringpool_str2557[sizeof("yuzhno-sakhalinsk.ru")];
+ char stringpool_str2558[sizeof("chikushino.fukuoka.jp")];
+ char stringpool_str2559[sizeof("kouyama.kagoshima.jp")];
+ char stringpool_str2560[sizeof("shinjo.yamagata.jp")];
+ char stringpool_str2561[sizeof("kanonji.kagawa.jp")];
+ char stringpool_str2562[sizeof("yoshida.shizuoka.jp")];
+ char stringpool_str2563[sizeof("akagi.shimane.jp")];
+ char stringpool_str2564[sizeof("szczecin.pl")];
+ char stringpool_str2565[sizeof("seranishi.hiroshima.jp")];
+ char stringpool_str2566[sizeof("konin.pl")];
+ char stringpool_str2567[sizeof("nakamura.kochi.jp")];
+ char stringpool_str2568[sizeof("fukui.jp")];
+ char stringpool_str2569[sizeof("koryo.nara.jp")];
+ char stringpool_str2570[sizeof("ikata.ehime.jp")];
+ char stringpool_str2571[sizeof("ide.kyoto.jp")];
+ char stringpool_str2572[sizeof("inami.wakayama.jp")];
+ char stringpool_str2573[sizeof("shinjo.okayama.jp")];
+ char stringpool_str2574[sizeof("sukumo.kochi.jp")];
+ char stringpool_str2575[sizeof("oirase.aomori.jp")];
+ char stringpool_str2576[sizeof("rakkestad.no")];
+ char stringpool_str2577[sizeof("setouchi.okayama.jp")];
+ char stringpool_str2578[sizeof("aridagawa.wakayama.jp")];
+ char stringpool_str2579[sizeof("yasaka.nagano.jp")];
+ char stringpool_str2580[sizeof("is-a-bruinsfan.org")];
+ char stringpool_str2581[sizeof("hirogawa.wakayama.jp")];
+ char stringpool_str2582[sizeof("ine.kyoto.jp")];
+ char stringpool_str2583[sizeof("higashine.yamagata.jp")];
+ char stringpool_str2584[sizeof("kamikawa.hyogo.jp")];
+ char stringpool_str2585[sizeof("hongo.hiroshima.jp")];
+ char stringpool_str2586[sizeof("shintomi.miyazaki.jp")];
+ char stringpool_str2587[sizeof("org.ru")];
+ char stringpool_str2588[sizeof("askoy.no")];
+ char stringpool_str2589[sizeof("is-by.us")];
+ char stringpool_str2590[sizeof("buzen.fukuoka.jp")];
+ char stringpool_str2591[sizeof("hanggliding.aero")];
+ char stringpool_str2592[sizeof("aisho.shiga.jp")];
+ char stringpool_str2593[sizeof("choyo.kumamoto.jp")];
+ char stringpool_str2594[sizeof("higashiomi.shiga.jp")];
+ char stringpool_str2595[sizeof("kunimi.fukushima.jp")];
+ char stringpool_str2596[sizeof("yoichi.hokkaido.jp")];
+ char stringpool_str2597[sizeof("org.ws")];
+ char stringpool_str2598[sizeof("fedje.no")];
+ char stringpool_str2599[sizeof("myoko.niigata.jp")];
+ char stringpool_str2600[sizeof("org.sg")];
+ char stringpool_str2601[sizeof("go.tz")];
+ char stringpool_str2602[sizeof("ed.ao")];
+ char stringpool_str2603[sizeof("stange.no")];
+ char stringpool_str2604[sizeof("co.ao")];
+ char stringpool_str2605[sizeof("co.sz")];
+ char stringpool_str2606[sizeof("co.uz")];
+ char stringpool_str2607[sizeof("co.tz")];
+ char stringpool_str2608[sizeof("ostrowwlkp.pl")];
+ char stringpool_str2609[sizeof("yashio.saitama.jp")];
+ char stringpool_str2610[sizeof("id.us")];
+ char stringpool_str2611[sizeof("co.us")];
+ char stringpool_str2612[sizeof("co.ls")];
+ char stringpool_str2613[sizeof("bykle.no")];
+ char stringpool_str2614[sizeof("media.hu")];
+ char stringpool_str2615[sizeof("nomi.ishikawa.jp")];
+ char stringpool_str2616[sizeof("nuernberg.museum")];
+ char stringpool_str2617[sizeof("org.ug")];
+ char stringpool_str2618[sizeof("az.us")];
+ char stringpool_str2619[sizeof("oristano.it")];
+ char stringpool_str2620[sizeof("il.us")];
+ char stringpool_str2621[sizeof("co.no")];
+ char stringpool_str2622[sizeof("kusatsu.gunma.jp")];
+ char stringpool_str2623[sizeof("as.us")];
+ char stringpool_str2624[sizeof("id.au")];
+ char stringpool_str2625[sizeof("ar.us")];
+ char stringpool_str2626[sizeof("shiraoi.hokkaido.jp")];
+ char stringpool_str2627[sizeof("vefsn.no")];
+ char stringpool_str2628[sizeof("gu.us")];
+ char stringpool_str2629[sizeof("co.rs")];
+ char stringpool_str2630[sizeof("org.ng")];
+ char stringpool_str2631[sizeof("al.us")];
+ char stringpool_str2632[sizeof("hl.no")];
+ char stringpool_str2633[sizeof("co.nl")];
+ char stringpool_str2634[sizeof("co.mu")];
+ char stringpool_str2635[sizeof("org.eg")];
+ char stringpool_str2636[sizeof("fl.us")];
+ char stringpool_str2637[sizeof("shibecha.hokkaido.jp")];
+ char stringpool_str2638[sizeof("in.us")];
+ char stringpool_str2639[sizeof("al.no")];
+ char stringpool_str2640[sizeof("co.ae")];
+ char stringpool_str2641[sizeof("it.ao")];
+ char stringpool_str2642[sizeof("co.st")];
+ char stringpool_str2643[sizeof("co.tt")];
+ char stringpool_str2644[sizeof("co.at")];
+ char stringpool_str2645[sizeof("hiroo.hokkaido.jp")];
+ char stringpool_str2646[sizeof("co.me")];
+ char stringpool_str2647[sizeof("aukra.no")];
+ char stringpool_str2648[sizeof("go.cr")];
+ char stringpool_str2649[sizeof("bu.no")];
+ char stringpool_str2650[sizeof("ed.cr")];
+ char stringpool_str2651[sizeof("ct.us")];
+ char stringpool_str2652[sizeof("in.rs")];
+ char stringpool_str2653[sizeof("co.cr")];
+ char stringpool_str2654[sizeof("gr.com")];
+ char stringpool_str2655[sizeof("bd.se")];
+ char stringpool_str2656[sizeof("naturbruksgymn.se")];
+ char stringpool_str2657[sizeof("co.cl")];
+ char stringpool_str2658[sizeof("ar.com")];
+ char stringpool_str2659[sizeof("ebino.miyazaki.jp")];
+ char stringpool_str2660[sizeof("hu.com")];
+ char stringpool_str2661[sizeof("eu.com")];
+ char stringpool_str2662[sizeof("atami.shizuoka.jp")];
+ char stringpool_str2663[sizeof("koriyama.fukushima.jp")];
+ char stringpool_str2664[sizeof("br.com")];
+ char stringpool_str2665[sizeof("hyuga.miyazaki.jp")];
+ char stringpool_str2666[sizeof("org.mu")];
+ char stringpool_str2667[sizeof("gd.cn")];
+ char stringpool_str2668[sizeof("gz.cn")];
+ char stringpool_str2669[sizeof("kanan.osaka.jp")];
+ char stringpool_str2670[sizeof("hi.us")];
+ char stringpool_str2671[sizeof("cn.com")];
+ char stringpool_str2672[sizeof("nuremberg.museum")];
+ char stringpool_str2673[sizeof("gs.cn")];
+ char stringpool_str2674[sizeof("karmoy.no")];
+ char stringpool_str2675[sizeof("orskog.no")];
+ char stringpool_str2676[sizeof("mo.us")];
+ char stringpool_str2677[sizeof("md.us")];
+ char stringpool_str2678[sizeof("bushey.museum")];
+ char stringpool_str2679[sizeof("hl.cn")];
+ char stringpool_str2680[sizeof("ms.us")];
+ char stringpool_str2681[sizeof("okinawa")];
+ char stringpool_str2682[sizeof("shinichi.hiroshima.jp")];
+ char stringpool_str2683[sizeof("york.museum")];
+ char stringpool_str2684[sizeof("id.ly")];
+ char stringpool_str2685[sizeof("chigasaki.kanagawa.jp")];
+ char stringpool_str2686[sizeof("shikaoi.hokkaido.jp")];
+ char stringpool_str2687[sizeof("mr.no")];
+ char stringpool_str2688[sizeof("go.kr")];
+ char stringpool_str2689[sizeof("co.kr")];
+ char stringpool_str2690[sizeof("vardo.no")];
+ char stringpool_str2691[sizeof("org.au")];
+ char stringpool_str2692[sizeof("hn.cn")];
+ char stringpool_str2693[sizeof("semboku.akita.jp")];
+ char stringpool_str2694[sizeof("hs.kr")];
+ char stringpool_str2695[sizeof("es.kr")];
+ char stringpool_str2696[sizeof("go.tj")];
+ char stringpool_str2697[sizeof("co.tj")];
+ char stringpool_str2698[sizeof("gb.com")];
+ char stringpool_str2699[sizeof("org.mg")];
+ char stringpool_str2700[sizeof("yatsushiro.kumamoto.jp")];
+ char stringpool_str2701[sizeof("mn.us")];
+ char stringpool_str2702[sizeof("he.cn")];
+ char stringpool_str2703[sizeof("co.gy")];
+ char stringpool_str2704[sizeof("co.tm")];
+ char stringpool_str2705[sizeof("go.ci")];
+ char stringpool_str2706[sizeof("me.tz")];
+ char stringpool_str2707[sizeof("yokohama")];
+ char stringpool_str2708[sizeof("ed.ci")];
+ char stringpool_str2709[sizeof("co.om")];
+ char stringpool_str2710[sizeof("co.ci")];
+ char stringpool_str2711[sizeof("sakura.chiba.jp")];
+ char stringpool_str2712[sizeof("sakaiminato.tottori.jp")];
+ char stringpool_str2713[sizeof("me.us")];
+ char stringpool_str2714[sizeof("cq.cn")];
+ char stringpool_str2715[sizeof("mt.us")];
+ char stringpool_str2716[sizeof("hm.no")];
+ char stringpool_str2717[sizeof("stargard.pl")];
+ char stringpool_str2718[sizeof("arida.wakayama.jp")];
+ char stringpool_str2719[sizeof("bibai.hokkaido.jp")];
+ char stringpool_str2720[sizeof("hb.cn")];
+ char stringpool_str2721[sizeof("vadso.no")];
+ char stringpool_str2722[sizeof("org.ag")];
+ char stringpool_str2723[sizeof("fi.cr")];
+ char stringpool_str2724[sizeof("yakutia.ru")];
+ char stringpool_str2725[sizeof("hi.cn")];
+ char stringpool_str2726[sizeof("co.ua")];
+ char stringpool_str2727[sizeof("sera.hiroshima.jp")];
+ char stringpool_str2728[sizeof("fm.no")];
+ char stringpool_str2729[sizeof("okayama.jp")];
+ char stringpool_str2730[sizeof("ga.us")];
+ char stringpool_str2731[sizeof("ia.us")];
+ char stringpool_str2732[sizeof("inami.toyama.jp")];
+ char stringpool_str2733[sizeof("ostroleka.pl")];
+ char stringpool_str2734[sizeof("mo.cn")];
+ char stringpool_str2735[sizeof("ca.us")];
+ char stringpool_str2736[sizeof("cr.ua")];
+ char stringpool_str2737[sizeof("mi.us")];
+ char stringpool_str2738[sizeof("co.ma")];
+ char stringpool_str2739[sizeof("shobara.hiroshima.jp")];
+ char stringpool_str2740[sizeof("koka.shiga.jp")];
+ char stringpool_str2741[sizeof("ut.us")];
+ char stringpool_str2742[sizeof("meiwa.mie.jp")];
+ char stringpool_str2743[sizeof("us.com")];
+ char stringpool_str2744[sizeof("aioi.hyogo.jp")];
+ char stringpool_str2745[sizeof("ha.no")];
+ char stringpool_str2746[sizeof("co.na")];
+ char stringpool_str2747[sizeof("erimo.hokkaido.jp")];
+ char stringpool_str2748[sizeof("yamatokoriyama.nara.jp")];
+ char stringpool_str2749[sizeof("nishihara.kumamoto.jp")];
+ char stringpool_str2750[sizeof("aa.no")];
+ char stringpool_str2751[sizeof("vagan.no")];
+ char stringpool_str2752[sizeof("gv.ao")];
+ char stringpool_str2753[sizeof("id.lv")];
+ char stringpool_str2754[sizeof("in.ua")];
+ char stringpool_str2755[sizeof("cn.ua")];
+ char stringpool_str2756[sizeof("iz.hr")];
+ char stringpool_str2757[sizeof("kitakata.fukushima.jp")];
+ char stringpool_str2758[sizeof("ms.kr")];
+ char stringpool_str2759[sizeof("inagi.tokyo.jp")];
+ char stringpool_str2760[sizeof("kiryu.gunma.jp")];
+ char stringpool_str2761[sizeof("sorfold.no")];
+ char stringpool_str2762[sizeof("k12.ny.us")];
+ char stringpool_str2763[sizeof("varoy.no")];
+ char stringpool_str2764[sizeof("in.na")];
+ char stringpool_str2765[sizeof("co.ca")];
+ char stringpool_str2766[sizeof("org.hu")];
+ char stringpool_str2767[sizeof("co.hu")];
+ char stringpool_str2768[sizeof("md.ci")];
+ char stringpool_str2769[sizeof("volda.no")];
+ char stringpool_str2770[sizeof("bj.cn")];
+ char stringpool_str2771[sizeof("stateofdelaware.museum")];
+ char stringpool_str2772[sizeof("fj.cn")];
+ char stringpool_str2773[sizeof("inawashiro.fukushima.jp")];
+ char stringpool_str2774[sizeof("saikai.nagasaki.jp")];
+ char stringpool_str2775[sizeof("ishigaki.okinawa.jp")];
+ char stringpool_str2776[sizeof("nuoro.it")];
+ char stringpool_str2777[sizeof("agrigento.it")];
+ char stringpool_str2778[sizeof("bv.nl")];
+ char stringpool_str2779[sizeof("gv.at")];
+ char stringpool_str2780[sizeof("ha.cn")];
+ char stringpool_str2781[sizeof("satosho.okayama.jp")];
+ char stringpool_str2782[sizeof("kagamiishi.fukushima.jp")];
+ char stringpool_str2783[sizeof("muika.niigata.jp")];
+ char stringpool_str2784[sizeof("ma.us")];
+ char stringpool_str2785[sizeof("valle.no")];
+ char stringpool_str2786[sizeof("city.yokohama.jp")];
+ char stringpool_str2787[sizeof("fussa.tokyo.jp")];
+ char stringpool_str2788[sizeof("go.th")];
+ char stringpool_str2789[sizeof("co.bi")];
+ char stringpool_str2790[sizeof("co.th")];
+ char stringpool_str2791[sizeof("zj.cn")];
+ char stringpool_str2792[sizeof("rovigo.it")];
+ char stringpool_str2793[sizeof("nishiwaki.hyogo.jp")];
+ char stringpool_str2794[sizeof("minamiawaji.hyogo.jp")];
+ char stringpool_str2795[sizeof("zt.ua")];
+ char stringpool_str2796[sizeof("za.com")];
+ char stringpool_str2797[sizeof("uy.com")];
+ char stringpool_str2798[sizeof("nishihara.okinawa.jp")];
+ char stringpool_str2799[sizeof("honjo.akita.jp")];
+ char stringpool_str2800[sizeof("nogata.fukuoka.jp")];
+ char stringpool_str2801[sizeof("ikeda.fukui.jp")];
+ char stringpool_str2802[sizeof("uz.ua")];
+ char stringpool_str2803[sizeof("suzu.ishikawa.jp")];
+ char stringpool_str2804[sizeof("ah.no")];
+ char stringpool_str2805[sizeof("ikawa.akita.jp")];
+ char stringpool_str2806[sizeof("kaminoyama.yamagata.jp")];
+ char stringpool_str2807[sizeof("ab.ca")];
+ char stringpool_str2808[sizeof("in.th")];
+ char stringpool_str2809[sizeof("kanegasaki.iwate.jp")];
+ char stringpool_str2810[sizeof("chijiwa.nagasaki.jp")];
+ char stringpool_str2811[sizeof("konan.shiga.jp")];
+ char stringpool_str2812[sizeof("sakado.saitama.jp")];
+ char stringpool_str2813[sizeof("us.na")];
+ char stringpool_str2814[sizeof("xz.cn")];
+ char stringpool_str2815[sizeof("kariwa.niigata.jp")];
+ char stringpool_str2816[sizeof("oji.nara.jp")];
+ char stringpool_str2817[sizeof("orenburg.ru")];
+ char stringpool_str2818[sizeof("fh.se")];
+ char stringpool_str2819[sizeof("am.br")];
+ char stringpool_str2820[sizeof("org.kg")];
+ char stringpool_str2821[sizeof("gs.oslo.no")];
+ char stringpool_str2822[sizeof("soma.fukushima.jp")];
+ char stringpool_str2823[sizeof("selfip.info")];
+ char stringpool_str2824[sizeof("asahi.toyama.jp")];
+ char stringpool_str2825[sizeof("fm.br")];
+ char stringpool_str2826[sizeof("kasai.hyogo.jp")];
+ char stringpool_str2827[sizeof("yorkshire.museum")];
+ char stringpool_str2828[sizeof("okinawa.jp")];
+ char stringpool_str2829[sizeof("xn--45q11c")];
+ char stringpool_str2830[sizeof("motegi.tochigi.jp")];
+ char stringpool_str2831[sizeof("co.ba")];
+ char stringpool_str2832[sizeof("ca.na")];
+ char stringpool_str2833[sizeof("uji.kyoto.jp")];
+ char stringpool_str2834[sizeof("qh.cn")];
+ char stringpool_str2835[sizeof("randaberg.no")];
+ char stringpool_str2836[sizeof("ak.us")];
+ char stringpool_str2837[sizeof("nishiazai.shiga.jp")];
+ char stringpool_str2838[sizeof("ah.cn")];
+ char stringpool_str2839[sizeof("ngo.ph")];
+ char stringpool_str2840[sizeof("cv.ua")];
+ char stringpool_str2841[sizeof("shiiba.miyazaki.jp")];
+ char stringpool_str2842[sizeof("kosei.shiga.jp")];
+ char stringpool_str2843[sizeof("fuchu.hiroshima.jp")];
+ char stringpool_str2844[sizeof("bl.uk")];
+ char stringpool_str2845[sizeof("shikabe.hokkaido.jp")];
+ char stringpool_str2846[sizeof("katashina.gunma.jp")];
+ char stringpool_str2847[sizeof("mb.ca")];
+ char stringpool_str2848[sizeof("stockholm.museum")];
+ char stringpool_str2849[sizeof("nachikatsuura.wakayama.jp")];
+ char stringpool_str2850[sizeof("kanna.gunma.jp")];
+ char stringpool_str2851[sizeof("video.hu")];
+ char stringpool_str2852[sizeof("kanra.gunma.jp")];
+ char stringpool_str2853[sizeof("ec")];
+ char stringpool_str2854[sizeof("cc")];
+ char stringpool_str2855[sizeof("gov.co")];
+ char stringpool_str2856[sizeof("edu.co")];
+ char stringpool_str2857[sizeof("gov.cm")];
+ char stringpool_str2858[sizeof("com.co")];
+ char stringpool_str2859[sizeof("chofu.tokyo.jp")];
+ char stringpool_str2860[sizeof("ac")];
+ char stringpool_str2861[sizeof("ketrzyn.pl")];
+ char stringpool_str2862[sizeof("koshu.yamanashi.jp")];
+ char stringpool_str2863[sizeof("omasvuotna.no")];
+ char stringpool_str2864[sizeof("gov.cl")];
+ char stringpool_str2865[sizeof("gob.cl")];
+ char stringpool_str2866[sizeof("sakuho.nagano.jp")];
+ char stringpool_str2867[sizeof("actor")];
+ char stringpool_str2868[sizeof("svizzera.museum")];
+ char stringpool_str2869[sizeof("zp.ua")];
+ char stringpool_str2870[sizeof("fudai.iwate.jp")];
+ char stringpool_str2871[sizeof("int.co")];
+ char stringpool_str2872[sizeof("overhalla.no")];
+ char stringpool_str2873[sizeof("hk.cn")];
+ char stringpool_str2874[sizeof("shimamaki.hokkaido.jp")];
+ char stringpool_str2875[sizeof("xj.cn")];
+ char stringpool_str2876[sizeof("mi.th")];
+ char stringpool_str2877[sizeof("abira.hokkaido.jp")];
+ char stringpool_str2878[sizeof("gov.cd")];
+ char stringpool_str2879[sizeof("xn--90a3ac")];
+ char stringpool_str2880[sizeof("wi.us")];
+ char stringpool_str2881[sizeof("monza.it")];
+ char stringpool_str2882[sizeof("ako.hyogo.jp")];
+ char stringpool_str2883[sizeof("minamiuonuma.niigata.jp")];
+ char stringpool_str2884[sizeof("fuchu.toyama.jp")];
+ char stringpool_str2885[sizeof("nishiarita.saga.jp")];
+ char stringpool_str2886[sizeof("hofu.yamaguchi.jp")];
+ char stringpool_str2887[sizeof("wy.us")];
+ char stringpool_str2888[sizeof("ecn.br")];
+ char stringpool_str2889[sizeof("urawa.saitama.jp")];
+ char stringpool_str2890[sizeof("xn--d1acj3b")];
+ char stringpool_str2891[sizeof("mc")];
+ char stringpool_str2892[sizeof("edu.cw")];
+ char stringpool_str2893[sizeof("org.sh")];
+ char stringpool_str2894[sizeof("yamanashi.yamanashi.jp")];
+ char stringpool_str2895[sizeof("xn--55qx5d")];
+ char stringpool_str2896[sizeof("eco.br")];
+ char stringpool_str2897[sizeof("fuchu.tokyo.jp")];
+ char stringpool_str2898[sizeof("com.cw")];
+ char stringpool_str2899[sizeof("fujisawa.kanagawa.jp")];
+ char stringpool_str2900[sizeof("ikeda.hokkaido.jp")];
+ char stringpool_str2901[sizeof("iwade.wakayama.jp")];
+ char stringpool_str2902[sizeof("edu.ci")];
+ char stringpool_str2903[sizeof("com.ci")];
+ char stringpool_str2904[sizeof("academy")];
+ char stringpool_str2905[sizeof("ck.ua")];
+ char stringpool_str2906[sizeof("setagaya.tokyo.jp")];
+ char stringpool_str2907[sizeof("makurazaki.kagoshima.jp")];
+ char stringpool_str2908[sizeof("uk.com")];
+ char stringpool_str2909[sizeof("meiwa.gunma.jp")];
+ char stringpool_str2910[sizeof("k12.ky.us")];
+ char stringpool_str2911[sizeof("xn--55qx5d.cn")];
+ char stringpool_str2912[sizeof("namegawa.saitama.jp")];
+ char stringpool_str2913[sizeof("wa.us")];
+ char stringpool_str2914[sizeof("oizumi.gunma.jp")];
+ char stringpool_str2915[sizeof("int.ci")];
+ char stringpool_str2916[sizeof("sobetsu.hokkaido.jp")];
+ char stringpool_str2917[sizeof("org.bh")];
+ char stringpool_str2918[sizeof("wa.au")];
+ char stringpool_str2919[sizeof("matsuyama.ehime.jp")];
+ char stringpool_str2920[sizeof("ws.na")];
+ char stringpool_str2921[sizeof("kanzaki.saga.jp")];
+ char stringpool_str2922[sizeof("otsuki.kochi.jp")];
+ char stringpool_str2923[sizeof("xn--io0a7i")];
+ char stringpool_str2924[sizeof("izena.okinawa.jp")];
+ char stringpool_str2925[sizeof("xn--slat-5na.no")];
+ char stringpool_str2926[sizeof("kozagawa.wakayama.jp")];
+ char stringpool_str2927[sizeof("wv.us")];
+ char stringpool_str2928[sizeof("yamatotakada.nara.jp")];
+ char stringpool_str2929[sizeof("xn--zfr164b")];
+ char stringpool_str2930[sizeof("blogspot.be")];
+ char stringpool_str2931[sizeof("iide.yamagata.jp")];
+ char stringpool_str2932[sizeof("xn--p1ai")];
+ char stringpool_str2933[sizeof("yamato.kanagawa.jp")];
+ char stringpool_str2934[sizeof("gf")];
+ char stringpool_str2935[sizeof("sakaki.nagano.jp")];
+ char stringpool_str2936[sizeof("cf")];
+ char stringpool_str2937[sizeof("kosai.shizuoka.jp")];
+ char stringpool_str2938[sizeof("mk.ua")];
+ char stringpool_str2939[sizeof("com.fr")];
+ char stringpool_str2940[sizeof("af")];
+ char stringpool_str2941[sizeof("xn--io0a7i.cn")];
+ char stringpool_str2942[sizeof("naka.hiroshima.jp")];
+ char stringpool_str2943[sizeof("bf")];
+ char stringpool_str2944[sizeof("kikugawa.shizuoka.jp")];
+ char stringpool_str2945[sizeof("ks.us")];
+ char stringpool_str2946[sizeof("aca.pro")];
+ char stringpool_str2947[sizeof("askim.no")];
+ char stringpool_str2948[sizeof("nesna.no")];
+ char stringpool_str2949[sizeof("yokote.akita.jp")];
+ char stringpool_str2950[sizeof("higashimatsushima.miyagi.jp")];
+ char stringpool_str2951[sizeof("yurihonjo.akita.jp")];
+ char stringpool_str2952[sizeof("orkdal.no")];
+ char stringpool_str2953[sizeof("online.museum")];
+ char stringpool_str2954[sizeof("asso.mc")];
+ char stringpool_str2955[sizeof("family.museum")];
+ char stringpool_str2956[sizeof("sakawa.kochi.jp")];
+ char stringpool_str2957[sizeof("onna.okinawa.jp")];
+ char stringpool_str2958[sizeof("go.id")];
+ char stringpool_str2959[sizeof("xn--smla-hra.no")];
+ char stringpool_str2960[sizeof("sannohe.aomori.jp")];
+ char stringpool_str2961[sizeof("co.id")];
+ char stringpool_str2962[sizeof("rikuzentakata.iwate.jp")];
+ char stringpool_str2963[sizeof("kyowa.akita.jp")];
+ char stringpool_str2964[sizeof("id.ir")];
+ char stringpool_str2965[sizeof("omi.nagano.jp")];
+ char stringpool_str2966[sizeof("blogspot.bj")];
+ char stringpool_str2967[sizeof("co.ir")];
+ char stringpool_str2968[sizeof("xn--seral-lra.no")];
+ char stringpool_str2969[sizeof("co.mw")];
+ char stringpool_str2970[sizeof("org.ph")];
+ char stringpool_str2971[sizeof("naroy.no")];
+ char stringpool_str2972[sizeof("xn--3bst00m")];
+ char stringpool_str2973[sizeof("chuo.yamanashi.jp")];
+ char stringpool_str2974[sizeof("xn--kpry57d")];
+ char stringpool_str2975[sizeof("kr.com")];
+ char stringpool_str2976[sizeof("info.ec")];
+ char stringpool_str2977[sizeof("co.rw")];
+ char stringpool_str2978[sizeof("uruma.okinawa.jp")];
+ char stringpool_str2979[sizeof("yokohama.jp")];
+ char stringpool_str2980[sizeof("sakata.yamagata.jp")];
+ char stringpool_str2981[sizeof("mil.co")];
+ char stringpool_str2982[sizeof("yamanakako.yamanashi.jp")];
+ char stringpool_str2983[sizeof("vestby.no")];
+ char stringpool_str2984[sizeof("honjo.saitama.jp")];
+ char stringpool_str2985[sizeof("omsk.ru")];
+ char stringpool_str2986[sizeof("co.in")];
+ char stringpool_str2987[sizeof("komae.tokyo.jp")];
+ char stringpool_str2988[sizeof("mil.cl")];
+ char stringpool_str2989[sizeof("xn--skjk-soa.no")];
+ char stringpool_str2990[sizeof("yokoze.saitama.jp")];
+ char stringpool_str2991[sizeof("go.it")];
+ char stringpool_str2992[sizeof("co.it")];
+ char stringpool_str2993[sizeof("kakegawa.shizuoka.jp")];
+ char stringpool_str2994[sizeof("cz.it")];
+ char stringpool_str2995[sizeof("grong.no")];
+ char stringpool_str2996[sizeof("xn--j1amh")];
+ char stringpool_str2997[sizeof("contractors")];
+ char stringpool_str2998[sizeof("yamashina.kyoto.jp")];
+ char stringpool_str2999[sizeof("is.it")];
+ char stringpool_str3000[sizeof("zgrad.ru")];
+ char stringpool_str3001[sizeof("yomitan.okinawa.jp")];
+ char stringpool_str3002[sizeof("gr.it")];
+ char stringpool_str3003[sizeof("cs.it")];
+ char stringpool_str3004[sizeof("shizuoka.jp")];
+ char stringpool_str3005[sizeof("cr.it")];
+ char stringpool_str3006[sizeof("ao.it")];
+ char stringpool_str3007[sizeof("ae.org")];
+ char stringpool_str3008[sizeof("cl.it")];
+ char stringpool_str3009[sizeof("shishikui.tokushima.jp")];
+ char stringpool_str3010[sizeof("brescia.it")];
+ char stringpool_str3011[sizeof("ar.it")];
+ char stringpool_str3012[sizeof("bo.it")];
+ char stringpool_str3013[sizeof("xn--yer-zna.no")];
+ char stringpool_str3014[sizeof("ky.us")];
+ char stringpool_str3015[sizeof("bz.it")];
+ char stringpool_str3016[sizeof("xn--rdal-poa.no")];
+ char stringpool_str3017[sizeof("al.it")];
+ char stringpool_str3018[sizeof("bs.it")];
+ char stringpool_str3019[sizeof("br.it")];
+ char stringpool_str3020[sizeof("fr.it")];
+ char stringpool_str3021[sizeof("xn--od0alg.cn")];
+ char stringpool_str3022[sizeof("bl.it")];
+ char stringpool_str3023[sizeof("en.it")];
+ char stringpool_str3024[sizeof("iwata.shizuoka.jp")];
+ char stringpool_str3025[sizeof("cn.it")];
+ char stringpool_str3026[sizeof("blogspot.cf")];
+ char stringpool_str3027[sizeof("2000.hu")];
+ char stringpool_str3028[sizeof("motorcycles")];
+ char stringpool_str3029[sizeof("ge.it")];
+ char stringpool_str3030[sizeof("an.it")];
+ char stringpool_str3031[sizeof("itano.tokushima.jp")];
+ char stringpool_str3032[sizeof("ce.it")];
+ char stringpool_str3033[sizeof("rieti.it")];
+ char stringpool_str3034[sizeof("xn--rland-uua.no")];
+ char stringpool_str3035[sizeof("bn.it")];
+ char stringpool_str3036[sizeof("ct.it")];
+ char stringpool_str3037[sizeof("is-an-actress.com")];
+ char stringpool_str3038[sizeof("aq.it")];
+ char stringpool_str3039[sizeof("vagsoy.no")];
+ char stringpool_str3040[sizeof("at.it")];
+ char stringpool_str3041[sizeof("xn--mely-ira.no")];
+ char stringpool_str3042[sizeof("fe.it")];
+ char stringpool_str3043[sizeof("is-a-caterer.com")];
+ char stringpool_str3044[sizeof("bt.it")];
+ char stringpool_str3045[sizeof("nagahama.shiga.jp")];
+ char stringpool_str3046[sizeof("cb.it")];
+ char stringpool_str3047[sizeof("okutama.tokyo.jp")];
+ char stringpool_str3048[sizeof("ks.ua")];
+ char stringpool_str3049[sizeof("kr.ua")];
+ char stringpool_str3050[sizeof("yonabaru.okinawa.jp")];
+ char stringpool_str3051[sizeof("co.im")];
+ char stringpool_str3052[sizeof("roros.no")];
+ char stringpool_str3053[sizeof("sanuki.kagawa.jp")];
+ char stringpool_str3054[sizeof("omi.niigata.jp")];
+ char stringpool_str3055[sizeof("xn--sr-aurdal-l8a.no")];
+ char stringpool_str3056[sizeof("ci.it")];
+ char stringpool_str3057[sizeof("us.org")];
+ char stringpool_str3058[sizeof("kitanakagusuku.okinawa.jp")];
+ char stringpool_str3059[sizeof("do")];
+ char stringpool_str3060[sizeof("nakijin.okinawa.jp")];
+ char stringpool_str3061[sizeof("dz")];
+ char stringpool_str3062[sizeof("mo.it")];
+ char stringpool_str3063[sizeof("yakumo.hokkaido.jp")];
+ char stringpool_str3064[sizeof("ms.it")];
+ char stringpool_str3065[sizeof("web.co")];
+ char stringpool_str3066[sizeof("edu.sn")];
+ char stringpool_str3067[sizeof("is-slick.com")];
+ char stringpool_str3068[sizeof("com.sn")];
+ char stringpool_str3069[sizeof("bi.it")];
+ char stringpool_str3070[sizeof("xn--troms-zua.no")];
+ char stringpool_str3071[sizeof("fi.it")];
+ char stringpool_str3072[sizeof("hiratsuka.kanagawa.jp")];
+ char stringpool_str3073[sizeof("ozu.ehime.jp")];
+ char stringpool_str3074[sizeof("is-an-artist.com")];
+ char stringpool_str3075[sizeof("coop")];
+ char stringpool_str3076[sizeof("navigation.aero")];
+ char stringpool_str3077[sizeof("xn--asky-ira.no")];
+ char stringpool_str3078[sizeof("art.sn")];
+ char stringpool_str3079[sizeof("feedback")];
+ char stringpool_str3080[sizeof("koori.fukushima.jp")];
+ char stringpool_str3081[sizeof("oshima.tokyo.jp")];
+ char stringpool_str3082[sizeof("d.bg")];
+ char stringpool_str3083[sizeof("grue.no")];
+ char stringpool_str3084[sizeof("coop.mw")];
+ char stringpool_str3085[sizeof("xn--rros-gra.no")];
+ char stringpool_str3086[sizeof("d.se")];
+ char stringpool_str3087[sizeof("ud.it")];
+ char stringpool_str3088[sizeof("mn.it")];
+ char stringpool_str3089[sizeof("dnp")];
+ char stringpool_str3090[sizeof("ukiha.fukuoka.jp")];
+ char stringpool_str3091[sizeof("omachi.nagano.jp")];
+ char stringpool_str3092[sizeof("enterprises")];
+ char stringpool_str3093[sizeof("zgora.pl")];
+ char stringpool_str3094[sizeof("alta.no")];
+ char stringpool_str3095[sizeof("de")];
+ char stringpool_str3096[sizeof("im.it")];
+ char stringpool_str3097[sizeof("k12.wy.us")];
+ char stringpool_str3098[sizeof("sumoto.hyogo.jp")];
+ char stringpool_str3099[sizeof("me.it")];
+ char stringpool_str3100[sizeof("co.bw")];
+ char stringpool_str3101[sizeof("arna.no")];
+ char stringpool_str3102[sizeof("kamakura.kanagawa.jp")];
+ char stringpool_str3103[sizeof("cloudcontrolled.com")];
+ char stringpool_str3104[sizeof("mt.it")];
+ char stringpool_str3105[sizeof("info.na")];
+ char stringpool_str3106[sizeof("gov.tn")];
+ char stringpool_str3107[sizeof("my.id")];
+ char stringpool_str3108[sizeof("aure.no")];
+ char stringpool_str3109[sizeof("com.tn")];
+ char stringpool_str3110[sizeof("coop.br")];
+ char stringpool_str3111[sizeof("xn--merker-kua.no")];
+ char stringpool_str3112[sizeof("fm.it")];
+ char stringpool_str3113[sizeof("xn--sr-odal-q1a.no")];
+ char stringpool_str3114[sizeof("coop.py")];
+ char stringpool_str3115[sizeof("horten.no")];
+ char stringpool_str3116[sizeof("xn--i1b6b1a6a2e")];
+ char stringpool_str3117[sizeof("xn--sknit-yqa.no")];
+ char stringpool_str3118[sizeof("mb.it")];
+ char stringpool_str3119[sizeof("info.nr")];
+ char stringpool_str3120[sizeof("gran.no")];
+ char stringpool_str3121[sizeof("fusa.no")];
+ char stringpool_str3122[sizeof("ca.it")];
+ char stringpool_str3123[sizeof("dep.no")];
+ char stringpool_str3124[sizeof("mi.it")];
+ char stringpool_str3125[sizeof("gov.in")];
+ char stringpool_str3126[sizeof("edu.in")];
+ char stringpool_str3127[sizeof("honefoss.no")];
+ char stringpool_str3128[sizeof("shingo.aomori.jp")];
+ char stringpool_str3129[sizeof("etne.no")];
+ char stringpool_str3130[sizeof("bodo.no")];
+ char stringpool_str3131[sizeof("arq.br")];
+ char stringpool_str3132[sizeof("xn--smna-gra.no")];
+ char stringpool_str3133[sizeof("ba.it")];
+ char stringpool_str3134[sizeof("xn--trgstad-r1a.no")];
+ char stringpool_str3135[sizeof("za.org")];
+ char stringpool_str3136[sizeof("risor.no")];
+ char stringpool_str3137[sizeof("city.kobe.jp")];
+ char stringpool_str3138[sizeof("mormon")];
+ char stringpool_str3139[sizeof("starnberg.museum")];
+ char stringpool_str3140[sizeof("is-a-painter.com")];
+ char stringpool_str3141[sizeof("berg.no")];
+ char stringpool_str3142[sizeof("istmein.de")];
+ char stringpool_str3143[sizeof("yame.fukuoka.jp")];
+ char stringpool_str3144[sizeof("iheya.okinawa.jp")];
+ char stringpool_str3145[sizeof("ap.it")];
+ char stringpool_str3146[sizeof("ens.tn")];
+ char stringpool_str3147[sizeof("xn--risa-5na.no")];
+ char stringpool_str3148[sizeof("arts.nf")];
+ char stringpool_str3149[sizeof("km.ua")];
+ char stringpool_str3150[sizeof("is-an-actor.com")];
+ char stringpool_str3151[sizeof("av.it")];
+ char stringpool_str3152[sizeof("dj")];
+ char stringpool_str3153[sizeof("from-co.net")];
+ char stringpool_str3154[sizeof("xn--mli-tla.no")];
+ char stringpool_str3155[sizeof("moss.no")];
+ char stringpool_str3156[sizeof("xn--linds-pra.no")];
+ char stringpool_str3157[sizeof("from-la.net")];
+ char stringpool_str3158[sizeof("xn--yfro4i67o")];
+ char stringpool_str3159[sizeof("xn--55qx5d.hk")];
+ char stringpool_str3160[sizeof("dm")];
+ char stringpool_str3161[sizeof("hole.no")];
+ char stringpool_str3162[sizeof("gov.mn")];
+ char stringpool_str3163[sizeof("historisch.museum")];
+ char stringpool_str3164[sizeof("edu.mn")];
+ char stringpool_str3165[sizeof("info.nf")];
+ char stringpool_str3166[sizeof("yakumo.shimane.jp")];
+ char stringpool_str3167[sizeof("from-ma.com")];
+ char stringpool_str3168[sizeof("gen.in")];
+ char stringpool_str3169[sizeof("coop.mv")];
+ char stringpool_str3170[sizeof("ind.tn")];
+ char stringpool_str3171[sizeof("steigen.no")];
+ char stringpool_str3172[sizeof("xn--risr-ira.no")];
+ char stringpool_str3173[sizeof("from-ca.com")];
+ char stringpool_str3174[sizeof("from-mo.com")];
+ char stringpool_str3175[sizeof("rodoy.no")];
+ char stringpool_str3176[sizeof("from-ri.com")];
+ char stringpool_str3177[sizeof("berlin")];
+ char stringpool_str3178[sizeof("from-mi.com")];
+ char stringpool_str3179[sizeof("omachi.saga.jp")];
+ char stringpool_str3180[sizeof("bergen.no")];
+ char stringpool_str3181[sizeof("hammerfest.no")];
+ char stringpool_str3182[sizeof("romsa.no")];
+ char stringpool_str3183[sizeof("from-pa.com")];
+ char stringpool_str3184[sizeof("suli.hu")];
+ char stringpool_str3185[sizeof("from-or.com")];
+ char stringpool_str3186[sizeof("swiebodzin.pl")];
+ char stringpool_str3187[sizeof("from-az.net")];
+ char stringpool_str3188[sizeof("from-ky.com")];
+ char stringpool_str3189[sizeof("wf")];
+ char stringpool_str3190[sizeof("fin.tn")];
+ char stringpool_str3191[sizeof("from-ok.com")];
+ char stringpool_str3192[sizeof("edu.an")];
+ char stringpool_str3193[sizeof("ind.in")];
+ char stringpool_str3194[sizeof("camp")];
+ char stringpool_str3195[sizeof("com.an")];
+ char stringpool_str3196[sizeof("iwaki.fukushima.jp")];
+ char stringpool_str3197[sizeof("okegawa.saitama.jp")];
+ char stringpool_str3198[sizeof("iwate.iwate.jp")];
+ char stringpool_str3199[sizeof("merseine.nu")];
+ char stringpool_str3200[sizeof("from-pr.com")];
+ char stringpool_str3201[sizeof("amot.no")];
+ char stringpool_str3202[sizeof("niki.hokkaido.jp")];
+ char stringpool_str3203[sizeof("okayama.okayama.jp")];
+ char stringpool_str3204[sizeof("xn--trany-yua.no")];
+ char stringpool_str3205[sizeof("ch.it")];
+ char stringpool_str3206[sizeof("kv.ua")];
+ char stringpool_str3207[sizeof("community")];
+ char stringpool_str3208[sizeof("from-al.com")];
+ char stringpool_str3209[sizeof("gov.pn")];
+ char stringpool_str3210[sizeof("from-mn.com")];
+ char stringpool_str3211[sizeof("edu.pn")];
+ char stringpool_str3212[sizeof("eniwa.hokkaido.jp")];
+ char stringpool_str3213[sizeof("omaezaki.shizuoka.jp")];
+ char stringpool_str3214[sizeof("agrar.hu")];
+ char stringpool_str3215[sizeof("bialowieza.pl")];
+ char stringpool_str3216[sizeof("gov.vn")];
+ char stringpool_str3217[sizeof("edu.vn")];
+ char stringpool_str3218[sizeof("homeunix.com")];
+ char stringpool_str3219[sizeof("com.vn")];
+ char stringpool_str3220[sizeof("nakasatsunai.hokkaido.jp")];
+ char stringpool_str3221[sizeof("xn--io0a7i.hk")];
+ char stringpool_str3222[sizeof("oxford.museum")];
+ char stringpool_str3223[sizeof("firm.nf")];
+ char stringpool_str3224[sizeof("aerodrome.aero")];
+ char stringpool_str3225[sizeof("from-ar.com")];
+ char stringpool_str3226[sizeof("gov.cu")];
+ char stringpool_str3227[sizeof("edu.cu")];
+ char stringpool_str3228[sizeof("is-a-socialist.com")];
+ char stringpool_str3229[sizeof("cremona.it")];
+ char stringpool_str3230[sizeof("com.cu")];
+ char stringpool_str3231[sizeof("rygge.no")];
+ char stringpool_str3232[sizeof("kofu.yamanashi.jp")];
+ char stringpool_str3233[sizeof("kunigami.okinawa.jp")];
+ char stringpool_str3234[sizeof("folkebibl.no")];
+ char stringpool_str3235[sizeof("xn--rennesy-v1a.no")];
+ char stringpool_str3236[sizeof("from-ak.com")];
+ char stringpool_str3237[sizeof("kagoshima.kagoshima.jp")];
+ char stringpool_str3238[sizeof("motorcycle.museum")];
+ char stringpool_str3239[sizeof("is-a-doctor.com")];
+ char stringpool_str3240[sizeof("net.sy")];
+ char stringpool_str3241[sizeof("from-wa.com")];
+ char stringpool_str3242[sizeof("xn--bmlo-gra.no")];
+ char stringpool_str3243[sizeof("coop.km")];
+ char stringpool_str3244[sizeof("bo.telemark.no")];
+ char stringpool_str3245[sizeof("fukui.fukui.jp")];
+ char stringpool_str3246[sizeof("net.ly")];
+ char stringpool_str3247[sizeof("homeunix.net")];
+ char stringpool_str3248[sizeof("int.vn")];
+ char stringpool_str3249[sizeof("from-wi.com")];
+ char stringpool_str3250[sizeof("net.uy")];
+ char stringpool_str3251[sizeof("radom.pl")];
+ char stringpool_str3252[sizeof("from-wy.com")];
+ char stringpool_str3253[sizeof("from-il.com")];
+ char stringpool_str3254[sizeof("from-ia.com")];
+ char stringpool_str3255[sizeof("sunagawa.hokkaido.jp")];
+ char stringpool_str3256[sizeof("inf.cu")];
+ char stringpool_str3257[sizeof("kh.ua")];
+ char stringpool_str3258[sizeof("nakaniikawa.toyama.jp")];
+ char stringpool_str3259[sizeof("rissa.no")];
+ char stringpool_str3260[sizeof("dni.us")];
+ char stringpool_str3261[sizeof("xn--rde-ula.no")];
+ char stringpool_str3262[sizeof("otsuki.yamanashi.jp")];
+ char stringpool_str3263[sizeof("shikokuchuo.ehime.jp")];
+ char stringpool_str3264[sizeof("xn--hobl-ira.no")];
+ char stringpool_str3265[sizeof("control.aero")];
+ char stringpool_str3266[sizeof("osakasayama.osaka.jp")];
+ char stringpool_str3267[sizeof("kasuga.hyogo.jp")];
+ char stringpool_str3268[sizeof("ivgu.no")];
+ char stringpool_str3269[sizeof("gob.hn")];
+ char stringpool_str3270[sizeof("edu.hn")];
+ char stringpool_str3271[sizeof("insurance.aero")];
+ char stringpool_str3272[sizeof("com.hn")];
+ char stringpool_str3273[sizeof("getmyip.com")];
+ char stringpool_str3274[sizeof("dance")];
+ char stringpool_str3275[sizeof("kaita.hiroshima.jp")];
+ char stringpool_str3276[sizeof("donetsk.ua")];
+ char stringpool_str3277[sizeof("onomichi.hiroshima.jp")];
+ char stringpool_str3278[sizeof("xn--sandy-yua.no")];
+ char stringpool_str3279[sizeof("dnsalias.com")];
+ char stringpool_str3280[sizeof("grozny.ru")];
+ char stringpool_str3281[sizeof("itoigawa.niigata.jp")];
+ char stringpool_str3282[sizeof("from-in.com")];
+ char stringpool_str3283[sizeof("beiarn.no")];
+ char stringpool_str3284[sizeof("seoul.kr")];
+ char stringpool_str3285[sizeof("xn--msy-ula0h.no")];
+ char stringpool_str3286[sizeof("xn--4gbrim")];
+ char stringpool_str3287[sizeof("batsfjord.no")];
+ char stringpool_str3288[sizeof("dnsalias.net")];
+ char stringpool_str3289[sizeof("xn--lcvr32d.hk")];
+ char stringpool_str3290[sizeof("radoy.no")];
+ char stringpool_str3291[sizeof("yonago.tottori.jp")];
+ char stringpool_str3292[sizeof("artgallery.museum")];
+ char stringpool_str3293[sizeof("in-the-band.net")];
+ char stringpool_str3294[sizeof("yoshikawa.saitama.jp")];
+ char stringpool_str3295[sizeof("historisches.museum")];
+ char stringpool_str3296[sizeof("from-wv.com")];
+ char stringpool_str3297[sizeof("rauma.no")];
+ char stringpool_str3298[sizeof("from-fl.com")];
+ char stringpool_str3299[sizeof("xn--od0alg.hk")];
+ char stringpool_str3300[sizeof("from-ms.com")];
+ char stringpool_str3301[sizeof("ninomiya.kanagawa.jp")];
+ char stringpool_str3302[sizeof("cooking")];
+ char stringpool_str3303[sizeof("xn--ngbc5azd")];
+ char stringpool_str3304[sizeof("is-a-democrat.com")];
+ char stringpool_str3305[sizeof("dk")];
+ char stringpool_str3306[sizeof("webhop.biz")];
+ char stringpool_str3307[sizeof("from-ks.com")];
+ char stringpool_str3308[sizeof("dynalias.com")];
+ char stringpool_str3309[sizeof("gov.kn")];
+ char stringpool_str3310[sizeof("edu.kn")];
+ char stringpool_str3311[sizeof("net.my")];
+ char stringpool_str3312[sizeof("volyn.ua")];
+ char stringpool_str3313[sizeof("halden.no")];
+ char stringpool_str3314[sizeof("salzburg.museum")];
+ char stringpool_str3315[sizeof("xn--vard-jra.no")];
+ char stringpool_str3316[sizeof("kurogi.fukuoka.jp")];
+ char stringpool_str3317[sizeof("xn--lrenskog-54a.no")];
+ char stringpool_str3318[sizeof("xn--mjndalen-64a.no")];
+ char stringpool_str3319[sizeof("elvendrell.museum")];
+ char stringpool_str3320[sizeof("histoire.museum")];
+ char stringpool_str3321[sizeof("mil.in")];
+ char stringpool_str3322[sizeof("ambulance.aero")];
+ char stringpool_str3323[sizeof("org.mx")];
+ char stringpool_str3324[sizeof("frosinone.it")];
+ char stringpool_str3325[sizeof("sopot.pl")];
+ char stringpool_str3326[sizeof("sasayama.hyogo.jp")];
+ char stringpool_str3327[sizeof("dynalias.net")];
+ char stringpool_str3328[sizeof("association.aero")];
+ char stringpool_str3329[sizeof("holdings")];
+ char stringpool_str3330[sizeof("otofuke.hokkaido.jp")];
+ char stringpool_str3331[sizeof("belluno.it")];
+ char stringpool_str3332[sizeof("act.au")];
+ char stringpool_str3333[sizeof("co.je")];
+ char stringpool_str3334[sizeof("is-a-rockstar.com")];
+ char stringpool_str3335[sizeof("biz.vn")];
+ char stringpool_str3336[sizeof("yokaichiba.chiba.jp")];
+ char stringpool_str3337[sizeof("namegata.ibaraki.jp")];
+ char stringpool_str3338[sizeof("yasuoka.nagano.jp")];
+ char stringpool_str3339[sizeof("bahccavuotna.no")];
+ char stringpool_str3340[sizeof("net.py")];
+ char stringpool_str3341[sizeof("xn--lesund-hua.no")];
+ char stringpool_str3342[sizeof("iamallama.com")];
+ char stringpool_str3343[sizeof("nanmoku.gunma.jp")];
+ char stringpool_str3344[sizeof("dyndns.tv")];
+ char stringpool_str3345[sizeof("medecin.km")];
+ char stringpool_str3346[sizeof("xn--hery-ira.nordland.no")];
+ char stringpool_str3347[sizeof("magazine.aero")];
+ char stringpool_str3348[sizeof("nakanoto.ishikawa.jp")];
+ char stringpool_str3349[sizeof("drobak.no")];
+ char stringpool_str3350[sizeof("balsfjord.no")];
+ char stringpool_str3351[sizeof("messina.it")];
+ char stringpool_str3352[sizeof("gx.cn")];
+ char stringpool_str3353[sizeof("xn--od0aq3b.hk")];
+ char stringpool_str3354[sizeof("brussel.museum")];
+ char stringpool_str3355[sizeof("xn--rst-0na.no")];
+ char stringpool_str3356[sizeof("funagata.yamagata.jp")];
+ char stringpool_str3357[sizeof("frogans")];
+ char stringpool_str3358[sizeof("gemological.museum")];
+ char stringpool_str3359[sizeof("mjondalen.no")];
+ char stringpool_str3360[sizeof("oshino.yamanashi.jp")];
+ char stringpool_str3361[sizeof("here-for-more.info")];
+ char stringpool_str3362[sizeof("com.gy")];
+ char stringpool_str3363[sizeof("from-de.com")];
+ char stringpool_str3364[sizeof("maison")];
+ char stringpool_str3365[sizeof("iki.fi")];
+ char stringpool_str3366[sizeof("xn--mgb2ddes")];
+ char stringpool_str3367[sizeof("xn--80aswg")];
+ char stringpool_str3368[sizeof("artdeco.museum")];
+ char stringpool_str3369[sizeof("kasuga.fukuoka.jp")];
+ char stringpool_str3370[sizeof("francaise.museum")];
+ char stringpool_str3371[sizeof("gose.nara.jp")];
+ char stringpool_str3372[sizeof("xn--lury-ira.no")];
+ char stringpool_str3373[sizeof("international")];
+ char stringpool_str3374[sizeof("wa.edu.au")];
+ char stringpool_str3375[sizeof("from-oh.com")];
+ char stringpool_str3376[sizeof("yamaga.kumamoto.jp")];
+ char stringpool_str3377[sizeof("crotone.it")];
+ char stringpool_str3378[sizeof("is-a-anarchist.com")];
+ char stringpool_str3379[sizeof("siena.it")];
+ char stringpool_str3380[sizeof("defense.tn")];
+ char stringpool_str3381[sizeof("history.museum")];
+ char stringpool_str3382[sizeof("k12.co.us")];
+ char stringpool_str3383[sizeof("dielddanuorri.no")];
+ char stringpool_str3384[sizeof("xn--zf0avx.hk")];
+ char stringpool_str3385[sizeof("vt.us")];
+ char stringpool_str3386[sizeof("rikubetsu.hokkaido.jp")];
+ char stringpool_str3387[sizeof("stord.no")];
+ char stringpool_str3388[sizeof("org.gr")];
+ char stringpool_str3389[sizeof("eastcoast.museum")];
+ char stringpool_str3390[sizeof("shinshinotsu.hokkaido.jp")];
+ char stringpool_str3391[sizeof("midatlantic.museum")];
+ char stringpool_str3392[sizeof("obihiro.hokkaido.jp")];
+ char stringpool_str3393[sizeof("association.museum")];
+ char stringpool_str3394[sizeof("raisa.no")];
+ char stringpool_str3395[sizeof("store.ro")];
+ char stringpool_str3396[sizeof("go.jp")];
+ char stringpool_str3397[sizeof("kr.it")];
+ char stringpool_str3398[sizeof("ed.jp")];
+ char stringpool_str3399[sizeof("co.jp")];
+ char stringpool_str3400[sizeof("sogne.no")];
+ char stringpool_str3401[sizeof("org.gp")];
+ char stringpool_str3402[sizeof("fishing")];
+ char stringpool_str3403[sizeof("cloudcontrolapp.com")];
+ char stringpool_str3404[sizeof("org.ge")];
+ char stringpool_str3405[sizeof("shioya.tochigi.jp")];
+ char stringpool_str3406[sizeof("store.st")];
+ char stringpool_str3407[sizeof("gr.jp")];
+ char stringpool_str3408[sizeof("vi.us")];
+ char stringpool_str3409[sizeof("yoro.gifu.jp")];
+ char stringpool_str3410[sizeof("ando.nara.jp")];
+ char stringpool_str3411[sizeof("ad.jp")];
+ char stringpool_str3412[sizeof("countryestate.museum")];
+ char stringpool_str3413[sizeof("encyclopedic.museum")];
+ char stringpool_str3414[sizeof("yuki.ibaraki.jp")];
+ char stringpool_str3415[sizeof("nishi.osaka.jp")];
+ char stringpool_str3416[sizeof("hagi.yamaguchi.jp")];
+ char stringpool_str3417[sizeof("murmansk.ru")];
+ char stringpool_str3418[sizeof("chambagri.fr")];
+ char stringpool_str3419[sizeof("xn--vgan-qoa.no")];
+ char stringpool_str3420[sizeof("sorum.no")];
+ char stringpool_str3421[sizeof("oumu.hokkaido.jp")];
+ char stringpool_str3422[sizeof("giessen.museum")];
+ char stringpool_str3423[sizeof("xn--zf0ao64a.tw")];
+ char stringpool_str3424[sizeof("mil.hn")];
+ char stringpool_str3425[sizeof("boston.museum")];
+ char stringpool_str3426[sizeof("afjord.no")];
+ char stringpool_str3427[sizeof("vikna.no")];
+ char stringpool_str3428[sizeof("k12.ca.us")];
+ char stringpool_str3429[sizeof("xn--uc0ay4a.hk")];
+ char stringpool_str3430[sizeof("drammen.no")];
+ char stringpool_str3431[sizeof("net.ky")];
+ char stringpool_str3432[sizeof("valley.museum")];
+ char stringpool_str3433[sizeof("wielun.pl")];
+ char stringpool_str3434[sizeof("mallorca.museum")];
+ char stringpool_str3435[sizeof("xn--b-5ga.nordland.no")];
+ char stringpool_str3436[sizeof("amusement.aero")];
+ char stringpool_str3437[sizeof("xn--muost-0qa.no")];
+ char stringpool_str3438[sizeof("xn--karmy-yua.no")];
+ char stringpool_str3439[sizeof("xn--mgbab2bd")];
+ char stringpool_str3440[sizeof("ozu.kumamoto.jp")];
+ char stringpool_str3441[sizeof("xn--osyro-wua.no")];
+ char stringpool_str3442[sizeof("miki.hyogo.jp")];
+ char stringpool_str3443[sizeof("florida.museum")];
+ char stringpool_str3444[sizeof("birkenes.no")];
+ char stringpool_str3445[sizeof("awaji.hyogo.jp")];
+ char stringpool_str3446[sizeof("gloppen.no")];
+ char stringpool_str3447[sizeof("stryn.no")];
+ char stringpool_str3448[sizeof("moskenes.no")];
+ char stringpool_str3449[sizeof("komforb.se")];
+ char stringpool_str3450[sizeof("somna.no")];
+ char stringpool_str3451[sizeof("orkanger.no")];
+ char stringpool_str3452[sizeof("campobasso.it")];
+ char stringpool_str3453[sizeof("mx.na")];
+ char stringpool_str3454[sizeof("niimi.okayama.jp")];
+ char stringpool_str3455[sizeof("org.gi")];
+ char stringpool_str3456[sizeof("va.us")];
+ char stringpool_str3457[sizeof("handson.museum")];
+ char stringpool_str3458[sizeof("ino.kochi.jp")];
+ char stringpool_str3459[sizeof("hobby-site.com")];
+ char stringpool_str3460[sizeof("homeunix.org")];
+ char stringpool_str3461[sizeof("xn--mlatvuopmi-s4a.no")];
+ char stringpool_str3462[sizeof("hammarfeasta.no")];
+ char stringpool_str3463[sizeof("va.no")];
+ char stringpool_str3464[sizeof("saka.hiroshima.jp")];
+ char stringpool_str3465[sizeof("nakagawa.nagano.jp")];
+ char stringpool_str3466[sizeof("seljord.no")];
+ char stringpool_str3467[sizeof("gniezno.pl")];
+ char stringpool_str3468[sizeof("austin.museum")];
+ char stringpool_str3469[sizeof("dyndns.org")];
+ char stringpool_str3470[sizeof("vn.ua")];
+ char stringpool_str3471[sizeof("snasa.no")];
+ char stringpool_str3472[sizeof("eastafrica.museum")];
+ char stringpool_str3473[sizeof("bristol.museum")];
+ char stringpool_str3474[sizeof("berlin.museum")];
+ char stringpool_str3475[sizeof("balsan.it")];
+ char stringpool_str3476[sizeof("shiroishi.saga.jp")];
+ char stringpool_str3477[sizeof("modern.museum")];
+ char stringpool_str3478[sizeof("campidanomedio.it")];
+ char stringpool_str3479[sizeof("radio.br")];
+ char stringpool_str3480[sizeof("charter.aero")];
+ char stringpool_str3481[sizeof("botanical.museum")];
+ char stringpool_str3482[sizeof("ama.aichi.jp")];
+ char stringpool_str3483[sizeof("xn--vg-yiab.no")];
+ char stringpool_str3484[sizeof("sakuragawa.ibaraki.jp")];
+ char stringpool_str3485[sizeof("kitagata.gifu.jp")];
+ char stringpool_str3486[sizeof("shimokawa.hokkaido.jp")];
+ char stringpool_str3487[sizeof("kyowa.hokkaido.jp")];
+ char stringpool_str3488[sizeof("chiropractic.museum")];
+ char stringpool_str3489[sizeof("costume.museum")];
+ char stringpool_str3490[sizeof("nakagawa.hokkaido.jp")];
+ char stringpool_str3491[sizeof("carrier.museum")];
+ char stringpool_str3492[sizeof("shizuoka.shizuoka.jp")];
+ char stringpool_str3493[sizeof("frei.no")];
+ char stringpool_str3494[sizeof("asahi.nagano.jp")];
+ char stringpool_str3495[sizeof("dnsalias.org")];
+ char stringpool_str3496[sizeof("slask.pl")];
+ char stringpool_str3497[sizeof("bauern.museum")];
+ char stringpool_str3498[sizeof("desi")];
+ char stringpool_str3499[sizeof("clinton.museum")];
+ char stringpool_str3500[sizeof("gallery.museum")];
+ char stringpool_str3501[sizeof("nakagawa.tokushima.jp")];
+ char stringpool_str3502[sizeof("helsinki.museum")];
+ char stringpool_str3503[sizeof("futsu.nagasaki.jp")];
+ char stringpool_str3504[sizeof("shikama.miyagi.jp")];
+ char stringpool_str3505[sizeof("k12.fl.us")];
+ char stringpool_str3506[sizeof("dvrdns.org")];
+ char stringpool_str3507[sizeof("xn--uc0atv.hk")];
+ char stringpool_str3508[sizeof("hizen.saga.jp")];
+ char stringpool_str3509[sizeof("garden.museum")];
+ char stringpool_str3510[sizeof("smola.no")];
+ char stringpool_str3511[sizeof("is-leet.com")];
+ char stringpool_str3512[sizeof("xn--pgbs0dh")];
+ char stringpool_str3513[sizeof("badajoz.museum")];
+ char stringpool_str3514[sizeof("shonai.fukuoka.jp")];
+ char stringpool_str3515[sizeof("xn--mot-tla.no")];
+ char stringpool_str3516[sizeof("salat.no")];
+ char stringpool_str3517[sizeof("deatnu.no")];
+ char stringpool_str3518[sizeof("miasa.nagano.jp")];
+ char stringpool_str3519[sizeof("mobi.na")];
+ char stringpool_str3520[sizeof("inuyama.aichi.jp")];
+ char stringpool_str3521[sizeof("sauda.no")];
+ char stringpool_str3522[sizeof("divtasvuodna.no")];
+ char stringpool_str3523[sizeof("is-a-green.com")];
+ char stringpool_str3524[sizeof("dynalias.org")];
+ char stringpool_str3525[sizeof("oppegard.no")];
+ char stringpool_str3526[sizeof("corporation.museum")];
+ char stringpool_str3527[sizeof("selbu.no")];
+ char stringpool_str3528[sizeof("xn--6qq986b3xl")];
+ char stringpool_str3529[sizeof("seirou.niigata.jp")];
+ char stringpool_str3530[sizeof("mansion.museum")];
+ char stringpool_str3531[sizeof("cechire.com")];
+ char stringpool_str3532[sizeof("hattfjelldal.no")];
+ char stringpool_str3533[sizeof("from-ga.com")];
+ char stringpool_str3534[sizeof("from-mt.com")];
+ char stringpool_str3535[sizeof("imari.saga.jp")];
+ char stringpool_str3536[sizeof("from-ct.com")];
+ char stringpool_str3537[sizeof("isshiki.aichi.jp")];
+ char stringpool_str3538[sizeof("alabama.museum")];
+ char stringpool_str3539[sizeof("okinawa.okinawa.jp")];
+ char stringpool_str3540[sizeof("burghof.museum")];
+ char stringpool_str3541[sizeof("castres.museum")];
+ char stringpool_str3542[sizeof("shinagawa.tokyo.jp")];
+ char stringpool_str3543[sizeof("naklo.pl")];
+ char stringpool_str3544[sizeof("kamigori.hyogo.jp")];
+ char stringpool_str3545[sizeof("community.museum")];
+ char stringpool_str3546[sizeof("culture.museum")];
+ char stringpool_str3547[sizeof("ushuaia.museum")];
+ char stringpool_str3548[sizeof("astronomy.museum")];
+ char stringpool_str3549[sizeof("cincinnati.museum")];
+ char stringpool_str3550[sizeof("izumi.kagoshima.jp")];
+ char stringpool_str3551[sizeof("farmers.museum")];
+ char stringpool_str3552[sizeof("art.museum")];
+ char stringpool_str3553[sizeof("yonezawa.yamagata.jp")];
+ char stringpool_str3554[sizeof("xn--krager-gya.no")];
+ char stringpool_str3555[sizeof("nakama.fukuoka.jp")];
+ char stringpool_str3556[sizeof("skaun.no")];
+ char stringpool_str3557[sizeof("nanbu.yamanashi.jp")];
+ char stringpool_str3558[sizeof("annefrank.museum")];
+ char stringpool_str3559[sizeof("massa-carrara.it")];
+ char stringpool_str3560[sizeof("aarborte.no")];
+ char stringpool_str3561[sizeof("vc")];
+ char stringpool_str3562[sizeof("sanok.pl")];
+ char stringpool_str3563[sizeof("osakikamijima.hiroshima.jp")];
+ char stringpool_str3564[sizeof("xn--kfjord-iua.no")];
+ char stringpool_str3565[sizeof("okinoshima.shimane.jp")];
+ char stringpool_str3566[sizeof("oiso.kanagawa.jp")];
+ char stringpool_str3567[sizeof("xn--koluokta-7ya57h.no")];
+ char stringpool_str3568[sizeof("halloffame.museum")];
+ char stringpool_str3569[sizeof("gets-it.net")];
+ char stringpool_str3570[sizeof("gov.dz")];
+ char stringpool_str3571[sizeof("edu.dz")];
+ char stringpool_str3572[sizeof("ps")];
+ char stringpool_str3573[sizeof("com.dz")];
+ char stringpool_str3574[sizeof("pr")];
+ char stringpool_str3575[sizeof("chino.nagano.jp")];
+ char stringpool_str3576[sizeof("yasu.shiga.jp")];
+ char stringpool_str3577[sizeof("is-a-personaltrainer.com")];
+ char stringpool_str3578[sizeof("xn--1qqw23a")];
+ char stringpool_str3579[sizeof("mihama.mie.jp")];
+ char stringpool_str3580[sizeof("pl")];
+ char stringpool_str3581[sizeof("bus.museum")];
+ char stringpool_str3582[sizeof("kvam.no")];
+ char stringpool_str3583[sizeof("xn--vgsy-qoa0j.no")];
+ char stringpool_str3584[sizeof("xn--bievt-0qa.no")];
+ char stringpool_str3585[sizeof("mobi.ng")];
+ char stringpool_str3586[sizeof("post")];
+ char stringpool_str3587[sizeof("kurgan.ru")];
+ char stringpool_str3588[sizeof("art.dz")];
+ char stringpool_str3589[sizeof("kaufen")];
+ char stringpool_str3590[sizeof("pub")];
+ char stringpool_str3591[sizeof("hamburg.museum")];
+ char stringpool_str3592[sizeof("pro")];
+ char stringpool_str3593[sizeof("asahi.yamagata.jp")];
+ char stringpool_str3594[sizeof("com.uz")];
+ char stringpool_str3595[sizeof("historicalsociety.museum")];
+ char stringpool_str3596[sizeof("mazowsze.pl")];
+ char stringpool_str3597[sizeof("onga.fukuoka.jp")];
+ char stringpool_str3598[sizeof("pro.om")];
+ char stringpool_str3599[sizeof("p.bg")];
+ char stringpool_str3600[sizeof("pn")];
+ char stringpool_str3601[sizeof("p.se")];
+ char stringpool_str3602[sizeof("groks-the.info")];
+ char stringpool_str3603[sizeof("wildlife.museum")];
+ char stringpool_str3604[sizeof("pe")];
+ char stringpool_str3605[sizeof("nd.us")];
+ char stringpool_str3606[sizeof("western.museum")];
+ char stringpool_str3607[sizeof("air.museum")];
+ char stringpool_str3608[sizeof("ikeda.nagano.jp")];
+ char stringpool_str3609[sizeof("and.museum")];
+ char stringpool_str3610[sizeof("dlugoleka.pl")];
+ char stringpool_str3611[sizeof("arita.saga.jp")];
+ char stringpool_str3612[sizeof("durham.museum")];
+ char stringpool_str3613[sizeof("pt")];
+ char stringpool_str3614[sizeof("agano.niigata.jp")];
+ char stringpool_str3615[sizeof("yamada.fukuoka.jp")];
+ char stringpool_str3616[sizeof("horonobe.hokkaido.jp")];
+ char stringpool_str3617[sizeof("amli.no")];
+ char stringpool_str3618[sizeof("yamato.fukushima.jp")];
+ char stringpool_str3619[sizeof("nl.no")];
+ char stringpool_str3620[sizeof("communication.museum")];
+ char stringpool_str3621[sizeof("gov.bz")];
+ char stringpool_str3622[sizeof("edu.bz")];
+ char stringpool_str3623[sizeof("communications.museum")];
+ char stringpool_str3624[sizeof("com.bz")];
+ char stringpool_str3625[sizeof("xn--ystre-slidre-ujb.no")];
+ char stringpool_str3626[sizeof("pro.ec")];
+ char stringpool_str3627[sizeof("xn--mgbaam7a8h")];
+ char stringpool_str3628[sizeof("anan.nagano.jp")];
+ char stringpool_str3629[sizeof("pub.sa")];
+ char stringpool_str3630[sizeof("ne.tz")];
+ char stringpool_str3631[sizeof("xn--wgbh1c")];
+ char stringpool_str3632[sizeof("missile.museum")];
+ char stringpool_str3633[sizeof("ne.us")];
+ char stringpool_str3634[sizeof("ulm.museum")];
+ char stringpool_str3635[sizeof("no.com")];
+ char stringpool_str3636[sizeof("unzen.nagasaki.jp")];
+ char stringpool_str3637[sizeof("homebuilt.aero")];
+ char stringpool_str3638[sizeof("funabashi.chiba.jp")];
+ char stringpool_str3639[sizeof("pro.br")];
+ char stringpool_str3640[sizeof("k12.tn.us")];
+ char stringpool_str3641[sizeof("botanicalgarden.museum")];
+ char stringpool_str3642[sizeof("yasugi.shimane.jp")];
+ char stringpool_str3643[sizeof("dallas.museum")];
+ char stringpool_str3644[sizeof("sklep.pl")];
+ char stringpool_str3645[sizeof("py")];
+ char stringpool_str3646[sizeof("for-the.biz")];
+ char stringpool_str3647[sizeof("nt.no")];
+ char stringpool_str3648[sizeof("nt.ro")];
+ char stringpool_str3649[sizeof("per.la")];
+ char stringpool_str3650[sizeof("nt.au")];
+ char stringpool_str3651[sizeof("marburg.museum")];
+ char stringpool_str3652[sizeof("pro.na")];
+ char stringpool_str3653[sizeof("usa.museum")];
+ char stringpool_str3654[sizeof("iida.nagano.jp")];
+ char stringpool_str3655[sizeof("presse.ml")];
+ char stringpool_str3656[sizeof("xn--hcesuolo-7ya35b.no")];
+ char stringpool_str3657[sizeof("rovno.ua")];
+ char stringpool_str3658[sizeof("xn--uc0atv.tw")];
+ char stringpool_str3659[sizeof("matsuno.ehime.jp")];
+ char stringpool_str3660[sizeof("chirurgiens-dentistes.fr")];
+ char stringpool_str3661[sizeof("pm")];
+ char stringpool_str3662[sizeof("kustanai.ru")];
+ char stringpool_str3663[sizeof("can.museum")];
+ char stringpool_str3664[sizeof("prof.pr")];
+ char stringpool_str3665[sizeof("k12.in.us")];
+ char stringpool_str3666[sizeof("groks-this.info")];
+ char stringpool_str3667[sizeof("casadelamoneda.museum")];
+ char stringpool_str3668[sizeof("amami.kagoshima.jp")];
+ char stringpool_str3669[sizeof("sport.hu")];
+ char stringpool_str3670[sizeof("xn--wcvs22d.hk")];
+ char stringpool_str3671[sizeof("skien.no")];
+ char stringpool_str3672[sizeof("xn--trna-woa.no")];
+ char stringpool_str3673[sizeof("dell-ogliastra.it")];
+ char stringpool_str3674[sizeof("ny.us")];
+ char stringpool_str3675[sizeof("hara.nagano.jp")];
+ char stringpool_str3676[sizeof("xn--bearalvhki-y4a.no")];
+ char stringpool_str3677[sizeof("presse.ci")];
+ char stringpool_str3678[sizeof("ureshino.mie.jp")];
+ char stringpool_str3679[sizeof("city.nagoya.jp")];
+ char stringpool_str3680[sizeof("onjuku.chiba.jp")];
+ char stringpool_str3681[sizeof("satsumasendai.kagoshima.jp")];
+ char stringpool_str3682[sizeof("hioki.kagoshima.jp")];
+ char stringpool_str3683[sizeof("shiga.jp")];
+ char stringpool_str3684[sizeof("pa")];
+ char stringpool_str3685[sizeof("nj.us")];
+ char stringpool_str3686[sizeof("xn--drbak-wua.no")];
+ char stringpool_str3687[sizeof("ritto.shiga.jp")];
+ char stringpool_str3688[sizeof("gov.az")];
+ char stringpool_str3689[sizeof("edu.az")];
+ char stringpool_str3690[sizeof("kicks-ass.net")];
+ char stringpool_str3691[sizeof("com.az")];
+ char stringpool_str3692[sizeof("nm.us")];
+ char stringpool_str3693[sizeof("parts")];
+ char stringpool_str3694[sizeof("british.museum")];
+ char stringpool_str3695[sizeof("xn--kprw13d")];
+ char stringpool_str3696[sizeof("appspot.com")];
+ char stringpool_str3697[sizeof("k12.mn.us")];
+ char stringpool_str3698[sizeof("shiroishi.miyagi.jp")];
+ char stringpool_str3699[sizeof("xn--wgbl6a")];
+ char stringpool_str3700[sizeof("boutique")];
+ char stringpool_str3701[sizeof("ne.kr")];
+ char stringpool_str3702[sizeof("urbinopesaro.it")];
+ char stringpool_str3703[sizeof("global.prod.fastly.net")];
+ char stringpool_str3704[sizeof("heritage.museum")];
+ char stringpool_str3705[sizeof("nakayama.yamagata.jp")];
+ char stringpool_str3706[sizeof("ueda.nagano.jp")];
+ char stringpool_str3707[sizeof("pink")];
+ char stringpool_str3708[sizeof("dudinka.ru")];
+ char stringpool_str3709[sizeof("wloclawek.pl")];
+ char stringpool_str3710[sizeof("int.az")];
+ char stringpool_str3711[sizeof("kamisunagawa.hokkaido.jp")];
+ char stringpool_str3712[sizeof("arteducation.museum")];
+ char stringpool_str3713[sizeof("pro.pr")];
+ char stringpool_str3714[sizeof("nanbu.tottori.jp")];
+ char stringpool_str3715[sizeof("presse.km")];
+ char stringpool_str3716[sizeof("yamagata.jp")];
+ char stringpool_str3717[sizeof("nishi.fukuoka.jp")];
+ char stringpool_str3718[sizeof("plo.ps")];
+ char stringpool_str3719[sizeof("higashiagatsuma.gunma.jp")];
+ char stringpool_str3720[sizeof("pila.pl")];
+ char stringpool_str3721[sizeof("hakui.ishikawa.jp")];
+ char stringpool_str3722[sizeof("nanto.toyama.jp")];
+ char stringpool_str3723[sizeof("nanae.hokkaido.jp")];
+ char stringpool_str3724[sizeof("to")];
+ char stringpool_str3725[sizeof("td")];
+ char stringpool_str3726[sizeof("port.fr")];
+ char stringpool_str3727[sizeof("tz")];
+ char stringpool_str3728[sizeof("kiho.mie.jp")];
+ char stringpool_str3729[sizeof("goto.nagasaki.jp")];
+ char stringpool_str3730[sizeof("rishirifuji.hokkaido.jp")];
+ char stringpool_str3731[sizeof("tr")];
+ char stringpool_str3732[sizeof("nv.us")];
+ char stringpool_str3733[sizeof("tl")];
+ char stringpool_str3734[sizeof("rivne.ua")];
+ char stringpool_str3735[sizeof("cosenza.it")];
+ char stringpool_str3736[sizeof("nm.cn")];
+ char stringpool_str3737[sizeof("yamal.ru")];
+ char stringpool_str3738[sizeof("geology.museum")];
+ char stringpool_str3739[sizeof("tools")];
+ char stringpool_str3740[sizeof("mad.museum")];
+ char stringpool_str3741[sizeof("matsumae.hokkaido.jp")];
+ char stringpool_str3742[sizeof("ns.ca")];
+ char stringpool_str3743[sizeof("t.bg")];
+ char stringpool_str3744[sizeof("blogsite.org")];
+ char stringpool_str3745[sizeof("tn")];
+ char stringpool_str3746[sizeof("psc.br")];
+ char stringpool_str3747[sizeof("t.se")];
+ char stringpool_str3748[sizeof("oga.akita.jp")];
+ char stringpool_str3749[sizeof("ph")];
+ char stringpool_str3750[sizeof("pics")];
+ char stringpool_str3751[sizeof("shichikashuku.miyagi.jp")];
+ char stringpool_str3752[sizeof("aki.kochi.jp")];
+ char stringpool_str3753[sizeof("nl.ca")];
+ char stringpool_str3754[sizeof("sango.nara.jp")];
+ char stringpool_str3755[sizeof("zoology.museum")];
+ char stringpool_str3756[sizeof("pri.ee")];
+ char stringpool_str3757[sizeof("nu.ca")];
+ char stringpool_str3758[sizeof("psi.br")];
+ char stringpool_str3759[sizeof("komono.mie.jp")];
+ char stringpool_str3760[sizeof("per.nf")];
+ char stringpool_str3761[sizeof("sejny.pl")];
+ char stringpool_str3762[sizeof("tt")];
+ char stringpool_str3763[sizeof("xn--srum-gra.no")];
+ char stringpool_str3764[sizeof("akune.kagoshima.jp")];
+ char stringpool_str3765[sizeof("photo")];
+ char stringpool_str3766[sizeof("photos")];
+ char stringpool_str3767[sizeof("seika.kyoto.jp")];
+ char stringpool_str3768[sizeof("manno.kagawa.jp")];
+ char stringpool_str3769[sizeof("otoineppu.hokkaido.jp")];
+ char stringpool_str3770[sizeof("xn--80adxhks")];
+ char stringpool_str3771[sizeof("interactive.museum")];
+ char stringpool_str3772[sizeof("tromso.no")];
+ char stringpool_str3773[sizeof("kumano.mie.jp")];
+ char stringpool_str3774[sizeof("vs.it")];
+ char stringpool_str3775[sizeof("partners")];
+ char stringpool_str3776[sizeof("vr.it")];
+ char stringpool_str3777[sizeof("org.gg")];
+ char stringpool_str3778[sizeof("nt.ca")];
+ char stringpool_str3779[sizeof("nh.us")];
+ char stringpool_str3780[sizeof("go.ug")];
+ char stringpool_str3781[sizeof("shimabara.nagasaki.jp")];
+ char stringpool_str3782[sizeof("ppg.br")];
+ char stringpool_str3783[sizeof("xn--vler-qoa.hedmark.no")];
+ char stringpool_str3784[sizeof("co.ug")];
+ char stringpool_str3785[sizeof("co.ag")];
+ char stringpool_str3786[sizeof("tips")];
+ char stringpool_str3787[sizeof("yaotsu.gifu.jp")];
+ char stringpool_str3788[sizeof("hirono.iwate.jp")];
+ char stringpool_str3789[sizeof("ibaraki.ibaraki.jp")];
+ char stringpool_str3790[sizeof("chizu.tottori.jp")];
+ char stringpool_str3791[sizeof("kirkenes.no")];
+ char stringpool_str3792[sizeof("nango.fukushima.jp")];
+ char stringpool_str3793[sizeof("nb.ca")];
+ char stringpool_str3794[sizeof("tur.br")];
+ char stringpool_str3795[sizeof("xn--rholt-mra.no")];
+ char stringpool_str3796[sizeof("kisosaki.mie.jp")];
+ char stringpool_str3797[sizeof("mil.tz")];
+ char stringpool_str3798[sizeof("bokn.no")];
+ char stringpool_str3799[sizeof("co.gg")];
+ char stringpool_str3800[sizeof("california.museum")];
+ char stringpool_str3801[sizeof("ve.it")];
+ char stringpool_str3802[sizeof("pk")];
+ char stringpool_str3803[sizeof("gov.kz")];
+ char stringpool_str3804[sizeof("edu.kz")];
+ char stringpool_str3805[sizeof("com.kz")];
+ char stringpool_str3806[sizeof("sandoy.no")];
+ char stringpool_str3807[sizeof("vt.it")];
+ char stringpool_str3808[sizeof("xn--mgbayh7gpa")];
+ char stringpool_str3809[sizeof("tromsa.no")];
+ char stringpool_str3810[sizeof("nishikawa.yamagata.jp")];
+ char stringpool_str3811[sizeof("tj")];
+ char stringpool_str3812[sizeof("kommune.no")];
+ char stringpool_str3813[sizeof("biz.az")];
+ char stringpool_str3814[sizeof("tm")];
+ char stringpool_str3815[sizeof("trd.br")];
+ char stringpool_str3816[sizeof("coldwar.museum")];
+ char stringpool_str3817[sizeof("vb.it")];
+ char stringpool_str3818[sizeof("teo.br")];
+ char stringpool_str3819[sizeof("automotive.museum")];
+ char stringpool_str3820[sizeof("troandin.no")];
+ char stringpool_str3821[sizeof("vi.it")];
+ char stringpool_str3822[sizeof("herokuapp.com")];
+ char stringpool_str3823[sizeof("tel")];
+ char stringpool_str3824[sizeof("eiheiji.fukui.jp")];
+ char stringpool_str3825[sizeof("yuzawa.niigata.jp")];
+ char stringpool_str3826[sizeof("khmelnitskiy.ua")];
+ char stringpool_str3827[sizeof("today")];
+ char stringpool_str3828[sizeof("tienda")];
+ char stringpool_str3829[sizeof("pistoia.it")];
+ char stringpool_str3830[sizeof("catanzaro.it")];
+ char stringpool_str3831[sizeof("elb.amazonaws.com")];
+ char stringpool_str3832[sizeof("imizu.toyama.jp")];
+ char stringpool_str3833[sizeof("tattoo")];
+ char stringpool_str3834[sizeof("prd.km")];
+ char stringpool_str3835[sizeof("ayase.kanagawa.jp")];
+ char stringpool_str3836[sizeof("kakogawa.hyogo.jp")];
+ char stringpool_str3837[sizeof("herokussl.com")];
+ char stringpool_str3838[sizeof("sakura.tochigi.jp")];
+ char stringpool_str3839[sizeof("palana.ru")];
+ char stringpool_str3840[sizeof("notogawa.shiga.jp")];
+ char stringpool_str3841[sizeof("xn--vhquv")];
+ char stringpool_str3842[sizeof("gateway.museum")];
+ char stringpool_str3843[sizeof("sveio.no")];
+ char stringpool_str3844[sizeof("equipment.aero")];
+ char stringpool_str3845[sizeof("iwakura.aichi.jp")];
+ char stringpool_str3846[sizeof("voss.no")];
+ char stringpool_str3847[sizeof("ookuwa.nagano.jp")];
+ char stringpool_str3848[sizeof("tur.ar")];
+ char stringpool_str3849[sizeof("nc")];
+ char stringpool_str3850[sizeof("from-hi.com")];
+ char stringpool_str3851[sizeof("tv")];
+ char stringpool_str3852[sizeof("gov.cx")];
+ char stringpool_str3853[sizeof("nom.co")];
+ char stringpool_str3854[sizeof("act.edu.au")];
+ char stringpool_str3855[sizeof("tmp.br")];
+ char stringpool_str3856[sizeof("tysnes.no")];
+ char stringpool_str3857[sizeof("mil.az")];
+ char stringpool_str3858[sizeof("birdart.museum")];
+ char stringpool_str3859[sizeof("shirahama.wakayama.jp")];
+ char stringpool_str3860[sizeof("is-a-musician.com")];
+ char stringpool_str3861[sizeof("rl.no")];
+ char stringpool_str3862[sizeof("fineart.museum")];
+ char stringpool_str3863[sizeof("yabuki.fukushima.jp")];
+ char stringpool_str3864[sizeof("va.it")];
+ char stringpool_str3865[sizeof("ryuoh.shiga.jp")];
+ char stringpool_str3866[sizeof("pescara.it")];
+ char stringpool_str3867[sizeof("dyndns.ws")];
+ char stringpool_str3868[sizeof("tozsde.hu")];
+ char stringpool_str3869[sizeof("net.co")];
+ char stringpool_str3870[sizeof("ohkura.yamagata.jp")];
+ char stringpool_str3871[sizeof("trader.aero")];
+ char stringpool_str3872[sizeof("mine.nu")];
+ char stringpool_str3873[sizeof("rebun.hokkaido.jp")];
+ char stringpool_str3874[sizeof("war.museum")];
+ char stringpool_str3875[sizeof("ro.com")];
+ char stringpool_str3876[sizeof("palermo.it")];
+ char stringpool_str3877[sizeof("portland.museum")];
+ char stringpool_str3878[sizeof("karpacz.pl")];
+ char stringpool_str3879[sizeof("vv.it")];
+ char stringpool_str3880[sizeof("th")];
+ char stringpool_str3881[sizeof("tottori.jp")];
+ char stringpool_str3882[sizeof("vega.no")];
+ char stringpool_str3883[sizeof("mulhouse.museum")];
+ char stringpool_str3884[sizeof("washingtondc.museum")];
+ char stringpool_str3885[sizeof("ru.com")];
+ char stringpool_str3886[sizeof("chonan.chiba.jp")];
+ char stringpool_str3887[sizeof("suita.osaka.jp")];
+ char stringpool_str3888[sizeof("samukawa.kanagawa.jp")];
+ char stringpool_str3889[sizeof("ath.cx")];
+ char stringpool_str3890[sizeof("ri.us")];
+ char stringpool_str3891[sizeof("safety.aero")];
+ char stringpool_str3892[sizeof("trento.it")];
+ char stringpool_str3893[sizeof("ooshika.nagano.jp")];
+ char stringpool_str3894[sizeof("medio-campidano.it")];
+ char stringpool_str3895[sizeof("plumbing")];
+ char stringpool_str3896[sizeof("maritime.museum")];
+ char stringpool_str3897[sizeof("hannan.osaka.jp")];
+ char stringpool_str3898[sizeof("from-ut.com")];
+ char stringpool_str3899[sizeof("kchr.ru")];
+ char stringpool_str3900[sizeof("khmelnytskyi.ua")];
+ char stringpool_str3901[sizeof("xn--mk0axi.hk")];
+ char stringpool_str3902[sizeof("seiyo.ehime.jp")];
+ char stringpool_str3903[sizeof("wada.nagano.jp")];
+ char stringpool_str3904[sizeof("indian.museum")];
+ char stringpool_str3905[sizeof("net.cw")];
+ char stringpool_str3906[sizeof("miura.kanagawa.jp")];
+ char stringpool_str3907[sizeof("andriatranibarletta.it")];
+ char stringpool_str3908[sizeof("xn--klbu-woa.no")];
+ char stringpool_str3909[sizeof("yamamoto.miyagi.jp")];
+ char stringpool_str3910[sizeof("tk")];
+ char stringpool_str3911[sizeof("shima.mie.jp")];
+ char stringpool_str3912[sizeof("chihayaakasaka.osaka.jp")];
+ char stringpool_str3913[sizeof("net.ci")];
+ char stringpool_str3914[sizeof("re.kr")];
+ char stringpool_str3915[sizeof("ogi.saga.jp")];
+ char stringpool_str3916[sizeof("zushi.kanagawa.jp")];
+ char stringpool_str3917[sizeof("workinggroup.aero")];
+ char stringpool_str3918[sizeof("firenze.it")];
+ char stringpool_str3919[sizeof("watchandclock.museum")];
+ char stringpool_str3920[sizeof("vang.no")];
+ char stringpool_str3921[sizeof("kameyama.mie.jp")];
+ char stringpool_str3922[sizeof("valer.ostfold.no")];
+ char stringpool_str3923[sizeof("xn--hpmir-xqa.no")];
+ char stringpool_str3924[sizeof("satte.saitama.jp")];
+ char stringpool_str3925[sizeof("teramo.it")];
+ char stringpool_str3926[sizeof("pomorskie.pl")];
+ char stringpool_str3927[sizeof("muenchen.museum")];
+ char stringpool_str3928[sizeof("tysfjord.no")];
+ char stringpool_str3929[sizeof("yugawa.fukushima.jp")];
+ char stringpool_str3930[sizeof("vaga.no")];
+ char stringpool_str3931[sizeof("mil.kz")];
+ char stringpool_str3932[sizeof("public.museum")];
+ char stringpool_str3933[sizeof("nf")];
+ char stringpool_str3934[sizeof("plants.museum")];
+ char stringpool_str3935[sizeof("homelinux.net")];
+ char stringpool_str3936[sizeof("nom.fr")];
+ char stringpool_str3937[sizeof("tra.kp")];
+ char stringpool_str3938[sizeof("verran.no")];
+ char stringpool_str3939[sizeof("tonsberg.no")];
+ char stringpool_str3940[sizeof("xn--vrggt-xqad.no")];
+ char stringpool_str3941[sizeof("pw")];
+ char stringpool_str3942[sizeof("yamagata.nagano.jp")];
+ char stringpool_str3943[sizeof("dating")];
+ char stringpool_str3944[sizeof("tourism.tn")];
+ char stringpool_str3945[sizeof("ichiba.tokushima.jp")];
+ char stringpool_str3946[sizeof("homelinux.com")];
+ char stringpool_str3947[sizeof("pasadena.museum")];
+ char stringpool_str3948[sizeof("hatsukaichi.hiroshima.jp")];
+ char stringpool_str3949[sizeof("divttasvuotna.no")];
+ char stringpool_str3950[sizeof("ebina.kanagawa.jp")];
+ char stringpool_str3951[sizeof("padova.it")];
+ char stringpool_str3952[sizeof("dellogliastra.it")];
+ char stringpool_str3953[sizeof("presidio.museum")];
+ char stringpool_str3954[sizeof("kinko.kagoshima.jp")];
+ char stringpool_str3955[sizeof("sanda.hyogo.jp")];
+ char stringpool_str3956[sizeof("saiki.oita.jp")];
+ char stringpool_str3957[sizeof("xn--leagaviika-52b.no")];
+ char stringpool_str3958[sizeof("zakopane.pl")];
+ char stringpool_str3959[sizeof("tingvoll.no")];
+ char stringpool_str3960[sizeof("kiso.nagano.jp")];
+ char stringpool_str3961[sizeof("portal.museum")];
+ char stringpool_str3962[sizeof("nanao.ishikawa.jp")];
+ char stringpool_str3963[sizeof("topology.museum")];
+ char stringpool_str3964[sizeof("per.sg")];
+ char stringpool_str3965[sizeof("veterinaire.fr")];
+ char stringpool_str3966[sizeof("publ.pt")];
+ char stringpool_str3967[sizeof("isa-geek.com")];
+ char stringpool_str3968[sizeof("xn--j6w193g")];
+ char stringpool_str3969[sizeof("xn--brum-voa.no")];
+ char stringpool_str3970[sizeof("sakahogi.gifu.jp")];
+ char stringpool_str3971[sizeof("environmentalconservation.museum")];
+ char stringpool_str3972[sizeof("akiruno.tokyo.jp")];
+ char stringpool_str3973[sizeof("chesapeakebay.museum")];
+ char stringpool_str3974[sizeof("surrey.museum")];
+ char stringpool_str3975[sizeof("isa-geek.net")];
+ char stringpool_str3976[sizeof("no.it")];
+ char stringpool_str3977[sizeof("higashikagawa.kagawa.jp")];
+ char stringpool_str3978[sizeof("indianapolis.museum")];
+ char stringpool_str3979[sizeof("ora.gunma.jp")];
+ char stringpool_str3980[sizeof("otsu.shiga.jp")];
+ char stringpool_str3981[sizeof("pilots.museum")];
+ char stringpool_str3982[sizeof("ptz.ru")];
+ char stringpool_str3983[sizeof("polkowice.pl")];
+ char stringpool_str3984[sizeof("nu.it")];
+ char stringpool_str3985[sizeof("yahiko.niigata.jp")];
+ char stringpool_str3986[sizeof("dinosaur.museum")];
+ char stringpool_str3987[sizeof("bo.nordland.no")];
+ char stringpool_str3988[sizeof("starostwo.gov.pl")];
+ char stringpool_str3989[sizeof("okuizumo.shimane.jp")];
+ char stringpool_str3990[sizeof("indianmarket.museum")];
+ char stringpool_str3991[sizeof("portlligat.museum")];
+ char stringpool_str3992[sizeof("rs.ba")];
+ char stringpool_str3993[sizeof("aguni.okinawa.jp")];
+ char stringpool_str3994[sizeof("org.gh")];
+ char stringpool_str3995[sizeof("express.aero")];
+ char stringpool_str3996[sizeof("shiso.hyogo.jp")];
+ char stringpool_str3997[sizeof("rv.ua")];
+ char stringpool_str3998[sizeof("seiro.niigata.jp")];
+ char stringpool_str3999[sizeof("preservation.museum")];
+ char stringpool_str4000[sizeof("ota.gunma.jp")];
+ char stringpool_str4001[sizeof("ichihara.chiba.jp")];
+ char stringpool_str4002[sizeof("minamiashigara.kanagawa.jp")];
+ char stringpool_str4003[sizeof("umi.fukuoka.jp")];
+ char stringpool_str4004[sizeof("xn--ses554g")];
+ char stringpool_str4005[sizeof("itayanagi.aomori.jp")];
+ char stringpool_str4006[sizeof("nt.edu.au")];
+ char stringpool_str4007[sizeof("xn--6frz82g")];
+ char stringpool_str4008[sizeof("sabae.fukui.jp")];
+ char stringpool_str4009[sizeof("soeda.fukuoka.jp")];
+ char stringpool_str4010[sizeof("ternopil.ua")];
+ char stringpool_str4011[sizeof("hamatonbetsu.hokkaido.jp")];
+ char stringpool_str4012[sizeof("prd.mg")];
+ char stringpool_str4013[sizeof("xn--3ds443g")];
+ char stringpool_str4014[sizeof("productions")];
+ char stringpool_str4015[sizeof("tom.ru")];
+ char stringpool_str4016[sizeof("tarnobrzeg.pl")];
+ char stringpool_str4017[sizeof("trentino.it")];
+ char stringpool_str4018[sizeof("ichikawa.chiba.jp")];
+ char stringpool_str4019[sizeof("sd.us")];
+ char stringpool_str4020[sizeof("onagawa.miyagi.jp")];
+ char stringpool_str4021[sizeof("bergbau.museum")];
+ char stringpool_str4022[sizeof("kitakyushu.jp")];
+ char stringpool_str4023[sizeof("sagamihara.kanagawa.jp")];
+ char stringpool_str4024[sizeof("chicago.museum")];
+ char stringpool_str4025[sizeof("pisa.it")];
+ char stringpool_str4026[sizeof("ham-radio-op.net")];
+ char stringpool_str4027[sizeof("sydney.museum")];
+ char stringpool_str4028[sizeof("asaminami.hiroshima.jp")];
+ char stringpool_str4029[sizeof("panama.museum")];
+ char stringpool_str4030[sizeof("kumakogen.ehime.jp")];
+ char stringpool_str4031[sizeof("ichinomiya.chiba.jp")];
+ char stringpool_str4032[sizeof("tw")];
+ char stringpool_str4033[sizeof("yamagata.ibaraki.jp")];
+ char stringpool_str4034[sizeof("koebenhavn.museum")];
+ char stringpool_str4035[sizeof("vibovalentia.it")];
+ char stringpool_str4036[sizeof("virtuel.museum")];
+ char stringpool_str4037[sizeof("selje.no")];
+ char stringpool_str4038[sizeof("hachinohe.aomori.jp")];
+ char stringpool_str4039[sizeof("skjak.no")];
+ char stringpool_str4040[sizeof("na.it")];
+ char stringpool_str4041[sizeof("paderborn.museum")];
+ char stringpool_str4042[sizeof("venice.it")];
+ char stringpool_str4043[sizeof("tourism.pl")];
+ char stringpool_str4044[sizeof("oguchi.aichi.jp")];
+ char stringpool_str4045[sizeof("virtual.museum")];
+ char stringpool_str4046[sizeof("xn--krehamn-dxa.no")];
+ char stringpool_str4047[sizeof("net.tn")];
+ char stringpool_str4048[sizeof("st.no")];
+ char stringpool_str4049[sizeof("xn--lrdal-sra.no")];
+ char stringpool_str4050[sizeof("happou.akita.jp")];
+ char stringpool_str4051[sizeof("xn--ygbi2ammx")];
+ char stringpool_str4052[sizeof("sd.cn")];
+ char stringpool_str4053[sizeof("torsken.no")];
+ char stringpool_str4054[sizeof("kyonan.chiba.jp")];
+ char stringpool_str4055[sizeof("tosu.saga.jp")];
+ char stringpool_str4056[sizeof("xn--bod-2na.no")];
+ char stringpool_str4057[sizeof("pyatigorsk.ru")];
+ char stringpool_str4058[sizeof("se.com")];
+ char stringpool_str4059[sizeof("net.in")];
+ char stringpool_str4060[sizeof("coop.ht")];
+ char stringpool_str4061[sizeof("yabu.hyogo.jp")];
+ char stringpool_str4062[sizeof("sn.cn")];
+ char stringpool_str4063[sizeof("production.aero")];
+ char stringpool_str4064[sizeof("daejeon.kr")];
+ char stringpool_str4065[sizeof("seki.gifu.jp")];
+ char stringpool_str4066[sizeof("xn--rady-ira.no")];
+ char stringpool_str4067[sizeof("virginia.museum")];
+ char stringpool_str4068[sizeof("namie.fukushima.jp")];
+ char stringpool_str4069[sizeof("medizinhistorisches.museum")];
+ char stringpool_str4070[sizeof("tsu.mie.jp")];
+ char stringpool_str4071[sizeof("saito.miyazaki.jp")];
+ char stringpool_str4072[sizeof("transport.museum")];
+ char stringpool_str4073[sizeof("name.na")];
+ char stringpool_str4074[sizeof("vegarshei.no")];
+ char stringpool_str4075[sizeof("ag.it")];
+ char stringpool_str4076[sizeof("xn--xhq521b")];
+ char stringpool_str4077[sizeof("bg.it")];
+ char stringpool_str4078[sizeof("tsukumi.oita.jp")];
+ char stringpool_str4079[sizeof("fg.it")];
+ char stringpool_str4080[sizeof("kg.kr")];
+ char stringpool_str4081[sizeof("pvt.k12.ma.us")];
+ char stringpool_str4082[sizeof("net.an")];
+ char stringpool_str4083[sizeof("sa.au")];
+ char stringpool_str4084[sizeof("nat.tn")];
+ char stringpool_str4085[sizeof("rec.co")];
+ char stringpool_str4086[sizeof("tottori.tottori.jp")];
+ char stringpool_str4087[sizeof("shiki.saitama.jp")];
+ char stringpool_str4088[sizeof("kyotango.kyoto.jp")];
+ char stringpool_str4089[sizeof("sor-odal.no")];
+ char stringpool_str4090[sizeof("is-a-guru.com")];
+ char stringpool_str4091[sizeof("verbania.it")];
+ char stringpool_str4092[sizeof("net.pn")];
+ char stringpool_str4093[sizeof("xn--s-1fa.no")];
+ char stringpool_str4094[sizeof("k12.az.us")];
+ char stringpool_str4095[sizeof("xn--l-1fa.no")];
+ char stringpool_str4096[sizeof("toda.saitama.jp")];
+ char stringpool_str4097[sizeof("net.vn")];
+ char stringpool_str4098[sizeof("sa.com")];
+ char stringpool_str4099[sizeof("kashima.ibaraki.jp")];
+ char stringpool_str4100[sizeof("net.cu")];
+ char stringpool_str4101[sizeof("sa.cr")];
+ char stringpool_str4102[sizeof("xn--krjohka-hwab49j.no")];
+ char stringpool_str4103[sizeof("xn--vestvgy-ixa6o.no")];
+ char stringpool_str4104[sizeof("sb.ua")];
+ char stringpool_str4105[sizeof("tara.saga.jp")];
+ char stringpool_str4106[sizeof("podhale.pl")];
+ char stringpool_str4107[sizeof("opole.pl")];
+ char stringpool_str4108[sizeof("gov.gn")];
+ char stringpool_str4109[sizeof("edu.gn")];
+ char stringpool_str4110[sizeof("xn--nry-yla5g.no")];
+ char stringpool_str4111[sizeof("com.gn")];
+ char stringpool_str4112[sizeof("bedzin.pl")];
+ char stringpool_str4113[sizeof("torino.it")];
+ char stringpool_str4114[sizeof("kamoenai.hokkaido.jp")];
+ char stringpool_str4115[sizeof("xn--sr-fron-q1a.no")];
+ char stringpool_str4116[sizeof("shibukawa.gunma.jp")];
+ char stringpool_str4117[sizeof("kunohe.iwate.jp")];
+ char stringpool_str4118[sizeof("ro.it")];
+ char stringpool_str4119[sizeof("isa-geek.org")];
+ char stringpool_str4120[sizeof("name.ng")];
+ char stringpool_str4121[sizeof("vision")];
+ char stringpool_str4122[sizeof("net.hn")];
+ char stringpool_str4123[sizeof("orsta.no")];
+ char stringpool_str4124[sizeof("morimachi.shizuoka.jp")];
+ char stringpool_str4125[sizeof("ogasawara.tokyo.jp")];
+ char stringpool_str4126[sizeof("sm.ua")];
+ char stringpool_str4127[sizeof("higashiura.aichi.jp")];
+ char stringpool_str4128[sizeof("sakyo.kyoto.jp")];
+ char stringpool_str4129[sizeof("uchihara.ibaraki.jp")];
+ char stringpool_str4130[sizeof("rn.it")];
+ char stringpool_str4131[sizeof("yamanouchi.nagano.jp")];
+ char stringpool_str4132[sizeof("asakawa.fukushima.jp")];
+ char stringpool_str4133[sizeof("tome.miyagi.jp")];
+ char stringpool_str4134[sizeof("re.it")];
+ char stringpool_str4135[sizeof("nic.in")];
+ char stringpool_str4136[sizeof("isahaya.nagasaki.jp")];
+ char stringpool_str4137[sizeof("tas.au")];
+ char stringpool_str4138[sizeof("perm.ru")];
+ char stringpool_str4139[sizeof("us-east-1.amazonaws.com")];
+ char stringpool_str4140[sizeof("xn--gls-elac.no")];
+ char stringpool_str4141[sizeof("oishida.yamagata.jp")];
+ char stringpool_str4142[sizeof("sh.cn")];
+ char stringpool_str4143[sizeof("kartuzy.pl")];
+ char stringpool_str4144[sizeof("palmsprings.museum")];
+ char stringpool_str4145[sizeof("ri.it")];
+ char stringpool_str4146[sizeof("osaka.jp")];
+ char stringpool_str4147[sizeof("teledata.mz")];
+ char stringpool_str4148[sizeof("chikujo.fukuoka.jp")];
+ char stringpool_str4149[sizeof("tosa.kochi.jp")];
+ char stringpool_str4150[sizeof("net.kn")];
+ char stringpool_str4151[sizeof("tonami.toyama.jp")];
+ char stringpool_str4152[sizeof("plantation.museum")];
+ char stringpool_str4153[sizeof("togane.chiba.jp")];
+ char stringpool_str4154[sizeof("mishima.fukushima.jp")];
+ char stringpool_str4155[sizeof("shari.hokkaido.jp")];
+ char stringpool_str4156[sizeof("from-sd.com")];
+ char stringpool_str4157[sizeof("pruszkow.pl")];
+ char stringpool_str4158[sizeof("tenkawa.nara.jp")];
+ char stringpool_str4159[sizeof("from-md.com")];
+ char stringpool_str4160[sizeof("sc")];
+ char stringpool_str4161[sizeof("aizubange.fukushima.jp")];
+ char stringpool_str4162[sizeof("nyc.mn")];
+ char stringpool_str4163[sizeof("nx.cn")];
+ char stringpool_str4164[sizeof("rost.no")];
+ char stringpool_str4165[sizeof("shizukuishi.iwate.jp")];
+ char stringpool_str4166[sizeof("dnsdojo.org")];
+ char stringpool_str4167[sizeof("rm.it")];
+ char stringpool_str4168[sizeof("xn--rskog-uua.no")];
+ char stringpool_str4169[sizeof("tadaoka.osaka.jp")];
+ char stringpool_str4170[sizeof("act.gov.au")];
+ char stringpool_str4171[sizeof("xn--vry-yla5g.no")];
+ char stringpool_str4172[sizeof("yugawara.kanagawa.jp")];
+ char stringpool_str4173[sizeof("xn--bjddar-pta.no")];
+ char stringpool_str4174[sizeof("xn--lhppi-xqa.no")];
+ char stringpool_str4175[sizeof("roan.no")];
+ char stringpool_str4176[sizeof("tomari.hokkaido.jp")];
+ char stringpool_str4177[sizeof("togura.nagano.jp")];
+ char stringpool_str4178[sizeof("sch.lk")];
+ char stringpool_str4179[sizeof("togo.aichi.jp")];
+ char stringpool_str4180[sizeof("ra.it")];
+ char stringpool_str4181[sizeof("rotorcraft.aero")];
+ char stringpool_str4182[sizeof("television.museum")];
+ char stringpool_str4183[sizeof("sch.uk")];
+ char stringpool_str4184[sizeof("rnu.tn")];
+ char stringpool_str4185[sizeof("norfolk.museum")];
+ char stringpool_str4186[sizeof("bolzano.it")];
+ char stringpool_str4187[sizeof("net.gy")];
+ char stringpool_str4188[sizeof("itoman.okinawa.jp")];
+ char stringpool_str4189[sizeof("xn--bdddj-mrabd.no")];
+ char stringpool_str4190[sizeof("is-a-soxfan.org")];
+ char stringpool_str4191[sizeof("imakane.hokkaido.jp")];
+ char stringpool_str4192[sizeof("xn--h-2fa.no")];
+ char stringpool_str4193[sizeof("rns.tn")];
+ char stringpool_str4194[sizeof("sch.sa")];
+ char stringpool_str4195[sizeof("showa.gunma.jp")];
+ char stringpool_str4196[sizeof("namdalseid.no")];
+ char stringpool_str4197[sizeof("from-id.com")];
+ char stringpool_str4198[sizeof("date.hokkaido.jp")];
+ char stringpool_str4199[sizeof("tone.ibaraki.jp")];
+ char stringpool_str4200[sizeof("sch.ir")];
+ char stringpool_str4201[sizeof("modelling.aero")];
+ char stringpool_str4202[sizeof("trani-andria-barletta.it")];
+ char stringpool_str4203[sizeof("res.in")];
+ char stringpool_str4204[sizeof("yuasa.wakayama.jp")];
+ char stringpool_str4205[sizeof("sch.qa")];
+ char stringpool_str4206[sizeof("tahara.aichi.jp")];
+ char stringpool_str4207[sizeof("hokuryu.hokkaido.jp")];
+ char stringpool_str4208[sizeof("knowsitall.info")];
+ char stringpool_str4209[sizeof("tananger.no")];
+ char stringpool_str4210[sizeof("kasukabe.saitama.jp")];
+ char stringpool_str4211[sizeof("is-a-hard-worker.com")];
+ char stringpool_str4212[sizeof("training")];
+ char stringpool_str4213[sizeof("sch.jo")];
+ char stringpool_str4214[sizeof("homedns.org")];
+ char stringpool_str4215[sizeof("tanabe.kyoto.jp")];
+ char stringpool_str4216[sizeof("tuva.ru")];
+ char stringpool_str4217[sizeof("ne.jp")];
+ char stringpool_str4218[sizeof("coastaldefence.museum")];
+ char stringpool_str4219[sizeof("sch.id")];
+ char stringpool_str4220[sizeof("photography")];
+ char stringpool_str4221[sizeof("rana.no")];
+ char stringpool_str4222[sizeof("bologna.it")];
+ char stringpool_str4223[sizeof("sk.ca")];
+ char stringpool_str4224[sizeof("kainan.tokushima.jp")];
+ char stringpool_str4225[sizeof("xn--bjarky-fya.no")];
+ char stringpool_str4226[sizeof("yoita.niigata.jp")];
+ char stringpool_str4227[sizeof("torino.museum")];
+ char stringpool_str4228[sizeof("sekikawa.niigata.jp")];
+ char stringpool_str4229[sizeof("tvedestrand.no")];
+ char stringpool_str4230[sizeof("nara.nara.jp")];
+ char stringpool_str4231[sizeof("xn--9dbhblg6di.museum")];
+ char stringpool_str4232[sizeof("test.ru")];
+ char stringpool_str4233[sizeof("hikari.yamaguchi.jp")];
+ char stringpool_str4234[sizeof("management")];
+ char stringpool_str4235[sizeof("xn--vads-jra.no")];
+ char stringpool_str4236[sizeof("volkenkunde.museum")];
+ char stringpool_str4237[sizeof("dyndns.info")];
+ char stringpool_str4238[sizeof("tatarstan.ru")];
+ char stringpool_str4239[sizeof("ohtawara.tochigi.jp")];
+ char stringpool_str4240[sizeof("tomobe.ibaraki.jp")];
+ char stringpool_str4241[sizeof("tokyo")];
+ char stringpool_str4242[sizeof("alesund.no")];
+ char stringpool_str4243[sizeof("embroidery.museum")];
+ char stringpool_str4244[sizeof("xn--gmq050i.hk")];
+ char stringpool_str4245[sizeof("blogdns.org")];
+ char stringpool_str4246[sizeof("sch.ae")];
+ char stringpool_str4247[sizeof("rade.no")];
+ char stringpool_str4248[sizeof("chungnam.kr")];
+ char stringpool_str4249[sizeof("is-a-blogger.com")];
+ char stringpool_str4250[sizeof("store.nf")];
+ char stringpool_str4251[sizeof("noda.iwate.jp")];
+ char stringpool_str4252[sizeof("odate.akita.jp")];
+ char stringpool_str4253[sizeof("showa.yamanashi.jp")];
+ char stringpool_str4254[sizeof("yokawa.hyogo.jp")];
+ char stringpool_str4255[sizeof("school.na")];
+ char stringpool_str4256[sizeof("yakage.okayama.jp")];
+ char stringpool_str4257[sizeof("research.aero")];
+ char stringpool_str4258[sizeof("matsuzaki.shizuoka.jp")];
+ char stringpool_str4259[sizeof("fetsund.no")];
+ char stringpool_str4260[sizeof("yalta.ua")];
+ char stringpool_str4261[sizeof("yn.cn")];
+ char stringpool_str4262[sizeof("tula.ru")];
+ char stringpool_str4263[sizeof("sakai.osaka.jp")];
+ char stringpool_str4264[sizeof("emergency.aero")];
+ char stringpool_str4265[sizeof("walbrzych.pl")];
+ char stringpool_str4266[sizeof("samegawa.fukushima.jp")];
+ char stringpool_str4267[sizeof("higashitsuno.kochi.jp")];
+ char stringpool_str4268[sizeof("toshima.tokyo.jp")];
+ char stringpool_str4269[sizeof("brumunddal.no")];
+ char stringpool_str4270[sizeof("ogliastra.it")];
+ char stringpool_str4271[sizeof("xn--rsta-fra.no")];
+ char stringpool_str4272[sizeof("yonaguni.okinawa.jp")];
+ char stringpool_str4273[sizeof("ringsaker.no")];
+ char stringpool_str4274[sizeof("xn--givuotna-8ya.no")];
+ char stringpool_str4275[sizeof("tsuyama.okayama.jp")];
+ char stringpool_str4276[sizeof("so.it")];
+ char stringpool_str4277[sizeof("tagajo.miyagi.jp")];
+ char stringpool_str4278[sizeof("ss.it")];
+ char stringpool_str4279[sizeof("sr.it")];
+ char stringpool_str4280[sizeof("przeworsk.pl")];
+ char stringpool_str4281[sizeof("hekinan.aichi.jp")];
+ char stringpool_str4282[sizeof("forsand.no")];
+ char stringpool_str4283[sizeof("hornindal.no")];
+ char stringpool_str4284[sizeof("hitachiota.ibaraki.jp")];
+ char stringpool_str4285[sizeof("traeumtgerade.de")];
+ char stringpool_str4286[sizeof("oyodo.nara.jp")];
+ char stringpool_str4287[sizeof("shingu.wakayama.jp")];
+ char stringpool_str4288[sizeof("org.sy")];
+ char stringpool_str4289[sizeof("xn--mxtq1m.hk")];
+ char stringpool_str4290[sizeof("nabari.mie.jp")];
+ char stringpool_str4291[sizeof("tver.ru")];
+ char stringpool_str4292[sizeof("kunitachi.tokyo.jp")];
+ char stringpool_str4293[sizeof("aurland.no")];
+ char stringpool_str4294[sizeof("org.ly")];
+ char stringpool_str4295[sizeof("sor-varanger.no")];
+ char stringpool_str4296[sizeof("farsund.no")];
+ char stringpool_str4297[sizeof("ravenna.it")];
+ char stringpool_str4298[sizeof("org.uy")];
+ char stringpool_str4299[sizeof("inazawa.aichi.jp")];
+ char stringpool_str4300[sizeof("tochigi.jp")];
+ char stringpool_str4301[sizeof("froland.no")];
+ char stringpool_str4302[sizeof("trani-barletta-andria.it")];
+ char stringpool_str4303[sizeof("dgca.aero")];
+ char stringpool_str4304[sizeof("kalisz.pl")];
+ char stringpool_str4305[sizeof("nanyo.yamagata.jp")];
+ char stringpool_str4306[sizeof("si.it")];
+ char stringpool_str4307[sizeof("shiogama.miyagi.jp")];
+ char stringpool_str4308[sizeof("midsund.no")];
+ char stringpool_str4309[sizeof("dali.museum")];
+ char stringpool_str4310[sizeof("tateyama.toyama.jp")];
+ char stringpool_str4311[sizeof("yorii.saitama.jp")];
+ char stringpool_str4312[sizeof("nedre-eiker.no")];
+ char stringpool_str4313[sizeof("hitachinaka.ibaraki.jp")];
+ char stringpool_str4314[sizeof("uchinomi.kagawa.jp")];
+ char stringpool_str4315[sizeof("kamimine.saga.jp")];
+ char stringpool_str4316[sizeof("aizuwakamatsu.fukushima.jp")];
+ char stringpool_str4317[sizeof("kuji.iwate.jp")];
+ char stringpool_str4318[sizeof("research.museum")];
+ char stringpool_str4319[sizeof("georgia.museum")];
+ char stringpool_str4320[sizeof("nakagawa.fukuoka.jp")];
+ char stringpool_str4321[sizeof("selfip.biz")];
+ char stringpool_str4322[sizeof("olawa.pl")];
+ char stringpool_str4323[sizeof("nagai.yamagata.jp")];
+ char stringpool_str4324[sizeof("naamesjevuemie.no")];
+ char stringpool_str4325[sizeof("gs.tr.no")];
+ char stringpool_str4326[sizeof("gs.ol.no")];
+ char stringpool_str4327[sizeof("gs.mr.no")];
+ char stringpool_str4328[sizeof("taxi.br")];
+ char stringpool_str4329[sizeof("niiza.saitama.jp")];
+ char stringpool_str4330[sizeof("sund.no")];
+ char stringpool_str4331[sizeof("gs.nl.no")];
+ char stringpool_str4332[sizeof("gs.rl.no")];
+ char stringpool_str4333[sizeof("nanjo.okinawa.jp")];
+ char stringpool_str4334[sizeof("tsushima.aichi.jp")];
+ char stringpool_str4335[sizeof("jo")];
+ char stringpool_str4336[sizeof("jobs")];
+ char stringpool_str4337[sizeof("org.my")];
+ char stringpool_str4338[sizeof("saijo.ehime.jp")];
+ char stringpool_str4339[sizeof("sa.it")];
+ char stringpool_str4340[sizeof("gs.st.no")];
+ char stringpool_str4341[sizeof("gov.st")];
+ char stringpool_str4342[sizeof("net.dz")];
+ char stringpool_str4343[sizeof("edu.st")];
+ char stringpool_str4344[sizeof("gouv.rw")];
+ char stringpool_str4345[sizeof("com.st")];
+ char stringpool_str4346[sizeof("gouv.ml")];
+ char stringpool_str4347[sizeof("vicenza.it")];
+ char stringpool_str4348[sizeof("gov.lt")];
+ char stringpool_str4349[sizeof("xn--mgba3a4fra")];
+ char stringpool_str4350[sizeof("sp.it")];
+ char stringpool_str4351[sizeof("gs.nt.no")];
+ char stringpool_str4352[sizeof("yamakita.kanagawa.jp")];
+ char stringpool_str4353[sizeof("net.uz")];
+ char stringpool_str4354[sizeof("gouv.ci")];
+ char stringpool_str4355[sizeof("j.bg")];
+ char stringpool_str4356[sizeof("bygland.no")];
+ char stringpool_str4357[sizeof("scotland.museum")];
+ char stringpool_str4358[sizeof("stat.no")];
+ char stringpool_str4359[sizeof("ichikawamisato.yamanashi.jp")];
+ char stringpool_str4360[sizeof("xn--mgba3a4f16a")];
+ char stringpool_str4361[sizeof("sa.edu.au")];
+ char stringpool_str4362[sizeof("sv.it")];
+ char stringpool_str4363[sizeof("je")];
+ char stringpool_str4364[sizeof("slupsk.pl")];
+ char stringpool_str4365[sizeof("date.fukushima.jp")];
+ char stringpool_str4366[sizeof("repbody.aero")];
+ char stringpool_str4367[sizeof("tohnosho.chiba.jp")];
+ char stringpool_str4368[sizeof("kamijima.ehime.jp")];
+ char stringpool_str4369[sizeof("sola.no")];
+ char stringpool_str4370[sizeof("gov.tt")];
+ char stringpool_str4371[sizeof("info.tz")];
+ char stringpool_str4372[sizeof("edu.tt")];
+ char stringpool_str4373[sizeof("org.py")];
+ char stringpool_str4374[sizeof("aoki.nagano.jp")];
+ char stringpool_str4375[sizeof("com.tt")];
+ char stringpool_str4376[sizeof("iveland.no")];
+ char stringpool_str4377[sizeof("xn--55qw42g")];
+ char stringpool_str4378[sizeof("gouv.sn")];
+ char stringpool_str4379[sizeof("pesarourbino.it")];
+ char stringpool_str4380[sizeof("hobby-site.org")];
+ char stringpool_str4381[sizeof("tateyama.chiba.jp")];
+ char stringpool_str4382[sizeof("gov.bt")];
+ char stringpool_str4383[sizeof("jor.br")];
+ char stringpool_str4384[sizeof("telekommunikation.museum")];
+ char stringpool_str4385[sizeof("edu.bt")];
+ char stringpool_str4386[sizeof("sula.no")];
+ char stringpool_str4387[sizeof("com.bt")];
+ char stringpool_str4388[sizeof("shibuya.tokyo.jp")];
+ char stringpool_str4389[sizeof("jet.uk")];
+ char stringpool_str4390[sizeof("net.bz")];
+ char stringpool_str4391[sizeof("tjeldsund.no")];
+ char stringpool_str4392[sizeof("school.museum")];
+ char stringpool_str4393[sizeof("gov.it")];
+ char stringpool_str4394[sizeof("idrett.no")];
+ char stringpool_str4395[sizeof("edu.it")];
+ char stringpool_str4396[sizeof("gs.tm.no")];
+ char stringpool_str4397[sizeof("int.tt")];
+ char stringpool_str4398[sizeof("higashichichibu.saitama.jp")];
+ char stringpool_str4399[sizeof("pisz.pl")];
+ char stringpool_str4400[sizeof("intl.tn")];
+ char stringpool_str4401[sizeof("nisshin.aichi.jp")];
+ char stringpool_str4402[sizeof("info.tn")];
+ char stringpool_str4403[sizeof("ulan-ude.ru")];
+ char stringpool_str4404[sizeof("shimosuwa.nagano.jp")];
+ char stringpool_str4405[sizeof("tree.museum")];
+ char stringpool_str4406[sizeof("azumino.nagano.jp")];
+ char stringpool_str4407[sizeof("jus.br")];
+ char stringpool_str4408[sizeof("gs.aa.no")];
+ char stringpool_str4409[sizeof("sanjo.niigata.jp")];
+ char stringpool_str4410[sizeof("xn--mgba3a4fra.ir")];
+ char stringpool_str4411[sizeof("jm")];
+ char stringpool_str4412[sizeof("photography.museum")];
+ char stringpool_str4413[sizeof("edu.mt")];
+ char stringpool_str4414[sizeof("com.mt")];
+ char stringpool_str4415[sizeof("xn--mgba3a4f16a.ir")];
+ char stringpool_str4416[sizeof("gs.fm.no")];
+ char stringpool_str4417[sizeof("storfjord.no")];
+ char stringpool_str4418[sizeof("chikugo.fukuoka.jp")];
+ char stringpool_str4419[sizeof("hitachiomiya.ibaraki.jp")];
+ char stringpool_str4420[sizeof("edunet.tn")];
+ char stringpool_str4421[sizeof("tamano.okayama.jp")];
+ char stringpool_str4422[sizeof("reggiocalabria.it")];
+ char stringpool_str4423[sizeof("gouv.bj")];
+ char stringpool_str4424[sizeof("songdalen.no")];
+ char stringpool_str4425[sizeof("gs.bu.no")];
+ char stringpool_str4426[sizeof("gs.hl.no")];
+ char stringpool_str4427[sizeof("misugi.mie.jp")];
+ char stringpool_str4428[sizeof("philadelphia.museum")];
+ char stringpool_str4429[sizeof("net.az")];
+ char stringpool_str4430[sizeof("higashi.fukuoka.jp")];
+ char stringpool_str4431[sizeof("abu.yamaguchi.jp")];
+ char stringpool_str4432[sizeof("yanagawa.fukuoka.jp")];
+ char stringpool_str4433[sizeof("time.museum")];
+ char stringpool_str4434[sizeof("toei.aichi.jp")];
+ char stringpool_str4435[sizeof("jp")];
+ char stringpool_str4436[sizeof("nichinan.tottori.jp")];
+ char stringpool_str4437[sizeof("reggio-calabria.it")];
+ char stringpool_str4438[sizeof("game.tw")];
+ char stringpool_str4439[sizeof("gov.pt")];
+ char stringpool_str4440[sizeof("edu.pt")];
+ char stringpool_str4441[sizeof("com.pt")];
+ char stringpool_str4442[sizeof("utazu.kagawa.jp")];
+ char stringpool_str4443[sizeof("gouv.km")];
+ char stringpool_str4444[sizeof("nyc.museum")];
+ char stringpool_str4445[sizeof("sells-for-u.com")];
+ char stringpool_str4446[sizeof("club.tw")];
+ char stringpool_str4447[sizeof("omihachiman.shiga.jp")];
+ char stringpool_str4448[sizeof("org.ky")];
+ char stringpool_str4449[sizeof("gjerstad.no")];
+ char stringpool_str4450[sizeof("yoka.hyogo.jp")];
+ char stringpool_str4451[sizeof("jur.pro")];
+ char stringpool_str4452[sizeof("yuza.yamagata.jp")];
+ char stringpool_str4453[sizeof("int.pt")];
+ char stringpool_str4454[sizeof("reggio-emilia.it")];
+ char stringpool_str4455[sizeof("gs.ah.no")];
+ char stringpool_str4456[sizeof("yk.ca")];
+ char stringpool_str4457[sizeof("mosvik.no")];
+ char stringpool_str4458[sizeof("jondal.no")];
+ char stringpool_str4459[sizeof("gouv.fr")];
+ char stringpool_str4460[sizeof("pg")];
+ char stringpool_str4461[sizeof("sch.ng")];
+ char stringpool_str4462[sizeof("skedsmokorset.no")];
+ char stringpool_str4463[sizeof("flakstad.no")];
+ char stringpool_str4464[sizeof("biz.tt")];
+ char stringpool_str4465[sizeof("shop.pl")];
+ char stringpool_str4466[sizeof("yaese.okinawa.jp")];
+ char stringpool_str4467[sizeof("baghdad.museum")];
+ char stringpool_str4468[sizeof("gjovik.no")];
+ char stringpool_str4469[sizeof("udmurtia.ru")];
+ char stringpool_str4470[sizeof("hakodate.hokkaido.jp")];
+ char stringpool_str4471[sizeof("tsk.ru")];
+ char stringpool_str4472[sizeof("edu.ht")];
+ char stringpool_str4473[sizeof("com.ht")];
+ char stringpool_str4474[sizeof("taxi.aero")];
+ char stringpool_str4475[sizeof("taishi.osaka.jp")];
+ char stringpool_str4476[sizeof("grimstad.no")];
+ char stringpool_str4477[sizeof("sakai.fukui.jp")];
+ char stringpool_str4478[sizeof("realestate.pl")];
+ char stringpool_str4479[sizeof("gs.hm.no")];
+ char stringpool_str4480[sizeof("gamvik.no")];
+ char stringpool_str4481[sizeof("showa.fukushima.jp")];
+ char stringpool_str4482[sizeof("mil.st")];
+ char stringpool_str4483[sizeof("art.ht")];
+ char stringpool_str4484[sizeof("usenet.pl")];
+ char stringpool_str4485[sizeof("sasaguri.fukuoka.jp")];
+ char stringpool_str4486[sizeof("sor-aurdal.no")];
+ char stringpool_str4487[sizeof("ube.yamaguchi.jp")];
+ char stringpool_str4488[sizeof("hasvik.no")];
+ char stringpool_str4489[sizeof("tomiya.miyagi.jp")];
+ char stringpool_str4490[sizeof("toride.ibaraki.jp")];
+ char stringpool_str4491[sizeof("presse.fr")];
+ char stringpool_str4492[sizeof("ne.ug")];
+ char stringpool_str4493[sizeof("village.museum")];
+ char stringpool_str4494[sizeof("muosat.no")];
+ char stringpool_str4495[sizeof("higashi.fukushima.jp")];
+ char stringpool_str4496[sizeof("settlement.museum")];
+ char stringpool_str4497[sizeof("industries")];
+ char stringpool_str4498[sizeof("otaki.saitama.jp")];
+ char stringpool_str4499[sizeof("tondabayashi.osaka.jp")];
+ char stringpool_str4500[sizeof("nantan.kyoto.jp")];
+ char stringpool_str4501[sizeof("nagato.yamaguchi.jp")];
+ char stringpool_str4502[sizeof("net.kz")];
+ char stringpool_str4503[sizeof("sx.cn")];
+ char stringpool_str4504[sizeof("sapporo.jp")];
+ char stringpool_str4505[sizeof("biz.at")];
+ char stringpool_str4506[sizeof("shika.ishikawa.jp")];
+ char stringpool_str4507[sizeof("syzran.ru")];
+ char stringpool_str4508[sizeof("tabayama.yamanashi.jp")];
+ char stringpool_str4509[sizeof("oskol.ru")];
+ char stringpool_str4510[sizeof("educator.aero")];
+ char stringpool_str4511[sizeof("tank.museum")];
+ char stringpool_str4512[sizeof("tas.edu.au")];
+ char stringpool_str4513[sizeof("odesa.ua")];
+ char stringpool_str4514[sizeof("smolensk.ru")];
+ char stringpool_str4515[sizeof("kolobrzeg.pl")];
+ char stringpool_str4516[sizeof("national.museum")];
+ char stringpool_str4517[sizeof("hashima.gifu.jp")];
+ char stringpool_str4518[sizeof("caserta.it")];
+ char stringpool_str4519[sizeof("supplies")];
+ char stringpool_str4520[sizeof("journalist.aero")];
+ char stringpool_str4521[sizeof("tsumagoi.gunma.jp")];
+ char stringpool_str4522[sizeof("salerno.it")];
+ char stringpool_str4523[sizeof("univ.sn")];
+ char stringpool_str4524[sizeof("jessheim.no")];
+ char stringpool_str4525[sizeof("sciences.museum")];
+ char stringpool_str4526[sizeof("sci.eg")];
+ char stringpool_str4527[sizeof("buryatia.ru")];
+ char stringpool_str4528[sizeof("xn--davvenjrga-y4a.no")];
+ char stringpool_str4529[sizeof("tamamura.gunma.jp")];
+ char stringpool_str4530[sizeof("scrapper-site.net")];
+ char stringpool_str4531[sizeof("tsubame.niigata.jp")];
+ char stringpool_str4532[sizeof("shingu.hyogo.jp")];
+ char stringpool_str4533[sizeof("mashiko.tochigi.jp")];
+ char stringpool_str4534[sizeof("med.ht")];
+ char stringpool_str4535[sizeof("education")];
+ char stringpool_str4536[sizeof("pvt.ge")];
+ char stringpool_str4537[sizeof("ibigawa.gifu.jp")];
+ char stringpool_str4538[sizeof("tg")];
+ char stringpool_str4539[sizeof("hichiso.gifu.jp")];
+ char stringpool_str4540[sizeof("tamayu.shimane.jp")];
+ char stringpool_str4541[sizeof("malvik.no")];
+ char stringpool_str4542[sizeof("nakagusuku.okinawa.jp")];
+ char stringpool_str4543[sizeof("balestrand.no")];
+ char stringpool_str4544[sizeof("utsunomiya.tochigi.jp")];
+ char stringpool_str4545[sizeof("jolster.no")];
+ char stringpool_str4546[sizeof("taku.saga.jp")];
+ char stringpool_str4547[sizeof("trondheim.no")];
+ char stringpool_str4548[sizeof("wakkanai.hokkaido.jp")];
+ char stringpool_str4549[sizeof("xn--gjvik-wua.no")];
+ char stringpool_str4550[sizeof("station.museum")];
+ char stringpool_str4551[sizeof("chukotka.ru")];
+ char stringpool_str4552[sizeof("jevnaker.no")];
+ char stringpool_str4553[sizeof("or.tz")];
+ char stringpool_str4554[sizeof("simple-url.com")];
+ char stringpool_str4555[sizeof("yokosuka.kanagawa.jp")];
+ char stringpool_str4556[sizeof("or.us")];
+ char stringpool_str4557[sizeof("ninohe.iwate.jp")];
+ char stringpool_str4558[sizeof("monza-e-della-brianza.it")];
+ char stringpool_str4559[sizeof("oz.au")];
+ char stringpool_str4560[sizeof("journalism.museum")];
+ char stringpool_str4561[sizeof("forgot.her.name")];
+ char stringpool_str4562[sizeof("ol.no")];
+ char stringpool_str4563[sizeof("magnitka.ru")];
+ char stringpool_str4564[sizeof("philadelphiaarea.museum")];
+ char stringpool_str4565[sizeof("tarumizu.kagoshima.jp")];
+ char stringpool_str4566[sizeof("or.mu")];
+ char stringpool_str4567[sizeof("xn--gmqw5a.hk")];
+ char stringpool_str4568[sizeof("sanfrancisco.museum")];
+ char stringpool_str4569[sizeof("sibenik.museum")];
+ char stringpool_str4570[sizeof("perugia.it")];
+ char stringpool_str4571[sizeof("obama.fukui.jp")];
+ char stringpool_str4572[sizeof("entertainment.aero")];
+ char stringpool_str4573[sizeof("or.at")];
+ char stringpool_str4574[sizeof("brand.se")];
+ char stringpool_str4575[sizeof("or.cr")];
+ char stringpool_str4576[sizeof("kuroiso.tochigi.jp")];
+ char stringpool_str4577[sizeof("odawara.kanagawa.jp")];
+ char stringpool_str4578[sizeof("software.aero")];
+ char stringpool_str4579[sizeof("support")];
+ char stringpool_str4580[sizeof("shiwa.iwate.jp")];
+ char stringpool_str4581[sizeof("yamagata.gifu.jp")];
+ char stringpool_str4582[sizeof("omuta.fukuoka.jp")];
+ char stringpool_str4583[sizeof("carbonia-iglesias.it")];
+ char stringpool_str4584[sizeof("chikuho.fukuoka.jp")];
+ char stringpool_str4585[sizeof("otaru.hokkaido.jp")];
+ char stringpool_str4586[sizeof("fukuchiyama.kyoto.jp")];
+ char stringpool_str4587[sizeof("kamitsue.oita.jp")];
+ char stringpool_str4588[sizeof("is-a-geek.org")];
+ char stringpool_str4589[sizeof("shingu.fukuoka.jp")];
+ char stringpool_str4590[sizeof("forgot.his.name")];
+ char stringpool_str4591[sizeof("or.kr")];
+ char stringpool_str4592[sizeof("omiya.saitama.jp")];
+ char stringpool_str4593[sizeof("ono.hyogo.jp")];
+ char stringpool_str4594[sizeof("or.ci")];
+ char stringpool_str4595[sizeof("flight.aero")];
+ char stringpool_str4596[sizeof("tozawa.yamagata.jp")];
+ char stringpool_str4597[sizeof("siracusa.it")];
+ char stringpool_str4598[sizeof("takatori.nara.jp")];
+ char stringpool_str4599[sizeof("otake.hiroshima.jp")];
+ char stringpool_str4600[sizeof("museet.museum")];
+ char stringpool_str4601[sizeof("tsushima.nagasaki.jp")];
+ char stringpool_str4602[sizeof("od.ua")];
+ char stringpool_str4603[sizeof("cargo.aero")];
+ char stringpool_str4604[sizeof("info.tt")];
+ char stringpool_str4605[sizeof("kasugai.aichi.jp")];
+ char stringpool_str4606[sizeof("ozora.hokkaido.jp")];
+ char stringpool_str4607[sizeof("is-a-photographer.com")];
+ char stringpool_str4608[sizeof("tsukui.kanagawa.jp")];
+ char stringpool_str4609[sizeof("group.aero")];
+ char stringpool_str4610[sizeof("aero.tt")];
+ char stringpool_str4611[sizeof("xn--rhqv96g")];
+ char stringpool_str4612[sizeof("or.na")];
+ char stringpool_str4613[sizeof("flights")];
+ char stringpool_str4614[sizeof("waw.pl")];
+ char stringpool_str4615[sizeof("jeju.kr")];
+ char stringpool_str4616[sizeof("sagae.yamagata.jp")];
+ char stringpool_str4617[sizeof("owani.aomori.jp")];
+ char stringpool_str4618[sizeof("muenster.museum")];
+ char stringpool_str4619[sizeof("mobi.tz")];
+ char stringpool_str4620[sizeof("cmw.ru")];
+ char stringpool_str4621[sizeof("ryugasaki.ibaraki.jp")];
+ char stringpool_str4622[sizeof("nanporo.hokkaido.jp")];
+ char stringpool_str4623[sizeof("daegu.kr")];
+ char stringpool_str4624[sizeof("sukagawa.fukushima.jp")];
+ char stringpool_str4625[sizeof("illustration.museum")];
+ char stringpool_str4626[sizeof("on.ca")];
+ char stringpool_str4627[sizeof("jeonnam.kr")];
+ char stringpool_str4628[sizeof("ojiya.niigata.jp")];
+ char stringpool_str4629[sizeof("jar.ru")];
+ char stringpool_str4630[sizeof("fujishiro.ibaraki.jp")];
+ char stringpool_str4631[sizeof("tarama.okinawa.jp")];
+ char stringpool_str4632[sizeof("agriculture.museum")];
+ char stringpool_str4633[sizeof("taketa.oita.jp")];
+ char stringpool_str4634[sizeof("otobe.hokkaido.jp")];
+ char stringpool_str4635[sizeof("oh.us")];
+ char stringpool_str4636[sizeof("or.bi")];
+ char stringpool_str4637[sizeof("or.th")];
+ char stringpool_str4638[sizeof("house.museum")];
+ char stringpool_str4639[sizeof("dovre.no")];
+ char stringpool_str4640[sizeof("glass.museum")];
+ char stringpool_str4641[sizeof("noboribetsu.hokkaido.jp")];
+ char stringpool_str4642[sizeof("writesthisblog.com")];
+ char stringpool_str4643[sizeof("readmyblog.org")];
+ char stringpool_str4644[sizeof("gorge.museum")];
+ char stringpool_str4645[sizeof("hino.tottori.jp")];
+ char stringpool_str4646[sizeof("kamo.niigata.jp")];
+ char stringpool_str4647[sizeof("ichikawa.hyogo.jp")];
+ char stringpool_str4648[sizeof("narashino.chiba.jp")];
+ char stringpool_str4649[sizeof("toho.fukuoka.jp")];
+ char stringpool_str4650[sizeof("oketo.hokkaido.jp")];
+ char stringpool_str4651[sizeof("johana.toyama.jp")];
+ char stringpool_str4652[sizeof("takamori.kumamoto.jp")];
+ char stringpool_str4653[sizeof("is-a-bulls-fan.com")];
+ char stringpool_str4654[sizeof("scienceandindustry.museum")];
+ char stringpool_str4655[sizeof("hawaii.museum")];
+ char stringpool_str4656[sizeof("field.museum")];
+ char stringpool_str4657[sizeof("kitashiobara.fukushima.jp")];
+ char stringpool_str4658[sizeof("komagane.nagano.jp")];
+ char stringpool_str4659[sizeof("force.museum")];
+ char stringpool_str4660[sizeof("ok.us")];
+ char stringpool_str4661[sizeof("sande.xn--mre-og-romsdal-qqb.no")];
+ char stringpool_str4662[sizeof("nichinan.miyazaki.jp")];
+ char stringpool_str4663[sizeof("otama.fukushima.jp")];
+ char stringpool_str4664[sizeof("swidnica.pl")];
+ char stringpool_str4665[sizeof("cyber.museum")];
+ char stringpool_str4666[sizeof("kainan.wakayama.jp")];
+ char stringpool_str4667[sizeof("union.aero")];
+ char stringpool_str4668[sizeof("tonaki.okinawa.jp")];
+ char stringpool_str4669[sizeof("bible.museum")];
+ char stringpool_str4670[sizeof("oyabe.toyama.jp")];
+ char stringpool_str4671[sizeof("cymru.museum")];
+ char stringpool_str4672[sizeof("amber.museum")];
+ char stringpool_str4673[sizeof("sherbrooke.museum")];
+ char stringpool_str4674[sizeof("suzuka.mie.jp")];
+ char stringpool_str4675[sizeof("k12.ut.us")];
+ char stringpool_str4676[sizeof("steinkjer.no")];
+ char stringpool_str4677[sizeof("donna.no")];
+ char stringpool_str4678[sizeof("sellsyourhome.org")];
+ char stringpool_str4679[sizeof("kamifurano.hokkaido.jp")];
+ char stringpool_str4680[sizeof("takaoka.toyama.jp")];
+ char stringpool_str4681[sizeof("shacknet.nu")];
+ char stringpool_str4682[sizeof("asuke.aichi.jp")];
+ char stringpool_str4683[sizeof("takasaki.gunma.jp")];
+ char stringpool_str4684[sizeof("obira.hokkaido.jp")];
+ char stringpool_str4685[sizeof("dyroy.no")];
+ char stringpool_str4686[sizeof("hino.tokyo.jp")];
+ char stringpool_str4687[sizeof("railway.museum")];
+ char stringpool_str4688[sizeof("sciencesnaturelles.museum")];
+ char stringpool_str4689[sizeof("sakegawa.yamagata.jp")];
+ char stringpool_str4690[sizeof("money.museum")];
+ char stringpool_str4691[sizeof("tsurugashima.saitama.jp")];
+ char stringpool_str4692[sizeof("works.aero")];
+ char stringpool_str4693[sizeof("aisai.aichi.jp")];
+ char stringpool_str4694[sizeof("org.co")];
+ char stringpool_str4695[sizeof("educational.museum")];
+ char stringpool_str4696[sizeof("tako.chiba.jp")];
+ char stringpool_str4697[sizeof("basel.museum")];
+ char stringpool_str4698[sizeof("rockart.museum")];
+ char stringpool_str4699[sizeof("uozu.toyama.jp")];
+ char stringpool_str4700[sizeof("tomakomai.hokkaido.jp")];
+ char stringpool_str4701[sizeof("sciencehistory.museum")];
+ char stringpool_str4702[sizeof("tsugaru.aomori.jp")];
+ char stringpool_str4703[sizeof("yamagata.yamagata.jp")];
+ char stringpool_str4704[sizeof("rochester.museum")];
+ char stringpool_str4705[sizeof("tanohata.iwate.jp")];
+ char stringpool_str4706[sizeof("space-to-rent.com")];
+ char stringpool_str4707[sizeof("ls")];
+ char stringpool_str4708[sizeof("lr")];
+ char stringpool_str4709[sizeof("gob.sv")];
+ char stringpool_str4710[sizeof("edu.sv")];
+ char stringpool_str4711[sizeof("www.ro")];
+ char stringpool_str4712[sizeof("com.sv")];
+ char stringpool_str4713[sizeof("nishiaizu.fukushima.jp")];
+ char stringpool_str4714[sizeof("shitara.aichi.jp")];
+ char stringpool_str4715[sizeof("tomisato.chiba.jp")];
+ char stringpool_str4716[sizeof("gov.lv")];
+ char stringpool_str4717[sizeof("soni.nara.jp")];
+ char stringpool_str4718[sizeof("edu.lv")];
+ char stringpool_str4719[sizeof("com.lv")];
+ char stringpool_str4720[sizeof("lu")];
+ char stringpool_str4721[sizeof("k12.mt.us")];
+ char stringpool_str4722[sizeof("l.bg")];
+ char stringpool_str4723[sizeof("l.se")];
+ char stringpool_str4724[sizeof("lom.no")];
+ char stringpool_str4725[sizeof("asn.lv")];
+ char stringpool_str4726[sizeof("joshkar-ola.ru")];
+ char stringpool_str4727[sizeof("university.museum")];
+ char stringpool_str4728[sizeof("lt")];
+ char stringpool_str4729[sizeof("marketplace.aero")];
+ char stringpool_str4730[sizeof("takamori.nagano.jp")];
+ char stringpool_str4731[sizeof("org.cw")];
+ char stringpool_str4732[sizeof("education.museum")];
+ char stringpool_str4733[sizeof("itako.ibaraki.jp")];
+ char stringpool_str4734[sizeof("lb")];
+ char stringpool_str4735[sizeof("tanabe.wakayama.jp")];
+ char stringpool_str4736[sizeof("bando.ibaraki.jp")];
+ char stringpool_str4737[sizeof("xn--mgb9awbf")];
+ char stringpool_str4738[sizeof("org.ci")];
+ char stringpool_str4739[sizeof("li")];
+ char stringpool_str4740[sizeof("other.nf")];
+ char stringpool_str4741[sizeof("shimane.jp")];
+ char stringpool_str4742[sizeof("limo")];
+ char stringpool_str4743[sizeof("k12.vt.us")];
+ char stringpool_str4744[sizeof("teshikaga.hokkaido.jp")];
+ char stringpool_str4745[sizeof("net.gn")];
+ char stringpool_str4746[sizeof("xn--aurskog-hland-jnb.no")];
+ char stringpool_str4747[sizeof("seihi.nagasaki.jp")];
+ char stringpool_str4748[sizeof("info.vn")];
+ char stringpool_str4749[sizeof("ly")];
+ char stringpool_str4750[sizeof("santafe.museum")];
+ char stringpool_str4751[sizeof("luster.no")];
+ char stringpool_str4752[sizeof("tajiri.osaka.jp")];
+ char stringpool_str4753[sizeof("os.hedmark.no")];
+ char stringpool_str4754[sizeof("technology")];
+ char stringpool_str4755[sizeof("joso.ibaraki.jp")];
+ char stringpool_str4756[sizeof("lunner.no")];
+ char stringpool_str4757[sizeof("kunstunddesign.museum")];
+ char stringpool_str4758[sizeof("okuma.fukushima.jp")];
+ char stringpool_str4759[sizeof("handa.aichi.jp")];
+ char stringpool_str4760[sizeof("chuo.tokyo.jp")];
+ char stringpool_str4761[sizeof("ltd.lk")];
+ char stringpool_str4762[sizeof("gov.mv")];
+ char stringpool_str4763[sizeof("edu.mv")];
+ char stringpool_str4764[sizeof("scienceandhistory.museum")];
+ char stringpool_str4765[sizeof("com.mv")];
+ char stringpool_str4766[sizeof("baths.museum")];
+ char stringpool_str4767[sizeof("sweden.museum")];
+ char stringpool_str4768[sizeof("expert")];
+ char stringpool_str4769[sizeof("takayama.gunma.jp")];
+ char stringpool_str4770[sizeof("lib.ee")];
+ char stringpool_str4771[sizeof("xn--dyry-ira.no")];
+ char stringpool_str4772[sizeof("naturhistorisches.museum")];
+ char stringpool_str4773[sizeof("lebork.pl")];
+ char stringpool_str4774[sizeof("farmstead.museum")];
+ char stringpool_str4775[sizeof("shimoichi.nara.jp")];
+ char stringpool_str4776[sizeof("tobetsu.hokkaido.jp")];
+ char stringpool_str4777[sizeof("bungotakada.oita.jp")];
+ char stringpool_str4778[sizeof("la")];
+ char stringpool_str4779[sizeof("sue.fukuoka.jp")];
+ char stringpool_str4780[sizeof("int.mv")];
+ char stringpool_str4781[sizeof("leg.br")];
+ char stringpool_str4782[sizeof("or.id")];
+ char stringpool_str4783[sizeof("jefferson.museum")];
+ char stringpool_str4784[sizeof("clock.museum")];
+ char stringpool_str4785[sizeof("uhren.museum")];
+ char stringpool_str4786[sizeof("sennan.osaka.jp")];
+ char stringpool_str4787[sizeof("christmas")];
+ char stringpool_str4788[sizeof("land")];
+ char stringpool_str4789[sizeof("lierne.no")];
+ char stringpool_str4790[sizeof("takayama.nagano.jp")];
+ char stringpool_str4791[sizeof("lv")];
+ char stringpool_str4792[sizeof("tas.gov.au")];
+ char stringpool_str4793[sizeof("link")];
+ char stringpool_str4794[sizeof("asahi.ibaraki.jp")];
+ char stringpool_str4795[sizeof("anan.tokushima.jp")];
+ char stringpool_str4796[sizeof("jeonbuk.kr")];
+ char stringpool_str4797[sizeof("nishinoshima.shimane.jp")];
+ char stringpool_str4798[sizeof("nankoku.kochi.jp")];
+ char stringpool_str4799[sizeof("takahama.aichi.jp")];
+ char stringpool_str4800[sizeof("mordovia.ru")];
+ char stringpool_str4801[sizeof("lel.br")];
+ char stringpool_str4802[sizeof("or.it")];
+ char stringpool_str4803[sizeof("takazaki.miyazaki.jp")];
+ char stringpool_str4804[sizeof("gdynia.pl")];
+ char stringpool_str4805[sizeof("tokushima.jp")];
+ char stringpool_str4806[sizeof("lerdal.no")];
+ char stringpool_str4807[sizeof("ski.museum")];
+ char stringpool_str4808[sizeof("limanowa.pl")];
+ char stringpool_str4809[sizeof("ot.it")];
+ char stringpool_str4810[sizeof("krokstadelva.no")];
+ char stringpool_str4811[sizeof("shirosato.ibaraki.jp")];
+ char stringpool_str4812[sizeof("xn--berlevg-jxa.no")];
+ char stringpool_str4813[sizeof("mima.tokushima.jp")];
+ char stringpool_str4814[sizeof("lapy.pl")];
+ char stringpool_str4815[sizeof("yusui.kagoshima.jp")];
+ char stringpool_str4816[sizeof("lindas.no")];
+ char stringpool_str4817[sizeof("mil.lv")];
+ char stringpool_str4818[sizeof("augustow.pl")];
+ char stringpool_str4819[sizeof("kiev.ua")];
+ char stringpool_str4820[sizeof("matsushige.tokushima.jp")];
+ char stringpool_str4821[sizeof("tamatsukuri.ibaraki.jp")];
+ char stringpool_str4822[sizeof("lib.or.us")];
+ char stringpool_str4823[sizeof("dontexist.org")];
+ char stringpool_str4824[sizeof("lugansk.ua")];
+ char stringpool_str4825[sizeof("lib.dc.us")];
+ char stringpool_str4826[sizeof("info.ve")];
+ char stringpool_str4827[sizeof("kikuchi.kumamoto.jp")];
+ char stringpool_str4828[sizeof("lib.ok.us")];
+ char stringpool_str4829[sizeof("biz.mv")];
+ char stringpool_str4830[sizeof("lib.sc.us")];
+ char stringpool_str4831[sizeof("kiwi")];
+ char stringpool_str4832[sizeof("institute")];
+ char stringpool_str4833[sizeof("lib.de.us")];
+ char stringpool_str4834[sizeof("tsukigata.hokkaido.jp")];
+ char stringpool_str4835[sizeof("rokunohe.aomori.jp")];
+ char stringpool_str4836[sizeof("lk")];
+ char stringpool_str4837[sizeof("yoshino.nara.jp")];
+ char stringpool_str4838[sizeof("lib.nj.us")];
+ char stringpool_str4839[sizeof("lib.nm.us")];
+ char stringpool_str4840[sizeof("chuvashia.ru")];
+ char stringpool_str4841[sizeof("lib.nc.us")];
+ char stringpool_str4842[sizeof("shinkamigoto.nagasaki.jp")];
+ char stringpool_str4843[sizeof("rg.it")];
+ char stringpool_str4844[sizeof("osen.no")];
+ char stringpool_str4845[sizeof("takasu.hokkaido.jp")];
+ char stringpool_str4846[sizeof("izumozaki.niigata.jp")];
+ char stringpool_str4847[sizeof("lib.ne.us")];
+ char stringpool_str4848[sizeof("keisen.fukuoka.jp")];
+ char stringpool_str4849[sizeof("lib.sd.us")];
+ char stringpool_str4850[sizeof("shimodate.ibaraki.jp")];
+ char stringpool_str4851[sizeof("org.sn")];
+ char stringpool_str4852[sizeof("odda.no")];
+ char stringpool_str4853[sizeof("lib.la.us")];
+ char stringpool_str4854[sizeof("beppu.oita.jp")];
+ char stringpool_str4855[sizeof("fukushima.fukushima.jp")];
+ char stringpool_str4856[sizeof("bryansk.ru")];
+ char stringpool_str4857[sizeof("lebesby.no")];
+ char stringpool_str4858[sizeof("lardal.no")];
+ char stringpool_str4859[sizeof("mobi.tt")];
+ char stringpool_str4860[sizeof("technology.museum")];
+ char stringpool_str4861[sizeof("koge.tottori.jp")];
+ char stringpool_str4862[sizeof("berlevag.no")];
+ char stringpool_str4863[sizeof("takehara.hiroshima.jp")];
+ char stringpool_str4864[sizeof("off.ai")];
+ char stringpool_str4865[sizeof("wales.museum")];
+ char stringpool_str4866[sizeof("lib.nd.us")];
+ char stringpool_str4867[sizeof("koeln.museum")];
+ char stringpool_str4868[sizeof("stjohn.museum")];
+ char stringpool_str4869[sizeof("boldlygoingnowhere.org")];
+ char stringpool_str4870[sizeof("chita.aichi.jp")];
+ char stringpool_str4871[sizeof("mil.mv")];
+ char stringpool_str4872[sizeof("ginan.gifu.jp")];
+ char stringpool_str4873[sizeof("lib.il.us")];
+ char stringpool_str4874[sizeof("xn--langevg-jxa.no")];
+ char stringpool_str4875[sizeof("org.tn")];
+ char stringpool_str4876[sizeof("prato.it")];
+ char stringpool_str4877[sizeof("konan.aichi.jp")];
+ char stringpool_str4878[sizeof("lib.ri.us")];
+ char stringpool_str4879[sizeof("kasamatsu.gifu.jp")];
+ char stringpool_str4880[sizeof("siljan.no")];
+ char stringpool_str4881[sizeof("oslo.no")];
+ char stringpool_str4882[sizeof("kunst.museum")];
+ char stringpool_str4883[sizeof("marugame.kagawa.jp")];
+ char stringpool_str4884[sizeof("lib.ms.us")];
+ char stringpool_str4885[sizeof("lib.mo.us")];
+ char stringpool_str4886[sizeof("lib.ia.us")];
+ char stringpool_str4887[sizeof("lib.id.us")];
+ char stringpool_str4888[sizeof("mantova.it")];
+ char stringpool_str4889[sizeof("org.in")];
+ char stringpool_str4890[sizeof("karasuyama.tochigi.jp")];
+ char stringpool_str4891[sizeof("askvoll.no")];
+ char stringpool_str4892[sizeof("xn--ggaviika-8ya47h.no")];
+ char stringpool_str4893[sizeof("oyer.no")];
+ char stringpool_str4894[sizeof("takaishi.osaka.jp")];
+ char stringpool_str4895[sizeof("lipetsk.ru")];
+ char stringpool_str4896[sizeof("koto.tokyo.jp")];
+ char stringpool_str4897[sizeof("okawa.fukuoka.jp")];
+ char stringpool_str4898[sizeof("lib.me.us")];
+ char stringpool_str4899[sizeof("tsurugi.ishikawa.jp")];
+ char stringpool_str4900[sizeof("voagat.no")];
+ char stringpool_str4901[sizeof("lib.as.us")];
+ char stringpool_str4902[sizeof("lib.ar.us")];
+ char stringpool_str4903[sizeof("yosemite.museum")];
+ char stringpool_str4904[sizeof("lib.ak.us")];
+ char stringpool_str4905[sizeof("lyngdal.no")];
+ char stringpool_str4906[sizeof("lib.ma.us")];
+ char stringpool_str4907[sizeof("media.aero")];
+ char stringpool_str4908[sizeof("gaivuotna.no")];
+ char stringpool_str4909[sizeof("lib.md.us")];
+ char stringpool_str4910[sizeof("lib.pr.us")];
+ char stringpool_str4911[sizeof("lib.al.us")];
+ char stringpool_str4912[sizeof("onojo.fukuoka.jp")];
+ char stringpool_str4913[sizeof("org.mn")];
+ char stringpool_str4914[sizeof("himi.toyama.jp")];
+ char stringpool_str4915[sizeof("kyiv.ua")];
+ char stringpool_str4916[sizeof("kawasaki.jp")];
+ char stringpool_str4917[sizeof("ryazan.ru")];
+ char stringpool_str4918[sizeof("minamitane.kagoshima.jp")];
+ char stringpool_str4919[sizeof("org.an")];
+ char stringpool_str4920[sizeof("ushistory.museum")];
+ char stringpool_str4921[sizeof("lillesand.no")];
+ char stringpool_str4922[sizeof("tachikawa.tokyo.jp")];
+ char stringpool_str4923[sizeof("nakai.kanagawa.jp")];
+ char stringpool_str4924[sizeof("klepp.no")];
+ char stringpool_str4925[sizeof("ivanovo.ru")];
+ char stringpool_str4926[sizeof("kita.tokyo.jp")];
+ char stringpool_str4927[sizeof("lib.pa.us")];
+ char stringpool_str4928[sizeof("austevoll.no")];
+ char stringpool_str4929[sizeof("lib.mi.us")];
+ char stringpool_str4930[sizeof("ogawara.miyagi.jp")];
+ char stringpool_str4931[sizeof("org.pn")];
+ char stringpool_str4932[sizeof("lib.va.us")];
+ char stringpool_str4933[sizeof("takaharu.miyazaki.jp")];
+ char stringpool_str4934[sizeof("nagakute.aichi.jp")];
+ char stringpool_str4935[sizeof("org.vn")];
+ char stringpool_str4936[sizeof("hiraizumi.iwate.jp")];
+ char stringpool_str4937[sizeof("lanbib.se")];
+ char stringpool_str4938[sizeof("accident-investigation.aero")];
+ char stringpool_str4939[sizeof("takahagi.ibaraki.jp")];
+ char stringpool_str4940[sizeof("org.cu")];
+ char stringpool_str4941[sizeof("xn--hylandet-54a.no")];
+ char stringpool_str4942[sizeof("gyokuto.kumamoto.jp")];
+ char stringpool_str4943[sizeof("perso.sn")];
+ char stringpool_str4944[sizeof("saves-the-whales.com")];
+ char stringpool_str4945[sizeof("legnica.pl")];
+ char stringpool_str4946[sizeof("tokorozawa.saitama.jp")];
+ char stringpool_str4947[sizeof("alto-adige.it")];
+ char stringpool_str4948[sizeof("yaizu.shizuoka.jp")];
+ char stringpool_str4949[sizeof("lib.vi.us")];
+ char stringpool_str4950[sizeof("nakagyo.kyoto.jp")];
+ char stringpool_str4951[sizeof("press.ma")];
+ char stringpool_str4952[sizeof("swinoujscie.pl")];
+ char stringpool_str4953[sizeof("co.lc")];
+ char stringpool_str4954[sizeof("sakae.nagano.jp")];
+ char stringpool_str4955[sizeof("luxe")];
+ char stringpool_str4956[sizeof("ac.sz")];
+ char stringpool_str4957[sizeof("ac.tz")];
+ char stringpool_str4958[sizeof("org.hn")];
+ char stringpool_str4959[sizeof("sykkylven.no")];
+ char stringpool_str4960[sizeof("s3-sa-east-1.amazonaws.com")];
+ char stringpool_str4961[sizeof("takahashi.okayama.jp")];
+ char stringpool_str4962[sizeof("lib.ks.us")];
+ char stringpool_str4963[sizeof("honbetsu.hokkaido.jp")];
+ char stringpool_str4964[sizeof("daito.osaka.jp")];
+ char stringpool_str4965[sizeof("ac.rs")];
+ char stringpool_str4966[sizeof("kopervik.no")];
+ char stringpool_str4967[sizeof("ac.mu")];
+ char stringpool_str4968[sizeof("nyuzen.toyama.jp")];
+ char stringpool_str4969[sizeof("nrw")];
+ char stringpool_str4970[sizeof("ac.ru")];
+ char stringpool_str4971[sizeof("ac.se")];
+ char stringpool_str4972[sizeof("yachimata.chiba.jp")];
+ char stringpool_str4973[sizeof("ac.ae")];
+ char stringpool_str4974[sizeof("qc.com")];
+ char stringpool_str4975[sizeof("shimane.shimane.jp")];
+ char stringpool_str4976[sizeof("lezajsk.pl")];
+ char stringpool_str4977[sizeof("lib.hi.us")];
+ char stringpool_str4978[sizeof("ac.at")];
+ char stringpool_str4979[sizeof("ac.me")];
+ char stringpool_str4980[sizeof("ac.gn")];
+ char stringpool_str4981[sizeof("porsgrunn.no")];
+ char stringpool_str4982[sizeof("ac.cr")];
+ char stringpool_str4983[sizeof("labour.museum")];
+ char stringpool_str4984[sizeof("kawahara.tottori.jp")];
+ char stringpool_str4985[sizeof("tsuruoka.yamagata.jp")];
+ char stringpool_str4986[sizeof("org.kn")];
+ char stringpool_str4987[sizeof("yamada.iwate.jp")];
+ char stringpool_str4988[sizeof("net.st")];
+ char stringpool_str4989[sizeof("ac.cn")];
+ char stringpool_str4990[sizeof("parma.it")];
+ char stringpool_str4991[sizeof("kawaba.gunma.jp")];
+ char stringpool_str4992[sizeof("iwama.ibaraki.jp")];
+ char stringpool_str4993[sizeof("zhytomyr.ua")];
+ char stringpool_str4994[sizeof("mombetsu.hokkaido.jp")];
+ char stringpool_str4995[sizeof("namikata.ehime.jp")];
+ char stringpool_str4996[sizeof("landes.museum")];
+ char stringpool_str4997[sizeof("sumita.iwate.jp")];
+ char stringpool_str4998[sizeof("nishigo.fukushima.jp")];
+ char stringpool_str4999[sizeof("artanddesign.museum")];
+ char stringpool_str5000[sizeof("media.museum")];
+ char stringpool_str5001[sizeof("ac.kr")];
+ char stringpool_str5002[sizeof("shichinohe.aomori.jp")];
+ char stringpool_str5003[sizeof("perso.ht")];
+ char stringpool_str5004[sizeof("ac.tj")];
+ char stringpool_str5005[sizeof("terni.it")];
+ char stringpool_str5006[sizeof("timekeeping.museum")];
+ char stringpool_str5007[sizeof("tagami.niigata.jp")];
+ char stringpool_str5008[sizeof("jetzt")];
+ char stringpool_str5009[sizeof("net.tt")];
+ char stringpool_str5010[sizeof("padua.it")];
+ char stringpool_str5011[sizeof("ac.ci")];
+ char stringpool_str5012[sizeof("land-4-sale.us")];
+ char stringpool_str5013[sizeof("tochio.niigata.jp")];
+ char stringpool_str5014[sizeof("tatebayashi.gunma.jp")];
+ char stringpool_str5015[sizeof("gouv.ht")];
+ char stringpool_str5016[sizeof("net.bt")];
+ char stringpool_str5017[sizeof("xn--hery-ira.xn--mre-og-romsdal-qqb.no")];
+ char stringpool_str5018[sizeof("obuse.nagano.jp")];
+ char stringpool_str5019[sizeof("drangedal.no")];
+ char stringpool_str5020[sizeof("nesset.no")];
+ char stringpool_str5021[sizeof("nakatane.kagoshima.jp")];
+ char stringpool_str5022[sizeof("yahaba.iwate.jp")];
+ char stringpool_str5023[sizeof("ikeda.gifu.jp")];
+ char stringpool_str5024[sizeof("cc.na")];
+ char stringpool_str5025[sizeof("ac.ma")];
+ char stringpool_str5026[sizeof("lighting")];
+ char stringpool_str5027[sizeof("ouda.nara.jp")];
+ char stringpool_str5028[sizeof("ogata.akita.jp")];
+ char stringpool_str5029[sizeof("kudamatsu.yamaguchi.jp")];
+ char stringpool_str5030[sizeof("moriguchi.osaka.jp")];
+ char stringpool_str5031[sizeof("pittsburgh.museum")];
+ char stringpool_str5032[sizeof("anamizu.ishikawa.jp")];
+ char stringpool_str5033[sizeof("oe.yamagata.jp")];
+ char stringpool_str5034[sizeof("jinsekikogen.hiroshima.jp")];
+ char stringpool_str5035[sizeof("juif.museum")];
+ char stringpool_str5036[sizeof("xn--gildeskl-g0a.no")];
+ char stringpool_str5037[sizeof("or.jp")];
+ char stringpool_str5038[sizeof("ontario.museum")];
+ char stringpool_str5039[sizeof("gc.ca")];
+ char stringpool_str5040[sizeof("qc.ca")];
+ char stringpool_str5041[sizeof("net.mt")];
+ char stringpool_str5042[sizeof("kisofukushima.nagano.jp")];
+ char stringpool_str5043[sizeof("takizawa.iwate.jp")];
+ char stringpool_str5044[sizeof("oregon.museum")];
+ char stringpool_str5045[sizeof("bc.ca")];
+ char stringpool_str5046[sizeof("ac.be")];
+ char stringpool_str5047[sizeof("la-spezia.it")];
+ char stringpool_str5048[sizeof("otari.nagano.jp")];
+ char stringpool_str5049[sizeof("barlettatraniandria.it")];
+ char stringpool_str5050[sizeof("doshi.yamanashi.jp")];
+ char stringpool_str5051[sizeof("obu.aichi.jp")];
+ char stringpool_str5052[sizeof("uchinada.ishikawa.jp")];
+ char stringpool_str5053[sizeof("net.pt")];
+ char stringpool_str5054[sizeof("leirvik.no")];
+ char stringpool_str5055[sizeof("ac.th")];
+ char stringpool_str5056[sizeof("essex.museum")];
+ char stringpool_str5057[sizeof("miyazaki.jp")];
+ char stringpool_str5058[sizeof("oshu.iwate.jp")];
+ char stringpool_str5059[sizeof("mugi.tokushima.jp")];
+ char stringpool_str5060[sizeof("furniture.museum")];
+ char stringpool_str5061[sizeof("gangaviika.no")];
+ char stringpool_str5062[sizeof("k12.nv.us")];
+ char stringpool_str5063[sizeof("kochi.kochi.jp")];
+ char stringpool_str5064[sizeof("barletta-trani-andria.it")];
+ char stringpool_str5065[sizeof("gob.gt")];
+ char stringpool_str5066[sizeof("edu.gt")];
+ char stringpool_str5067[sizeof("takikawa.hokkaido.jp")];
+ char stringpool_str5068[sizeof("com.gt")];
+ char stringpool_str5069[sizeof("ebiz.tw")];
+ char stringpool_str5070[sizeof("narvik.no")];
+ char stringpool_str5071[sizeof("kawanishi.nara.jp")];
+ char stringpool_str5072[sizeof("tomioka.gunma.jp")];
+ char stringpool_str5073[sizeof("otaki.nagano.jp")];
+ char stringpool_str5074[sizeof("tainai.niigata.jp")];
+ char stringpool_str5075[sizeof("opoczno.pl")];
+ char stringpool_str5076[sizeof("hoyanger.no")];
+ char stringpool_str5077[sizeof("navuotna.no")];
+ char stringpool_str5078[sizeof("is-saved.org")];
+ char stringpool_str5079[sizeof("kuchinotsu.nagasaki.jp")];
+ char stringpool_str5080[sizeof("oseto.nagasaki.jp")];
+ char stringpool_str5081[sizeof("net.ht")];
+ char stringpool_str5082[sizeof("name.tj")];
+ char stringpool_str5083[sizeof("tydal.no")];
+ char stringpool_str5084[sizeof("targi.pl")];
+ char stringpool_str5085[sizeof("shop.ht")];
+ char stringpool_str5086[sizeof("if.ua")];
+ char stringpool_str5087[sizeof("chikuzen.fukuoka.jp")];
+ char stringpool_str5088[sizeof("tjome.no")];
+ char stringpool_str5089[sizeof("olsztyn.pl")];
+ char stringpool_str5090[sizeof("lib.wa.us")];
+ char stringpool_str5091[sizeof("levanger.no")];
+ char stringpool_str5092[sizeof("saigawa.fukuoka.jp")];
+ char stringpool_str5093[sizeof("ind.gt")];
+ char stringpool_str5094[sizeof("perso.tn")];
+ char stringpool_str5095[sizeof("co.pl")];
+ char stringpool_str5096[sizeof("trana.no")];
+ char stringpool_str5097[sizeof("saku.nagano.jp")];
+ char stringpool_str5098[sizeof("nakamichi.yamanashi.jp")];
+ char stringpool_str5099[sizeof("nakatombetsu.hokkaido.jp")];
+ char stringpool_str5100[sizeof("shinyoshitomi.fukuoka.jp")];
+ char stringpool_str5101[sizeof("kaminokawa.tochigi.jp")];
+ char stringpool_str5102[sizeof("co.pn")];
+ char stringpool_str5103[sizeof("ogano.saitama.jp")];
+ char stringpool_str5104[sizeof("lib.wi.us")];
+ char stringpool_str5105[sizeof("ogose.saitama.jp")];
+ char stringpool_str5106[sizeof("de.us")];
+ char stringpool_str5107[sizeof("freight.aero")];
+ char stringpool_str5108[sizeof("turek.pl")];
+ char stringpool_str5109[sizeof("xn--80asehdb")];
+ char stringpool_str5110[sizeof("xn--45brj9c")];
+ char stringpool_str5111[sizeof("xn--s9brj9c")];
+ char stringpool_str5112[sizeof("latina.it")];
+ char stringpool_str5113[sizeof("taishi.hyogo.jp")];
+ char stringpool_str5114[sizeof("osaki.miyagi.jp")];
+ char stringpool_str5115[sizeof("vinnytsia.ua")];
+ char stringpool_str5116[sizeof("tolga.no")];
+ char stringpool_str5117[sizeof("kamiizumi.saitama.jp")];
+ char stringpool_str5118[sizeof("usculture.museum")];
+ char stringpool_str5119[sizeof("report")];
+ char stringpool_str5120[sizeof("de.com")];
+ char stringpool_str5121[sizeof("xn--tysvr-vra.no")];
+ char stringpool_str5122[sizeof("lavangen.no")];
+ char stringpool_str5123[sizeof("tomsk.ru")];
+ char stringpool_str5124[sizeof("kawakami.nara.jp")];
+ char stringpool_str5125[sizeof("iwamizawa.hokkaido.jp")];
+ char stringpool_str5126[sizeof("narviika.no")];
+ char stringpool_str5127[sizeof("tamakawa.fukushima.jp")];
+ char stringpool_str5128[sizeof("rnrt.tn")];
+ char stringpool_str5129[sizeof("xn--q9jyb4c")];
+ char stringpool_str5130[sizeof("gs.svalbard.no")];
+ char stringpool_str5131[sizeof("oguni.kumamoto.jp")];
+ char stringpool_str5132[sizeof("miyada.nagano.jp")];
+ char stringpool_str5133[sizeof("taketomi.okinawa.jp")];
+ char stringpool_str5134[sizeof("brandywinevalley.museum")];
+ char stringpool_str5135[sizeof("oceanographique.museum")];
+ char stringpool_str5136[sizeof("openair.museum")];
+ char stringpool_str5137[sizeof("xn--loabt-0qa.no")];
+ char stringpool_str5138[sizeof("xn--rdy-0nab.no")];
+ char stringpool_str5139[sizeof("shinshiro.aichi.jp")];
+ char stringpool_str5140[sizeof("iiyama.nagano.jp")];
+ char stringpool_str5141[sizeof("takatsuki.osaka.jp")];
+ char stringpool_str5142[sizeof("dr.na")];
+ char stringpool_str5143[sizeof("ostre-toten.no")];
+ char stringpool_str5144[sizeof("org.dz")];
+ char stringpool_str5145[sizeof("dn.ua")];
+ char stringpool_str5146[sizeof("mil.gt")];
+ char stringpool_str5147[sizeof("miyota.nagano.jp")];
+ char stringpool_str5148[sizeof("org.sz")];
+ char stringpool_str5149[sizeof("krym.ua")];
+ char stringpool_str5150[sizeof("org.uz")];
+ char stringpool_str5151[sizeof("xn--nqv7f")];
+ char stringpool_str5152[sizeof("obama.nagasaki.jp")];
+ char stringpool_str5153[sizeof("kanie.aichi.jp")];
+ char stringpool_str5154[sizeof("is-very-bad.org")];
+ char stringpool_str5155[sizeof("omura.nagasaki.jp")];
+ char stringpool_str5156[sizeof("ac.id")];
+ char stringpool_str5157[sizeof("est-le-patron.com")];
+ char stringpool_str5158[sizeof("tomika.gifu.jp")];
+ char stringpool_str5159[sizeof("miyake.nara.jp")];
+ char stringpool_str5160[sizeof("turen.tn")];
+ char stringpool_str5161[sizeof("raholt.no")];
+ char stringpool_str5162[sizeof("ac.ir")];
+ char stringpool_str5163[sizeof("org.bz")];
+ char stringpool_str5164[sizeof("xn--p1acf")];
+ char stringpool_str5165[sizeof("ac.mw")];
+ char stringpool_str5166[sizeof("xn--fl-zia.no")];
+ char stringpool_str5167[sizeof("ac.rw")];
+ char stringpool_str5168[sizeof("okaya.nagano.jp")];
+ char stringpool_str5169[sizeof("ouchi.saga.jp")];
+ char stringpool_str5170[sizeof("tychy.pl")];
+ char stringpool_str5171[sizeof("nishikata.tochigi.jp")];
+ char stringpool_str5172[sizeof("ac.in")];
+ char stringpool_str5173[sizeof("turin.it")];
+ char stringpool_str5174[sizeof("kibichuo.okayama.jp")];
+ char stringpool_str5175[sizeof("xn--fiqz9s")];
+ char stringpool_str5176[sizeof("ono.fukui.jp")];
+ char stringpool_str5177[sizeof("fc.it")];
+ char stringpool_str5178[sizeof("shimofusa.chiba.jp")];
+ char stringpool_str5179[sizeof("xn--h2brj9c")];
+ char stringpool_str5180[sizeof("pavia.it")];
+ char stringpool_str5181[sizeof("xn--fjord-lra.no")];
+ char stringpool_str5182[sizeof("sarpsborg.no")];
+ char stringpool_str5183[sizeof("marketing")];
+ char stringpool_str5184[sizeof("umaji.kochi.jp")];
+ char stringpool_str5185[sizeof("plc.ly")];
+ char stringpool_str5186[sizeof("xn--fiqs8s")];
+ char stringpool_str5187[sizeof("dp.ua")];
+ char stringpool_str5188[sizeof("likescandy.com")];
+ char stringpool_str5189[sizeof("kakamigahara.gifu.jp")];
+ char stringpool_str5190[sizeof("org.az")];
+ char stringpool_str5191[sizeof("ogori.fukuoka.jp")];
+ char stringpool_str5192[sizeof("niigata.jp")];
+ char stringpool_str5193[sizeof("kiyose.tokyo.jp")];
+ char stringpool_str5194[sizeof("rawa-maz.pl")];
+ char stringpool_str5195[sizeof("tokashiki.okinawa.jp")];
+ char stringpool_str5196[sizeof("mc.it")];
+ char stringpool_str5197[sizeof("ac.im")];
+ char stringpool_str5198[sizeof("gov.cn")];
+ char stringpool_str5199[sizeof("edu.cn")];
+ char stringpool_str5200[sizeof("com.cn")];
+ char stringpool_str5201[sizeof("komvux.se")];
+ char stringpool_str5202[sizeof("cci.fr")];
+ char stringpool_str5203[sizeof("avocat.fr")];
+ char stringpool_str5204[sizeof("barrell-of-knowledge.info")];
+ char stringpool_str5205[sizeof("kesennuma.miyagi.jp")];
+ char stringpool_str5206[sizeof("kawakami.nagano.jp")];
+ char stringpool_str5207[sizeof("lib.oh.us")];
+ char stringpool_str5208[sizeof("nsw.au")];
+ char stringpool_str5209[sizeof("kawajima.saitama.jp")];
+ char stringpool_str5210[sizeof("lodi.it")];
+ char stringpool_str5211[sizeof("ohda.shimane.jp")];
+ char stringpool_str5212[sizeof("est-a-la-maison.com")];
+ char stringpool_str5213[sizeof("og.ao")];
+ char stringpool_str5214[sizeof("operaunite.com")];
+ char stringpool_str5215[sizeof("heimatunduhren.museum")];
+ char stringpool_str5216[sizeof("est-a-la-masion.com")];
+ char stringpool_str5217[sizeof("tranoy.no")];
+ char stringpool_str5218[sizeof("shop.hu")];
+ char stringpool_str5219[sizeof("lib.nh.us")];
+ char stringpool_str5220[sizeof("or.ug")];
+ char stringpool_str5221[sizeof("tenri.nara.jp")];
+ char stringpool_str5222[sizeof("losangeles.museum")];
+ char stringpool_str5223[sizeof("tagawa.fukuoka.jp")];
+ char stringpool_str5224[sizeof("rel.ht")];
+ char stringpool_str5225[sizeof("neues.museum")];
+ char stringpool_str5226[sizeof("xn--frya-hra.no")];
+ char stringpool_str5227[sizeof("democrat")];
+ char stringpool_str5228[sizeof("kawanehon.shizuoka.jp")];
+ char stringpool_str5229[sizeof("name.tt")];
+ char stringpool_str5230[sizeof("rhcloud.com")];
+ char stringpool_str5231[sizeof("nozawaonsen.nagano.jp")];
+ char stringpool_str5232[sizeof("ftpaccess.cc")];
+ char stringpool_str5233[sizeof("xn--ciqpn.hk")];
+ char stringpool_str5234[sizeof("savannahga.museum")];
+ char stringpool_str5235[sizeof("nishinomiya.hyogo.jp")];
+ char stringpool_str5236[sizeof("xn--nnx388a")];
+ char stringpool_str5237[sizeof("ohira.miyagi.jp")];
+ char stringpool_str5238[sizeof("kawatana.nagasaki.jp")];
+ char stringpool_str5239[sizeof("luxembourg.museum")];
+ char stringpool_str5240[sizeof("togakushi.nagano.jp")];
+ char stringpool_str5241[sizeof("ochi.kochi.jp")];
+ char stringpool_str5242[sizeof("est-mon-blogueur.com")];
+ char stringpool_str5243[sizeof("tranby.no")];
+ char stringpool_str5244[sizeof("k12.wv.us")];
+ char stringpool_str5245[sizeof("for-better.biz")];
+ char stringpool_str5246[sizeof("org.kz")];
+ char stringpool_str5247[sizeof("koya.wakayama.jp")];
+ char stringpool_str5248[sizeof("dyn-o-saur.com")];
+ char stringpool_str5249[sizeof("oto.fukuoka.jp")];
+ char stringpool_str5250[sizeof("miyazaki.miyazaki.jp")];
+ char stringpool_str5251[sizeof("surgut.ru")];
+ char stringpool_str5252[sizeof("naval.museum")];
+ char stringpool_str5253[sizeof("is-an-anarchist.com")];
+ char stringpool_str5254[sizeof("yokkaichi.mie.jp")];
+ char stringpool_str5255[sizeof("ranzan.saitama.jp")];
+ char stringpool_str5256[sizeof("xn--tjme-hra.no")];
+ char stringpool_str5257[sizeof("xn--srfold-bya.no")];
+ char stringpool_str5258[sizeof("xn--brnnysund-m8ac.no")];
+ char stringpool_str5259[sizeof("xn--aroport-bya.ci")];
+ char stringpool_str5260[sizeof("is-a-liberal.com")];
+ char stringpool_str5261[sizeof("is-a-landscaper.com")];
+ char stringpool_str5262[sizeof("medecin.fr")];
+ char stringpool_str5263[sizeof("tokushima.tokushima.jp")];
+ char stringpool_str5264[sizeof("shimogo.fukushima.jp")];
+ char stringpool_str5265[sizeof("on-the-web.tv")];
+ char stringpool_str5266[sizeof("omitama.ibaraki.jp")];
+ char stringpool_str5267[sizeof("assedic.fr")];
+ char stringpool_str5268[sizeof("tateshina.nagano.jp")];
+ char stringpool_str5269[sizeof("lodingen.no")];
+ char stringpool_str5270[sizeof("tsuiki.fukuoka.jp")];
+ char stringpool_str5271[sizeof("asso.nc")];
+ char stringpool_str5272[sizeof("miyazu.kyoto.jp")];
+ char stringpool_str5273[sizeof("xn--snase-nra.no")];
+ char stringpool_str5274[sizeof("xn--nqv7fs00ema")];
+ char stringpool_str5275[sizeof("go.pw")];
+ char stringpool_str5276[sizeof("ed.pw")];
+ char stringpool_str5277[sizeof("co.pw")];
+ char stringpool_str5278[sizeof("xn--flor-jra.no")];
+ char stringpool_str5279[sizeof("dyndns.biz")];
+ char stringpool_str5280[sizeof("mil.cn")];
+ char stringpool_str5281[sizeof("north.museum")];
+ char stringpool_str5282[sizeof("xn--jrpeland-54a.no")];
+ char stringpool_str5283[sizeof("buyshouses.net")];
+ char stringpool_str5284[sizeof("ono.fukushima.jp")];
+ char stringpool_str5285[sizeof("kawaminami.miyazaki.jp")];
+ char stringpool_str5286[sizeof("tsuru.yamanashi.jp")];
+ char stringpool_str5287[sizeof("xn--jlster-bya.no")];
+ char stringpool_str5288[sizeof("mochizuki.nagano.jp")];
+ char stringpool_str5289[sizeof("servebbs.com")];
+ char stringpool_str5290[sizeof("xn--srreisa-q1a.no")];
+ char stringpool_str5291[sizeof("jelenia-gora.pl")];
+ char stringpool_str5292[sizeof("net.lv")];
+ char stringpool_str5293[sizeof("conference.aero")];
+ char stringpool_str5294[sizeof("taiki.mie.jp")];
+ char stringpool_str5295[sizeof("is-an-accountant.com")];
+ char stringpool_str5296[sizeof("is-a-player.com")];
+ char stringpool_str5297[sizeof("oregontrail.museum")];
+ char stringpool_str5298[sizeof("lans.museum")];
+ char stringpool_str5299[sizeof("from-sc.com")];
+ char stringpool_str5300[sizeof("ohi.fukui.jp")];
+ char stringpool_str5301[sizeof("sado.niigata.jp")];
+ char stringpool_str5302[sizeof("servebbs.net")];
+ char stringpool_str5303[sizeof("higashishirakawa.gifu.jp")];
+ char stringpool_str5304[sizeof("valer.hedmark.no")];
+ char stringpool_str5305[sizeof("is-a-libertarian.com")];
+ char stringpool_str5306[sizeof("store.bb")];
+ char stringpool_str5307[sizeof("xn--snsa-roa.no")];
+ char stringpool_str5308[sizeof("council.aero")];
+ char stringpool_str5309[sizeof("vanylven.no")];
+ char stringpool_str5310[sizeof("xn--rmskog-bya.no")];
+ char stringpool_str5311[sizeof("is-uberleet.com")];
+ char stringpool_str5312[sizeof("from-dc.com")];
+ char stringpool_str5313[sizeof("xn--vegrshei-c0a.no")];
+ char stringpool_str5314[sizeof("takahama.fukui.jp")];
+ char stringpool_str5315[sizeof("paragliding.aero")];
+ char stringpool_str5316[sizeof("kayabe.hokkaido.jp")];
+ char stringpool_str5317[sizeof("leksvik.no")];
+ char stringpool_str5318[sizeof("takagi.nagano.jp")];
+ char stringpool_str5319[sizeof("betainabox.com")];
+ char stringpool_str5320[sizeof("ogawa.saitama.jp")];
+ char stringpool_str5321[sizeof("okoppe.hokkaido.jp")];
+ char stringpool_str5322[sizeof("for-our.info")];
+ char stringpool_str5323[sizeof("googlecode.com")];
+ char stringpool_str5324[sizeof("takasago.hyogo.jp")];
+ char stringpool_str5325[sizeof("manx.museum")];
+ char stringpool_str5326[sizeof("net.mv")];
+ char stringpool_str5327[sizeof("dnsdojo.net")];
+ char stringpool_str5328[sizeof("shiriuchi.hokkaido.jp")];
+ char stringpool_str5329[sizeof("nnov.ru")];
+ char stringpool_str5330[sizeof("kawazu.shizuoka.jp")];
+ char stringpool_str5331[sizeof("dyndns-remote.com")];
+ char stringpool_str5332[sizeof("xn--snes-poa.no")];
+ char stringpool_str5333[sizeof("takayama.gifu.jp")];
+ char stringpool_str5334[sizeof("dnsdojo.com")];
+ char stringpool_str5335[sizeof("xn--lgrd-poac.no")];
+ char stringpool_str5336[sizeof("pr.us")];
+ char stringpool_str5337[sizeof("agency")];
+ char stringpool_str5338[sizeof("xn--dnna-gra.no")];
+ char stringpool_str5339[sizeof("hayakawa.yamanashi.jp")];
+ char stringpool_str5340[sizeof("xn--finny-yua.no")];
+ char stringpool_str5341[sizeof("pskov.ru")];
+ char stringpool_str5342[sizeof("ujiie.tochigi.jp")];
+ char stringpool_str5343[sizeof("academy.museum")];
+ char stringpool_str5344[sizeof("name.vn")];
+ char stringpool_str5345[sizeof("tsuno.miyazaki.jp")];
+ char stringpool_str5346[sizeof("judygarland.museum")];
+ char stringpool_str5347[sizeof("living.museum")];
+ char stringpool_str5348[sizeof("dyndns-pics.com")];
+ char stringpool_str5349[sizeof("kiyama.saga.jp")];
+ char stringpool_str5350[sizeof("from-ny.net")];
+ char stringpool_str5351[sizeof("suwalki.pl")];
+ char stringpool_str5352[sizeof("s3-fips-us-gov-west-1.amazonaws.com")];
+ char stringpool_str5353[sizeof("pb.ao")];
+ char stringpool_str5354[sizeof("tajimi.gifu.jp")];
+ char stringpool_str5355[sizeof("xn--ksnes-uua.no")];
+ char stringpool_str5356[sizeof("ac.jp")];
+ char stringpool_str5357[sizeof("dyndns-home.com")];
+ char stringpool_str5358[sizeof("takarazuka.hyogo.jp")];
+ char stringpool_str5359[sizeof("birthplace.museum")];
+ char stringpool_str5360[sizeof("takata.fukuoka.jp")];
+ char stringpool_str5361[sizeof("os.hordaland.no")];
+ char stringpool_str5362[sizeof("is-very-evil.org")];
+ char stringpool_str5363[sizeof("stavern.no")];
+ char stringpool_str5364[sizeof("fujikawaguchiko.yamanashi.jp")];
+ char stringpool_str5365[sizeof("mibu.tochigi.jp")];
+ char stringpool_str5366[sizeof("xn--slt-elab.no")];
+ char stringpool_str5367[sizeof("tokyo.jp")];
+ char stringpool_str5368[sizeof("endofinternet.net")];
+ char stringpool_str5369[sizeof("bato.tochigi.jp")];
+ char stringpool_str5370[sizeof("skanit.no")];
+ char stringpool_str5371[sizeof("culturalcenter.museum")];
+ char stringpool_str5372[sizeof("intelligence.museum")];
+ char stringpool_str5373[sizeof("isteingeek.de")];
+ char stringpool_str5374[sizeof("company")];
+ char stringpool_str5375[sizeof("sarufutsu.hokkaido.jp")];
+ char stringpool_str5376[sizeof("government.aero")];
+ char stringpool_str5377[sizeof("localhistory.museum")];
+ char stringpool_str5378[sizeof("xn--lgbbat1ad8j")];
+ char stringpool_str5379[sizeof("haga.tochigi.jp")];
+ char stringpool_str5380[sizeof("pulawy.pl")];
+ char stringpool_str5381[sizeof("pe.kr")];
+ char stringpool_str5382[sizeof("xn--blt-elab.no")];
+ char stringpool_str5383[sizeof("lib.tx.us")];
+ char stringpool_str5384[sizeof("ascolipiceno.it")];
+ char stringpool_str5385[sizeof("pa.us")];
+ char stringpool_str5386[sizeof("from-nv.com")];
+ char stringpool_str5387[sizeof("pl.ua")];
+ char stringpool_str5388[sizeof("blogdns.net")];
+ char stringpool_str5389[sizeof("pp.az")];
+ char stringpool_str5390[sizeof("oki.fukuoka.jp")];
+ char stringpool_str5391[sizeof("museumcenter.museum")];
+ char stringpool_str5392[sizeof("vibo-valentia.it")];
+ char stringpool_str5393[sizeof("stavropol.ru")];
+ char stringpool_str5394[sizeof("from-nj.com")];
+ char stringpool_str5395[sizeof("bahcavuotna.no")];
+ char stringpool_str5396[sizeof("services.aero")];
+ char stringpool_str5397[sizeof("vf.no")];
+ char stringpool_str5398[sizeof("blogdns.com")];
+ char stringpool_str5399[sizeof("matsudo.chiba.jp")];
+ char stringpool_str5400[sizeof("daiwa.hiroshima.jp")];
+ char stringpool_str5401[sizeof("graphics")];
+ char stringpool_str5402[sizeof("karuizawa.nagano.jp")];
+ char stringpool_str5403[sizeof("tokke.no")];
+ char stringpool_str5404[sizeof("domains")];
+ char stringpool_str5405[sizeof("tamba.hyogo.jp")];
+ char stringpool_str5406[sizeof("pp.ru")];
+ char stringpool_str5407[sizeof("pp.se")];
+ char stringpool_str5408[sizeof("sevastopol.ua")];
+ char stringpool_str5409[sizeof("sebastopol.ua")];
+ char stringpool_str5410[sizeof("lacaixa")];
+ char stringpool_str5411[sizeof("is-an-entertainer.com")];
+ char stringpool_str5412[sizeof("is-gone.com")];
+ char stringpool_str5413[sizeof("ogimi.okinawa.jp")];
+ char stringpool_str5414[sizeof("vladivostok.ru")];
+ char stringpool_str5415[sizeof("yuu.yamaguchi.jp")];
+ char stringpool_str5416[sizeof("oshima.yamaguchi.jp")];
+ char stringpool_str5417[sizeof("dyndns-mail.com")];
+ char stringpool_str5418[sizeof("from-nm.com")];
+ char stringpool_str5419[sizeof("tr.no")];
+ char stringpool_str5420[sizeof("pe.ca")];
+ char stringpool_str5421[sizeof("sannan.hyogo.jp")];
+ char stringpool_str5422[sizeof("tn.us")];
+ char stringpool_str5423[sizeof("malatvuopmi.no")];
+ char stringpool_str5424[sizeof("servebbs.org")];
+ char stringpool_str5425[sizeof("katsuyama.fukui.jp")];
+ char stringpool_str5426[sizeof("uryu.hokkaido.jp")];
+ char stringpool_str5427[sizeof("ltd.gi")];
+ char stringpool_str5428[sizeof("og.it")];
+ char stringpool_str5429[sizeof("red.sv")];
+ char stringpool_str5430[sizeof("toki.gifu.jp")];
+ char stringpool_str5431[sizeof("olbia-tempio.it")];
+ char stringpool_str5432[sizeof("kiyosu.aichi.jp")];
+ char stringpool_str5433[sizeof("xn--brnny-wuac.no")];
+ char stringpool_str5434[sizeof("from-ne.com")];
+ char stringpool_str5435[sizeof("pp.ua")];
+ char stringpool_str5436[sizeof("xn--mosjen-eya.no")];
+ char stringpool_str5437[sizeof("nasushiobara.tochigi.jp")];
+ char stringpool_str5438[sizeof("xn--mgbbh1a71e")];
+ char stringpool_str5439[sizeof("is-a-designer.com")];
+ char stringpool_str5440[sizeof("xn--mgberp4a5d4ar")];
+ char stringpool_str5441[sizeof("owariasahi.aichi.jp")];
+ char stringpool_str5442[sizeof("tm.no")];
+ char stringpool_str5443[sizeof("tm.ro")];
+ char stringpool_str5444[sizeof("bremanger.no")];
+ char stringpool_str5445[sizeof("tohma.hokkaido.jp")];
+ char stringpool_str5446[sizeof("tm.se")];
+ char stringpool_str5447[sizeof("dyndns-ip.com")];
+ char stringpool_str5448[sizeof("flatanger.no")];
+ char stringpool_str5449[sizeof("gratangen.no")];
+ char stringpool_str5450[sizeof("xn--sgne-gra.no")];
+ char stringpool_str5451[sizeof("from-nh.com")];
+ char stringpool_str5452[sizeof("tm.fr")];
+ char stringpool_str5453[sizeof("campidano-medio.it")];
+ char stringpool_str5454[sizeof("tv.sd")];
+ char stringpool_str5455[sizeof("tv.tz")];
+ char stringpool_str5456[sizeof("nc.us")];
+ char stringpool_str5457[sizeof("is-a-bookkeeper.com")];
+ char stringpool_str5458[sizeof("xn--lns-qla.museum")];
+ char stringpool_str5459[sizeof("shirakawa.fukushima.jp")];
+ char stringpool_str5460[sizeof("yamatsuri.fukushima.jp")];
+ char stringpool_str5461[sizeof("tj.cn")];
+ char stringpool_str5462[sizeof("lib.ga.us")];
+ char stringpool_str5463[sizeof("te.ua")];
+ char stringpool_str5464[sizeof("xn--o3cw4h")];
+ char stringpool_str5465[sizeof("tonosho.kagawa.jp")];
+ char stringpool_str5466[sizeof("org.gn")];
+ char stringpool_str5467[sizeof("xn--mgbqly7cvafr")];
+ char stringpool_str5468[sizeof("xn--ygarden-p1a.no")];
+ char stringpool_str5469[sizeof("tenei.fukushima.jp")];
+ char stringpool_str5470[sizeof("xn--skierv-uta.no")];
+ char stringpool_str5471[sizeof("nsw.edu.au")];
+ char stringpool_str5472[sizeof("takino.hyogo.jp")];
+ char stringpool_str5473[sizeof("okagaki.fukuoka.jp")];
+ char stringpool_str5474[sizeof("aeroclub.aero")];
+ char stringpool_str5475[sizeof("is-a-student.com")];
+ char stringpool_str5476[sizeof("oyamazaki.kyoto.jp")];
+ char stringpool_str5477[sizeof("miyoshi.saitama.jp")];
+ char stringpool_str5478[sizeof("state.museum")];
+ char stringpool_str5479[sizeof("miyakonojo.miyazaki.jp")];
+ char stringpool_str5480[sizeof("stadt.museum")];
+ char stringpool_str5481[sizeof("olkusz.pl")];
+ char stringpool_str5482[sizeof("yamaguchi.jp")];
+ char stringpool_str5483[sizeof("livinghistory.museum")];
+ char stringpool_str5484[sizeof("miyashiro.saitama.jp")];
+ char stringpool_str5485[sizeof("joetsu.niigata.jp")];
+ char stringpool_str5486[sizeof("mitou.yamaguchi.jp")];
+ char stringpool_str5487[sizeof("is-a-financialadvisor.com")];
+ char stringpool_str5488[sizeof("aerobatic.aero")];
+ char stringpool_str5489[sizeof("database.museum")];
+ char stringpool_str5490[sizeof("steam.museum")];
+ char stringpool_str5491[sizeof("niigata.niigata.jp")];
+ char stringpool_str5492[sizeof("botanicgarden.museum")];
+ char stringpool_str5493[sizeof("sch.ly")];
+ char stringpool_str5494[sizeof("xn--laheadju-7ya.no")];
+ char stringpool_str5495[sizeof("denmark.museum")];
+ char stringpool_str5496[sizeof("tm.hu")];
+ char stringpool_str5497[sizeof("xn--skjervy-v1a.no")];
+ char stringpool_str5498[sizeof("jamal.ru")];
+ char stringpool_str5499[sizeof("penza.ru")];
+ char stringpool_str5500[sizeof("is-certified.com")];
+ char stringpool_str5501[sizeof("pf")];
+ char stringpool_str5502[sizeof("tm.km")];
+ char stringpool_str5503[sizeof("gliding.aero")];
+ char stringpool_str5504[sizeof("shimonita.gunma.jp")];
+ char stringpool_str5505[sizeof("dyndns-at-home.com")];
+ char stringpool_str5506[sizeof("tv.bo")];
+ char stringpool_str5507[sizeof("tv.na")];
+ char stringpool_str5508[sizeof("usdecorativearts.museum")];
+ char stringpool_str5509[sizeof("tc")];
+ char stringpool_str5510[sizeof("tv.br")];
+ char stringpool_str5511[sizeof("xn--b-5ga.telemark.no")];
+ char stringpool_str5512[sizeof("airline.aero")];
+ char stringpool_str5513[sizeof("yekaterinburg.ru")];
+ char stringpool_str5514[sizeof("xn--unup4y")];
+ char stringpool_str5515[sizeof("taito.tokyo.jp")];
+ char stringpool_str5516[sizeof("agematsu.nagano.jp")];
+ char stringpool_str5517[sizeof("heroy.more-og-romsdal.no")];
+ char stringpool_str5518[sizeof("lorenskog.no")];
+ char stringpool_str5519[sizeof("andria-barletta-trani.it")];
+ char stringpool_str5520[sizeof("togitsu.nagasaki.jp")];
+ char stringpool_str5521[sizeof("caltanissetta.it")];
+ char stringpool_str5522[sizeof("prd.fr")];
+ char stringpool_str5523[sizeof("huissier-justice.fr")];
+ char stringpool_str5524[sizeof("shell.museum")];
+ char stringpool_str5525[sizeof("ballangen.no")];
+ char stringpool_str5526[sizeof("yamanobe.yamagata.jp")];
+ char stringpool_str5527[sizeof("kawaue.gifu.jp")];
+ char stringpool_str5528[sizeof("westfalen.museum")];
+ char stringpool_str5529[sizeof("serveftp.net")];
+ char stringpool_str5530[sizeof("xn--mlselv-iua.no")];
+ char stringpool_str5531[sizeof("space.museum")];
+ char stringpool_str5532[sizeof("xn--frna-woa.no")];
+ char stringpool_str5533[sizeof("vc.it")];
+ char stringpool_str5534[sizeof("yukuhashi.fukuoka.jp")];
+ char stringpool_str5535[sizeof("tokigawa.saitama.jp")];
+ char stringpool_str5536[sizeof("tadotsu.kagawa.jp")];
+ char stringpool_str5537[sizeof("po.it")];
+ char stringpool_str5538[sizeof("pd.it")];
+ char stringpool_str5539[sizeof("pz.it")];
+ char stringpool_str5540[sizeof("shimizu.shizuoka.jp")];
+ char stringpool_str5541[sizeof("dominic.ua")];
+ char stringpool_str5542[sizeof("pr.it")];
+ char stringpool_str5543[sizeof("salvadordali.museum")];
+ char stringpool_str5544[sizeof("ac.ug")];
+ char stringpool_str5545[sizeof("sowa.ibaraki.jp")];
+ char stringpool_str5546[sizeof("wallonie.museum")];
+ char stringpool_str5547[sizeof("pu.it")];
+ char stringpool_str5548[sizeof("kobierzyce.pl")];
+ char stringpool_str5549[sizeof("kiyosato.hokkaido.jp")];
+ char stringpool_str5550[sizeof("pn.it")];
+ char stringpool_str5551[sizeof("ddr.museum")];
+ char stringpool_str5552[sizeof("pe.it")];
+ char stringpool_str5553[sizeof("gs.jan-mayen.no")];
+ char stringpool_str5554[sizeof("pt.it")];
+ char stringpool_str5555[sizeof("does-it.net")];
+ char stringpool_str5556[sizeof("taiki.hokkaido.jp")];
+ char stringpool_str5557[sizeof("kawasaki.miyagi.jp")];
+ char stringpool_str5558[sizeof("skole.museum")];
+ char stringpool_str5559[sizeof("salem.museum")];
+ char stringpool_str5560[sizeof("pi.it")];
+ char stringpool_str5561[sizeof("suifu.ibaraki.jp")];
+ char stringpool_str5562[sizeof("net.gt")];
+ char stringpool_str5563[sizeof("taira.toyama.jp")];
+ char stringpool_str5564[sizeof("medical.museum")];
+ char stringpool_str5565[sizeof("shiranuka.hokkaido.jp")];
+ char stringpool_str5566[sizeof("hayashima.okayama.jp")];
+ char stringpool_str5567[sizeof("sanagochi.tokushima.jp")];
+ char stringpool_str5568[sizeof("sodegaura.chiba.jp")];
+ char stringpool_str5569[sizeof("is-a-conservative.com")];
+ char stringpool_str5570[sizeof("tf")];
+ char stringpool_str5571[sizeof("christiansburg.museum")];
+ char stringpool_str5572[sizeof("leangaviika.no")];
+ char stringpool_str5573[sizeof("nf.ca")];
+ char stringpool_str5574[sizeof("lavagis.no")];
+ char stringpool_str5575[sizeof("watch-and-clock.museum")];
+ char stringpool_str5576[sizeof("royrvik.no")];
+ char stringpool_str5577[sizeof("xn--vre-eiker-k8a.no")];
+ char stringpool_str5578[sizeof("pa.it")];
+ char stringpool_str5579[sizeof("plc.co.im")];
+ char stringpool_str5580[sizeof("kawagoe.mie.jp")];
+ char stringpool_str5581[sizeof("issmarterthanyou.com")];
+ char stringpool_str5582[sizeof("omotego.fukushima.jp")];
+ char stringpool_str5583[sizeof("pv.it")];
+ char stringpool_str5584[sizeof("takatsuki.shiga.jp")];
+ char stringpool_str5585[sizeof("podlasie.pl")];
+ char stringpool_str5586[sizeof("pesaro-urbino.it")];
+ char stringpool_str5587[sizeof("miyagi.jp")];
+ char stringpool_str5588[sizeof("nayoro.hokkaido.jp")];
+ char stringpool_str5589[sizeof("is-a-lawyer.com")];
+ char stringpool_str5590[sizeof("airport.aero")];
+ char stringpool_str5591[sizeof("air-surveillance.aero")];
+ char stringpool_str5592[sizeof("to.it")];
+ char stringpool_str5593[sizeof("ts.it")];
+ char stringpool_str5594[sizeof("tgory.pl")];
+ char stringpool_str5595[sizeof("tr.it")];
+ char stringpool_str5596[sizeof("delaware.museum")];
+ char stringpool_str5597[sizeof("xn--xkc2dl3a5ee0h")];
+ char stringpool_str5598[sizeof("taka.hyogo.jp")];
+ char stringpool_str5599[sizeof("xn--sknland-fxa.no")];
+ char stringpool_str5600[sizeof("tw.cn")];
+ char stringpool_str5601[sizeof("carboniaiglesias.it")];
+ char stringpool_str5602[sizeof("supply")];
+ char stringpool_str5603[sizeof("tn.it")];
+ char stringpool_str5604[sizeof("takashima.shiga.jp")];
+ char stringpool_str5605[sizeof("te.it")];
+ char stringpool_str5606[sizeof("shinanomachi.nagano.jp")];
+ char stringpool_str5607[sizeof("lib.gu.us")];
+ char stringpool_str5608[sizeof("boleslawiec.pl")];
+ char stringpool_str5609[sizeof("kawara.fukuoka.jp")];
+ char stringpool_str5610[sizeof("pro.vn")];
+ char stringpool_str5611[sizeof("takahata.yamagata.jp")];
+ char stringpool_str5612[sizeof("kawakita.ishikawa.jp")];
+ char stringpool_str5613[sizeof("kawanishi.hyogo.jp")];
+ char stringpool_str5614[sizeof("dyndns-web.com")];
+ char stringpool_str5615[sizeof("oguni.yamagata.jp")];
+ char stringpool_str5616[sizeof("kashiwa.chiba.jp")];
+ char stringpool_str5617[sizeof("shimizu.hokkaido.jp")];
+ char stringpool_str5618[sizeof("shakotan.hokkaido.jp")];
+ char stringpool_str5619[sizeof("achi.nagano.jp")];
+ char stringpool_str5620[sizeof("xn--hbmer-xqa.no")];
+ char stringpool_str5621[sizeof("tt.im")];
+ char stringpool_str5622[sizeof("takko.aomori.jp")];
+ char stringpool_str5623[sizeof("org.st")];
+ char stringpool_str5624[sizeof("serveftp.org")];
+ char stringpool_str5625[sizeof("is-a-geek.net")];
+ char stringpool_str5626[sizeof("pordenone.it")];
+ char stringpool_str5627[sizeof("xn--xkc2al3hye2a")];
+ char stringpool_str5628[sizeof("miyoshi.hiroshima.jp")];
+ char stringpool_str5629[sizeof("shijonawate.osaka.jp")];
+ char stringpool_str5630[sizeof("otsuchi.iwate.jp")];
+ char stringpool_str5631[sizeof("yoshinogari.saga.jp")];
+ char stringpool_str5632[sizeof("ta.it")];
+ char stringpool_str5633[sizeof("is-a-geek.com")];
+ char stringpool_str5634[sizeof("news.hu")];
+ char stringpool_str5635[sizeof("org.tt")];
+ char stringpool_str5636[sizeof("accident-prevention.aero")];
+ char stringpool_str5637[sizeof("tp.it")];
+ char stringpool_str5638[sizeof("yazu.tottori.jp")];
+ char stringpool_str5639[sizeof("time.no")];
+ char stringpool_str5640[sizeof("artcenter.museum")];
+ char stringpool_str5641[sizeof("tv.it")];
+ char stringpool_str5642[sizeof("is-a-nurse.com")];
+ char stringpool_str5643[sizeof("org.bt")];
+ char stringpool_str5644[sizeof("detroit.museum")];
+ char stringpool_str5645[sizeof("okazaki.aichi.jp")];
+ char stringpool_str5646[sizeof("masaki.ehime.jp")];
+ char stringpool_str5647[sizeof("moka.tochigi.jp")];
+ char stringpool_str5648[sizeof("tinn.no")];
+ char stringpool_str5649[sizeof("xn--sr-varanger-ggb.no")];
+ char stringpool_str5650[sizeof("poznan.pl")];
+ char stringpool_str5651[sizeof("katowice.pl")];
+ char stringpool_str5652[sizeof("kawagoe.saitama.jp")];
+ char stringpool_str5653[sizeof("youth.museum")];
+ char stringpool_str5654[sizeof("dyndns-at-work.com")];
+ char stringpool_str5655[sizeof("z-2.compute-1.amazonaws.com")];
+ char stringpool_str5656[sizeof("ichinomiya.aichi.jp")];
+ char stringpool_str5657[sizeof("whaling.museum")];
+ char stringpool_str5658[sizeof("org.mt")];
+ char stringpool_str5659[sizeof("xn--holtlen-hxa.no")];
+ char stringpool_str5660[sizeof("palace.museum")];
+ char stringpool_str5661[sizeof("newmexico.museum")];
+ char stringpool_str5662[sizeof("tv.im")];
+ char stringpool_str5663[sizeof("tana.no")];
+ char stringpool_str5664[sizeof("indiana.museum")];
+ char stringpool_str5665[sizeof("xn--node")];
+ char stringpool_str5666[sizeof("dyndns-wiki.com")];
+ char stringpool_str5667[sizeof("kvanangen.no")];
+ char stringpool_str5668[sizeof("delmenhorst.museum")];
+ char stringpool_str5669[sizeof("tyumen.ru")];
+ char stringpool_str5670[sizeof("sc.tz")];
+ char stringpool_str5671[sizeof("org.pt")];
+ char stringpool_str5672[sizeof("sc.us")];
+ char stringpool_str5673[sizeof("net.cn")];
+ char stringpool_str5674[sizeof("piacenza.it")];
+ char stringpool_str5675[sizeof("kyotanabe.kyoto.jp")];
+ char stringpool_str5676[sizeof("miyoshi.tokushima.jp")];
+ char stringpool_str5677[sizeof("porsangu.no")];
+ char stringpool_str5678[sizeof("yawata.kyoto.jp")];
+ char stringpool_str5679[sizeof("dynathome.net")];
+ char stringpool_str5680[sizeof("shirakawa.gifu.jp")];
+ char stringpool_str5681[sizeof("echizen.fukui.jp")];
+ char stringpool_str5682[sizeof("org.ht")];
+ char stringpool_str5683[sizeof("sc.cn")];
+ char stringpool_str5684[sizeof("voyage")];
+ char stringpool_str5685[sizeof("oamishirasato.chiba.jp")];
+ char stringpool_str5686[sizeof("xn--rhkkervju-01af.no")];
+ char stringpool_str5687[sizeof("daisen.akita.jp")];
+ char stringpool_str5688[sizeof("sc.kr")];
+ char stringpool_str5689[sizeof("is-very-good.org")];
+ char stringpool_str5690[sizeof("tx.us")];
+ char stringpool_str5691[sizeof("toba.mie.jp")];
+ char stringpool_str5692[sizeof("dyndns-work.com")];
+ char stringpool_str5693[sizeof("xn--bidr-5nac.no")];
+ char stringpool_str5694[sizeof("urayasu.chiba.jp")];
+ char stringpool_str5695[sizeof("pharmacy.museum")];
+ char stringpool_str5696[sizeof("xn--bhcavuotna-s4a.no")];
+ char stringpool_str5697[sizeof("sf.no")];
+ char stringpool_str5698[sizeof("linz.museum")];
+ char stringpool_str5699[sizeof("tanagura.fukushima.jp")];
+ char stringpool_str5700[sizeof("sor-fron.no")];
+ char stringpool_str5701[sizeof("loten.no")];
+ char stringpool_str5702[sizeof("minamiechizen.fukui.jp")];
+ char stringpool_str5703[sizeof("skierva.no")];
+ char stringpool_str5704[sizeof("trolley.museum")];
+ char stringpool_str5705[sizeof("yawara.ibaraki.jp")];
+ char stringpool_str5706[sizeof("thruhere.net")];
+ char stringpool_str5707[sizeof("lecco.it")];
+ char stringpool_str5708[sizeof("nowaruda.pl")];
+ char stringpool_str5709[sizeof("uscountryestate.museum")];
+ char stringpool_str5710[sizeof("ne.pw")];
+ char stringpool_str5711[sizeof("rc.it")];
+ char stringpool_str5712[sizeof("bryne.no")];
+ char stringpool_str5713[sizeof("miyama.fukuoka.jp")];
+ char stringpool_str5714[sizeof("lecce.it")];
+ char stringpool_str5715[sizeof("luroy.no")];
+ char stringpool_str5716[sizeof("ogawa.nagano.jp")];
+ char stringpool_str5717[sizeof("taiji.wakayama.jp")];
+ char stringpool_str5718[sizeof("takamatsu.kagawa.jp")];
+ char stringpool_str5719[sizeof("shikatsu.aichi.jp")];
+ char stringpool_str5720[sizeof("xn--ldingen-q1a.no")];
+ char stringpool_str5721[sizeof("tado.mie.jp")];
+ char stringpool_str5722[sizeof("phoenix.museum")];
+ char stringpool_str5723[sizeof("decorativearts.museum")];
+ char stringpool_str5724[sizeof("hitachi.ibaraki.jp")];
+ char stringpool_str5725[sizeof("kawanishi.yamagata.jp")];
+ char stringpool_str5726[sizeof("tono.iwate.jp")];
+ char stringpool_str5727[sizeof("tendo.yamagata.jp")];
+ char stringpool_str5728[sizeof("xn--c1avg")];
+ char stringpool_str5729[sizeof("skjervoy.no")];
+ char stringpool_str5730[sizeof("lucca.it")];
+ char stringpool_str5731[sizeof("ichinohe.iwate.jp")];
+ char stringpool_str5732[sizeof("exchange.aero")];
+ char stringpool_str5733[sizeof("miyako.fukuoka.jp")];
+ char stringpool_str5734[sizeof("parliament.uk")];
+ char stringpool_str5735[sizeof("naturalsciences.museum")];
+ char stringpool_str5736[sizeof("shibata.niigata.jp")];
+ char stringpool_str5737[sizeof("shibetsu.hokkaido.jp")];
+ char stringpool_str5738[sizeof("properties")];
+ char stringpool_str5739[sizeof("tomigusuku.okinawa.jp")];
+ char stringpool_str5740[sizeof("trustee.museum")];
+ char stringpool_str5741[sizeof("pol.dz")];
+ char stringpool_str5742[sizeof("co.ve")];
+ char stringpool_str5743[sizeof("dontexist.net")];
+ char stringpool_str5744[sizeof("theater.museum")];
+ char stringpool_str5745[sizeof("kawai.nara.jp")];
+ char stringpool_str5746[sizeof("dontexist.com")];
+ char stringpool_str5747[sizeof("nasu.tochigi.jp")];
+ char stringpool_str5748[sizeof("kawamata.fukushima.jp")];
+ char stringpool_str5749[sizeof("co.vi")];
+ char stringpool_str5750[sizeof("hu.net")];
+ char stringpool_str5751[sizeof("js.cn")];
+ char stringpool_str5752[sizeof("xn--h1aegh.museum")];
+ char stringpool_str5753[sizeof("jl.cn")];
+ char stringpool_str5754[sizeof("zgorzelec.pl")];
+ char stringpool_str5755[sizeof("pharmaciens.km")];
+ char stringpool_str5756[sizeof("pro.az")];
+ char stringpool_str5757[sizeof("xn--sandnessjen-ogb.no")];
+ char stringpool_str5758[sizeof("niepce.museum")];
+ char stringpool_str5759[sizeof("gb.net")];
+ char stringpool_str5760[sizeof("tranibarlettaandria.it")];
+ char stringpool_str5761[sizeof("xn--tn0ag.hk")];
+ char stringpool_str5762[sizeof("potenza.it")];
+ char stringpool_str5763[sizeof("otago.museum")];
+ char stringpool_str5764[sizeof("tempioolbia.it")];
+ char stringpool_str5765[sizeof("sakai.ibaraki.jp")];
+ char stringpool_str5766[sizeof("traniandriabarletta.it")];
+ char stringpool_str5767[sizeof("xn--andy-ira.no")];
+ char stringpool_str5768[sizeof("sekigahara.gifu.jp")];
+ char stringpool_str5769[sizeof("nikko.tochigi.jp")];
+ char stringpool_str5770[sizeof("iglesiascarbonia.it")];
+ char stringpool_str5771[sizeof("szczytno.pl")];
+ char stringpool_str5772[sizeof("arkhangelsk.ru")];
+ char stringpool_str5773[sizeof("endofinternet.org")];
+ char stringpool_str5774[sizeof("xn--mgbc0a9azcg")];
+ char stringpool_str5775[sizeof("miyawaka.fukuoka.jp")];
+ char stringpool_str5776[sizeof("xn--unjrga-rta.no")];
+ char stringpool_str5777[sizeof("is-a-hunter.com")];
+ char stringpool_str5778[sizeof("is-an-engineer.com")];
+ char stringpool_str5779[sizeof("shimotsuma.ibaraki.jp")];
+ char stringpool_str5780[sizeof("sayama.osaka.jp")];
+ char stringpool_str5781[sizeof("paroch.k12.ma.us")];
+ char stringpool_str5782[sizeof("tobe.ehime.jp")];
+ char stringpool_str5783[sizeof("za.net")];
+ char stringpool_str5784[sizeof("tsukuba.ibaraki.jp")];
+ char stringpool_str5785[sizeof("from-nd.com")];
+ char stringpool_str5786[sizeof("toon.ehime.jp")];
+ char stringpool_str5787[sizeof("is-a-chef.org")];
+ char stringpool_str5788[sizeof("otoyo.kochi.jp")];
+ char stringpool_str5789[sizeof("trainer.aero")];
+ char stringpool_str5790[sizeof("lubin.pl")];
+ char stringpool_str5791[sizeof("xn--porsgu-sta26f.no")];
+ char stringpool_str5792[sizeof("diamonds")];
+ char stringpool_str5793[sizeof("org.sv")];
+ char stringpool_str5794[sizeof("kihoku.ehime.jp")];
+ char stringpool_str5795[sizeof("org.lv")];
+ char stringpool_str5796[sizeof("sayama.saitama.jp")];
+ char stringpool_str5797[sizeof("ichinoseki.iwate.jp")];
+ char stringpool_str5798[sizeof("tamaki.mie.jp")];
+ char stringpool_str5799[sizeof("oharu.aichi.jp")];
+ char stringpool_str5800[sizeof("oarai.ibaraki.jp")];
+ char stringpool_str5801[sizeof("tatsuno.hyogo.jp")];
+ char stringpool_str5802[sizeof("tabuse.yamaguchi.jp")];
+ char stringpool_str5803[sizeof("org.mv")];
+ char stringpool_str5804[sizeof("doomdns.org")];
+ char stringpool_str5805[sizeof("uk.net")];
+ char stringpool_str5806[sizeof("xn--ostery-fya.no")];
+ char stringpool_str5807[sizeof("is-a-celticsfan.org")];
+ char stringpool_str5808[sizeof("gs.sf.no")];
+ char stringpool_str5809[sizeof("gs.of.no")];
+ char stringpool_str5810[sizeof("xn--hnefoss-q1a.no")];
+ char stringpool_str5811[sizeof("ap-northeast-1.compute.amazonaws.com")];
+ char stringpool_str5812[sizeof("omaha.museum")];
+ char stringpool_str5813[sizeof("stuff-4-sale.us")];
+ char stringpool_str5814[sizeof("nogi.tochigi.jp")];
+ char stringpool_str5815[sizeof("pomorze.pl")];
+ char stringpool_str5816[sizeof("xn--mgberp4a5d4a87g")];
+ char stringpool_str5817[sizeof("misconfused.org")];
+ char stringpool_str5818[sizeof("xn--kranghke-b0a.no")];
+ char stringpool_str5819[sizeof("tm.mg")];
+ char stringpool_str5820[sizeof("schlesisches.museum")];
+ char stringpool_str5821[sizeof("at-band-camp.net")];
+ char stringpool_str5822[sizeof("lib.ny.us")];
+ char stringpool_str5823[sizeof("xn--bhccavuotna-k7a.no")];
+ char stringpool_str5824[sizeof("xn--krdsherad-m8a.no")];
+ char stringpool_str5825[sizeof("satx.museum")];
+ char stringpool_str5826[sizeof("artsandcrafts.museum")];
+ char stringpool_str5827[sizeof("adygeya.ru")];
+ char stringpool_str5828[sizeof("sosnowiec.pl")];
+ char stringpool_str5829[sizeof("kimitsu.chiba.jp")];
+ char stringpool_str5830[sizeof("izumizaki.fukushima.jp")];
+ char stringpool_str5831[sizeof("textile.museum")];
+ char stringpool_str5832[sizeof("eu.int")];
+ char stringpool_str5833[sizeof("yaita.tochigi.jp")];
+ char stringpool_str5834[sizeof("sells-for-less.com")];
+ char stringpool_str5835[sizeof("servegame.org")];
+ char stringpool_str5836[sizeof("xn--stjrdal-s1a.no")];
+ char stringpool_str5837[sizeof("jgora.pl")];
+ char stringpool_str5838[sizeof("jpn.com")];
+ char stringpool_str5839[sizeof("tomi.nagano.jp")];
+ char stringpool_str5840[sizeof("england.museum")];
+ char stringpool_str5841[sizeof("finland.museum")];
+ char stringpool_str5842[sizeof("s3.amazonaws.com")];
+ char stringpool_str5843[sizeof("myphotos.cc")];
+ char stringpool_str5844[sizeof("sano.tochigi.jp")];
+ char stringpool_str5845[sizeof("tsukiyono.gunma.jp")];
+ char stringpool_str5846[sizeof("mutsuzawa.chiba.jp")];
+ char stringpool_str5847[sizeof("xn--hgebostad-g3a.no")];
+ char stringpool_str5848[sizeof("luxury")];
+ char stringpool_str5849[sizeof("from-tx.com")];
+ char stringpool_str5850[sizeof("pg.it")];
+ char stringpool_str5851[sizeof("schoenbrunn.museum")];
+ char stringpool_str5852[sizeof("xn--oppegrd-ixa.no")];
+ char stringpool_str5853[sizeof("olbiatempio.it")];
+ char stringpool_str5854[sizeof("lib.ky.us")];
+ char stringpool_str5855[sizeof("tsuwano.shimane.jp")];
+ char stringpool_str5856[sizeof("from-tn.com")];
+ char stringpool_str5857[sizeof("eu-west-1.compute.amazonaws.com")];
+ char stringpool_str5858[sizeof("nakatsugawa.gifu.jp")];
+ char stringpool_str5859[sizeof("xn--vler-qoa.xn--stfold-9xa.no")];
+ char stringpool_str5860[sizeof("taiwa.miyagi.jp")];
+ char stringpool_str5861[sizeof("tsuruga.fukui.jp")];
+ char stringpool_str5862[sizeof("xn--rlingen-mxa.no")];
+ char stringpool_str5863[sizeof("xn--lten-gra.no")];
+ char stringpool_str5864[sizeof("design.aero")];
+ char stringpool_str5865[sizeof("schokoladen.museum")];
+ char stringpool_str5866[sizeof("lutsk.ua")];
+ char stringpool_str5867[sizeof("us-west-2.compute.amazonaws.com")];
+ char stringpool_str5868[sizeof("dagestan.ru")];
+ char stringpool_str5869[sizeof("chippubetsu.hokkaido.jp")];
+ char stringpool_str5870[sizeof("lesja.no")];
+ char stringpool_str5871[sizeof("us-west-1.compute.amazonaws.com")];
+ char stringpool_str5872[sizeof("computer")];
+ char stringpool_str5873[sizeof("kawai.iwate.jp")];
+ char stringpool_str5874[sizeof("sciencecenter.museum")];
+ char stringpool_str5875[sizeof("ln.cn")];
+ char stringpool_str5876[sizeof("sciencecenters.museum")];
+ char stringpool_str5877[sizeof("ap-southeast-2.compute.amazonaws.com")];
+ char stringpool_str5878[sizeof("of.no")];
+ char stringpool_str5879[sizeof("journal.aero")];
+ char stringpool_str5880[sizeof("jorpeland.no")];
+ char stringpool_str5881[sizeof("ap-southeast-1.compute.amazonaws.com")];
+ char stringpool_str5882[sizeof("juedisches.museum")];
+ char stringpool_str5883[sizeof("guovdageaidnu.no")];
+ char stringpool_str5884[sizeof("la.us")];
+ char stringpool_str5885[sizeof("szex.hu")];
+ char stringpool_str5886[sizeof("kiyokawa.kanagawa.jp")];
+ char stringpool_str5887[sizeof("science.museum")];
+ char stringpool_str5888[sizeof("jx.cn")];
+ char stringpool_str5889[sizeof("donostia.museum")];
+ char stringpool_str5890[sizeof("davvesiida.no")];
+ char stringpool_str5891[sizeof("lt.ua")];
+ char stringpool_str5892[sizeof("yachiyo.ibaraki.jp")];
+ char stringpool_str5893[sizeof("lib.wy.us")];
+ char stringpool_str5894[sizeof("hembygdsforbund.museum")];
+ char stringpool_str5895[sizeof("cc.sd.us")];
+ char stringpool_str5896[sizeof("cc.az.us")];
+ char stringpool_str5897[sizeof("k12.ct.us")];
+ char stringpool_str5898[sizeof("cc.as.us")];
+ char stringpool_str5899[sizeof("cc.ar.us")];
+ char stringpool_str5900[sizeof("org.gt")];
+ char stringpool_str5901[sizeof("cc.or.us")];
+ char stringpool_str5902[sizeof("cc.mo.us")];
+ char stringpool_str5903[sizeof("cc.md.us")];
+ char stringpool_str5904[sizeof("cc.al.us")];
+ char stringpool_str5905[sizeof("cc.ms.us")];
+ char stringpool_str5906[sizeof("project.museum")];
+ char stringpool_str5907[sizeof("samnanger.no")];
+ char stringpool_str5908[sizeof("cc.nd.us")];
+ char stringpool_str5909[sizeof("okawa.kochi.jp")];
+ char stringpool_str5910[sizeof("neyagawa.osaka.jp")];
+ char stringpool_str5911[sizeof("cc.tn.us")];
+ char stringpool_str5912[sizeof("tosashimizu.kochi.jp")];
+ char stringpool_str5913[sizeof("lakas.hu")];
+ char stringpool_str5914[sizeof("shirako.chiba.jp")];
+ char stringpool_str5915[sizeof("judaica.museum")];
+ char stringpool_str5916[sizeof("cc.gu.us")];
+ char stringpool_str5917[sizeof("cc.mn.us")];
+ char stringpool_str5918[sizeof("cc.co.us")];
+ char stringpool_str5919[sizeof("cc.de.us")];
+ char stringpool_str5920[sizeof("cc.ut.us")];
+ char stringpool_str5921[sizeof("cc.me.us")];
+ char stringpool_str5922[sizeof("ichikai.tochigi.jp")];
+ char stringpool_str5923[sizeof("dazaifu.fukuoka.jp")];
+ char stringpool_str5924[sizeof("cc.ne.us")];
+ char stringpool_str5925[sizeof("cc.mt.us")];
+ char stringpool_str5926[sizeof("tokoname.aichi.jp")];
+ char stringpool_str5927[sizeof("cc.fl.us")];
+ char stringpool_str5928[sizeof("xn--stjrdalshalsen-sqb.no")];
+ char stringpool_str5929[sizeof("um.gov.pl")];
+ char stringpool_str5930[sizeof("atlanta.museum")];
+ char stringpool_str5931[sizeof("lv.ua")];
+ char stringpool_str5932[sizeof("oyama.tochigi.jp")];
+ char stringpool_str5933[sizeof("cc.mi.us")];
+ char stringpool_str5934[sizeof("cc.ri.us")];
+ char stringpool_str5935[sizeof("cc.ct.us")];
+ char stringpool_str5936[sizeof("lc")];
+ char stringpool_str5937[sizeof("design.museum")];
+ char stringpool_str5938[sizeof("cc.ks.us")];
+ char stringpool_str5939[sizeof("is-a-techie.com")];
+ char stringpool_str5940[sizeof("www.ck")];
+ char stringpool_str5941[sizeof("of.by")];
+ char stringpool_str5942[sizeof("computer.museum")];
+ char stringpool_str5943[sizeof("cc.ny.us")];
+ char stringpool_str5944[sizeof("lukow.pl")];
+ char stringpool_str5945[sizeof("cc.nj.us")];
+ char stringpool_str5946[sizeof("cc.nm.us")];
+ char stringpool_str5947[sizeof("jerusalem.museum")];
+ char stringpool_str5948[sizeof("tachiarai.fukuoka.jp")];
+ char stringpool_str5949[sizeof("cc.la.us")];
+ char stringpool_str5950[sizeof("lomza.pl")];
+ char stringpool_str5951[sizeof("cc.ma.us")];
+ char stringpool_str5952[sizeof("coop.tt")];
+ char stringpool_str5953[sizeof("schweiz.museum")];
+ char stringpool_str5954[sizeof("cc.ga.us")];
+ char stringpool_str5955[sizeof("sc.ug")];
+ char stringpool_str5956[sizeof("barrel-of-knowledge.info")];
+ char stringpool_str5957[sizeof("sande.more-og-romsdal.no")];
+ char stringpool_str5958[sizeof("anpachi.gifu.jp")];
+ char stringpool_str5959[sizeof("cc.ky.us")];
+ char stringpool_str5960[sizeof("cc.nv.us")];
+ char stringpool_str5961[sizeof("cc.ca.us")];
+ char stringpool_str5962[sizeof("isumi.chiba.jp")];
+ char stringpool_str5963[sizeof("pharmacien.fr")];
+ char stringpool_str5964[sizeof("go.dyndns.org")];
+ char stringpool_str5965[sizeof("cc.oh.us")];
+ char stringpool_str5966[sizeof("cc.hi.us")];
+ char stringpool_str5967[sizeof("cc.nh.us")];
+ char stringpool_str5968[sizeof("shibata.miyagi.jp")];
+ char stringpool_str5969[sizeof("is-into-anime.com")];
+ char stringpool_str5970[sizeof("fukuchi.fukuoka.jp")];
+ char stringpool_str5971[sizeof("taki.mie.jp")];
+ char stringpool_str5972[sizeof("inzai.chiba.jp")];
+ char stringpool_str5973[sizeof("cc.ak.us")];
+ char stringpool_str5974[sizeof("cc.ok.us")];
+ char stringpool_str5975[sizeof("depot.museum")];
+ char stringpool_str5976[sizeof("dolls.museum")];
+ char stringpool_str5977[sizeof("wa.gov.au")];
+ char stringpool_str5978[sizeof("spydeberg.no")];
+ char stringpool_str5979[sizeof("iwafune.tochigi.jp")];
+ char stringpool_str5980[sizeof("taishin.fukushima.jp")];
+ char stringpool_str5981[sizeof("lo.it")];
+ char stringpool_str5982[sizeof("lib.co.us")];
+ char stringpool_str5983[sizeof("ohira.tochigi.jp")];
+ char stringpool_str5984[sizeof("student.aero")];
+ char stringpool_str5985[sizeof("pro.tt")];
+ char stringpool_str5986[sizeof("lu.it")];
+ char stringpool_str5987[sizeof("s3-us-west-1.amazonaws.com")];
+ char stringpool_str5988[sizeof("s3-us-west-2.amazonaws.com")];
+ char stringpool_str5989[sizeof("asahi.chiba.jp")];
+ char stringpool_str5990[sizeof("le.it")];
+ char stringpool_str5991[sizeof("takanabe.miyazaki.jp")];
+ char stringpool_str5992[sizeof("lt.it")];
+ char stringpool_str5993[sizeof("lib.ca.us")];
+ char stringpool_str5994[sizeof("iwakuni.yamaguchi.jp")];
+ char stringpool_str5995[sizeof("s3-eu-west-1.amazonaws.com")];
+ char stringpool_str5996[sizeof("org.cn")];
+ char stringpool_str5997[sizeof("ltd.co.im")];
+ char stringpool_str5998[sizeof("li.it")];
+ char stringpool_str5999[sizeof("abiko.chiba.jp")];
+ char stringpool_str6000[sizeof("london")];
+ char stringpool_str6001[sizeof("seaport.museum")];
+ char stringpool_str6002[sizeof("jogasz.hu")];
+ char stringpool_str6003[sizeof("kiwa.mie.jp")];
+ char stringpool_str6004[sizeof("lund.no")];
+ char stringpool_str6005[sizeof("priv.pl")];
+ char stringpool_str6006[sizeof("uw.gov.pl")];
+ char stringpool_str6007[sizeof("tsuchiura.ibaraki.jp")];
+ char stringpool_str6008[sizeof("starachowice.pl")];
+ char stringpool_str6009[sizeof("lier.no")];
+ char stringpool_str6010[sizeof("music.museum")];
+ char stringpool_str6011[sizeof("from-va.com")];
+ char stringpool_str6012[sizeof("lib.fl.us")];
+ char stringpool_str6013[sizeof("pro.ht")];
+ char stringpool_str6014[sizeof("cc.id.us")];
+ char stringpool_str6015[sizeof("lebtimnetz.de")];
+ char stringpool_str6016[sizeof("cc.il.us")];
+ char stringpool_str6017[sizeof("tobishima.aichi.jp")];
+ char stringpool_str6018[sizeof("shirataka.yamagata.jp")];
+ char stringpool_str6019[sizeof("or.pw")];
+ char stringpool_str6020[sizeof("cc.in.us")];
+ char stringpool_str6021[sizeof("cc.wi.us")];
+ char stringpool_str6022[sizeof("travel")];
+ char stringpool_str6023[sizeof("architecture.museum")];
+ char stringpool_str6024[sizeof("trogstad.no")];
+ char stringpool_str6025[sizeof("kuwana.mie.jp")];
+ char stringpool_str6026[sizeof("teaches-yoga.com")];
+ char stringpool_str6027[sizeof("cc.wy.us")];
+ char stringpool_str6028[sizeof("computerhistory.museum")];
+ char stringpool_str6029[sizeof("lyngen.no")];
+ char stringpool_str6030[sizeof("pol.ht")];
+ char stringpool_str6031[sizeof("ostrowiec.pl")];
+ char stringpool_str6032[sizeof("jamison.museum")];
+ char stringpool_str6033[sizeof("daigo.ibaraki.jp")];
+ char stringpool_str6034[sizeof("tynset.no")];
+ char stringpool_str6035[sizeof("cc.wa.us")];
+ char stringpool_str6036[sizeof("travel.pl")];
+ char stringpool_str6037[sizeof("tatsuno.nagano.jp")];
+ char stringpool_str6038[sizeof("joboji.iwate.jp")];
+ char stringpool_str6039[sizeof("travel.tt")];
+ char stringpool_str6040[sizeof("test.tj")];
+ char stringpool_str6041[sizeof("livorno.it")];
+ char stringpool_str6042[sizeof("cc.wv.us")];
+ char stringpool_str6043[sizeof("xn--ryken-vua.no")];
+ char stringpool_str6044[sizeof("cc.ia.us")];
+ char stringpool_str6045[sizeof("lindesnes.no")];
+ char stringpool_str6046[sizeof("priv.me")];
+ char stringpool_str6047[sizeof("shunan.yamaguchi.jp")];
+ char stringpool_str6048[sizeof("lib.tn.us")];
+ char stringpool_str6049[sizeof("treviso.it")];
+ char stringpool_str6050[sizeof("press.aero")];
+ char stringpool_str6051[sizeof("press.se")];
+ char stringpool_str6052[sizeof("scrapping.cc")];
+ char stringpool_str6053[sizeof("leirfjord.no")];
+ char stringpool_str6054[sizeof("tysvar.no")];
+ char stringpool_str6055[sizeof("lib.in.us")];
+ char stringpool_str6056[sizeof("harvestcelebration.museum")];
+ char stringpool_str6057[sizeof("lib.mn.us")];
+ char stringpool_str6058[sizeof("laquila.it")];
+ char stringpool_str6059[sizeof("taranto.it")];
+ char stringpool_str6060[sizeof("tsunan.niigata.jp")];
+ char stringpool_str6061[sizeof("lahppi.no")];
+ char stringpool_str6062[sizeof("bruxelles.museum")];
+ char stringpool_str6063[sizeof("london.museum")];
+ char stringpool_str6064[sizeof("xn--avery-yua.no")];
+ char stringpool_str6065[sizeof("xn--ryrvik-bya.no")];
+ char stringpool_str6066[sizeof("obanazawa.yamagata.jp")];
+ char stringpool_str6067[sizeof("leitungsen.de")];
+ char stringpool_str6068[sizeof("lincoln.museum")];
+ char stringpool_str6069[sizeof("pilot.aero")];
+ char stringpool_str6070[sizeof("parti.se")];
+ char stringpool_str6071[sizeof("larsson.museum")];
+ char stringpool_str6072[sizeof("cc.tx.us")];
+ char stringpool_str6073[sizeof("press.museum")];
+ char stringpool_str6074[sizeof("dc.us")];
+ char stringpool_str6075[sizeof("luzern.museum")];
+ char stringpool_str6076[sizeof("pubol.museum")];
+ char stringpool_str6077[sizeof("ac.pr")];
+ char stringpool_str6078[sizeof("towada.aomori.jp")];
+ char stringpool_str6079[sizeof("oceanographic.museum")];
+ char stringpool_str6080[sizeof("laakesvuemie.no")];
+ char stringpool_str6081[sizeof("z-1.compute-1.amazonaws.com")];
+ char stringpool_str6082[sizeof("monzaedellabrianza.it")];
+ char stringpool_str6083[sizeof("for-more.biz")];
+ char stringpool_str6084[sizeof("stuff-4-sale.org")];
+ char stringpool_str6085[sizeof("tsaritsyn.ru")];
+ char stringpool_str6086[sizeof("trieste.it")];
+ char stringpool_str6087[sizeof("for-some.biz")];
+ char stringpool_str6088[sizeof("xn--3e0b707e")];
+ char stringpool_str6089[sizeof("priv.at")];
+ char stringpool_str6090[sizeof("torahime.shiga.jp")];
+ char stringpool_str6091[sizeof("from-vt.com")];
+ char stringpool_str6092[sizeof("turystyka.pl")];
+ char stringpool_str6093[sizeof("ac.pa")];
+ char stringpool_str6094[sizeof("se.net")];
+ char stringpool_str6095[sizeof("planetarium.museum")];
+ char stringpool_str6096[sizeof("miyama.mie.jp")];
+ char stringpool_str6097[sizeof("homeftp.org")];
+ char stringpool_str6098[sizeof("omigawa.chiba.jp")];
+ char stringpool_str6099[sizeof("xn--fiq64b")];
+ char stringpool_str6100[sizeof("museumvereniging.museum")];
+ char stringpool_str6101[sizeof("s3-ap-northeast-1.amazonaws.com")];
+ char stringpool_str6102[sizeof("paleo.museum")];
+ char stringpool_str6103[sizeof("trust.museum")];
+ char stringpool_str6104[sizeof("toga.toyama.jp")];
+ char stringpool_str6105[sizeof("xn--kvnangen-k0a.no")];
+ char stringpool_str6106[sizeof("office-on-the.net")];
+ char stringpool_str6107[sizeof("lancashire.museum")];
+ char stringpool_str6108[sizeof("ogaki.gifu.jp")];
+ char stringpool_str6109[sizeof("tsuno.kochi.jp")];
+ char stringpool_str6110[sizeof("praxi")];
+ char stringpool_str6111[sizeof("vaapste.no")];
+ char stringpool_str6112[sizeof("pro.mv")];
+ char stringpool_str6113[sizeof("s3-ap-southeast-2.amazonaws.com")];
+ char stringpool_str6114[sizeof("s3-ap-southeast-1.amazonaws.com")];
+ char stringpool_str6115[sizeof("tochigi.tochigi.jp")];
+ char stringpool_str6116[sizeof("tama.tokyo.jp")];
+ char stringpool_str6117[sizeof("ogawa.ibaraki.jp")];
+ char stringpool_str6118[sizeof("kawanabe.kagoshima.jp")];
+ char stringpool_str6119[sizeof("xn--fiq228c5hs")];
+ char stringpool_str6120[sizeof("touch.museum")];
+ char stringpool_str6121[sizeof("discovery.museum")];
+ char stringpool_str6122[sizeof("s3-us-gov-west-1.amazonaws.com")];
+ char stringpool_str6123[sizeof("leka.no")];
+ char stringpool_str6124[sizeof("newyork.museum")];
+ char stringpool_str6125[sizeof("trysil.no")];
+ char stringpool_str6126[sizeof("lajolla.museum")];
+ char stringpool_str6127[sizeof("isa-hockeynut.com")];
+ char stringpool_str6128[sizeof("tsuruta.aomori.jp")];
+ char stringpool_str6129[sizeof("sayo.hyogo.jp")];
+ char stringpool_str6130[sizeof("poltava.ua")];
+ char stringpool_str6131[sizeof("podzone.org")];
+ char stringpool_str6132[sizeof("lg.ua")];
+ char stringpool_str6133[sizeof("lib.az.us")];
+ char stringpool_str6134[sizeof("sa-east-1.compute.amazonaws.com")];
+ char stringpool_str6135[sizeof("xn--btsfjord-9za.no")];
+ char stringpool_str6136[sizeof("newspaper.museum")];
+ char stringpool_str6137[sizeof("ug.gov.pl")];
+ char stringpool_str6138[sizeof("likes-pie.com")];
+ char stringpool_str6139[sizeof("paris.museum")];
+ char stringpool_str6140[sizeof("takinoue.hokkaido.jp")];
+ char stringpool_str6141[sizeof("lillehammer.no")];
+ char stringpool_str6142[sizeof("bellevue.museum")];
+ char stringpool_str6143[sizeof("nrw.museum")];
+ char stringpool_str6144[sizeof("tambov.ru")];
+ char stringpool_str6145[sizeof("texas.museum")];
+ char stringpool_str6146[sizeof("is-a-republican.com")];
+ char stringpool_str6147[sizeof("miyako.iwate.jp")];
+ char stringpool_str6148[sizeof("tawaramoto.nara.jp")];
+ char stringpool_str6149[sizeof("forli-cesena.it")];
+ char stringpool_str6150[sizeof("philately.museum")];
+ char stringpool_str6151[sizeof("s3-website-us-east-1.amazonaws.com")];
+ char stringpool_str6152[sizeof("tarui.gifu.jp")];
+ char stringpool_str6153[sizeof("s3-website-sa-east-1.amazonaws.com")];
+ char stringpool_str6154[sizeof("xn--cg4bki")];
+ char stringpool_str6155[sizeof("sologne.museum")];
+ char stringpool_str6156[sizeof("game-server.cc")];
+ char stringpool_str6157[sizeof("doesntexist.org")];
+ char stringpool_str6158[sizeof("xn--kvfjord-nxa.no")];
+ char stringpool_str6159[sizeof("town.museum")];
+ char stringpool_str6160[sizeof("parachuting.aero")];
+ char stringpool_str6161[sizeof("gs.va.no")];
+ char stringpool_str6162[sizeof("tokuyama.yamaguchi.jp")];
+ char stringpool_str6163[sizeof("newhampshire.museum")];
+ char stringpool_str6164[sizeof("florence.it")];
+ char stringpool_str6165[sizeof("tsubetsu.hokkaido.jp")];
+ char stringpool_str6166[sizeof("from-nc.com")];
+ char stringpool_str6167[sizeof("tokamachi.niigata.jp")];
+ char stringpool_str6168[sizeof("miyoshi.aichi.jp")];
+ char stringpool_str6169[sizeof("xn--ogbpf8fl")];
+ char stringpool_str6170[sizeof("xn--mgbqly7c0a67fbc")];
+ char stringpool_str6171[sizeof("historyofscience.museum")];
+ char stringpool_str6172[sizeof("oryol.ru")];
+ char stringpool_str6173[sizeof("so.gov.pl")];
+ char stringpool_str6174[sizeof("toyama.jp")];
+ char stringpool_str6175[sizeof("sr.gov.pl")];
+ char stringpool_str6176[sizeof("dyndns-server.com")];
+ char stringpool_str6177[sizeof("is-a-chef.net")];
+ char stringpool_str6178[sizeof("tm.mc")];
+ char stringpool_str6179[sizeof("xn--czr694b")];
+ char stringpool_str6180[sizeof("nationalheritage.museum")];
+ char stringpool_str6181[sizeof("xn--czrs0t")];
+ char stringpool_str6182[sizeof("bievat.no")];
+ char stringpool_str6183[sizeof("is-a-chef.com")];
+ char stringpool_str6184[sizeof("xn--mgbtf8fl")];
+ char stringpool_str6185[sizeof("pippu.hokkaido.jp")];
+ char stringpool_str6186[sizeof("elasticbeanstalk.com")];
+ char stringpool_str6187[sizeof("s3-website-ap-southeast-2.amazonaws.com")];
+ char stringpool_str6188[sizeof("xn--comunicaes-v6a2o.museum")];
+ char stringpool_str6189[sizeof("oi.kanagawa.jp")];
+ char stringpool_str6190[sizeof("toyama.toyama.jp")];
+ char stringpool_str6191[sizeof("takanezawa.tochigi.jp")];
+ char stringpool_str6192[sizeof("s3-website-ap-southeast-1.amazonaws.com")];
+ char stringpool_str6193[sizeof("sa.gov.au")];
+ char stringpool_str6194[sizeof("xn--czru2d")];
+ char stringpool_str6195[sizeof("s3-website-ap-northeast-1.amazonaws.com")];
+ char stringpool_str6196[sizeof("toyooka.hyogo.jp")];
+ char stringpool_str6197[sizeof("toyone.aichi.jp")];
+ char stringpool_str6198[sizeof("doomdns.com")];
+ char stringpool_str6199[sizeof("toyo.kochi.jp")];
+ char stringpool_str6200[sizeof("tsuga.tochigi.jp")];
+ char stringpool_str6201[sizeof("s3-website-us-west-2.amazonaws.com")];
+ char stringpool_str6202[sizeof("shinonsen.hyogo.jp")];
+ char stringpool_str6203[sizeof("xn--moreke-jua.no")];
+ char stringpool_str6204[sizeof("tokai.aichi.jp")];
+ char stringpool_str6205[sizeof("toyota.aichi.jp")];
+ char stringpool_str6206[sizeof("s3-website-us-west-1.amazonaws.com")];
+ char stringpool_str6207[sizeof("is-very-sweet.org")];
+ char stringpool_str6208[sizeof("xn--hyanger-q1a.no")];
+ char stringpool_str6209[sizeof("kawachinagano.osaka.jp")];
+ char stringpool_str6210[sizeof("toyono.osaka.jp")];
+ char stringpool_str6211[sizeof("nishitosa.kochi.jp")];
+ char stringpool_str6212[sizeof("tokai.ibaraki.jp")];
+ char stringpool_str6213[sizeof("pc.it")];
+ char stringpool_str6214[sizeof("xn--nvuotna-hwa.no")];
+ char stringpool_str6215[sizeof("sande.vestfold.no")];
+ char stringpool_str6216[sizeof("jobs.tt")];
+ char stringpool_str6217[sizeof("xn--kvitsy-fya.no")];
+ char stringpool_str6218[sizeof("royken.no")];
+ char stringpool_str6219[sizeof("tm.pl")];
+ char stringpool_str6220[sizeof("xn--eveni-0qa01ga.no")];
+ char stringpool_str6221[sizeof("nishinoomote.kagoshima.jp")];
+ char stringpool_str6222[sizeof("kommunalforbund.se")];
+ char stringpool_str6223[sizeof("xn--nmesjevuemie-tcba.no")];
+ char stringpool_str6224[sizeof("priv.hu")];
+ char stringpool_str6225[sizeof("suwa.nagano.jp")];
+ char stringpool_str6226[sizeof("toyako.hokkaido.jp")];
+ char stringpool_str6227[sizeof("toyonaka.osaka.jp")];
+ char stringpool_str6228[sizeof("toyokawa.aichi.jp")];
+ char stringpool_str6229[sizeof("egyptian.museum")];
+ char stringpool_str6230[sizeof("yokoshibahikari.chiba.jp")];
+ char stringpool_str6231[sizeof("toyotomi.hokkaido.jp")];
+ char stringpool_str6232[sizeof("lg.jp")];
+ char stringpool_str6233[sizeof("plaza.museum")];
+ char stringpool_str6234[sizeof("shimonoseki.yamaguchi.jp")];
+ char stringpool_str6235[sizeof("principe.st")];
+ char stringpool_str6236[sizeof("kongsvinger.no")];
+ char stringpool_str6237[sizeof("toyoura.hokkaido.jp")];
+ char stringpool_str6238[sizeof("newjersey.museum")];
+ char stringpool_str6239[sizeof("prochowice.pl")];
+ char stringpool_str6240[sizeof("tsubata.ishikawa.jp")];
+ char stringpool_str6241[sizeof("lenvik.no")];
+ char stringpool_str6242[sizeof("society.museum")];
+ char stringpool_str6243[sizeof("is-a-cubicle-slave.com")];
+ char stringpool_str6244[sizeof("dreamhosters.com")];
+ char stringpool_str6245[sizeof("xn--gecrj9c")];
+ char stringpool_str6246[sizeof("larvik.no")];
+ char stringpool_str6247[sizeof("lib.ut.us")];
+ char stringpool_str6248[sizeof("law.pro")];
+ char stringpool_str6249[sizeof("dnepropetrovsk.ua")];
+ char stringpool_str6250[sizeof("loabat.no")];
+ char stringpool_str6251[sizeof("niyodogawa.kochi.jp")];
+ char stringpool_str6252[sizeof("lib.mt.us")];
+ char stringpool_str6253[sizeof("uchiko.ehime.jp")];
+ char stringpool_str6254[sizeof("porsanger.no")];
+ char stringpool_str6255[sizeof("lib.vt.us")];
+ char stringpool_str6256[sizeof("louvre.museum")];
+ char stringpool_str6257[sizeof("toya.hokkaido.jp")];
+ char stringpool_str6258[sizeof("dnipropetrovsk.ua")];
+ char stringpool_str6259[sizeof("tempio-olbia.it")];
+ char stringpool_str6260[sizeof("vossevangen.no")];
+ char stringpool_str6261[sizeof("ac.vn")];
+ char stringpool_str6262[sizeof("xn--sndre-land-0cb.no")];
+ char stringpool_str6263[sizeof("yanaizu.fukushima.jp")];
+ char stringpool_str6264[sizeof("tcm.museum")];
+ char stringpool_str6265[sizeof("trapani.it")];
+ char stringpool_str6266[sizeof("xn--frde-gra.no")];
+ char stringpool_str6267[sizeof("kawaguchi.saitama.jp")];
+ char stringpool_str6268[sizeof("skiptvet.no")];
+ char stringpool_str6269[sizeof("trading.aero")];
+ char stringpool_str6270[sizeof("xn--tnsberg-q1a.no")];
+ char stringpool_str6271[sizeof("sakae.chiba.jp")];
+ char stringpool_str6272[sizeof("loppa.no")];
+ char stringpool_str6273[sizeof("spy.museum")];
+ char stringpool_str6274[sizeof("labor.museum")];
+ char stringpool_str6275[sizeof("dyndns-blog.com")];
+ char stringpool_str6276[sizeof("is-a-nascarfan.com")];
+ char stringpool_str6277[sizeof("saskatchewan.museum")];
+ char stringpool_str6278[sizeof("yawatahama.ehime.jp")];
+ char stringpool_str6279[sizeof("joyo.kyoto.jp")];
+ char stringpool_str6280[sizeof("lviv.ua")];
+ char stringpool_str6281[sizeof("dyndns-free.com")];
+ char stringpool_str6282[sizeof("xn--czrw28b.tw")];
+ char stringpool_str6283[sizeof("otaki.chiba.jp")];
+ char stringpool_str6284[sizeof("dyndns-office.com")];
+ char stringpool_str6285[sizeof("ruovat.no")];
+ char stringpool_str6286[sizeof("xn--lt-liac.no")];
+ char stringpool_str6287[sizeof("jewish.museum")];
+ char stringpool_str6288[sizeof("yachiyo.chiba.jp")];
+ char stringpool_str6289[sizeof("lib.nv.us")];
+ char stringpool_str6290[sizeof("jewishart.museum")];
+ char stringpool_str6291[sizeof("langevag.no")];
+ char stringpool_str6292[sizeof("jan-mayen.no")];
+ char stringpool_str6293[sizeof("homeftp.net")];
+ char stringpool_str6294[sizeof("directory")];
+ char stringpool_str6295[sizeof("loyalist.museum")];
+ char stringpool_str6296[sizeof("natuurwetenschappen.museum")];
+ char stringpool_str6297[sizeof("is-a-teacher.com")];
+ char stringpool_str6298[sizeof("s3-website-us-gov-west-1.amazonaws.com")];
+ char stringpool_str6299[sizeof("is-not-certified.com")];
+ char stringpool_str6300[sizeof("cc.sc.us")];
+ char stringpool_str6301[sizeof("science-fiction.museum")];
+ char stringpool_str6302[sizeof("cc.dc.us")];
+ char stringpool_str6303[sizeof("cc.nc.us")];
+ char stringpool_str6304[sizeof("is-into-cars.com")];
+ char stringpool_str6305[sizeof("is-into-cartoons.com")];
+ char stringpool_str6306[sizeof("podzone.net")];
+ char stringpool_str6307[sizeof("ofunato.iwate.jp")];
+ char stringpool_str6308[sizeof("doesntexist.com")];
+ char stringpool_str6309[sizeof("is-a-therapist.com")];
+ char stringpool_str6310[sizeof("nationalfirearms.museum")];
+ char stringpool_str6311[sizeof("toyosato.shiga.jp")];
+ char stringpool_str6312[sizeof("cc.pr.us")];
+ char stringpool_str6313[sizeof("lc.it")];
+ char stringpool_str6314[sizeof("national-library-scotland.uk")];
+ char stringpool_str6315[sizeof("cc.pa.us")];
+ char stringpool_str6316[sizeof("is-with-theband.com")];
+ char stringpool_str6317[sizeof("davvenjarga.no")];
+ char stringpool_str6318[sizeof("priv.no")];
+ char stringpool_str6319[sizeof("convent.museum")];
+ char stringpool_str6320[sizeof("xn--indery-fya.no")];
+ char stringpool_str6321[sizeof("po.gov.pl")];
+ char stringpool_str6322[sizeof("pa.gov.pl")];
+ char stringpool_str6323[sizeof("compute.amazonaws.com")];
+ char stringpool_str6324[sizeof("compute-1.amazonaws.com")];
+ char stringpool_str6325[sizeof("experts-comptables.fr")];
+ char stringpool_str6326[sizeof("leasing.aero")];
+ char stringpool_str6327[sizeof("xn--54b7fta0cc")];
+ char stringpool_str6328[sizeof("is-very-nice.org")];
+ char stringpool_str6329[sizeof("xn--fpcrj9c3d")];
+ char stringpool_str6330[sizeof("jfk.museum")];
+ char stringpool_str6331[sizeof("leikanger.no")];
+ char stringpool_str6332[sizeof("lucerne.museum")];
+ char stringpool_str6333[sizeof("jp.net")];
+ char stringpool_str6334[sizeof("xn--mtta-vrjjat-k7af.no")];
+ char stringpool_str6335[sizeof("gs.vf.no")];
+ char stringpool_str6336[sizeof("laspezia.it")];
+ char stringpool_str6337[sizeof("is-into-games.com")];
+ char stringpool_str6338[sizeof("resistance.museum")];
+ char stringpool_str6339[sizeof("pc.pl")];
+ char stringpool_str6340[sizeof("scientist.aero")];
+ char stringpool_str6341[sizeof("s3-website-eu-west-1.amazonaws.com")];
+ char stringpool_str6342[sizeof("xn--hmmrfeasta-s4ac.no")];
+ char stringpool_str6343[sizeof("newport.museum")];
+ char stringpool_str6344[sizeof("stavanger.no")];
+ char stringpool_str6345[sizeof("toyoake.aichi.jp")];
+ char stringpool_str6346[sizeof("jewelry.museum")];
+ char stringpool_str6347[sizeof("cc.vt.us")];
+ char stringpool_str6348[sizeof("cc.vi.us")];
+ char stringpool_str6349[sizeof("toyota.yamaguchi.jp")];
+ char stringpool_str6350[sizeof("cc.va.us")];
+ char stringpool_str6351[sizeof("hoylandet.no")];
+ char stringpool_str6352[sizeof("corvette.museum")];
+ char stringpool_str6353[sizeof("toyohashi.aichi.jp")];
+ char stringpool_str6354[sizeof("lib.ct.us")];
+ char stringpool_str6355[sizeof("air-traffic-control.aero")];
+ char stringpool_str6356[sizeof("us-gov-west-1.compute.amazonaws.com")];
+ char stringpool_str6357[sizeof("jaworzno.pl")];
+ char stringpool_str6358[sizeof("posts-and-telecommunications.museum")];
+ char stringpool_str6359[sizeof("powiat.pl")];
+ char stringpool_str6360[sizeof("passenger-association.aero")];
+ char stringpool_str6361[sizeof("logistics.aero")];
+ char stringpool_str6362[sizeof("lewismiller.museum")];
+ char stringpool_str6363[sizeof("xn--stre-toten-zcb.no")];
+ char stringpool_str6364[sizeof("toyotsu.fukuoka.jp")];
+ char stringpool_str6365[sizeof("pacific.museum")];
+ char stringpool_str6366[sizeof("xn--nttery-byae.no")];
+ char stringpool_str6367[sizeof("shimotsuke.tochigi.jp")];
+ char stringpool_str6368[sizeof("geometre-expert.fr")];
+ char stringpool_str6369[sizeof("endoftheinternet.org")];
+ char stringpool_str6370[sizeof("skydiving.aero")];
+ char stringpool_str6371[sizeof("xn--correios-e-telecomunicaes-ghc29a.museum")];
+ char stringpool_str6372[sizeof("lowicz.pl")];
+ char stringpool_str6373[sizeof("xn--clchc0ea0b2g2a9gcd")];
+ char stringpool_str6374[sizeof("xn--fzc2c9e2c")];
};
static const struct stringpool_t stringpool_contents =
{
- "gu",
- "eu",
- "gd",
+ "io",
"gov",
+ "gd",
+ "id",
+ "edu",
"co",
- "cv",
- "cu",
- "gm",
+ "gop",
"cd",
- "edu",
- "so",
- "sv",
- "su",
- "ao",
- "sd",
- "au",
- "cm",
- "ad",
- "ro",
- "ru",
"cz",
- "sm",
+ "gov.do",
"com",
- "am",
- "sz",
- "gov.to",
- "gov.tm",
- "az",
- "edu.to",
- "edu.tm",
- "gov.bo",
- "gov.bm",
- "cx",
- "edu.bo",
- "edu.bm",
- "sx",
- "gov.ae",
- "ax",
- "com.to",
- "com.tm",
- "com.bo",
- "com.bm",
- "gov.bz",
- "edu.bi",
+ "gob.do",
+ "gov.om",
+ "edu.do",
+ "gov.dm",
+ "gs",
+ "is",
+ "edu.om",
+ "es",
+ "edu.dm",
+ "com.do",
"gr",
+ "ir",
+ "hr",
"er",
- "edu.bz",
- "gov.az",
+ "com.om",
+ "com.dm",
"cr",
- "edu.az",
- "com.bi",
- "co.ma",
- "go.it",
- "sr",
- "com.bz",
- "ar",
- "com.ai",
- "co.it",
- "com.az",
- "so.it",
- "sv.it",
- "ao.it",
- "av.it",
- "km",
- "gov.qa",
- "com.ag",
- "ro.it",
- "kz",
- "cz.it",
- "edu.qa",
- "gov.ba",
- "gov.sd",
- "edu.ba",
- "rm.it",
- "edu.sd",
- "com.qa",
- "gt",
- "et",
- "com.ba",
- "gov.bs",
+ "ao",
+ "gov.rs",
+ "ad",
+ "az",
+ "edu.rs",
"com.so",
- "com.sd",
- "edu.bs",
- "gov.as",
- "co.ca",
- "st",
- "at",
- "gov.sg",
- "gr.it",
- "com.bs",
- "edu.sg",
- "kr",
- "cr.it",
- "co.ua",
- "cv.ua",
- "sr.it",
- "com.sg",
- "ar.it",
- "gs",
- "es",
- "rv.ua",
- "gov.ac",
- "sm.ua",
- "gov.sa",
- "gov.jo",
- "edu.ac",
- "gov.je",
- "edu.sa",
- "edu.jo",
- "as",
- "ge",
- "ee",
- "rs",
- "com.ac",
- "com.sa",
- "como.it",
- "com.jo",
- "se",
- "ae",
- "gov.bb",
- "re",
- "gu.us",
- "ct.it",
- "edu.bb",
- "co.us",
- "at.it",
- "cr.ua",
- "sd.us",
- "com.bb",
- "kr.it",
+ "gl",
+ "il",
+ "com.ro",
"gov.sc",
- "kv.ua",
+ "cl",
+ "homes",
+ "as",
+ "gov.lr",
"edu.sc",
- "az.us",
- "km.ua",
- "com.sc",
- "cs.it",
- "mo",
- "mv",
- "mu",
- "md",
- "ss.it",
- "ge.it",
- "mm",
- "mz",
- "ke",
- "ce.it",
"gov.sb",
+ "edu.lr",
+ "ar",
+ "bo",
"edu.sb",
- "aero",
- "re.it",
- "mx",
- "ar.us",
- "com.sb",
- "kr.ua",
- "to",
- "tv",
- "gov.au",
- "educ.ar",
- "td",
- "lv",
- "lu",
- "edu.au",
- "tm",
- "tz",
- "mr",
- "com.au",
- "g.se",
- "e.se",
- "gov.co",
- "gov.cm",
- "gov.cd",
- "rome.it",
- "edu.co",
- "c.se",
- "mo.it",
- "gov.tt",
- "s.se",
- "ct.us",
- "a.se",
- "edu.tt",
- "gov.bt",
- "com.co",
- "r.se",
- "edu.ci",
- "edu.bt",
- "com.tt",
- "com.ci",
- "com.bt",
- "tr",
- "lr",
- "jo",
+ "com.sc",
+ "bd",
+ "bz",
"fo",
- "mt",
- "to.it",
- "tv.it",
- "lo.it",
- "lu.it",
- "jm",
- "fm",
- "as.us",
- "coop",
- "ks.ua",
- "gi",
- "gov.tn",
- "k.se",
- "ci",
- "gov.st",
- "gov.br",
- "si",
- "edu.st",
- "aero.mv",
- "ai",
- "edu.br",
- "ms",
- "tt",
- "lt",
- "com.tn",
- "co.tt",
- "edu.an",
- "com.st",
- "com.br",
- "adv.br",
- "gn",
- "me",
- "fr",
- "com.an",
- "tr.it",
- "cn",
- "adm.br",
- "sn",
- "lv.ua",
- "an",
- "mt.it",
- "ks.us",
- "mo.us",
- "gouv.km",
- "md.us",
- "fm.it",
- "ls",
- "do",
- "ki",
- "ci.it",
- "edu.sn",
- "dm",
- "srv.br",
- "si.it",
- "dz",
- "ms.it",
- "ri.it",
- "com.sn",
- "lt.it",
- "asso.km",
- "gov.tl",
- "asti.it",
- "lodi.it",
- "en.it",
- "me.it",
- "fr.it",
- "kn",
- "cn.it",
- "gov.al",
- "an.it",
- "edu.al",
- "coop.mv",
- "rn.it",
- "tx.us",
- "gouv.sn",
- "coop.km",
- "tj",
- "ts.it",
- "com.al",
- "co.na",
- "ato.br",
- "med.sd",
- "je",
- "gl",
- "go.tj",
- "te.it",
- "asso.gp",
- "le.it",
- "cl",
- "co.tj",
- "lt.ua",
- "sl",
- "gouv.ml",
- "m.se",
+ "com.lr",
+ "com.sb",
+ "arpa",
+ "gu",
+ "art.do",
+ "hu",
+ "eu",
+ "gov.lc",
+ "cool",
+ "condos",
+ "guru",
"al",
- "gov.cu",
- "mt.us",
- "edu.cu",
+ "cu",
+ "edu.lc",
+ "bs",
+ "gov.lb",
+ "edu.lb",
+ "br",
+ "com.lc",
+ "gov.lk",
"gov.sl",
- "cn.ua",
+ "fr",
+ "edu.lk",
+ "com.lb",
"edu.sl",
- "com.cu",
+ "com.de",
+ "com.lk",
"com.sl",
- "med.sa",
- "art.br",
- "fj",
- "t.se",
- "bo",
- "tromso.no",
- "l.se",
- "bd",
- "ms.us",
- "ri.us",
- "te.ua",
- "bm",
- "ga",
- "bz",
- "fe.it",
- "ca",
- "me.us",
- "cl.it",
- "sa",
- "gov.tj",
- "al.it",
- "tm.mc",
- "edu.tj",
- "de",
- "com.tj",
- "gouv.bj",
- "art.sn",
- "br",
- "mn",
- "tromsa.no",
- "f.se",
- "gov.cn",
- "bo.it",
- "li",
- "edu.cn",
- "coop.br",
- "bz.it",
- "sb",
- "com.cn",
- "ca.it",
- "dj",
- "aero.tt",
- "sa.it",
- "asso.bj",
- "mi.it",
- "tn",
- "ra.it",
"g.bg",
+ "i.bg",
+ "h.bg",
"e.bg",
"6.bg",
"2.bg",
- "gob.bo",
- "1.bg",
+ "au",
"9.bg",
- "bt",
"8.bg",
- "c.bg",
"7.bg",
"5.bg",
"4.bg",
+ "c.bg",
+ "q.bg",
"3.bg",
- "co.ls",
- "s.bg",
+ "1.bg",
+ "gn",
+ "in",
+ "hn",
+ "int",
+ "g.se",
+ "i.se",
+ "h.se",
+ "e.se",
"0.bg",
+ "cn",
+ "grp.lk",
+ "com.re",
+ "arts.ro",
+ "c.se",
+ "gov.nr",
+ "edu.nr",
+ "blue",
+ "com.nr",
"a.bg",
- "r.bg",
- "vu",
- "br.it",
- "mn.it",
- "cat",
- "fi",
- "tur.br",
- "trd.br",
- "li.it",
- "al.us",
- "gov.ee",
- "bs",
- "cb.it",
- "edu.ee",
- "d.se",
- "gov.cl",
- "com.ee",
- "be",
- "tn.it",
- "ml",
- "co.me",
- "gov.eg",
- "ruovat.no",
- "bt.it",
- "k.bg",
- "edu.eg",
- "mx.na",
- "gp",
- "cim.br",
- "mus.br",
- "com.eg",
- "tv.na",
- "vv.it",
- "ga.us",
- "coop.tt",
- "ab.ca",
- "ca.us",
- "jor.br",
- "fi.it",
- "med.br",
- "tl",
- "mi.us",
- "sb.ua",
- "rnu.tn",
- "bj",
- "bs.it",
- "de.us",
- "gv.at",
+ "autos",
+ "eus",
+ "arts.co",
+ "ge",
+ "ie",
+ "info",
+ "ee",
+ "hof.no",
+ "an",
+ "a.se",
+ "house",
+ "horse",
+ "gob.es",
+ "b.br",
"edu.es",
- "co.at",
- "asso.re",
- "ma",
- "kurgan.ru",
+ "b.bg",
"com.es",
- "co.mw",
- "gh",
- "mn.us",
- "teo.br",
- "ch",
- "vr.it",
- "coop.mw",
- "sh",
+ "gq",
+ "iq",
+ "f.bg",
+ "gt",
+ "it",
+ "ht",
+ "et",
+ "bn",
"gov.ec",
- "fot.br",
- "co.uz",
- "kp",
+ "gob.ec",
+ "b.se",
+ "ae",
"edu.ec",
- "crew.aero",
- "asn.au",
- "sp.it",
- "ap.it",
- "ck",
+ "f.se",
+ "gov.to",
+ "glass",
+ "gov.tj",
"com.ec",
- "sk",
- "eti.br",
- "la",
- "tn.us",
- "b.se",
- "ve",
- "gov.ws",
- "edu.ws",
- "jus.br",
- "vt.it",
- "com.ws",
- "co.lc",
- "cnt.br",
- "kh",
- "ch.it",
- "m.bg",
- "riik.ee",
- "mobi",
- "vs.it",
- "lb",
- "ens.tn",
- "ta.it",
- "firm.in",
- "andebu.no",
+ "edu.to",
+ "gov.tm",
+ "aero",
+ "edu.tj",
+ "edu.tm",
+ "com.to",
+ "gov.sa",
+ "com.tj",
+ "com.tm",
+ "aq",
+ "int.lk",
+ "edu.sa",
+ "gov.sd",
+ "info.ro",
+ "be",
+ "at",
+ "edu.sd",
+ "com.sa",
+ "ceo",
+ "com.sd",
+ "auto.pl",
+ "isa.us",
+ "gov.la",
+ "codes",
+ "info.co",
+ "edu.la",
+ "gov.ee",
+ "asso.ci",
+ "edu.ee",
+ "bt",
+ "com.la",
+ "com.ee",
+ "info.la",
+ "gov.tl",
+ "info.pl",
+ "gov.bs",
+ "gov.br",
+ "gov.bo",
+ "gob.bo",
+ "gov.ua",
+ "edu.bs",
+ "edu.br",
+ "edu.bo",
+ "gov.bm",
+ "edu.ua",
+ "info.ki",
+ "edu.bm",
+ "com.bs",
+ "com.br",
+ "com.bo",
+ "zone",
+ "com.ua",
+ "com.bm",
+ "gi",
+ "gov.bb",
+ "esp.br",
+ "best",
+ "estate",
+ "ci",
+ "edu.bb",
+ "gov.iq",
+ "gov.is",
+ "gov.ir",
+ "adv.br",
+ "edu.iq",
+ "edu.is",
+ "com.bb",
+ "adm.br",
+ "mo",
+ "com.iq",
+ "com.is",
+ "md",
+ "com.io",
+ "mz",
+ "gift",
+ "bb",
+ "com.im",
+ "int.tj",
+ "beer",
+ "com.na",
+ "ai",
+ "z.bg",
+ "art.br",
+ "ms",
+ "country",
+ "fot.br",
+ "mr",
+ "info.pr",
+ "z.se",
+ "gov.nc.tr",
+ "moe",
+ "gov.rw",
+ "edu.rw",
"bi",
- "ve.it",
- "rns.tn",
- "roma.it",
- "mb.it",
- "t.bg",
- "l.bg",
- "biz",
- "bmd.br",
- "tel",
- "sk.ca",
- "bn",
- "dn.ua",
- "jeju.kr",
- "ck.ua",
- "conf.lv",
"fst.br",
- "mp",
- "dr.na",
- "mb.ca",
- "vt.us",
- "ma.us",
- "bi.it",
- "biz.az",
- "co.ve",
- "j.bg",
- "f.bg",
- "gov.ng",
- "edu.ng",
- "kh.ua",
- "komi.ru",
- "bn.it",
- "conf.au",
- "com.ng",
- "ak.us",
- "co.in",
- "fl.us",
- "la.us",
- "mh",
- "ltd.co.im",
- "vi",
- "gd.cn",
- "mk",
- "com.na",
- "gz.cn",
- "ca.na",
- "sd.cn",
- "go.tz",
- "th",
- "vn",
- "gx.cn",
- "co.tz",
- "gouv.rw",
- "jp",
- "mobi.gp",
- "tp.it",
- "sx.cn",
- "tk",
- "d.bg",
- "lk",
- "mil",
- "fnd.br",
- "med.ee",
- "vi.it",
- "biz.bb",
- "mil.to",
- "mil.tm",
- "go.pw",
- "emp.br",
- "mil.bo",
- "ed.pw",
- "eun.eg",
- "ba",
- "co.pw",
- "bl.it",
- "mil.ae",
- "mil.tz",
+ "fet.no",
+ "ml",
+ "int.la",
+ "fi",
+ "com.rw",
+ "center",
+ "asso.dz",
+ "gotdns.com",
+ "gov.qa",
+ "edu.qa",
+ "info.bb",
+ "fla.no",
+ "info.az",
+ "gy",
+ "gifu.jp",
+ "gov.ie",
+ "com.qa",
+ "info.pk",
+ "cy",
+ "int.bo",
+ "mu",
+ "cnt.br",
+ "blog.br",
+ "inf.br",
"flog.br",
- "eidfjord.no",
- "res.aero",
- "mil.az",
- "fk",
- "mil.qa",
- "mk.ua",
- "sirdal.no",
- "mil.ba",
- "bb",
- "taxi.br",
- "gs.cn",
- "ba.it",
- "vn.ua",
- "rnrt.tn",
- "med.ec",
- "b.bg",
- "vi.us",
- "biz.tt",
- "fhv.se",
- "mil.ac",
- "biz.at",
- "mil.jo",
- "lerdal.no",
- "dk",
- "va",
- "lom.no",
- "tas.au",
- "taxi.aero",
- "esp.br",
- "suldal.no",
- "asso.mc",
- "alvdal.no",
- "frog.museum",
- "skodje.no",
- "mo.cn",
- "gov.nc.tr",
- "mat.br",
- "asia",
- "rollag.no",
"c.la",
- "bio.br",
- "antiques.museum",
- "eu.int",
- "mobi.tt",
- "dp.ua",
- "gov.nr",
- "lel.br",
- "edu.nr",
- "va.it",
- "com.nr",
- "assisi.museum",
- "vet.br",
- "co.pn",
- "far.br",
- "eid.no",
- "tv.tz",
- "v.bg",
- "gob.cl",
- "surnadal.no",
- "blog.br",
- "bh",
- "bari.it",
- "mil.co",
- "test.tj",
- "vb.it",
- "tmp.br",
- "asmatart.museum",
- "show.aero",
- "trento.it",
- "jx.cn",
- "gob.es",
- "lindas.no",
- "kvafjord.no",
- "fuel.aero",
- "game.tw",
- "snoasa.no",
- "va.us",
- "gob.ec",
- "sn.cn",
- "fin.tn",
- "gw",
"assn.lk",
+ "int.is",
+ "m.bg",
+ "uz",
+ "mn",
+ "m.se",
+ "by",
+ "gov.ba",
+ "gov.jo",
+ "edu.ba",
+ "us",
+ "edu.jo",
+ "fosnes.no",
+ "com.ba",
+ "com.jo",
+ "coffee",
+ "gm",
+ "im",
+ "hm",
+ "me",
+ "firm.ro",
+ "cm",
+ "int.rw",
+ "hemnes.no",
+ "gov.mr",
+ "gov.mo",
+ "edu.mo",
+ "com.mo",
+ "firm.co",
+ "mq",
"g12.br",
- "mil.st",
- "mil.br",
- "gotdns.com",
- "cw",
- "me.tz",
- "co.ae",
- "aw",
- "rw",
+ "fed.us",
+ "mt",
+ "moda",
+ "am",
+ "bj",
+ "meet",
+ "fj",
+ "gov.tw",
+ "menu",
+ "gov.mk",
+ "blogspot.no",
+ "idv.tw",
+ "edu.tw",
"gol.no",
- "jondal.no",
- "tree.museum",
- "vlog.br",
- "gov.bf",
- "k12.ak.us",
- "gov.af",
- "vdonsk.ru",
- "edu.af",
- "k12.az.us",
- "evenes.no",
- "com.af",
- "biz.tj",
- "rindal.no",
- "fhsk.se",
- "js.cn",
- "kw",
- "tj.cn",
- "kobe.jp",
- "k12.sd.us",
- "stuttgart.museum",
- "mil.al",
- "k12.as.us",
+ "edu.mk",
+ "hol.no",
+ "blogspot.cz",
+ "com.tw",
+ "com.mk",
+ "bm",
+ "blogspot.ro",
+ "fm",
+ "gov.ml",
+ "bid",
+ "u.bg",
+ "edu.ml",
+ "com.ml",
+ "gov.me",
+ "ato.br",
+ "u.se",
+ "edu.me",
+ "blogspot.nl",
+ "gdansk.pl",
+ "ind.br",
+ "cim.br",
+ "eng.br",
+ "info.mv",
+ "algard.no",
+ "museum",
+ "aip.ee",
+ "cng.br",
+ "blogspot.kr",
+ "fin.ec",
+ "ga",
+ "codespot.com",
+ "blogspot.td",
+ "isla.pr",
+ "haus",
+ "ca",
+ "qa",
+ "cat",
+ "gov.as",
+ "cab",
+ "gob.ar",
+ "edu.ar",
+ "eid.no",
+ "com.ar",
+ "mod.uk",
+ "uno",
+ "frosta.no",
+ "gov.ac",
+ "aero.mv",
+ "edu.ac",
+ "com.ac",
"fie.ee",
- "arpa",
- "juif.museum",
- "gov.ve",
- "jevnaker.no",
- "edu.ve",
- "fet.no",
- "lib.ak.us",
- "com.ve",
- "kiev.ua",
- "fj.cn",
- "se.net",
- "lib.az.us",
- "asso.nc",
- "com.vi",
- "military.museum",
- "sshn.se",
- "crafts.museum",
- "firm.nf",
- "time.museum",
- "lviv.ua",
- "kustanai.ru",
- "gaular.no",
- "lib.sd.us",
- "rendalen.no",
- "roma.museum",
- "meldal.no",
- "k12.sc.us",
- "lardal.no",
- "sel.no",
- "verdal.no",
- "trogstad.no",
- "lib.as.us",
- "sor-aurdal.no",
- "mil.tj",
- "enna.it",
- "mw",
+ "blogspot.com",
+ "fnd.br",
+ "edu.bi",
+ "gp",
+ "gov.ma",
+ "ba",
+ "inf.mk",
+ "cards",
+ "bar",
+ "com.bi",
+ "blogspot.mr",
+ "museum.no",
+ "gov.ps",
+ "gov.pr",
+ "gov.al",
+ "med.om",
+ "edu.ps",
+ "edu.pr",
+ "asso.bj",
+ "edu.al",
+ "biz",
+ "casa",
+ "com.ps",
+ "com.pr",
+ "qsl.br",
+ "com.al",
+ "gov.ae",
+ "zm",
+ "est.pr",
+ "blogspot.re",
+ "bio.br",
+ "my",
+ "unsa.ba",
+ "gov.pk",
+ "gob.pk",
+ "farm",
+ "edu.pk",
+ "gop.pk",
+ "cv",
+ "com.pk",
+ "club",
+ "conf.lv",
+ "zlg.br",
+ "homeip.net",
+ "int.ar",
+ "gov.pl",
+ "mus.br",
+ "imb.br",
"gov.vc",
- "hu",
+ "edu.pl",
+ "consulado.st",
+ "gon.pk",
"edu.vc",
- "hm",
- "voagat.no",
- "solund.no",
+ "emp.br",
+ "i.ph",
+ "com.pl",
+ "gob.pe",
"com.vc",
- "ln.cn",
- "mil.cn",
- "mobi.na",
- "tw",
- "muenster.museum",
- "k12.co.us",
- "hr",
- "lib.sc.us",
- "grimstad.no",
- "lodingen.no",
- "silk.museum",
- "jpn.com",
- "chieti.it",
- "mari.ru",
- "torino.it",
- "k12.ca.us",
- "ht",
- "bievat.no",
- "co.rs",
- "k12.tn.us",
- "mil.cl",
- "test.ru",
- "k12.ar.us",
- "bj.cn",
- "aip.ee",
- "mil.eg",
- "stalbans.museum",
- "fosnes.no",
- "lib.co.us",
- "modena.it",
- "gy",
- "murmansk.ru",
- "cy",
- "farm.museum",
- "sy",
- "svalbard.no",
- "moma.museum",
- "sh.cn",
- "ah.cn",
- "rimini.it",
- "gov.bh",
- "gouv.fr",
- "edu.bh",
- "jl.cn",
- "com.bh",
- "lib.ca.us",
- "crimea.ua",
- "fin.ec",
- "masfjorden.no",
- "mil.ec",
- "estate.museum",
- "santacruz.museum",
- "lib.tn.us",
- "tuva.ru",
- "gov.vn",
- "ky",
- "k12.al.us",
- "asso.fr",
- "edu.vn",
- "lib.ar.us",
- "luster.no",
- "com.vn",
- "evenassi.no",
- "gov.sh",
- "edunet.tn",
- "mandal.no",
- "snaase.no",
- "com.sh",
- "bergen.no",
- "caa.aero",
- "lib.ee",
- "baseball.museum",
- "h.se",
- "varese.it",
- "k12.ec",
- "mine.nu",
- "moskenes.no",
- "k12.ct.us",
- "coal.museum",
- "bw",
- "lib.al.us",
- "venice.it",
- "strand.no",
- "beauxarts.museum",
- "marker.no",
- "freiburg.museum",
- "maritimo.museum",
- "suedtirol.it",
- "gb.net",
- "auto.pl",
- "bindal.no",
- "finearts.museum",
- "mil.no",
- "my",
- "cadaques.museum",
- "savona.it",
- "hn",
- "film.museum",
- "gq",
- "bern.museum",
- "grue.no",
- "amursk.ru",
- "ky.us",
- "reklam.hu",
- "aq",
- "lib.ct.us",
- "ly",
- "aure.no",
- "kirkenes.no",
- "tank.museum",
- "rubtsovsk.ru",
- "kvalsund.no",
- "marine.ru",
- "baidar.no",
- "co.ba",
- "fuettertdasnetz.de",
- "ski.no",
- "aq.it",
- "retina.ar",
- "torino.museum",
- "casino.hu",
- "trentino.it",
- "hi.us",
- "k12.wi.us",
+ "edu.pe",
+ "gsm.pl",
+ "com.pe",
+ "asia",
+ "gos.pk",
+ "globo",
+ "mm",
+ "gov.mw",
+ "career",
+ "gov.ve",
+ "edu.mw",
+ "art.pl",
+ "edu.ve",
+ "qpon",
+ "com.mw",
+ "com.ve",
"biz.nr",
- "gouv.ht",
- "bonn.museum",
- "baikal.ru",
- "fhs.no",
- "lunner.no",
- "k12.wa.us",
- "amot.no",
- "dinosaur.museum",
- "asso.ht",
- "travel",
- "servebbs.net",
- "rs.ba",
- "dep.no",
- "mq",
- "coop.ht",
- "berkeley.museum",
- "lib.wi.us",
- "exhibition.museum",
- "museet.museum",
- "eastcoast.museum",
- "h.bg",
- "karate.museum",
- "lib.wa.us",
- "research.museum",
- "fla.no",
- "from.hr",
- "by",
- "verona.it",
- "farmstead.museum",
- "dali.museum",
- "tula.ru",
- "k12.nm.us",
- "k12.ne.us",
- "k12.nd.us",
- "rost.no",
- "chel.ru",
- "exeter.museum",
+ "za",
+ "uy",
+ "its.me",
+ "amursk.ru",
+ "blogspot.de",
+ "glogow.pl",
+ "is-a-cpa.com",
+ "med.ec",
+ "camera",
+ "gob.pa",
"com.nf",
- "firm.co",
- "sendai.jp",
- "latina.it",
- "sund.no",
- "co.rw",
- "amli.no",
- "bodo.no",
- "gg",
- "eg",
+ "edu.pa",
+ "blogspot.se",
+ "blogspot.com.es",
+ "gda.pl",
"hurdal.no",
- "jp.net",
- "cg",
- "hk",
- "sg",
- "ag",
- "frei.no",
- "lib.nm.us",
- "lib.ne.us",
- "lib.nd.us",
- "mill.museum",
- "k12.nc.us",
- "arq.br",
- "etne.no",
- "living.museum",
- "travel.tt",
- "co.je",
- "kg",
- "ralingen.no",
- "kvam.no",
- "ag.it",
- "rg.it",
- "birkenes.no",
- "mie.jp",
- "gouv.ci",
- "servebbs.org",
- "amur.ru",
- "bale.museum",
+ "com.pa",
+ "build",
+ "alvdal.no",
+ "med.sa",
+ "asso.km",
+ "med.sd",
+ "biz.tj",
+ "habmer.no",
+ "blogspot.pt",
+ "futbol",
+ "blogspot.hu",
+ "fjaler.no",
+ "moscow",
+ "med.ee",
+ "ma",
"aseral.no",
- "rade.no",
- "lib.nc.us",
- "asso.ci",
- "genova.it",
+ "int.mw",
+ "blogspot.co.nz",
+ "x.bg",
+ "med.br",
+ "com.aw",
+ "museum.tt",
+ "x.se",
+ "far.br",
+ "gh",
+ "ch",
+ "asso.fr",
+ "atm.pl",
+ "quebec",
+ "blogspot.com.br",
+ "biz.bb",
+ "mp",
+ "gov.bf",
+ "bieszczady.pl",
+ "com.hr",
+ "guide",
+ "gal",
+ "bmd.br",
+ "ingatlan.hu",
+ "mil",
+ "events",
+ "gov.hk",
+ "com.ai",
+ "idv.hk",
+ "edu.hk",
+ "mil.do",
+ "firm.in",
+ "com.hk",
+ "eng.pro",
+ "bh",
+ "mv",
+ "hapmir.no",
+ "belgorod.ru",
+ "ua",
"e12.ve",
- "mil.ve",
+ "hemsedal.no",
+ "mango",
+ "evenes.no",
+ "miami",
+ "engerdal.no",
+ "blogspot.in",
+ "hvaler.no",
+ "mielno.pl",
+ "hadsel.no",
+ "bronnoysund.no",
+ "blogspot.ie",
+ "blogspot.ca",
+ "com.vi",
+ "etc.br",
+ "broke-it.net",
+ "mil.no",
+ "mincom.tn",
+ "asso.re",
+ "blogspot.co.il",
+ "fhv.se",
+ "blogspot.it",
+ "mielec.pl",
+ "fish",
+ "e164.arpa",
+ "mie.jp",
+ "ing.pa",
+ "eti.br",
+ "biz.id",
+ "mat.br",
+ "bindal.no",
+ "mil.ec",
+ "mil.to",
+ "hareid.no",
+ "mil.tj",
+ "mil.tm",
+ "abo.pa",
+ "fyresdal.no",
+ "gallery",
+ "hk",
+ "builders",
+ "blogspot.cv",
+ "ck",
+ "fhs.no",
+ "gov.km",
"broker.aero",
- "time.no",
- "firm.ro",
- "garden.museum",
- "krym.ua",
- "berg.no",
- "mg",
- "divtasvuodna.no",
- "lund.no",
- "fortworth.museum",
- "firm.ht",
+ "edu.km",
+ "aid.pl",
+ "com.km",
"meland.no",
- "k12.vi",
- "drobak.no",
- "flakstad.no",
- "tg",
- "tw.cn",
+ "mil.br",
+ "mil.bo",
+ "mh",
+ "gaular.no",
+ "fk",
+ "isernia.it",
+ "mil.iq",
+ "gov.kp",
+ "ws",
+ "ullensaker.no",
+ "blogspot.com.ar",
+ "edu.kp",
+ "gov.af",
+ "com.kp",
+ "edu.af",
+ "com.af",
+ "biz.pr",
+ "biella.it",
+ "mil.rw",
+ "blogspot.com.au",
+ "med.pro",
+ "author.aero",
+ "bar.pro",
+ "ass.km",
+ "mil.qa",
+ "fuossko.no",
+ "fam.pk",
+ "edu.pf",
+ "biz.pk",
+ "com.pf",
+ "med.pl",
+ "fuel.aero",
+ "urn.arpa",
+ "w.bg",
+ "eidfjord.no",
+ "w.se",
+ "biz.pl",
+ "arendal.no",
+ "irc.pl",
+ "miasta.pl",
+ "mil.ba",
+ "mil.jo",
+ "web.do",
+ "biz.mw",
+ "blogspot.ch",
+ "fuettertdasnetz.de",
+ "googleapis.com",
+ "bronnoy.no",
+ "mil.id",
+ "inderoy.no",
+ "cpa.pro",
+ "museum.mv",
+ "blogspot.gr",
+ "etnedal.no",
+ "careers",
+ "med.pa",
+ "mil.tw",
+ "xyz",
+ "mk",
+ "web.lk",
+ "hjartdal.no",
+ "foggia.it",
+ "brussels.museum",
+ "marker.no",
+ "modena.it",
+ "bamble.no",
+ "ip6.arpa",
+ "ferrara.it",
+ "imperia.it",
+ "blogspot.co.at",
+ "flesberg.no",
+ "bergamo.it",
+ "aircraft.aero",
+ "mil.ar",
+ "gov.ki",
+ "edu.ki",
+ "hjelmeland.no",
+ "wed",
+ "mil.ac",
+ "com.ki",
+ "meldal.no",
+ "github.io",
+ "web.tj",
+ "black",
+ "uk",
+ "cheap",
+ "horology.museum",
+ "mil.al",
+ "wroc.pl",
+ "work",
+ "wien",
+ "mil.ae",
+ "caravan",
+ "works",
+ "eidsvoll.no",
+ "folldal.no",
+ "gjesdal.no",
+ "mil.pl",
+ "mandal.no",
"mil.vc",
- "levanger.no",
- "smolensk.ru",
- "sumoto.kumamoto.jp",
- "krokstadelva.no",
- "center.museum",
- "deatnu.no",
- "vik.no",
- "biz.vn",
+ "mail.pl",
+ "melhus.no",
+ "immobilien",
+ "mil.pe",
+ "cleaning",
+ "fredrikstad.no",
+ "asmatart.museum",
+ "hamaroy.no",
+ "catania.it",
+ "mil.ve",
+ "museum.om",
+ "genova.it",
+ "badaddja.no",
+ "iris.arpa",
+ "flanders.museum",
"creation.museum",
- "chuvashia.ru",
- "bill.museum",
- "fjaler.no",
- "durham.museum",
- "co.bw",
- "mining.museum",
- "he.cn",
- "lg.ua",
- "fg.it",
- "b.br",
- "educator.aero",
- "agr.br",
- "roan.no",
- "suli.hu",
- "vercelli.it",
- "research.aero",
- "stat.no",
- "vantaa.museum",
+ "milano.it",
+ "gausdal.no",
+ "ancona.it",
+ "matera.it",
+ "budapest",
+ "modalen.no",
+ "gotdns.org",
+ "blogspot.dk",
+ "eidsberg.no",
+ "aremark.no",
"club.aero",
- "kviteseid.no",
- "k12.nj.us",
- "gran.no",
- "e164.arpa",
- "aviation.museum",
- "capebreton.museum",
- "kunisaki.oita.jp",
- "krodsherad.no",
- "tver.ru",
- "mil.sh",
- "town.museum",
- "tysfjord.no",
- "tysvar.no",
- "k12.vi.us",
- "landes.museum",
- "lavangen.no",
- "khakassia.ru",
- "royken.no",
- "dallas.museum",
- "bg",
+ "blogspot.sk",
+ "web.id",
+ "is-a-llama.com",
+ "izhevsk.ru",
+ "hita.oita.jp",
+ "benevento.it",
+ "wang",
+ "blogspot.hk",
+ "ibaraki.jp",
+ "holtalen.no",
+ "fauske.no",
+ "uri.arpa",
+ "masfjorden.no",
+ "airguard.museum",
+ "baidar.no",
+ "american.museum",
+ "blogspot.co.uk",
+ "montreal.museum",
+ "guitars",
+ "bargains",
+ "estate.museum",
+ "wtc",
+ "uzhgorod.ua",
+ "bydgoszcz.pl",
+ "web.pk",
+ "cartoonart.museum",
+ "caa.aero",
+ "kz",
+ "cloudfront.net",
+ "cultural.museum",
+ "center.museum",
+ "kr",
+ "catering",
+ "gov.ru",
+ "edu.ru",
"brunel.museum",
- "stpetersburg.museum",
- "avocat.fr",
- "lib.nj.us",
- "k12.va.us",
- "mosreg.ru",
- "shop.pl",
- "trader.aero",
- "hi.cn",
- "verran.no",
+ "com.ru",
+ "mil.kr",
+ "mil.km",
+ "web.ve",
+ "chtr.k12.ma.us",
+ "czeladz.pl",
+ "kobe.jp",
+ "kred",
+ "in-addr.arpa",
+ "k.bg",
+ "web.nf",
+ "kn",
+ "k.se",
+ "biz.ki",
+ "mragowo.pl",
+ "gw",
+ "cw",
+ "ke",
+ "gov.ws",
+ "int.ru",
+ "edu.ws",
+ "com.ws",
+ "wegrow.pl",
+ "gov.sg",
+ "aw",
+ "edu.sg",
+ "ascoli-piceno.it",
+ "com.sg",
+ "columbia.museum",
+ "erotica.hu",
+ "crafts.museum",
+ "gildeskal.no",
+ "krd",
+ "bw",
+ "erotika.hu",
"audnedaln.no",
- "amsterdam.museum",
- "hu.net",
- "hn.cn",
- "bg.it",
- "shop.ht",
- "arna.no",
- "lib.vi.us",
- "cq.cn",
- "fitjar.no",
- "tingvoll.no",
- "fusa.no",
- "hol.no",
- "evje-og-hornnes.no",
- "lib.va.us",
- "vg",
- "sola.no",
- "sula.no",
- "hemnes.no",
- "balestrand.no",
- "surgeonshall.museum",
- "arao.kumamoto.jp",
- "benevento.it",
- "siljan.no",
- "bahn.museum",
- "hl.cn",
- "fyresdal.no",
- "horten.no",
- "eng.br",
- "cng.br",
- "kyiv.ua",
- "milano.it",
- "eisenbahn.museum",
- "salangen.no",
- "filatelia.museum",
- "k12.vt.us",
- "alta.no",
- "ha.cn",
+ "circus.museum",
+ "blogspot.jp",
+ "aomori.aomori.jp",
+ "brasil.museum",
+ "com.ug",
"guernsey.museum",
- "collection.museum",
- "leg.br",
- "cheltenham.museum",
- "losangeles.museum",
- "kurotaki.nara.jp",
- "mypets.ws",
- "muenchen.museum",
- "kuji.iwate.jp",
- "club.tw",
- "contemporary.museum",
- "catanzaro.it",
- "hb.cn",
- "tinn.no",
- "loabat.no",
- "slg.br",
- "lib.vt.us",
- "siracusa.it",
- "lancashire.museum",
- "gjerstad.no",
- "jorpeland.no",
- "kirovograd.ua",
- "tyumen.ru",
- "holtalen.no",
- "hokksund.no",
- "kosa.kumamoto.jp",
- "k-uralsk.ru",
- "shop.hu",
- "hk.cn",
- "avoues.fr",
- "vang.no",
- "tananger.no",
- "toon.ehime.jp",
- "lierne.no",
- "tysnes.no",
- "film.hu",
- "sandnessjoen.no",
- "sigdal.no",
- "mesaverde.museum",
- "vennesla.no",
- "mo-i-rana.no",
- "mail.pl",
- "rana.no",
- "tono.iwate.jp",
- "lyngen.no",
- "steiermark.museum",
- "slupsk.pl",
- "rennesoy.no",
- "sweden.museum",
- "komono.mie.jp",
- "geelvinck.museum",
- "bokn.no",
- "viking.museum",
- "ragusa.it",
- "matta-varjjat.no",
- "giehtavuoatna.no",
- "bolt.hu",
- "kazo.saitama.jp",
- "gdansk.pl",
- "coop.py",
- "fuji.shizuoka.jp",
- "astrakhan.ru",
- "tana.no",
- "tobe.ehime.jp",
+ "aomori.jp",
+ "gov.ng",
+ "edu.ng",
+ "ki",
+ "com.ng",
+ "kim",
+ "grandrapids.museum",
+ "cagliari.it",
+ "fhsk.se",
+ "gov.eg",
+ "edu.eg",
+ "gjemnes.no",
+ "historical.museum",
+ "magadan.ru",
+ "com.eg",
+ "alessandria.it",
+ "asso.gp",
+ "crimea.ua",
+ "miners.museum",
+ "zw",
+ "memorial.museum",
+ "ky",
+ "webhop.net",
"meeres.museum",
- "hellas.museum",
- "riodejaneiro.museum",
- "kamijima.ehime.jp",
- "leka.no",
- "bahccavuotna.no",
- "cahcesuolo.no",
- "arai.shizuoka.jp",
- "hvaler.no",
- "dyndns.tv",
- "vindafjord.no",
- "kalisz.pl",
- "education.museum",
- "lillesand.no",
- "rakkestad.no",
- "sauherad.no",
- "likescandy.com",
- "habmer.no",
- "kuki.saitama.jp",
- "halden.no",
- "contemporaryart.museum",
- "sorreisa.no",
- "andasuolo.no",
+ "granvin.no",
+ "contemporary.museum",
+ "bir.ru",
+ "k12.ec",
+ "eun.eg",
+ "evenassi.no",
+ "baikal.ru",
+ "warszawa.pl",
+ "clothing",
+ "mw",
+ "km",
+ "cupcake.is",
+ "castle.museum",
+ "mobi",
+ "enebakk.no",
+ "gov.mu",
+ "beskidy.pl",
+ "udm.ru",
+ "com.mu",
+ "canada.museum",
+ "cbg.ru",
+ "hagebostad.no",
+ "usarts.museum",
+ "catering.aero",
+ "beardu.no",
+ "info.at",
+ "gorlice.pl",
+ "celtic.museum",
"altoadige.it",
- "toda.saitama.jp",
- "gyeonggi.kr",
- "gose.nara.jp",
- "dyndns.ws",
- "misasa.tottori.jp",
- "joso.ibaraki.jp",
- "jogasz.hu",
- "sells-it.net",
- "broke-it.net",
- "sandefjord.no",
- "syzran.ru",
- "agents.aero",
- "hole.no",
"fundacio.museum",
- "zm",
- "k12.nh.us",
- "gov.im",
- "gov.ie",
- "gildeskal.no",
- "donostia.museum",
- "com.io",
- "vgs.no",
- "ando.nara.jp",
- "kumatori.osaka.jp",
- "go.ci",
- "soni.nara.jp",
- "santabarbara.museum",
- "ed.ci",
- "gov.is",
- "co.ci",
- "edu.is",
- "journalism.museum",
- "lib.nh.us",
- "com.is",
- "divttasvuotna.no",
- "kawasaki.jp",
- "blogspot.mx",
- "mito.ibaraki.jp",
- "blogspot.ro",
- "lier.no",
- "blogspot.mr",
- "bilbao.museum",
- "dagestan.ru",
- "kumano.mie.jp",
- "blogspot.td",
- "tone.ibaraki.jp",
- "kvinnherad.no",
- "kvinesdal.no",
- "zt.ua",
- "elblag.pl",
- "marnardal.no",
+ "moscow.museum",
+ "warmia.pl",
+ "bielawa.pl",
+ "anthro.museum",
+ "moareke.no",
+ "avellino.it",
+ "massacarrara.it",
+ "como.it",
+ "fylkesbibl.no",
+ "gov.au",
+ "ise.mie.jp",
+ "broadcast.museum",
+ "edu.au",
+ "mansions.museum",
+ "com.au",
+ "quebec.museum",
+ "gov.mg",
+ "ullensvang.no",
+ "edu.mg",
+ "com.mg",
+ "muncie.museum",
+ "e-burg.ru",
+ "kp",
+ "baseball.museum",
+ "hinode.tokyo.jp",
+ "cinema.museum",
+ "asn.au",
+ "florist",
+ "andebu.no",
+ "enna.it",
+ "blogspot.tw",
"karasjok.no",
- "agro.pl",
- "blogspot.de",
- "francaise.museum",
- "z.se",
- "gov.it",
- "edu.it",
- "saga.jp",
- "kunitomi.miyazaki.jp",
- "ama.aichi.jp",
- "co.vi",
- "suzu.ishikawa.jp",
- "kongsberg.no",
- "md.ci",
- "troandin.no",
- "journalist.aero",
- "blogspot.re",
- "saintlouis.museum",
- "gov.ir",
- "gov.in",
- "edu.in",
- "television.museum",
- "shinto.gunma.jp",
- "misawa.aomori.jp",
- "limanowa.pl",
- "rakpetroleum.om",
- "minnesota.museum",
- "haugesund.no",
- "blogspot.se",
- "gyeongnam.kr",
- "futtsu.chiba.jp",
- "kurobe.toyama.jp",
- "dell-ogliastra.it",
- "soka.saitama.jp",
- "salvadordali.museum",
- "blogspot.no",
- "gotdns.org",
- "tomobe.ibaraki.jp",
- "botanical.museum",
- "humanities.museum",
- "lowicz.pl",
- "tosu.saga.jp",
- "jewish.museum",
- "chernivtsi.ua",
+ "meraker.no",
+ "capebreton.museum",
+ "com.ag",
+ "ina.ibaraki.jp",
+ "unbi.ba",
+ "berkeley.museum",
+ "maryland.museum",
+ "holiday",
+ "email",
+ "mini",
+ "malselv.no",
+ "hellas.museum",
+ "zaporizhzhe.ua",
+ "hirosaki.aomori.jp",
+ "usgarden.museum",
+ "chieti.it",
+ "better-than.tv",
+ "qld.au",
+ "carraramassa.it",
"figueres.museum",
- "stateofdelaware.museum",
- "za",
- "blogspot.it",
- "barcelona.museum",
- "kizu.kyoto.jp",
- "hokkaido.jp",
- "chuo.chiba.jp",
- "dyndns-web.com",
- "fujisato.akita.jp",
- "mielec.pl",
- "kamisato.saitama.jp",
- "servegame.org",
- "saskatchewan.museum",
- "cranbrook.museum",
- "blogspot.ie",
- "gjovik.no",
+ "gonohe.aomori.jp",
+ "watch",
+ "chernovtsy.ua",
+ "aejrie.no",
+ "bjarkoy.no",
+ "forlicesena.it",
+ "brindisi.it",
+ "cesenaforli.it",
+ "foundation",
+ "meguro.tokyo.jp",
+ "museum.mw",
+ "kh",
+ "mosreg.ru",
+ "akrehamn.no",
+ "zaporizhzhia.ua",
+ "uda.nara.jp",
+ "undersea.museum",
+ "cruises",
+ "eisenbahn.museum",
+ "mil.ru",
+ "wroclaw.pl",
+ "eidskog.no",
+ "aviation.museum",
+ "k12.or.us",
+ "hamura.tokyo.jp",
+ "k12.dc.us",
+ "mifune.kumamoto.jp",
+ "minato.tokyo.jp",
+ "k12.ok.us",
+ "k12.sc.us",
+ "ballooning.aero",
+ "muroto.kochi.jp",
+ "ambulance.museum",
+ "elblag.pl",
+ "ina.saitama.jp",
+ "k12.de.us",
+ "utsira.no",
+ "assassination.museum",
+ "zhitomir.ua",
+ "americanart.museum",
+ "kostroma.ru",
+ "krakow.pl",
+ "k12.nj.us",
+ "k12.nm.us",
+ "incheon.kr",
+ "bunkyo.tokyo.jp",
+ "k12.nc.us",
+ "gorizia.it",
"engine.aero",
- "z.bg",
- "franziskaner.museum",
- "heimatunduhren.museum",
- "goto.nagasaki.jp",
- "sosa.chiba.jp",
- "res.in",
- "jewishart.museum",
- "kamo.kyoto.jp",
- "susono.shizuoka.jp",
- "davvesiida.no",
- "vlaanderen.museum",
- "epilepsy.museum",
- "engineer.aero",
- "hjartdal.no",
- "mielno.pl",
- "settsu.osaka.jp",
- "mediaphone.om",
- "travel.pl",
- "aremark.no",
- "misato.saitama.jp",
+ "contemporaryart.museum",
"carrara-massa.it",
- "mosvik.no",
- "kraanghke.no",
- "kami.kochi.jp",
- "gyeongbuk.kr",
- "hirosaki.aomori.jp",
+ "astrakhan.ru",
+ "k12.ne.us",
+ "crew.aero",
+ "alaska.museum",
+ "mil.ng",
+ "bearalvahki.no",
+ "heguri.nara.jp",
+ "k12.la.us",
+ "mitsue.nara.jp",
+ "usantiques.museum",
+ "misasa.tottori.jp",
+ "cheltenham.museum",
+ "consultant.aero",
+ "imageandsound.museum",
+ "epilepsy.museum",
+ "mil.eg",
+ "madrid.museum",
+ "aquila.it",
+ "gobo.wakayama.jp",
+ "malbork.pl",
+ "k12.vi",
+ "hinohara.tokyo.jp",
+ "k12.nd.us",
+ "blackfriday",
+ "gov.kg",
+ "ashoro.hokkaido.jp",
+ "building.museum",
+ "edu.kg",
+ "city.sendai.jp",
+ "com.kg",
+ "franziskaner.museum",
+ "kemerovo.ru",
+ "k12.il.us",
+ "casino.hu",
+ "mihara.kochi.jp",
+ "marine.ru",
+ "k12.ri.us",
+ "australia.museum",
+ "business",
+ "furano.hokkaido.jp",
+ "kragero.no",
+ "mobara.chiba.jp",
+ "k12.ms.us",
+ "k12.mo.us",
+ "k12.ia.us",
+ "k12.id.us",
+ "chocolate.museum",
+ "giehtavuoatna.no",
+ "americana.museum",
+ "maintenance.aero",
+ "baltimore.museum",
+ "k12.me.us",
+ "minnesota.museum",
+ "mil.mg",
+ "klodzko.pl",
+ "children.museum",
+ "flekkefjord.no",
+ "monticello.museum",
+ "k12.as.us",
+ "k12.ar.us",
+ "fuso.aichi.jp",
+ "certification.aero",
+ "bilbao.museum",
+ "college",
+ "historichouses.museum",
+ "championship.aero",
+ "bihoro.hokkaido.jp",
+ "grosseto.it",
+ "k12.ak.us",
+ "chernivtsi.ua",
+ "gyeonggi.kr",
+ "k12.ma.us",
+ "kitchen",
+ "k12.md.us",
+ "k12.pr.us",
+ "k12.al.us",
+ "barcelona.museum",
+ "ami.ibaraki.jp",
+ "federation.aero",
+ "kvafjord.no",
+ "malopolska.pl",
+ "karlsoy.no",
+ "bungoono.oita.jp",
+ "holmestrand.no",
+ "mesaverde.museum",
+ "microlight.aero",
+ "americanantiques.museum",
+ "webhop.org",
+ "ethnology.museum",
+ "ina.nagano.jp",
+ "kusu.oita.jp",
+ "beeldengeluid.museum",
+ "elverum.no",
+ "ibaraki.osaka.jp",
+ "city.sapporo.jp",
+ "haboro.hokkaido.jp",
"chernigov.ua",
- "miho.ibaraki.jp",
- "blogspot.in",
- "fylkesbibl.no",
- "zp.ua",
- "fareast.ru",
- "dvrdns.org",
- "misato.shimane.jp",
- "chuo.osaka.jp",
- "blogspot.be",
- "fuoisku.no",
- "blogspot.hu",
- "gen.in",
- "randaberg.no",
- "blogspot.dk",
- "chonan.chiba.jp",
- "biz.id",
- "blogspot.bj",
- "blogspot.pt",
+ "cx",
+ "consulting",
+ "kherson.ua",
+ "aurskog-holand.no",
+ "k12.pa.us",
+ "kalmykia.ru",
+ "gov.sh",
+ "ax",
+ "k12.mi.us",
+ "com.sh",
+ "foundation.museum",
+ "k-uralsk.ru",
+ "geisei.kochi.jp",
+ "aknoluokta.no",
+ "adachi.tokyo.jp",
+ "chelyabinsk.ru",
+ "andasuolo.no",
+ "k12.va.us",
+ "wolomin.pl",
+ "windmill.museum",
+ "manchester.museum",
+ "matsusaka.mie.jp",
+ "ink",
+ "civilwar.museum",
+ "fortmissoula.museum",
+ "axa",
+ "midtre-gauldal.no",
+ "midori.gunma.jp",
+ "elburg.museum",
+ "kristiansand.no",
+ "karelia.ru",
+ "hiraya.nagano.jp",
+ "missoula.museum",
+ "filatelia.museum",
+ "murata.miyagi.jp",
+ "freemasonry.museum",
+ "mizuho.tokyo.jp",
+ "gov.bh",
+ "engineer.aero",
+ "edu.bh",
+ "iizuna.nagano.jp",
+ "motoyama.kochi.jp",
+ "k12.vi.us",
+ "com.bh",
+ "atsuma.hokkaido.jp",
+ "equipment",
+ "collection.museum",
+ "bajddar.no",
+ "mx",
+ "from.hr",
+ "imabari.ehime.jp",
+ "midori.chiba.jp",
+ "cherkassy.ua",
+ "izumisano.osaka.jp",
+ "misato.miyagi.jp",
+ "isleofman.museum",
+ "konyvelo.hu",
+ "minamiise.mie.jp",
+ "info.au",
+ "voto",
+ "monash",
+ "mitane.akita.jp",
+ "bike",
+ "hasama.oita.jp",
+ "mitaka.tokyo.jp",
+ "vote",
+ "k12.ks.us",
+ "is-found.org",
+ "kw",
"misato.akita.jp",
- "shikatsu.aichi.jp",
- "blogspot.kr",
- "transport.museum",
- "alto-adige.it",
- "blogspot.nl",
- "koenig.ru",
- "gamvik.no",
- "egersund.no",
- "laspezia.it",
+ "matta-varjjat.no",
+ "vu",
+ "conf.au",
+ "minato.osaka.jp",
+ "mihama.chiba.jp",
+ "goshiki.hyogo.jp",
+ "gotemba.shizuoka.jp",
+ "hazu.aichi.jp",
+ "v.bg",
+ "vn",
+ "consulting.aero",
+ "mihama.aichi.jp",
+ "cherkasy.ua",
+ "mil.kg",
+ "mito.ibaraki.jp",
+ "ve",
+ "edogawa.tokyo.jp",
+ "hidaka.kochi.jp",
"chernihiv.ua",
- "blogspot.jp",
- "furubira.hokkaido.jp",
- "livinghistory.museum",
- "blogspot.sk",
- "miyazaki.jp",
- "saratov.ru",
- "muko.kyoto.jp",
- "seto.aichi.jp",
- "mil.id",
- "cesena-forli.it",
+ "hyllestad.no",
+ "inagawa.hyogo.jp",
+ "cranbrook.museum",
+ "urbino-pesaro.it",
+ "annaka.gunma.jp",
+ "krasnoyarsk.ru",
+ "mari-el.ru",
+ "fareast.ru",
+ "hamada.shimane.jp",
+ "andriabarlettatrani.it",
+ "mo-i-rana.no",
+ "miho.ibaraki.jp",
+ "amur.ru",
"karasjohka.no",
- "shiojiri.nagano.jp",
- "serveftp.net",
- "takatori.nara.jp",
- "kazuno.akita.jp",
- "sennan.osaka.jp",
- "egyptian.museum",
- "kusu.oita.jp",
- "minobu.yamanashi.jp",
- "kamisu.ibaraki.jp",
+ "blogspot.mx",
+ "kristiansund.no",
+ "assisi.museum",
+ "minami.kyoto.jp",
+ "konskowola.pl",
+ "finearts.museum",
+ "humanities.museum",
+ "vi",
+ "gov.ph",
+ "environment.museum",
+ "edu.ph",
+ "misato.shimane.jp",
+ "com.ph",
+ "zoological.museum",
+ "chosei.chiba.jp",
+ "kvitsoy.no",
+ "gangwon.kr",
+ "gok.pk",
+ "biratori.hokkaido.jp",
+ "andria-trani-barletta.it",
+ "vlog.br",
+ "gjerdrum.no",
+ "minano.saitama.jp",
+ "bjerkreim.no",
+ "city.kitakyushu.jp",
+ "vegas",
+ "vdonsk.ru",
+ "hiranai.aomori.jp",
+ "furubira.hokkaido.jp",
+ "aya.miyazaki.jp",
+ "elk.pl",
+ "vet.br",
+ "hasuda.saitama.jp",
+ "misato.saitama.jp",
+ "esashi.hokkaido.jp",
+ "karate.museum",
+ "childrens.museum",
+ "watarai.mie.jp",
+ "hachioji.tokyo.jp",
+ "geelvinck.museum",
+ "kms.ru",
+ "matsue.shimane.jp",
+ "construction",
+ "military.museum",
+ "itabashi.tokyo.jp",
+ "isen.kagoshima.jp",
+ "arakawa.tokyo.jp",
+ "va",
+ "mobi.gp",
+ "masuda.shimane.jp",
+ "kautokeino.no",
+ "macerata.it",
+ "koenig.ru",
+ "mil.sh",
+ "mypets.ws",
+ "chel.ru",
+ "voronezh.ru",
+ "fitjar.no",
+ "asti.it",
+ "misawa.aomori.jp",
+ "kotoura.tottori.jp",
+ "fukuoka.jp",
+ "vennesla.no",
+ "vladimir.ru",
+ "chuo.chiba.jp",
+ "isa.kagoshima.jp",
+ "bifuka.hokkaido.jp",
+ "mediocampidano.it",
+ "bashkiria.ru",
+ "kurobe.toyama.jp",
+ "arakawa.saitama.jp",
+ "hidaka.hokkaido.jp",
+ "vestre-toten.no",
+ "babia-gora.pl",
+ "mihara.hiroshima.jp",
+ "civilization.museum",
+ "gyeongnam.kr",
+ "khv.ru",
+ "fuefuki.yamanashi.jp",
+ "verdal.no",
+ "genkai.saga.jp",
+ "chuo.osaka.jp",
+ "irkutsk.ru",
+ "mimata.miyazaki.jp",
+ "hamatama.saga.jp",
+ "cadaques.museum",
+ "chattanooga.museum",
+ "aizumi.tokushima.jp",
+ "minami.tokushima.jp",
+ "viterbo.it",
+ "usa.oita.jp",
+ "futtsu.chiba.jp",
+ "worse-than.tv",
+ "british-library.uk",
+ "britishcolumbia.museum",
+ "choshi.chiba.jp",
+ "archaeology.museum",
+ "kuzbass.ru",
+ "kharkov.ua",
+ "kids.us",
+ "kameoka.kyoto.jp",
+ "vodka",
+ "kvalsund.no",
+ "komoro.nagano.jp",
+ "kurotaki.nara.jp",
+ "verona.it",
+ "gliwice.pl",
+ "kanmaki.nara.jp",
+ "zachpomor.pl",
+ "hashikami.aomori.jp",
+ "minamiizu.shizuoka.jp",
+ "eigersund.no",
+ "venezia.it",
+ "arts.museum",
+ "matsubara.osaka.jp",
+ "mishima.shizuoka.jp",
+ "chiyoda.tokyo.jp",
+ "villas",
+ "mil.ph",
+ "fortworth.museum",
+ "k12.wa.us",
+ "bari.it",
+ "vinnica.ua",
+ "coal.museum",
+ "mosjoen.no",
+ "michigan.museum",
+ "kirovograd.ua",
+ "kota.aichi.jp",
+ "iraq.museum",
+ "iron.museum",
+ "bonn.museum",
+ "glas.museum",
+ "hachijo.tokyo.jp",
+ "vestre-slidre.no",
+ "watari.miyagi.jp",
+ "moseushi.hokkaido.jp",
+ "fribourg.museum",
+ "ventures",
+ "ebetsu.hokkaido.jp",
+ "varese.it",
+ "amakusa.kumamoto.jp",
+ "frog.museum",
+ "hidaka.saitama.jp",
+ "archaeological.museum",
+ "childrensgarden.museum",
+ "arboretum.museum",
+ "ariake.saga.jp",
+ "iyo.ehime.jp",
+ "kazo.saitama.jp",
+ "budejju.no",
+ "bern.museum",
+ "ikaruga.nara.jp",
+ "k12.wi.us",
"assabu.hokkaido.jp",
- "carraramassa.it",
- "fujisawa.iwate.jp",
- "lenvik.no",
- "trieste.it",
- "zj.cn",
- "medecin.km",
- "kitaaiki.nagano.jp",
- "gorizia.it",
- "kuju.oita.jp",
- "sakhalin.ru",
- "toei.aichi.jp",
- "caltanissetta.it",
- "tosa.kochi.jp",
- "fuso.aichi.jp",
- "larvik.no",
+ "kharkiv.ua",
+ "moma.museum",
+ "akishima.tokyo.jp",
+ "evje-og-hornnes.no",
+ "haugesund.no",
+ "misaki.osaka.jp",
+ "abashiri.hokkaido.jp",
"mizusawa.iwate.jp",
+ "aquarium.museum",
+ "koza.wakayama.jp",
+ "kashiba.nara.jp",
+ "ujitawara.kyoto.jp",
+ "no",
+ "nz",
+ "civilisation.museum",
+ "hirado.nagasaki.jp",
+ "nr",
+ "gov.sx",
+ "ishikawa.jp",
+ "muroran.hokkaido.jp",
+ "nom.ro",
+ "nl",
"kita.kyoto.jp",
- "kumano.hiroshima.jp",
- "donetsk.ua",
- "ebetsu.hokkaido.jp",
- "kita.osaka.jp",
- "media.pl",
- "shinjuku.tokyo.jp",
- "shintomi.miyazaki.jp",
- "lipetsk.ru",
- "realestate.pl",
- "kainan.tokushima.jp",
- "serveftp.org",
- "shonai.yamagata.jp",
- "tako.chiba.jp",
+ "hiroshima.jp",
+ "iki.nagasaki.jp",
+ "exeter.museum",
+ "kira.aichi.jp",
+ "nu",
"anjo.aichi.jp",
- "mil.in",
- "zw",
- "mari-el.ru",
- "k12.id.us",
- "hino.tottori.jp",
- "swidnica.pl",
- "health.museum",
- "dudinka.ru",
- "augustow.pl",
- "ringerike.no",
- "aurland.no",
- "k12.ia.us",
- "kimino.wakayama.jp",
- "rawa-maz.pl",
- "gov.by",
- "com.by",
- "shoo.okayama.jp",
- "lib.id.us",
- "minato.osaka.jp",
- "kimobetsu.hokkaido.jp",
- "chuo.fukuoka.jp",
- "muncie.museum",
- "alaheadju.no",
- "shimamoto.osaka.jp",
- "misato.wakayama.jp",
- "gov.sy",
- "edu.sy",
- "com.sy",
- "lib.ia.us",
- "hoyanger.no",
- "gs.jan-mayen.no",
- "sowa.ibaraki.jp",
- "blogspot.tw",
- "kawaba.gunma.jp",
- "shintoku.hokkaido.jp",
- "slattum.no",
- "assassination.museum",
- "tara.saga.jp",
- "kijo.miyazaki.jp",
- "koebenhavn.museum",
- "services.aero",
- "cosenza.it",
- "koge.tottori.jp",
- "sopot.pl",
- "kuwana.mie.jp",
- "soja.okayama.jp",
- "sevastopol.ua",
- "malvik.no",
- "blogspot.hk",
- "austin.museum",
- "association.museum",
- "kota.aichi.jp",
- "koto.tokyo.jp",
- "babia-gora.pl",
- "vega.no",
- "siemens.om",
- "gmina.pl",
- "sor-varanger.no",
- "taku.saga.jp",
- "k12.in.us",
- "koto.shiga.jp",
- "roros.no",
- "budejju.no",
- "lorenskog.no",
- "toho.fukuoka.jp",
- "soma.fukushima.jp",
- "jeonbuk.kr",
- "froland.no",
- "sugito.saitama.jp",
- "hagebostad.no",
- "kumejima.okinawa.jp",
- "mitane.akita.jp",
- "biratori.hokkaido.jp",
- "kainan.wakayama.jp",
- "k12.il.us",
- "shinjo.yamagata.jp",
- "lib.in.us",
- "gjemnes.no",
+ "moroyama.saitama.jp",
+ "vercelli.it",
+ "n.bg",
+ "grajewo.pl",
+ "nom.re",
+ "n.se",
+ "koganei.tokyo.jp",
+ "kyotamba.kyoto.jp",
+ "kuroishi.aomori.jp",
+ "cody.museum",
+ "nsn.us",
+ "ne",
+ "net",
+ "urausu.hokkaido.jp",
+ "kodaira.tokyo.jp",
+ "net.do",
+ "nom.es",
+ "net.om",
+ "net.dm",
+ "net.so",
+ "ivano-frankivsk.ua",
+ "nom.tm",
+ "net.sc",
+ "net.lr",
+ "net.sb",
+ "minamiyamashiro.kyoto.jp",
+ "qld.edu.au",
+ "kviteseid.no",
+ "net.lc",
+ "kuju.oita.jp",
+ "notteroy.no",
+ "net.lb",
+ "nls.uk",
+ "net.lk",
+ "net.sl",
+ "not.br",
+ "nom.br",
+ "columbus.museum",
+ "machida.tokyo.jp",
+ "net.nr",
+ "ni",
+ "maritimo.museum",
+ "civilaviation.aero",
+ "unjarga.no",
+ "koga.ibaraki.jp",
+ "vacations",
"copenhagen.museum",
- "firenze.it",
- "minano.saitama.jp",
- "kakinoki.shimane.jp",
- "za.net",
- "lib.il.us",
- "tozawa.yamagata.jp",
- "stavern.no",
- "chernovtsy.ua",
- "celtic.museum",
- "council.aero",
- "furano.hokkaido.jp",
- "greta.fr",
- "kyonan.chiba.jp",
- "minato.tokyo.jp",
- "kira.aichi.jp",
- "ringebu.no",
- "essex.museum",
- "tondabayashi.osaka.jp",
- "tsumagoi.gunma.jp",
- "qa",
- "amagasaki.hyogo.jp",
- "tanabe.wakayama.jp",
- "media.museum",
- "tanabe.kyoto.jp",
- "media.hu",
- "ashibetsu.hokkaido.jp",
- "gs.va.no",
- "co.bi",
- "somna.no",
- "shimane.jp",
- "gs.oslo.no",
- "q.bg",
+ "minamiboso.chiba.jp",
+ "mitsuke.niigata.jp",
+ "farm.museum",
+ "monmouth.museum",
+ "net.ec",
+ "katori.chiba.jp",
+ "health.museum",
+ "net.to",
+ "net.tj",
+ "net.tm",
+ "kamo.kyoto.jp",
+ "kizu.kyoto.jp",
+ "net.sa",
+ "net.sd",
+ "bill.museum",
+ "hatoyama.saitama.jp",
+ "net.la",
+ "arao.kumamoto.jp",
+ "film.museum",
+ "hanamaki.iwate.jp",
+ "net.bs",
+ "net.br",
+ "net.bo",
+ "net.ua",
+ "net.bm",
+ "bahn.museum",
+ "net.bb",
+ "ntr.br",
+ "net.iq",
+ "net.is",
+ "net.ir",
+ "buzz",
+ "net.im",
+ "minakami.gunma.jp",
+ "inashiki.ibaraki.jp",
+ "gob.mx",
+ "edu.mx",
+ "gojome.akita.jp",
+ "com.mx",
+ "maibara.shiga.jp",
+ "gyeongbuk.kr",
+ "cahcesuolo.no",
+ "bialystok.pl",
+ "kagami.kochi.jp",
+ "net.rw",
+ "warabi.saitama.jp",
+ "kumenan.okayama.jp",
+ "vyatka.ru",
+ "net.qa",
+ "asso.ht",
+ "katsuragi.nara.jp",
+ "info.ht",
+ "minowa.nagano.jp",
+ "katano.osaka.jp",
+ "haibara.shizuoka.jp",
+ "nysa.pl",
+ "msk.ru",
+ "na",
+ "minamata.kumamoto.jp",
+ "hiji.oita.jp",
+ "net.ba",
+ "net.jo",
+ "williamsburg.museum",
+ "neustar",
+ "name",
+ "mill.museum",
+ "vestnes.no",
+ "net.mo",
+ "kasaoka.okayama.jp",
+ "net.id",
+ "uenohara.yamanashi.jp",
+ "np",
+ "nara.jp",
+ "name.qa",
+ "nel.uk",
+ "net.tw",
+ "net.mk",
+ "net.je",
+ "vrn.ru",
+ "namsos.no",
+ "name.jo",
+ "kitami.hokkaido.jp",
+ "bale.museum",
+ "net.ml",
+ "net.me",
+ "arai.shizuoka.jp",
+ "name.my",
+ "nom.pl",
+ "nom.pe",
+ "kumano.hiroshima.jp",
+ "net.ar",
+ "net.ac",
+ "wazuka.kyoto.jp",
+ "name.mk",
+ "nom.ad",
+ "firm.ht",
+ "name.pr",
+ "net.ma",
+ "arezzo.it",
+ "kazuno.akita.jp",
+ "net.ps",
+ "net.pr",
+ "net.al",
+ "mashiki.kumamoto.jp",
+ "net.ae",
+ "name.az",
+ "nom.pa",
+ "net.pk",
+ "iwanai.hokkaido.jp",
+ "kita.osaka.jp",
+ "barreau.bj",
+ "net.pl",
+ "net.vc",
+ "net.pe",
+ "kisarazu.chiba.jp",
+ "kumatori.osaka.jp",
+ "novara.it",
+ "net.mw",
+ "net.ve",
+ "beauxarts.museum",
+ "izumiotsu.osaka.jp",
+ "funahashi.toyama.jp",
+ "gg",
+ "eg",
+ "komaki.aichi.jp",
+ "cg",
+ "kunneppu.hokkaido.jp",
+ "gov.gr",
+ "kitaakita.akita.jp",
+ "edu.gr",
+ "net.nf",
+ "com.gr",
+ "net.pa",
+ "hokksund.no",
+ "khakassia.ru",
+ "ag",
+ "xxx",
+ "ama.shimane.jp",
+ "ggee",
+ "gushikami.okinawa.jp",
+ "bg",
+ "vlaanderen.museum",
+ "health.vn",
+ "name.mv",
+ "edu.gp",
+ "gov.ge",
+ "com.gp",
+ "edu.ge",
+ "freiburg.museum",
+ "nic.uk",
+ "com.ge",
+ "utah.museum",
+ "khabarovsk.ru",
+ "hitoyoshi.kumamoto.jp",
+ "workshop.museum",
+ "urakawa.hokkaido.jp",
+ "kai.yamanashi.jp",
+ "agro.pl",
+ "antiques.museum",
+ "net.ai",
+ "nic.tr",
+ "nic.tj",
+ "net.hk",
+ "nittedal.no",
+ "info.sd",
+ "maebashi.gunma.jp",
+ "name.eg",
+ "notodden.no",
+ "austrheim.no",
+ "moriya.ibaraki.jp",
+ "nissedal.no",
+ "hasami.nagasaki.jp",
+ "mining.museum",
+ "nom.km",
+ "kozaki.chiba.jp",
+ "net.vi",
+ "kosaka.akita.jp",
+ "k12.oh.us",
+ "ggf.br",
+ "kraanghke.no",
+ "kadoma.osaka.jp",
+ "norddal.no",
+ "agr.br",
+ "mg",
+ "mari.ru",
+ "minamioguni.kumamoto.jp",
+ "nagoya",
+ "gov.gi",
+ "versailles.museum",
+ "edu.gi",
+ "hirara.okinawa.jp",
+ "com.gi",
+ "k12.nh.us",
+ "ro",
+ "misaki.okayama.jp",
+ "ginoza.okinawa.jp",
+ "ug",
+ "rs",
"kagawa.jp",
- "vaga.no",
- "kamoenai.hokkaido.jp",
- "association.aero",
- "swiebodzin.pl",
- "gamo.shiga.jp",
- "kaho.fukuoka.jp",
+ "nesodden.no",
+ "vindafjord.no",
+ "esan.hokkaido.jp",
+ "net.af",
+ "ru",
+ "naples.it",
+ "moriyoshi.akita.jp",
+ "kitaaiki.nagano.jp",
+ "naustdal.no",
+ "chiryu.aichi.jp",
+ "kasama.ibaraki.jp",
+ "r.bg",
+ "kannami.shizuoka.jp",
+ "r.se",
+ "blogspot.fr",
+ "minami-alps.yamanashi.jp",
+ "minobu.yamanashi.jp",
+ "urasoe.okinawa.jp",
+ "izu.shizuoka.jp",
+ "nesseby.no",
+ "kui.hiroshima.jp",
+ "re",
+ "akabira.hokkaido.jp",
+ "aso.kumamoto.jp",
+ "ren",
+ "rodeo",
+ "hokuto.hokkaido.jp",
+ "kijo.miyazaki.jp",
+ "city.kawasaki.jp",
+ "rest",
+ "ruhr",
+ "nordre-land.no",
+ "kumamoto.jp",
+ "home.dyndns.org",
+ "uvic.museum",
+ "vantaa.museum",
+ "kitaura.miyazaki.jp",
+ "blogspot.sg",
+ "nordkapp.no",
+ "fuoisku.no",
+ "red",
+ "asakuchi.okayama.jp",
+ "napoli.it",
+ "net.ki",
+ "blogspot.fi",
+ "ito.shizuoka.jp",
+ "utazas.hu",
+ "hamamatsu.shizuoka.jp",
+ "himeshima.oita.jp",
+ "agents.aero",
+ "farmequipment.museum",
+ "chikusei.ibaraki.jp",
+ "repair",
+ "chitose.hokkaido.jp",
+ "hadano.kanagawa.jp",
+ "mod.gi",
+ "rennesoy.no",
+ "embaixada.st",
+ "veterinaire.km",
+ "wiki",
+ "notaires.km",
+ "ishikari.hokkaido.jp",
+ "muko.kyoto.jp",
+ "nordreisa.no",
+ "mil.ge",
+ "avoues.fr",
+ "honjyo.akita.jp",
+ "aeroport.fr",
+ "hanamigawa.chiba.jp",
+ "kamchatka.ru",
+ "wiki.br",
+ "vestvagoy.no",
+ "higashikurume.tokyo.jp",
+ "vic.au",
+ "krodsherad.no",
+ "uto.kumamoto.jp",
+ "kamioka.akita.jp",
+ "nov.ru",
+ "kunisaki.oita.jp",
+ "kitadaito.okinawa.jp",
+ "mashike.hokkaido.jp",
"mikasa.hokkaido.jp",
- "joyo.kyoto.jp",
- "gangwon.kr",
- "aejrie.no",
- "toyo.kochi.jp",
- "adult.ht",
- "mima.tokushima.jp",
- "toyotomi.hokkaido.jp",
- "skanit.no",
- "saitama.jp",
- "sandiego.museum",
- "from-la.net",
- "smola.no",
- "gs.nt.no",
- "stranda.no",
- "sarpsborg.no",
- "furniture.museum",
- "rauma.no",
- "qld.au",
- "date.fukushima.jp",
- "katano.osaka.jp",
- "rennebu.no",
- "tas.edu.au",
- "anan.tokushima.jp",
- "turen.tn",
- "music.museum",
- "starnberg.museum",
- "murata.miyagi.jp",
- "sebastopol.ua",
- "minowa.nagano.jp",
- "verbania.it",
- "bergamo.it",
- "sakata.yamagata.jp",
- "chuo.tokyo.jp",
- "sumoto.hyogo.jp",
- "gorge.museum",
- "rikubetsu.hokkaido.jp",
- "asnes.no",
- "konin.pl",
- "monticello.museum",
- "sauda.no",
- "semine.miyagi.jp",
- "games.hu",
- "lezajsk.pl",
- "tolga.no",
- "ravenna.it",
- "chita.ru",
- "jeonnam.kr",
- "kunitachi.tokyo.jp",
- "dominic.ua",
- "svelvik.no",
+ "hirakata.osaka.jp",
+ "rec.ro",
+ "fukuroi.shizuoka.jp",
+ "kids.museum",
+ "info.hu",
+ "namsskogan.no",
+ "vevelstad.no",
+ "upow.gov.pl",
+ "ginowan.okinawa.jp",
+ "kuzumaki.iwate.jp",
+ "chichibu.saitama.jp",
+ "net.ru",
+ "nebraska.museum",
+ "izunokuni.shizuoka.jp",
+ "kumamoto.kumamoto.jp",
+ "kami.miyagi.jp",
+ "kembuchi.hokkaido.jp",
+ "kosa.kumamoto.jp",
+ "nome.pt",
+ "kushima.miyazaki.jp",
+ "network",
+ "rocks",
+ "hakuba.nagano.jp",
+ "net.ws",
+ "musashino.tokyo.jp",
+ "rec.br",
+ "rybnik.pl",
+ "net.sg",
+ "rindal.no",
+ "is-a-candidate.org",
+ "kami.kochi.jp",
+ "nature.museum",
+ "kumiyama.kyoto.jp",
+ "zamami.okinawa.jp",
+ "horokanai.hokkaido.jp",
+ "gokase.miyazaki.jp",
+ "volgograd.ru",
+ "komi.ru",
+ "bolt.hu",
+ "kushiro.hokkaido.jp",
+ "net.ng",
+ "cesena-forli.it",
+ "nes.akershus.no",
+ "kashima.kumamoto.jp",
+ "airtraffic.aero",
+ "net.eg",
+ "kishiwada.osaka.jp",
+ "rel.pl",
+ "uslivinghistory.museum",
+ "hokuto.yamanashi.jp",
+ "frankfurt.museum",
+ "mykolaiv.ua",
+ "ibestad.no",
+ "wakasa.tottori.jp",
+ "kagoshima.jp",
+ "city.hu",
+ "from-me.org",
+ "kanoya.kagoshima.jp",
+ "fukaya.saitama.jp",
+ "nom.mg",
+ "net.mu",
+ "katsuura.chiba.jp",
+ "kashiwara.osaka.jp",
+ "fukudomi.saga.jp",
+ "kariya.aichi.jp",
+ "rzeszow.pl",
+ "zama.kanagawa.jp",
+ "novosibirsk.ru",
+ "rep.kp",
+ "noheji.aomori.jp",
+ "hachirogata.akita.jp",
+ "higashiyoshino.nara.jp",
+ "nagano.jp",
+ "vik.no",
+ "katsushika.tokyo.jp",
+ "wake.okayama.jp",
+ "monzabrianza.it",
+ "film.hu",
+ "so",
+ "sd",
+ "sz",
+ "nom.ag",
+ "net.au",
+ "sr",
+ "aogashima.tokyo.jp",
+ "nord-fron.no",
+ "sl",
+ "rentals",
+ "iijima.nagano.jp",
+ "kutchan.hokkaido.jp",
+ "monza-brianza.it",
+ "su",
+ "matsuura.nagasaki.jp",
+ "sohu",
+ "fuji.shizuoka.jp",
+ "higashiyamato.tokyo.jp",
+ "harstad.no",
+ "s.bg",
+ "fujimi.nagano.jp",
+ "sn",
+ "viajes",
+ "s.se",
+ "rec.nf",
+ "res.aero",
+ "rich",
+ "monzaebrianza.it",
+ "se",
+ "misato.wakayama.jp",
+ "net.ag",
+ "mitoyo.kagawa.jp",
+ "st",
+ "ragusa.it",
+ "minamifurano.hokkaido.jp",
+ "fujieda.shizuoka.jp",
+ "kg",
+ "vladikavkaz.ru",
+ "sld.do",
+ "higashiyama.kyoto.jp",
+ "sb",
+ "voting",
+ "chuo.fukuoka.jp",
+ "qld.gov.au",
+ "agdenes.no",
+ "si",
+ "srv.br",
+ "is-a-linux-user.org",
+ "kin.okinawa.jp",
+ "utashinai.hokkaido.jp",
+ "entomology.museum",
+ "kazimierz-dolny.pl",
+ "morioka.iwate.jp",
+ "rendalen.no",
+ "ringerike.no",
+ "kamaishi.iwate.jp",
+ "sy",
+ "nagoya.jp",
+ "habikino.osaka.jp",
+ "solar",
+ "wakayama.jp",
+ "snaase.no",
+ "sm",
+ "snoasa.no",
+ "k12.tx.us",
+ "slg.br",
+ "numata.gunma.jp",
+ "neat-url.com",
+ "iwatsuki.saitama.jp",
+ "nagasaki.jp",
+ "kobayashi.miyazaki.jp",
+ "norilsk.ru",
+ "strand.no",
+ "sa",
+ "kitakami.iwate.jp",
+ "sortland.no",
+ "mihama.wakayama.jp",
+ "nemuro.hokkaido.jp",
+ "sel.no",
+ "kvinnherad.no",
+ "kokonoe.oita.jp",
"motobu.okinawa.jp",
- "student.aero",
- "vestvagoy.no",
- "stadt.museum",
- "tvedestrand.no",
- "qsl.br",
- "venezia.it",
- "hokuto.hokkaido.jp",
- "kuzbass.ru",
+ "sv",
+ "fujimi.saitama.jp",
+ "nalchik.ru",
+ "egersund.no",
+ "nore-og-uvdal.no",
+ "soc.lk",
+ "is-lost.org",
+ "hashimoto.wakayama.jp",
+ "uwajima.ehime.jp",
+ "ueno.gunma.jp",
+ "net.kg",
+ "solund.no",
+ "rw",
+ "kitahata.saga.jp",
+ "sos.pl",
+ "kuriyama.hokkaido.jp",
+ "nkz.ru",
+ "nagaokakyo.kyoto.jp",
+ "a.prod.fastly.net",
+ "higashinaruse.akita.jp",
+ "saga.jp",
+ "kamikoani.akita.jp",
+ "nahari.kochi.jp",
+ "aibetsu.hokkaido.jp",
+ "fujisawa.iwate.jp",
+ "numata.hokkaido.jp",
+ "uki.kumamoto.jp",
+ "koshimizu.hokkaido.jp",
+ "zentsuji.kagawa.jp",
+ "kasumigaura.ibaraki.jp",
+ "fukuyama.hiroshima.jp",
+ "russia.museum",
+ "riik.ee",
+ "webhop.info",
+ "sh",
+ "higashi.okinawa.jp",
+ "rnd.ru",
+ "sells-it.net",
+ "samara.ru",
+ "marnardal.no",
+ "fukushima.jp",
+ "solutions",
+ "embetsu.hokkaido.jp",
+ "biei.hokkaido.jp",
+ "shoes",
+ "sirdal.no",
+ "sld.pa",
+ "wakuya.miyagi.jp",
+ "nes.buskerud.no",
+ "kamiichi.toyama.jp",
+ "kounosu.saitama.jp",
+ "koshigaya.saitama.jp",
+ "kagamino.okayama.jp",
+ "railroad.museum",
+ "karumai.iwate.jp",
+ "sshn.se",
+ "sondrio.it",
+ "hidaka.wakayama.jp",
+ "musashimurayama.tokyo.jp",
+ "higashimurayama.tokyo.jp",
+ "romskog.no",
+ "sk",
+ "roma.it",
+ "kadena.okinawa.jp",
+ "kusatsu.shiga.jp",
+ "nagara.chiba.jp",
+ "noshiro.akita.jp",
+ "rome.it",
+ "suldal.no",
+ "kotohira.kagawa.jp",
+ "singles",
+ "sigdal.no",
+ "kitamoto.saitama.jp",
+ "naturalhistory.museum",
+ "mihama.fukui.jp",
+ "net.sh",
+ "higashisumiyoshi.osaka.jp",
"selfip.com",
- "vaapste.no",
+ "kure.hiroshima.jp",
+ "kunitomi.miyazaki.jp",
+ "kanazawa.ishikawa.jp",
+ "ushiku.ibaraki.jp",
+ "systems",
+ "saarland",
+ "nagano.nagano.jp",
+ "vaksdal.no",
"mukawa.hokkaido.jp",
- "kvitsoy.no",
- "campidanomedio.it",
- "berlin.museum",
- "hareid.no",
- "health.vn",
- "hokuto.yamanashi.jp",
- "gs.aa.no",
- "joetsu.niigata.jp",
- "mil.by",
- "hamatama.saga.jp",
- "takasu.hokkaido.jp",
- "granvin.no",
- "blogspot.gr",
- "sandnes.no",
- "tsunan.niigata.jp",
- "kiyose.tokyo.jp",
- "kawajima.saitama.jp",
- "alstahaug.no",
- "mil.sy",
- "takatsuki.osaka.jp",
- "6bone.pl",
- "skedsmo.no",
- "shiraoka.saitama.jp",
- "misato.miyagi.jp",
- "american.museum",
- "jelenia-gora.pl",
- "barlettatraniandria.it",
- "blogspot.sg",
- "kokubunji.tokyo.jp",
- "koga.ibaraki.jp",
- "sherbrooke.museum",
- "force.museum",
+ "higashiizu.shizuoka.jp",
+ "rubtsovsk.ru",
"selfip.net",
- "lukow.pl",
- "skoczow.pl",
- "takasaki.gunma.jp",
- "hasvik.no",
- "tjome.no",
- "lubin.pl",
- "county.museum",
- "enebakk.no",
+ "noda.chiba.jp",
+ "sunndal.no",
+ "surnadal.no",
+ "k12.ga.us",
+ "net.th",
+ "sec.ps",
+ "axis.museum",
+ "kaszuby.pl",
+ "nesoddtangen.no",
+ "sogndal.no",
+ "kamikawa.hokkaido.jp",
+ "net.bh",
+ "svalbard.no",
+ "marylhurst.museum",
+ "stranda.no",
+ "stordal.no",
+ "kaluga.ru",
+ "nannestad.no",
+ "kakuda.miyagi.jp",
+ "nose.osaka.jp",
+ "natori.miyagi.jp",
+ "etajima.hiroshima.jp",
+ "savona.it",
+ "sorreisa.no",
+ "ena.gifu.jp",
"godo.gifu.jp",
- "kita.tokyo.jp",
- "catania.it",
- "giske.no",
- "vestnes.no",
- "taketomi.okinawa.jp",
- "forde.no",
- "toyono.osaka.jp",
- "for-the.biz",
- "toyonaka.osaka.jp",
- "mbone.pl",
- "donna.no",
- "texas.museum",
- "kitaakita.akita.jp",
- "hyllestad.no",
- "volkenkunde.museum",
- "komatsushima.tokushima.jp",
- "shinagawa.tokyo.jp",
- "takizawa.iwate.jp",
- "kirov.ru",
- "savannahga.museum",
- "tranby.no",
- "depot.museum",
- "kure.hiroshima.jp",
- "vestby.no",
- "trana.no",
- "kariwa.niigata.jp",
- "frogn.no",
- "kherson.ua",
- "volda.no",
- "loppa.no",
- "from-co.net",
- "dyndns.org",
- "juedisches.museum",
- "karlsoy.no",
- "miyota.nagano.jp",
- "suginami.tokyo.jp",
- "seranishi.hiroshima.jp",
- "ferrara.it",
- "frana.no",
- "kiyosato.hokkaido.jp",
- "cincinnati.museum",
- "gujo.gifu.jp",
- "trainer.aero",
- "loten.no",
- "agematsu.nagano.jp",
- "takazaki.miyazaki.jp",
- "lebesby.no",
- "mikawa.yamagata.jp",
- "tainai.niigata.jp",
- "chtr.k12.ma.us",
+ "nishio.aichi.jp",
+ "koga.fukuoka.jp",
+ "sondre-land.no",
+ "riodejaneiro.museum",
+ "sauherad.no",
+ "nieruchomosci.pl",
+ "alaheadju.no",
"groundhandling.aero",
+ "anthropology.museum",
+ "matsumoto.nagano.jp",
+ "settlers.museum",
+ "amsterdam.museum",
"morotsuka.miyazaki.jp",
- "tama.tokyo.jp",
- "hazu.aichi.jp",
- "kayabe.hokkaido.jp",
- "johana.toyama.jp",
- "hiji.oita.jp",
- "spydeberg.no",
- "kragero.no",
- "mytis.ru",
- "moareke.no",
- "dolls.museum",
- "kunneppu.hokkaido.jp",
- "molde.no",
- "gulen.no",
- "koka.shiga.jp",
- "hannan.osaka.jp",
- "kurate.fukuoka.jp",
- "2000.hu",
- "kazan.ru",
- "sasebo.nagasaki.jp",
- "kuban.ru",
- "qh.cn",
- "americana.museum",
- "state.museum",
- "zlg.br",
- "from-me.org",
- "foggia.it",
- "land-4-sale.us",
- "madrid.museum",
- "futaba.fukushima.jp",
- "kawazu.shizuoka.jp",
- "bjugn.no",
- "grane.no",
- "koeln.museum",
- "shimamaki.hokkaido.jp",
- "ginoza.okinawa.jp",
- "saikai.nagasaki.jp",
- "game-host.org",
- "tokke.no",
- "agriculture.museum",
- "rivne.ua",
- "kyotamba.kyoto.jp",
- "gunma.jp",
- "hapmir.no",
- "from-ny.net",
- "tomi.nagano.jp",
- "salat.no",
- "sano.tochigi.jp",
- "barletta-trani-andria.it",
- "aosta.it",
- "kawanishi.nara.jp",
- "genoa.it",
- "togo.aichi.jp",
- "tsugaru.aomori.jp",
- "kokonoe.oita.jp",
- "busan.kr",
- "cesenaforli.it",
- "kuroishi.aomori.jp",
- "mugi.tokushima.jp",
- "shinjo.nara.jp",
- "shonai.fukuoka.jp",
- "kadena.okinawa.jp",
- "shiiba.miyazaki.jp",
- "agrinet.tn",
- "kyotango.kyoto.jp",
- "bronnoy.no",
- "fujinomiya.shizuoka.jp",
- "space.museum",
- "k12.wy.us",
- "skole.museum",
- "sera.hiroshima.jp",
- "biei.hokkaido.jp",
- "mombetsu.hokkaido.jp",
- "khabarovsk.ru",
- "bato.tochigi.jp",
- "kiso.nagano.jp",
- "klodzko.pl",
- "trapani.it",
- "esan.hokkaido.jp",
- "hakuba.nagano.jp",
- "better-than.tv",
- "hita.oita.jp",
- "mimata.miyazaki.jp",
- "togane.chiba.jp",
- "mibu.tochigi.jp",
- "lib.wy.us",
- "bandai.fukushima.jp",
+ "siellak.no",
+ "higashiosaka.osaka.jp",
"hikawa.shimane.jp",
+ "gifu.gifu.jp",
+ "isesaki.gunma.jp",
+ "ryukyu",
+ "higashiizumo.shimane.jp",
+ "iglesias-carbonia.it",
+ "itakura.gunma.jp",
+ "naruto.tokushima.jp",
+ "fujimino.saitama.jp",
+ "name.hr",
+ "niihama.ehime.jp",
+ "rollag.no",
+ "matsubushi.saitama.jp",
+ "kitakata.miyazaki.jp",
+ "unazuki.toyama.jp",
+ "exhibition.museum",
+ "hida.gifu.jp",
+ "kurashiki.okayama.jp",
+ "skodje.no",
+ "net.ph",
+ "maniwa.okayama.jp",
+ "sassari.it",
+ "fujiidera.osaka.jp",
+ "y.bg",
+ "y.se",
+ "saotome.st",
+ "kashihara.nara.jp",
+ "ye",
+ "stokke.no",
+ "skanland.no",
+ "ninja",
+ "kaisei.kanagawa.jp",
+ "yt",
+ "ski.no",
+ "fujikawa.yamanashi.jp",
+ "usui.fukuoka.jp",
+ "global.ssl.fastly.net",
"mino.gifu.jp",
- "date.hokkaido.jp",
- "shinjo.okayama.jp",
- "saga.saga.jp",
- "miyazaki.miyazaki.jp",
- "seki.gifu.jp",
- "lanbib.se",
- "christiansburg.museum",
- "skien.no",
- "k12.ny.us",
- "kani.gifu.jp",
- "homeip.net",
- "bo.telemark.no",
- "tsubetsu.hokkaido.jp",
- "sado.niigata.jp",
- "delmenhorst.museum",
- "store.st",
- "vikna.no",
- "toki.gifu.jp",
+ "gov.gh",
+ "edu.gh",
+ "amagasaki.hyogo.jp",
+ "ikusaka.nagano.jp",
+ "com.gh",
+ "square.museum",
+ "kamikawa.saitama.jp",
+ "kicks-ass.org",
+ "rifu.miyagi.jp",
+ "reviews",
+ "reggioemilia.it",
+ "kaho.fukuoka.jp",
+ "suedtirol.it",
"simbirsk.ru",
- "siena.it",
- "kawasaki.miyagi.jp",
- "hino.tokyo.jp",
- "lib.ny.us",
- "kamo.niigata.jp",
- "maebashi.gunma.jp",
- "tsaritsyn.ru",
- "balat.no",
- "rikuzentakata.iwate.jp",
- "gokase.miyazaki.jp",
- "aoki.nagano.jp",
- "toyosato.shiga.jp",
- "bryansk.ru",
- "koga.fukuoka.jp",
+ "kamiamakusa.kumamoto.jp",
+ "hotel.lk",
+ "saratov.ru",
+ "gamagori.aichi.jp",
"kaga.ishikawa.jp",
- "skaun.no",
- "mizunami.gifu.jp",
- "lesja.no",
- "sport.hu",
- "sannan.hyogo.jp",
- "kamiichi.toyama.jp",
- "holmestrand.no",
- "lakas.hu",
- "maniwa.okayama.jp",
- "makinohara.shizuoka.jp",
- "om",
- "agdenes.no",
- "store.ro",
- "baltimore.museum",
- "gov.tw",
- "edu.tw",
- "aoste.it",
- "com.tw",
- "daejeon.kr",
- "aukra.no",
- "flora.no",
- "com.aw",
- "miyazu.kyoto.jp",
- "leirvik.no",
- "gniezno.pl",
- "bronnoysund.no",
- "shiga.jp",
- "tokushima.jp",
- "vladimir.ru",
- "charter.aero",
- "or.it",
- "od.ua",
- "tempio-olbia.it",
- "turin.it",
- "moka.tochigi.jp",
- "ot.it",
- "journal.aero",
- "fukushima.jp",
- "botanicalgarden.museum",
- "taketa.oita.jp",
+ "uonuma.niigata.jp",
+ "exposed",
+ "saltdal.no",
+ "kahoku.yamagata.jp",
+ "fujikawa.shizuoka.jp",
+ "nobeoka.miyazaki.jp",
+ "kumejima.okinawa.jp",
+ "stalbans.museum",
+ "fujinomiya.shizuoka.jp",
+ "haebaru.okinawa.jp",
+ "rimini.it",
+ "cuneo.it",
+ "naumburg.museum",
+ "ishikawa.okinawa.jp",
+ "nagareyama.chiba.jp",
+ "nord-aurdal.no",
+ "kamisu.ibaraki.jp",
"akaiwa.okayama.jp",
- "or.us",
- "baths.museum",
- "taranto.it",
- "kumenan.okayama.jp",
- "o.se",
- "bible.museum",
- "edu.cw",
- "com.cw",
- "fukusaki.hyogo.jp",
- "cagliari.it",
- "dovre.no",
- "fujiidera.osaka.jp",
- "kamiamakusa.kumamoto.jp",
- "odo.br",
- "barreau.bj",
- "virginia.museum",
- "saitama.saitama.jp",
- "takatsuki.shiga.jp",
- "soeda.fukuoka.jp",
- "anan.nagano.jp",
- "ec",
- "akita.jp",
- "cc",
- "sc",
- "ac",
- "kawatana.nagasaki.jp",
- "hemne.no",
- "bozen.it",
- "on.ca",
- "meiwa.mie.jp",
- "valle.no",
- "tamano.okayama.jp",
- "saku.nagano.jp",
- "educational.museum",
- "aioi.hyogo.jp",
+ "stv.ru",
+ "furukawa.miyagi.jp",
+ "skedsmo.no",
+ "chikuma.nagano.jp",
+ "aga.niigata.jp",
+ "kushimoto.wakayama.jp",
+ "vic.edu.au",
+ "hikimi.shimane.jp",
+ "kongsberg.no",
"himeji.hyogo.jp",
- "ac.ma",
- "fedje.no",
- "or.na",
- "shibetsu.hokkaido.jp",
- "rc.it",
- "colonialwilliamsburg.museum",
- "gc.ca",
- "kamitonda.wakayama.jp",
- "botany.museum",
- "sc.us",
- "o.bg",
- "kawanehon.shizuoka.jp",
- "kusatsu.shiga.jp",
- "mc",
- "surrey.museum",
- "lewismiller.museum",
- "shima.mie.jp",
- "takata.fukuoka.jp",
- "selje.no",
- "himeshima.oita.jp",
- "tc",
- "lc",
+ "aoste.it",
+ "fermo.it",
+ "hirono.fukushima.jp",
+ "nagasu.kumamoto.jp",
+ "vg",
+ "naha.okinawa.jp",
+ "marumori.miyagi.jp",
+ "kitahiroshima.hokkaido.jp",
+ "kuki.saitama.jp",
+ "zao.miyagi.jp",
+ "nagaoka.niigata.jp",
+ "busan.kr",
+ "gamo.shiga.jp",
+ "naturalhistorymuseum.museum",
+ "nago.okinawa.jp",
+ "iitate.fukushima.jp",
"sumy.ua",
- "saka.hiroshima.jp",
- "lugansk.ua",
- "magnitka.ru",
- "mc.it",
- "ehime.jp",
- "aridagawa.wakayama.jp",
- "lc.it",
- "express.aero",
- "eco.br",
- "or.at",
- "embetsu.hokkaido.jp",
- "sobetsu.hokkaido.jp",
- "takino.hyogo.jp",
- "act.au",
- "kanazawa.ishikawa.jp",
- "ac.pa",
- "fc.it",
- "cody.museum",
+ "nerima.tokyo.jp",
+ "futaba.fukushima.jp",
+ "sexy",
+ "snz.ru",
+ "sandnes.no",
+ "narusawa.yamanashi.jp",
+ "nirasaki.yamanashi.jp",
+ "vgs.no",
+ "sumoto.kumamoto.jp",
"hirata.fukushima.jp",
- "shimane.shimane.jp",
- "britishcolumbia.museum",
- "gdynia.pl",
- "rec.co",
- "genkai.saga.jp",
- "etc.br",
- "shikabe.hokkaido.jp",
- "cc.na",
- "aikawa.kanagawa.jp",
- "ac.tj",
- "oh.us",
- "hikone.shiga.jp",
- "ok.us",
- "rec.br",
- "hirono.fukushima.jp",
- "hiroshima.jp",
- "omsk.ru",
- "dc.us",
- "bryne.no",
- "bushey.museum",
- "lillehammer.no",
- "kawanishi.hyogo.jp",
- "tobetsu.hokkaido.jp",
- "stor-elvdal.no",
- "mil.tw",
- "or.tz",
- "bc.ca",
- "sogne.no",
- "shimabara.nagasaki.jp",
- "royrvik.no",
- "vc",
- "or.pw",
- "shibecha.hokkaido.jp",
- "ac.me",
- "hornindal.no",
- "aibetsu.hokkaido.jp",
- "hawaii.museum",
- "vc.it",
- "sydney.museum",
- "ecn.br",
- "kamiizumi.saitama.jp",
- "valley.museum",
- "suwa.nagano.jp",
- "ac.at",
- "ac.mw",
- "erotika.hu",
- "quebec.museum",
- "kanmaki.nara.jp",
- "tagajo.miyagi.jp",
- "sch.ae",
- "musashino.tokyo.jp",
- "toya.hokkaido.jp",
- "jgora.pl",
- "shimada.shizuoka.jp",
- "reggioemilia.it",
- "sch.qa",
- "hitra.no",
- "kesennuma.miyagi.jp",
- "erotica.hu",
- "fujieda.shizuoka.jp",
- "sch.sa",
- "sch.jo",
- "sch.je",
- "honbetsu.hokkaido.jp",
- "fujisawa.kanagawa.jp",
- "ac.gn",
- "chattanooga.museum",
- "ac.in",
- "hida.gifu.jp",
- "rybnik.pl",
- "sc.cn",
- "kibichuo.okayama.jp",
- "ac.cn",
- "showa.fukushima.jp",
- "sc.tz",
- "ac.tz",
- "himi.toyama.jp",
- "shiranuka.hokkaido.jp",
- "miki.hyogo.jp",
- "sci.eg",
- "for-better.biz",
- "orkdal.no",
- "kaita.hiroshima.jp",
- "milan.it",
+ "bozen.it",
+ "suisse.museum",
+ "czest.pl",
+ "mitake.gifu.jp",
+ "siedlce.pl",
+ "saitama.jp",
+ "furudono.fukushima.jp",
+ "wodzislaw.pl",
+ "karikatur.museum",
"selfip.org",
- "gorlice.pl",
- "buzen.fukuoka.jp",
- "ac.vn",
- "tranibarlettaandria.it",
- "asaka.saitama.jp",
- "store.nf",
- "vic.au",
- "tsuwano.shimane.jp",
- "kusatsu.gunma.jp",
- "orenburg.ru",
- "takasago.hyogo.jp",
- "ginowan.okinawa.jp",
- "daiwa.hiroshima.jp",
- "oita.jp",
- "ac.ae",
- "targi.pl",
- "bearalvahki.no",
- "bykle.no",
- "shinshinotsu.hokkaido.jp",
- "koshigaya.saitama.jp",
- "davvenjarga.no",
- "kagoshima.jp",
- "kamaishi.iwate.jp",
- "hara.nagano.jp",
- "asaminami.hiroshima.jp",
- "hakata.fukuoka.jp",
- "kaminoyama.yamagata.jp",
- "hanawa.fukushima.jp",
- "hadano.kanagawa.jp",
- "gliwice.pl",
- "bygland.no",
- "chiba.jp",
- "tsubame.niigata.jp",
- "home.dyndns.org",
- "hiraizumi.iwate.jp",
- "trani-andria-barletta.it",
- "katashina.gunma.jp",
- "oppdal.no",
+ "graz.museum",
+ "spb.ru",
+ "ashibetsu.hokkaido.jp",
+ "ulsan.kr",
+ "kimobetsu.hokkaido.jp",
+ "aosta.it",
"hakone.kanagawa.jp",
- "tourism.tn",
- "ac.rs",
- "trani-barletta-andria.it",
- "karatsu.saga.jp",
- "oksnes.no",
- "andriabarlettatrani.it",
- "ancona.it",
- "americanantiques.museum",
+ "skoczow.pl",
+ "sandefjord.no",
+ "wassamu.hokkaido.jp",
+ "mizunami.gifu.jp",
+ "hobol.no",
+ "fujisato.akita.jp",
+ "snillfjord.no",
+ "recreation.aero",
+ "bomlo.no",
+ "genoa.it",
+ "kujukuri.chiba.jp",
+ "svelvik.no",
+ "greta.fr",
+ "kunstsammlung.museum",
+ "asnes.no",
+ "stathelle.no",
+ "fukumitsu.toyama.jp",
+ "sex.pl",
+ "herad.no",
+ "cambridge.museum",
+ "recipes",
+ "aland.fi",
+ "katsuragi.wakayama.jp",
+ "nagatoro.saitama.jp",
+ "6bone.pl",
+ "mil.gh",
+ "nagi.okayama.jp",
+ "kuromatsunai.hokkaido.jp",
+ "aogaki.hyogo.jp",
+ "mikawa.yamagata.jp",
+ "nakhodka.ru",
+ "hisayama.fukuoka.jp",
+ "floro.no",
+ "forde.no",
+ "wajiki.tokushima.jp",
+ "kikonai.hokkaido.jp",
+ "sendai.jp",
+ "kahoku.ishikawa.jp",
+ "naganohara.gunma.jp",
+ "ardal.no",
+ "sandnessjoen.no",
"altai.ru",
- "orland.no",
- "tokushima.tokushima.jp",
- "miyashiro.saitama.jp",
- "zarow.pl",
- "seika.kyoto.jp",
- "tsukigata.hokkaido.jp",
- "treviso.it",
- "tome.miyagi.jp",
- "kurashiki.okayama.jp",
- "sciences.museum",
- "resistance.museum",
- "taka.hyogo.jp",
- "forlicesena.it",
- "sayo.hyogo.jp",
- "takaishi.osaka.jp",
- "rygge.no",
+ "chiyoda.gunma.jp",
+ "hyogo.jp",
+ "kanagawa.jp",
+ "kvinesdal.no",
+ "stjordal.no",
+ "higashimatsuyama.saitama.jp",
+ "hirokawa.fukuoka.jp",
+ "frogn.no",
+ "grane.no",
+ "saga.saga.jp",
+ "hemne.no",
+ "sandiego.museum",
+ "milan.it",
+ "chungbuk.kr",
+ "coloradoplateau.museum",
+ "nsk.ru",
+ "asahikawa.hokkaido.jp",
+ "motosu.gifu.jp",
+ "agrinet.tn",
+ "mbone.pl",
+ "nyny.museum",
+ "mizumaki.fukuoka.jp",
+ "santabarbara.museum",
+ "k12.gu.us",
+ "hurum.no",
+ "hatogaya.saitama.jp",
+ "gunma.jp",
+ "nativeamerican.museum",
+ "a.ssl.fastly.net",
+ "kitagawa.kochi.jp",
+ "bytom.pl",
+ "fjell.no",
+ "minami.fukuoka.jp",
+ "b.ssl.fastly.net",
+ "higashikagura.hokkaido.jp",
+ "gulen.no",
+ "narita.chiba.jp",
+ "hamar.no",
+ "kaizuka.osaka.jp",
+ "niikappu.hokkaido.jp",
+ "kudoyama.wakayama.jp",
+ "udine.it",
+ "kitayama.wakayama.jp",
+ "csiro.au",
+ "adult.ht",
+ "nagiso.nagano.jp",
+ "rahkkeravju.no",
+ "bjugn.no",
+ "andoy.no",
+ "kamisato.saitama.jp",
+ "yufu.oita.jp",
+ "social",
+ "higashihiroshima.hiroshima.jp",
+ "bardu.no",
+ "iwaizumi.iwate.jp",
+ "zagan.pl",
+ "soundandvision.museum",
+ "net.mx",
+ "ryokami.saitama.jp",
+ "southcarolina.museum",
+ "game-host.org",
+ "stor-elvdal.no",
+ "bandai.fukushima.jp",
+ "reklam.hu",
+ "flora.no",
+ "nagawa.nagano.jp",
+ "seto.aichi.jp",
+ "homelinux.org",
+ "surgeonshall.museum",
+ "frana.no",
+ "molde.no",
+ "kinokawa.wakayama.jp",
+ "giske.no",
+ "fujiyoshida.yamanashi.jp",
+ "saintlouis.museum",
+ "gujo.gifu.jp",
+ "murayama.yamagata.jp",
+ "hitra.no",
+ "modum.no",
+ "kashima.saga.jp",
+ "iwanuma.miyagi.jp",
+ "haram.no",
+ "minokamo.gifu.jp",
+ "higashiyodogawa.osaka.jp",
+ "shoo.okayama.jp",
+ "froya.no",
+ "ustka.pl",
+ "iizuka.fukuoka.jp",
+ "akashi.hyogo.jp",
+ "rennebu.no",
+ "barum.no",
+ "sx",
+ "yachts",
+ "ng",
+ "stpetersburg.museum",
+ "hotel.hu",
+ "vologda.ru",
+ "roma.museum",
+ "yao.osaka.jp",
+ "wajima.ishikawa.jp",
+ "koto.shiga.jp",
+ "nagasaki.nagasaki.jp",
+ "balat.no",
+ "meloy.no",
+ "hakusan.ishikawa.jp",
+ "wlocl.pl",
+ "ringebu.no",
+ "kimino.wakayama.jp",
+ "minamiaiki.nagano.jp",
+ "ngo.lk",
+ "net.gr",
+ "sosa.chiba.jp",
+ "nishiizu.shizuoka.jp",
+ "heroy.nordland.no",
+ "nakano.tokyo.jp",
+ "santacruz.museum",
+ "slattum.no",
+ "masoy.no",
+ "kamikitayama.nara.jp",
+ "wanouchi.gifu.jp",
+ "net.gp",
+ "murakami.niigata.jp",
+ "inatsuki.fukuoka.jp",
+ "net.ge",
+ "ashiya.hyogo.jp",
+ "matsushima.miyagi.jp",
+ "minamisanriku.miyagi.jp",
+ "gmina.pl",
+ "show.aero",
+ "namerikawa.toyama.jp",
+ "salangen.no",
+ "matsumoto.kagoshima.jp",
+ "susaki.kochi.jp",
+ "galsa.no",
+ "halsa.no",
+ "hotel.tz",
+ "kurate.fukuoka.jp",
+ "forum.hu",
+ "kanuma.tochigi.jp",
+ "ehime.jp",
+ "szkola.pl",
+ "kouzushima.tokyo.jp",
+ "saroma.hokkaido.jp",
+ "games.hu",
+ "alstahaug.no",
+ "minamimaki.nagano.jp",
+ "steiermark.museum",
+ "numazu.shizuoka.jp",
+ "aichi.jp",
+ "stalowa-wola.pl",
+ "yono.saitama.jp",
+ "kamogawa.chiba.jp",
+ "udono.mie.jp",
+ "kurume.fukuoka.jp",
+ "kamagaya.chiba.jp",
+ "makinohara.shizuoka.jp",
+ "southwest.museum",
+ "kosuge.yamanashi.jp",
+ "rankoshi.hokkaido.jp",
+ "ngo.pl",
+ "nishikatsura.yamanashi.jp",
+ "komatsushima.tokushima.jp",
+ "kutno.pl",
+ "shinjo.nara.jp",
+ "harima.hyogo.jp",
+ "kasahara.gifu.jp",
+ "miharu.fukushima.jp",
+ "aikawa.kanagawa.jp",
+ "shinto.gunma.jp",
+ "kepno.pl",
+ "gov.sy",
+ "edu.sy",
+ "com.sy",
+ "sumida.tokyo.jp",
+ "yamanashi.jp",
+ "gov.ly",
+ "ayabe.kyoto.jp",
+ "edu.ly",
+ "ashiya.fukuoka.jp",
+ "com.ly",
+ "kakinoki.shimane.jp",
+ "edu.uy",
+ "com.uy",
+ "o.bg",
+ "soo.kagoshima.jp",
+ "o.se",
+ "yamato.kumamoto.jp",
+ "stjordalshalsen.no",
+ "kumagaya.saitama.jp",
+ "stuttgart.museum",
+ "chita.ru",
+ "gub.uy",
+ "rishiri.hokkaido.jp",
+ "hanawa.fukushima.jp",
"org",
- "og.it",
- "oslo.no",
+ "org.do",
+ "org.om",
+ "kamitonda.wakayama.jp",
+ "org.dm",
+ "suzaka.nagano.jp",
+ "org.so",
+ "org.rs",
+ "org.ro",
+ "kuban.ru",
+ "gov.by",
+ "ralingen.no",
+ "org.sc",
+ "org.ls",
+ "org.lr",
+ "org.sb",
+ "com.by",
+ "nakano.nagano.jp",
+ "izumi.osaka.jp",
+ "noto.ishikawa.jp",
+ "org.lc",
+ "org.lb",
+ "soja.okayama.jp",
+ "org.lk",
+ "org.sl",
+ "akita.jp",
+ "shiroi.chiba.jp",
+ "org.se",
+ "inabe.mie.jp",
+ "shisui.chiba.jp",
+ "odo.br",
+ "abeno.osaka.jp",
+ "org.nr",
+ "iwate.jp",
+ "yamada.toyama.jp",
+ "kokubunji.tokyo.jp",
+ "oita.jp",
+ "kitagawa.miyazaki.jp",
+ "kyoto.jp",
+ "org.es",
+ "sokndal.no",
+ "org.ec",
+ "nakadomari.aomori.jp",
"org.to",
+ "org.tj",
"org.tm",
- "ama.shimane.jp",
+ "org.sa",
+ "org.sd",
+ "kasuya.fukuoka.jp",
+ "asahi.mie.jp",
+ "vic.gov.au",
+ "org.la",
+ "org.ee",
+ "yasuda.kochi.jp",
+ "om",
+ "izumo.shimane.jp",
+ "gov.my",
+ "edu.my",
+ "org.bs",
+ "org.br",
"org.bo",
+ "yura.wakayama.jp",
+ "org.ua",
+ "com.my",
"org.bm",
- "org.ae",
- "servebbs.com",
- "org.bi",
- "org.bz",
- "org.ai",
- "org.az",
- "airline.aero",
- "org.ag",
- "gliding.aero",
- "gf",
- "vinnica.ua",
- "muika.niigata.jp",
- "cf",
+ "sex.hu",
+ "ashikaga.tochigi.jp",
+ "onl",
+ "gotsu.shimane.jp",
+ "org.bb",
+ "org.iq",
+ "org.is",
+ "org.ir",
+ "osoyro.no",
+ "org.im",
+ "ilawa.pl",
+ "org.na",
+ "nishimera.miyazaki.jp",
+ "finnoy.no",
+ "yamazoe.nara.jp",
+ "komatsu.ishikawa.jp",
"org.qa",
- "af",
+ "maizuru.kyoto.jp",
+ "fukusaki.hyogo.jp",
+ "moriyama.shiga.jp",
+ "notaires.fr",
+ "honai.ehime.jp",
+ "kyuragi.saga.jp",
"org.ba",
- "org.so",
- "org.se",
- "org.sd",
- "trading.aero",
- "org.bs",
- "osen.no",
- "org.sz",
- "odda.no",
- "org.sg",
- "satte.saitama.jp",
- "org.ac",
- "org.sa",
- "chigasaki.kanagawa.jp",
+ "gov.py",
"org.jo",
+ "edu.py",
+ "com.py",
+ "chiba.jp",
+ "yatsuka.shimane.jp",
+ "susono.shizuoka.jp",
+ "org.mo",
+ "naie.hokkaido.jp",
+ "naka.ibaraki.jp",
+ "med.ly",
+ "saitama.saitama.jp",
+ "org.tw",
+ "org.mk",
+ "zarow.pl",
+ "hikone.shiga.jp",
+ "ayagawa.kagawa.jp",
+ "atsugi.kanagawa.jp",
"org.je",
- "eniwa.hokkaido.jp",
- "ryokami.saitama.jp",
- "ome.tokyo.jp",
- "org.bb",
- "org.sc",
- "online.museum",
- "kami.miyagi.jp",
- "andria-trani-barletta.it",
- "aeroclub.aero",
- "org.sb",
- "musashimurayama.tokyo.jp",
- "tateshina.nagano.jp",
- "komatsu.ishikawa.jp",
- "tohma.hokkaido.jp",
- "org.au",
- "shinichi.hiroshima.jp",
- "org.co",
- "org.tt",
- "org.ci",
- "org.bt",
- "city.hu",
- "shikaoi.hokkaido.jp",
- "kamisunagawa.hokkaido.jp",
- "chuo.yamanashi.jp",
- "tf",
- "org.tn",
- "org.st",
- "org.br",
- "org.an",
- "tamatsukuri.ibaraki.jp",
- "zama.kanagawa.jp",
- "ac.rw",
- "vagan.no",
- "toga.toyama.jp",
- "org.sn",
- "conference.aero",
- "tourism.pl",
+ "suginami.tokyo.jp",
+ "munakata.fukuoka.jp",
+ "org.ml",
+ "org.me",
+ "ovh",
+ "akkeshi.hokkaido.jp",
+ "nord-odal.no",
+ "org.bw",
+ "ainan.ehime.jp",
+ "orland.no",
+ "org.ar",
+ "org.ac",
+ "spjelkavik.no",
+ "kadogawa.miyazaki.jp",
+ "org.bi",
+ "org.ma",
+ "org.ps",
+ "org.pr",
"org.al",
- "fukushima.hokkaido.jp",
- "certification.aero",
- "british-library.uk",
- "org.cu",
- "rec.nf",
- "org.sl",
- "ftpaccess.cc",
- "satosho.okayama.jp",
- "tagawa.fukuoka.jp",
- "org.tj",
- "maibara.shiga.jp",
- "org.cn",
- "karuizawa.nagano.jp",
- "bf",
- "zentsuji.kagawa.jp",
- "americanart.museum",
- "kodaira.tokyo.jp",
- "gosen.niigata.jp",
- "orkanger.no",
- "ota.tokyo.jp",
- "tokashiki.okinawa.jp",
- "org.ee",
- "est-a-la-maison.com",
- "oji.nara.jp",
- "ac.be",
- "org.eg",
- "org.es",
- "reggiocalabria.it",
- "kannami.shizuoka.jp",
- "est-a-la-masion.com",
- "org.ec",
- "org.ws",
- "arita.saga.jp",
- "qld.edu.au",
- "operaunite.com",
- "muroto.kochi.jp",
- "kitanakagusuku.okinawa.jp",
- "likes-pie.com",
- "ami.ibaraki.jp",
- "lapy.pl",
- "gushikami.okinawa.jp",
- "no",
- "nu",
- "beskidy.pl",
- "org.ng",
- "oirase.aomori.jp",
- "nz",
- "rebun.hokkaido.jp",
- "meiwa.gunma.jp",
- "nom.tm",
- "org.na",
- "shibata.niigata.jp",
- "nom.ad",
- "nr",
- "no.it",
- "nu.it",
- "nom.ag",
- "showa.gunma.jp",
- "kikuchi.kumamoto.jp",
- "nu.ca",
- "hashikami.aomori.jp",
- "ne",
- "nv.us",
- "nd.us",
- "nm.us",
- "konyvelo.hu",
- "kashihara.nara.jp",
- "buryatia.ru",
- "nt.ca",
- "shikama.miyagi.jp",
- "gifu.jp",
- "elb.amazonaws.com",
- "koganei.tokyo.jp",
- "ns.ca",
- "arida.wakayama.jp",
- "eu.com",
- "ovre-eiker.no",
- "net",
- "ru.com",
- "n.se",
- "nom.co",
- "net.to",
- "net.tm",
- "net.bo",
- "net.bm",
- "org.nr",
- "net.ae",
- "haga.tochigi.jp",
- "gr.com",
- "net.bz",
- "net.ai",
- "net.az",
- "kyowa.hokkaido.jp",
- "ar.com",
- "net.ag",
- "ne.us",
- "os.hedmark.no",
- "ni",
- "net.qa",
- "groks-the.info",
- "net.ba",
- "net.so",
- "net.sd",
- "toshima.tokyo.jp",
- "kchr.ru",
- "nom.br",
- "maritime.museum",
- "net.bs",
- "kikonai.hokkaido.jp",
- "net.sg",
- "kr.com",
- "nj.us",
- "jerusalem.museum",
- "net.ac",
- "rieti.it",
- "net.sa",
- "net.jo",
- "net.je",
- "laquila.it",
- "se.com",
- "takashima.shiga.jp",
- "shobara.hiroshima.jp",
- "net.bb",
- "terni.it",
- "not.br",
- "tempioolbia.it",
- "net.sc",
- "space-to-rent.com",
- "oshu.iwate.jp",
- "omi.nagano.jp",
- "nl",
- "org.af",
- "kanna.gunma.jp",
- "net.sb",
- "ntr.br",
- "net.au",
- "shirataka.yamagata.jp",
- "showa.yamanashi.jp",
- "net.co",
- "na",
- "net.tt",
- "net.ci",
- "net.bt",
+ "colonialwilliamsburg.museum",
+ "org.ae",
+ "fujioka.gunma.jp",
+ "org.pk",
+ "mytis.ru",
+ "shimoda.shizuoka.jp",
+ "asago.hyogo.jp",
+ "averoy.no",
+ "org.pl",
+ "ishikawa.fukushima.jp",
+ "org.vc",
+ "org.pe",
+ "mutsu.aomori.jp",
+ "kafjord.no",
+ "yaroslavl.ru",
+ "org.mw",
"org.ve",
+ "nikaho.akita.jp",
+ "klabu.no",
+ "mil.sy",
+ "nishiokoppe.hokkaido.jp",
+ "settsu.osaka.jp",
+ "yusuhara.kochi.jp",
+ "katagami.akita.jp",
+ "kirov.ru",
+ "org.pa",
+ "bizen.okayama.jp",
+ "usuki.oita.jp",
+ "mil.uy",
+ "kazan.ru",
+ "matsuda.kanagawa.jp",
+ "hokkaido.jp",
+ "wakasa.fukui.jp",
+ "ishinomaki.miyagi.jp",
+ "nonoichi.ishikawa.jp",
+ "unnan.shimane.jp",
+ "media.pl",
+ "shiksha",
+ "kaneyama.fukushima.jp",
+ "gwangju.kr",
+ "osteroy.no",
+ "org.ai",
+ "org.hk",
+ "gov.ky",
+ "edu.ky",
+ "semine.miyagi.jp",
+ "com.ky",
+ "nishiawakura.okayama.jp",
+ "sakhalin.ru",
+ "mil.by",
+ "isehara.kanagawa.jp",
+ "is-a-patsfan.org",
+ "ibara.okayama.jp",
+ "itami.hyogo.jp",
+ "matsukawa.nagano.jp",
+ "nakanojo.gunma.jp",
"org.vi",
- "nl.ca",
- "co.no",
- "na.it",
- "net.tn",
- "city.kawasaki.jp",
- "net.st",
- "net.br",
- "adygeya.ru",
- "hiranai.aomori.jp",
- "net.an",
- "sellsyourhome.org",
- "n.bg",
- "cn.com",
- "asahikawa.hokkaido.jp",
- "olkusz.pl",
- "org.vc",
- "name",
- "turystyka.pl",
- "codespot.com",
- "ogliastra.it",
- "np",
- "nb.ca",
- "net.al",
- "st.no",
- "corvette.museum",
- "nom.es",
- "net.cu",
- "net.sl",
- "name.mv",
- "name.eg",
+ "nikolaev.ua",
+ "kaneyama.yamagata.jp",
+ "kursk.ru",
+ "naoshima.kagawa.jp",
+ "aizumisato.fukushima.jp",
+ "shimokitayama.nara.jp",
+ "kamishihoro.hokkaido.jp",
+ "fukagawa.hokkaido.jp",
+ "ovre-eiker.no",
+ "oppdal.no",
+ "org.km",
+ "yotsukaido.chiba.jp",
+ "viking.museum",
+ "shintoku.hokkaido.jp",
+ "mil.my",
+ "shimamoto.osaka.jp",
+ "org.kp",
+ "shimada.shizuoka.jp",
+ "org.af",
+ "shiojiri.nagano.jp",
+ "ota.tokyo.jp",
+ "minoh.osaka.jp",
+ "fukushima.hokkaido.jp",
+ "yatomi.aichi.jp",
+ "mazury.pl",
+ "iruma.saitama.jp",
+ "net.gg",
+ "kochi.jp",
+ "mamurogawa.yamagata.jp",
+ "org.pf",
+ "oksnes.no",
+ "kani.gifu.jp",
+ "hanno.saitama.jp",
+ "oystre-slidre.no",
+ "gosen.niigata.jp",
+ "odessa.ua",
+ "mil.py",
+ "otsuka",
+ "ikoma.nara.jp",
+ "yoshioka.gunma.jp",
+ "ostroda.pl",
+ "sasebo.nagasaki.jp",
+ "minamiminowa.nagano.jp",
+ "silk.museum",
+ "ome.tokyo.jp",
+ "higashikawa.hokkaido.jp",
+ "varggat.no",
+ "kashiwazaki.niigata.jp",
+ "oygarden.no",
+ "sugito.saitama.jp",
+ "olecko.pl",
+ "yoshimi.saitama.jp",
+ "ikeda.osaka.jp",
+ "org.ki",
+ "minamidaito.okinawa.jp",
+ "belau.pw",
+ "kitagata.saga.jp",
+ "soka.saitama.jp",
+ "is-a-knight.org",
+ "shinjuku.tokyo.jp",
+ "cieszyn.pl",
+ "hanyu.saitama.jp",
+ "yoshida.saitama.jp",
+ "oita.oita.jp",
+ "ulvik.no",
+ "yashiro.hyogo.jp",
+ "chikuhoku.nagano.jp",
+ "sg",
+ "botany.museum",
+ "kouhoku.saga.jp",
+ "shonai.yamagata.jp",
+ "sakurai.nara.jp",
+ "shiraoka.saitama.jp",
+ "hakata.fukuoka.jp",
+ "nosegawa.nara.jp",
+ "karatsu.saga.jp",
+ "akita.akita.jp",
+ "wakayama.wakayama.jp",
+ "asaka.saitama.jp",
+ "county.museum",
+ "asker.no",
+ "shimoji.okinawa.jp",
+ "yuzhno-sakhalinsk.ru",
+ "chikushino.fukuoka.jp",
+ "kouyama.kagoshima.jp",
+ "shinjo.yamagata.jp",
+ "kanonji.kagawa.jp",
+ "yoshida.shizuoka.jp",
+ "akagi.shimane.jp",
+ "szczecin.pl",
+ "seranishi.hiroshima.jp",
+ "konin.pl",
+ "nakamura.kochi.jp",
"fukui.jp",
- "or.ci",
- "sa.com",
- "artcenter.museum",
- "tadotsu.kagawa.jp",
- "net.tj",
- "de.com",
- "aogashima.tokyo.jp",
- "org.bh",
- "br.com",
- "abira.hokkaido.jp",
- "gb.com",
- "net.cn",
- "tm.no",
- "hitachiota.ibaraki.jp",
- "mr.no",
- "org.vn",
- "akune.kagoshima.jp",
- "org.sh",
- "kicks-ass.org",
- "taira.toyama.jp",
- "gv.ao",
- "dgca.aero",
+ "koryo.nara.jp",
+ "ikata.ehime.jp",
+ "ide.kyoto.jp",
+ "inami.wakayama.jp",
+ "shinjo.okayama.jp",
+ "sukumo.kochi.jp",
+ "oirase.aomori.jp",
+ "rakkestad.no",
+ "setouchi.okayama.jp",
+ "aridagawa.wakayama.jp",
+ "yasaka.nagano.jp",
+ "is-a-bruinsfan.org",
+ "hirogawa.wakayama.jp",
+ "ine.kyoto.jp",
+ "higashine.yamagata.jp",
+ "kamikawa.hyogo.jp",
+ "hongo.hiroshima.jp",
+ "shintomi.miyazaki.jp",
+ "org.ru",
+ "askoy.no",
+ "is-by.us",
+ "buzen.fukuoka.jp",
+ "hanggliding.aero",
+ "aisho.shiga.jp",
+ "choyo.kumamoto.jp",
+ "higashiomi.shiga.jp",
+ "kunimi.fukushima.jp",
+ "yoichi.hokkaido.jp",
+ "org.ws",
+ "fedje.no",
+ "myoko.niigata.jp",
+ "org.sg",
+ "go.tz",
"ed.ao",
+ "stange.no",
"co.ao",
- "tr.no",
- "groks-this.info",
- "name.mk",
- "fm.no",
- "nh.us",
+ "co.sz",
+ "co.uz",
+ "co.tz",
+ "ostrowwlkp.pl",
+ "yashio.saitama.jp",
+ "id.us",
+ "co.us",
+ "co.ls",
+ "bykle.no",
+ "media.hu",
+ "nomi.ishikawa.jp",
+ "nuernberg.museum",
+ "org.ug",
+ "az.us",
+ "oristano.it",
+ "il.us",
+ "co.no",
+ "kusatsu.gunma.jp",
+ "as.us",
+ "id.au",
+ "ar.us",
"shiraoi.hokkaido.jp",
- "net.eg",
- "taiwa.miyagi.jp",
- "obu.aichi.jp",
- "nat.tn",
- "kawanishi.yamagata.jp",
- "statecouncil.om",
- "nm.cn",
- "eastafrica.museum",
- "nx.cn",
- "tsubata.ishikawa.jp",
- "sor-odal.no",
- "net.ec",
- "recreation.aero",
- "name.tt",
- "ouda.nara.jp",
- "ogi.saga.jp",
- "hiratsuka.kanagawa.jp",
- "aga.niigata.jp",
- "net.ws",
+ "vefsn.no",
+ "gu.us",
+ "co.rs",
+ "org.ng",
+ "al.us",
+ "hl.no",
+ "co.nl",
+ "co.mu",
+ "org.eg",
+ "fl.us",
+ "shibecha.hokkaido.jp",
+ "in.us",
"al.no",
- "name.tj",
- "rl.no",
- "blogsite.org",
+ "co.ae",
+ "it.ao",
+ "co.st",
+ "co.tt",
+ "co.at",
+ "hiroo.hokkaido.jp",
+ "co.me",
+ "aukra.no",
+ "go.cr",
"bu.no",
- "for-some.biz",
- "tatebayashi.gunma.jp",
- "hakusan.ishikawa.jp",
- "aa.no",
- "ne.tz",
- "legnica.pl",
- "ac.ci",
- "blogspot.cv",
- "chambagri.fr",
- "blogspot.cz",
- "net.ng",
- "dyndns.biz",
- "ne.pw",
- "teshikaga.hokkaido.jp",
- "sande.more-og-romsdal.no",
- "higashiizu.shizuoka.jp",
- "vladikavkaz.ru",
- "ringsaker.no",
- "taiki.mie.jp",
- "kashima.kumamoto.jp",
- "tomisato.chiba.jp",
- "ainan.ehime.jp",
- "dyndns-remote.com",
- "ah.no",
- "omantel.om",
- "kamishihoro.hokkaido.jp",
- "heritage.museum",
- "bremanger.no",
- "akita.akita.jp",
- "name.na",
- "leikanger.no",
- "nnov.ru",
- "satx.museum",
- "net.nr",
- "kashiba.nara.jp",
- "kisosaki.mie.jp",
- "miyoshi.saitama.jp",
- "higashiyoshino.nara.jp",
- "k12.ok.us",
- "haibara.shizuoka.jp",
- "blogspot.com",
- "shirahama.wakayama.jp",
- "stavanger.no",
- "ketrzyn.pl",
- "steinkjer.no",
- "sciencesnaturelles.museum",
- "zgora.pl",
- "samnanger.no",
- "lib.ok.us",
- "hof.no",
- "co.gy",
- "mincom.tn",
- "kanra.gunma.jp",
- "net.af",
- "monmouth.museum",
- "higashinaruse.akita.jp",
- "akkeshi.hokkaido.jp",
- "blogspot.ca",
- "net.ve",
- "saves-the-whales.com",
- "gobiernoelectronico.ar",
- "koshimizu.hokkaido.jp",
- "kautokeino.no",
- "net.vi",
- "nsw.au",
- "va.no",
- "higashiizumo.shimane.jp",
- "shimizu.hokkaido.jp",
- "sakae.nagano.jp",
- "akagi.shimane.jp",
- "nome.pt",
- "ggf.br",
- "omaezaki.shizuoka.jp",
+ "ed.cr",
+ "ct.us",
+ "in.rs",
+ "co.cr",
+ "gr.com",
+ "bd.se",
+ "naturbruksgymn.se",
+ "co.cl",
+ "ar.com",
+ "ebino.miyazaki.jp",
"hu.com",
- "kawachinagano.osaka.jp",
- "database.museum",
- "net.vc",
- "medizinhistorisches.museum",
- "k12.or.us",
- "from-mn.com",
- "from-mt.com",
- "from-de.com",
- "from-or.com",
- "from-in.com",
- "sch.id",
- "gratangen.no",
- "skiptvet.no",
- "blogspot.com.es",
- "ny.us",
- "niepce.museum",
- "naumburg.museum",
- "haebaru.okinawa.jp",
- "from-ar.com",
- "nes.akershus.no",
- "manx.museum",
- "blogspot.ch",
- "oyer.no",
- "lib.or.us",
- "kyotanabe.kyoto.jp",
- "from-ct.com",
- "nara.jp",
- "from-il.com",
- "tenei.fukushima.jp",
- "shimizu.shizuoka.jp",
- "kyowa.akita.jp",
- "kvanangen.no",
- "from-ok.com",
- "bizen.okayama.jp",
- "from-al.com",
- "net.th",
- "delaware.museum",
- "net.bh",
- "city.sapporo.jp",
- "shiriuchi.hokkaido.jp",
- "oyamazaki.kyoto.jp",
- "tm.ro",
- "volgograd.ru",
- "chukotka.ru",
- "from-ak.com",
- "net.vn",
- "from-ut.com",
- "net.sh",
- "london.museum",
- "hizen.saga.jp",
- "knowsitall.info",
- "k12.wv.us",
- "air-surveillance.aero",
- "miyoshi.tokushima.jp",
- "from-tx.com",
- "from-tn.com",
+ "eu.com",
+ "atami.shizuoka.jp",
+ "koriyama.fukushima.jp",
+ "br.com",
"hyuga.miyazaki.jp",
- "zagan.pl",
- "toyota.aichi.jp",
- "blogspot.com.au",
- "sabae.fukui.jp",
- "togitsu.nagasaki.jp",
- "campobasso.it",
- "laakesvuemie.no",
- "kamitsue.oita.jp",
- "shika.ishikawa.jp",
- "suita.osaka.jp",
- "from-nv.com",
- "from-nm.com",
- "lib.wv.us",
- "from-ne.com",
- "nittedal.no",
- "blogspot.com.ar",
- "sch.ir",
+ "org.mu",
+ "gd.cn",
+ "gz.cn",
+ "kanan.osaka.jp",
+ "hi.us",
+ "cn.com",
+ "nuremberg.museum",
+ "gs.cn",
+ "karmoy.no",
+ "orskog.no",
+ "mo.us",
+ "md.us",
+ "bushey.museum",
+ "hl.cn",
+ "ms.us",
+ "okinawa",
+ "shinichi.hiroshima.jp",
+ "york.museum",
+ "id.ly",
+ "chigasaki.kanagawa.jp",
+ "shikaoi.hokkaido.jp",
+ "mr.no",
+ "go.kr",
+ "co.kr",
+ "vardo.no",
+ "org.au",
+ "hn.cn",
+ "semboku.akita.jp",
+ "hs.kr",
+ "es.kr",
+ "go.tj",
+ "co.tj",
+ "gb.com",
+ "org.mg",
+ "yatsushiro.kumamoto.jp",
+ "mn.us",
+ "he.cn",
+ "co.gy",
+ "co.tm",
+ "go.ci",
+ "me.tz",
+ "yokohama",
+ "ed.ci",
+ "co.om",
+ "co.ci",
+ "sakura.chiba.jp",
+ "sakaiminato.tottori.jp",
+ "me.us",
+ "cq.cn",
+ "mt.us",
"hm.no",
- "from-ma.com",
- "fukuchiyama.kyoto.jp",
- "from-ia.com",
- "higashikurume.tokyo.jp",
- "from-ga.com",
- "from-nj.com",
- "forgot.her.name",
- "lindesnes.no",
- "okuizumo.shimane.jp",
- "saiki.oita.jp",
- "asahi.mie.jp",
- "blogspot.com.br",
- "higashiyamato.tokyo.jp",
- "higashisumiyoshi.osaka.jp",
- "folkebibl.no",
- "k12.nv.us",
- "chocolate.museum",
- "shiwa.iwate.jp",
- "from-ca.com",
- "boston.museum",
- "sanda.hyogo.jp",
- "flatanger.no",
- "from-md.com",
- "from-id.com",
- "nes.buskerud.no",
- "ng",
- "elvendrell.museum",
- "scienceandindustry.museum",
- "name.my",
- "lib.nv.us",
- "name.pr",
- "from-ms.com",
- "kyuragi.saga.jp",
- "from-ks.com",
- "artgallery.museum",
- "onna.okinawa.jp",
- "from-sd.com",
- "sciencehistory.museum",
- "tv.bo",
- "sakawa.kochi.jp",
- "shibata.miyagi.jp",
- "nore-og-uvdal.no",
- "ebina.kanagawa.jp",
- "szex.hu",
- "act.edu.au",
- "dyndns-ip.com",
- "oshino.yamanashi.jp",
- "atami.shizuoka.jp",
- "otsu.shiga.jp",
- "cc.mt.us",
- "forgot.his.name",
- "cc.ga.us",
- "cc.ma.us",
- "kiyosu.aichi.jp",
- "name.hr",
- "edogawa.tokyo.jp",
- "cc.ia.us",
- "mashike.hokkaido.jp",
- "cc.ct.us",
- "net.nf",
- "from-oh.com",
- "cc.ca.us",
- "cc.ms.us",
- "cc.ut.us",
- "sumita.iwate.jp",
- "cc.ks.us",
- "oiso.kanagawa.jp",
- "jefferson.museum",
- "katowice.pl",
- "funabashi.chiba.jp",
- "cartoonart.museum",
- "froya.no",
- "qc.ca",
- "from-dc.com",
- "oita.oita.jp",
- "from-nd.com",
- "hl.no",
- "name.jo",
- "shunan.yamaguchi.jp",
- "tenri.nara.jp",
- "tabuse.yamaguchi.jp",
- "shiki.saitama.jp",
- "from-sc.com",
- "or.bi",
- "cc.wa.us",
+ "stargard.pl",
+ "arida.wakayama.jp",
+ "bibai.hokkaido.jp",
+ "hb.cn",
+ "vadso.no",
+ "org.ag",
+ "fi.cr",
+ "yakutia.ru",
+ "hi.cn",
+ "co.ua",
+ "sera.hiroshima.jp",
+ "fm.no",
+ "okayama.jp",
+ "ga.us",
+ "ia.us",
+ "inami.toyama.jp",
+ "ostroleka.pl",
+ "mo.cn",
+ "ca.us",
+ "cr.ua",
+ "mi.us",
+ "co.ma",
+ "shobara.hiroshima.jp",
+ "koka.shiga.jp",
+ "ut.us",
+ "meiwa.mie.jp",
+ "us.com",
+ "aioi.hyogo.jp",
"ha.no",
- "kosai.shizuoka.jp",
- "sakaiminato.tottori.jp",
- "cc.vt.us",
- "orsta.no",
- "city.sendai.jp",
- "koori.fukushima.jp",
- "cc.va.us",
- "ookuwa.nagano.jp",
- "olawa.pl",
- "cc.tx.us",
- "komae.tokyo.jp",
- "cc.pa.us",
- "countryestate.museum",
- "kushimoto.wakayama.jp",
- "hayashima.okayama.jp",
- "mishima.shizuoka.jp",
- "gobo.wakayama.jp",
- "from-nh.com",
- "cc.dc.us",
- "skedsmokorset.no",
- "harvestcelebration.museum",
- "author.aero",
- "hammerfest.no",
- "naples.it",
- "kagoshima.kagoshima.jp",
- "from-nc.com",
- "tado.mie.jp",
- "toyone.aichi.jp",
- "scienceandhistory.museum",
- "kawai.nara.jp",
- "cc.nj.us",
- "cc.la.us",
- "hitachiomiya.ibaraki.jp",
- "ballangen.no",
- "koza.wakayama.jp",
- "miyoshi.hiroshima.jp",
- "org.im",
- "kashima.ibaraki.jp",
- "mashiki.kumamoto.jp",
- "cc.me.us",
- "arakawa.tokyo.jp",
- "cc.nc.us",
- "org.is",
- "noheji.aomori.jp",
- "notteroy.no",
- "toyota.yamaguchi.jp",
- "oumu.hokkaido.jp",
- "higashimurayama.tokyo.jp",
- "from-mo.com",
- "miura.kanagawa.jp",
- "dlugoleka.pl",
- "cc.as.us",
- "k12.oh.us",
- "cc.de.us",
- "mifune.kumamoto.jp",
- "higashiosaka.osaka.jp",
- "belgorod.ru",
- "stryn.no",
- "blogspot.fr",
- "azumino.nagano.jp",
- "ayabe.kyoto.jp",
- "hitachi.ibaraki.jp",
- "vic.edu.au",
- "tonosho.kagawa.jp",
- "from-fl.com",
- "langevag.no",
- "kiho.mie.jp",
- "dyndns-at-home.com",
- "betainabox.com",
- "lib.oh.us",
- "at-band-camp.net",
- "anamizu.ishikawa.jp",
- "cc.mn.us",
- "bielawa.pl",
- "org.ir",
- "org.in",
- "cc.in.us",
- "sakae.chiba.jp",
- "taiki.hokkaido.jp",
- "opole.pl",
- "sells-for-u.com",
- "berlevag.no",
- "kashima.saga.jp",
- "from-ky.com",
- "from-pr.com",
- "dyndns.info",
- "joboji.iwate.jp",
- "kushiro.hokkaido.jp",
- "vicenza.it",
- "cc.ne.us",
- "nebraska.museum",
- "noda.iwate.jp",
- "midatlantic.museum",
- "olbiatempio.it",
- "blogspot.fi",
- "nord-odal.no",
- "medecin.fr",
- "numata.gunma.jp",
- "amami.kagoshima.jp",
- "okutama.tokyo.jp",
- "kushima.miyazaki.jp",
- "bungoono.oita.jp",
- "higashiomi.shiga.jp",
- "cc.tn.us",
- "mecon.ar",
- "ryugasaki.ibaraki.jp",
- "toba.mie.jp",
- "etajima.hiroshima.jp",
- "michigan.museum",
- "florence.it",
- "higashiyodogawa.osaka.jp",
- "taki.mie.jp",
- "nannestad.no",
- "ozu.ehime.jp",
- "from-pa.com",
- "gov.hk",
- "medical.museum",
- "edu.hk",
- "com.hk",
- "hammarfeasta.no",
- "homebuilt.aero",
- "selfip.biz",
- "from-mi.com",
- "cc.az.us",
- "yt",
- "kanonji.kagawa.jp",
- "mediocampidano.it",
- "ye",
- "rokunohe.aomori.jp",
- "schoenbrunn.museum",
- "jamison.museum",
- "mallorca.museum",
- "tenkawa.nara.jp",
- "io",
- "id",
- "im",
- "marketplace.aero",
- "chihayaakasaka.osaka.jp",
- "higashihiroshima.hiroshima.jp",
- "tamba.hyogo.jp",
- "co.st",
- "ir",
- "y.se",
- "edu.ht",
- "im.it",
- "dellogliastra.it",
- "com.ht",
- "kanan.osaka.jp",
- "narita.chiba.jp",
- "it",
- "archaeological.museum",
- "goshiki.hyogo.jp",
- "dyn-o-saur.com",
- "edu.hn",
- "austevoll.no",
+ "co.na",
+ "erimo.hokkaido.jp",
+ "yamatokoriyama.nara.jp",
+ "nishihara.kumamoto.jp",
+ "aa.no",
+ "vagan.no",
+ "gv.ao",
+ "id.lv",
+ "in.ua",
+ "cn.ua",
+ "iz.hr",
+ "kitakata.fukushima.jp",
+ "ms.kr",
+ "inagi.tokyo.jp",
+ "kiryu.gunma.jp",
+ "sorfold.no",
+ "k12.ny.us",
+ "varoy.no",
+ "in.na",
+ "co.ca",
+ "org.hu",
+ "co.hu",
+ "md.ci",
+ "volda.no",
+ "bj.cn",
+ "stateofdelaware.museum",
+ "fj.cn",
+ "inawashiro.fukushima.jp",
+ "saikai.nagasaki.jp",
+ "ishigaki.okinawa.jp",
+ "nuoro.it",
+ "agrigento.it",
+ "bv.nl",
+ "gv.at",
+ "ha.cn",
+ "satosho.okayama.jp",
+ "kagamiishi.fukushima.jp",
+ "muika.niigata.jp",
+ "ma.us",
+ "valle.no",
+ "city.yokohama.jp",
+ "fussa.tokyo.jp",
"go.th",
- "is",
- "tokoname.aichi.jp",
- "com.hr",
- "com.hn",
+ "co.bi",
"co.th",
- "ie",
- "city.kitakyushu.jp",
- "from-ri.com",
- "omaha.museum",
- "id.us",
- "maintenance.aero",
- "cc.wv.us",
- "aizubange.fukushima.jp",
- "is.it",
- "bergbau.museum",
- "fribourg.museum",
- "sex.hu",
- "akabira.hokkaido.jp",
- "clinton.museum",
- "asahi.toyama.jp",
- "art.ht",
- "nomi.ishikawa.jp",
- "tsukiyono.gunma.jp",
- "i.se",
- "osaka.jp",
- "lucca.it",
- "vibovalentia.it",
- "net.im",
- "net.id",
- "noto.ishikawa.jp",
+ "zj.cn",
+ "rovigo.it",
+ "nishiwaki.hyogo.jp",
+ "minamiawaji.hyogo.jp",
+ "zt.ua",
+ "za.com",
+ "uy.com",
+ "nishihara.okinawa.jp",
+ "honjo.akita.jp",
+ "nogata.fukuoka.jp",
+ "ikeda.fukui.jp",
+ "uz.ua",
+ "suzu.ishikawa.jp",
+ "ah.no",
+ "ikawa.akita.jp",
+ "kaminoyama.yamagata.jp",
+ "ab.ca",
+ "in.th",
+ "kanegasaki.iwate.jp",
+ "chijiwa.nagasaki.jp",
"konan.shiga.jp",
- "botanicgarden.museum",
- "naruto.tokushima.jp",
- "oga.akita.jp",
- "nose.osaka.jp",
- "in",
- "net.is",
- "cc.nv.us",
- "arakawa.saitama.jp",
- "coldwar.museum",
- "birdart.museum",
- "boleslawiec.pl",
- "y.bg",
- "nysa.pl",
- "denmark.museum",
- "asso.dz",
- "rishiri.hokkaido.jp",
- "med.ht",
- "bibai.hokkaido.jp",
- "nawras.om",
- "tsuyama.okayama.jp",
- "il",
- "fineart.museum",
- "int",
- "s3-website-us-east-1.amazonaws.com",
- "in.ua",
- "hagi.yamaguchi.jp",
- "int.bo",
- "gangaviika.no",
- "noda.chiba.jp",
- "int.az",
- "nord-fron.no",
- "store.bb",
- "in.us",
- "ohtawara.tochigi.jp",
- "magazine.aero",
- "volyn.ua",
- "idrett.no",
- "vibo-valentia.it",
- "frosta.no",
- "org.sy",
- "convent.museum",
- "hamatonbetsu.hokkaido.jp",
- "opoczno.pl",
- "net.ir",
- "net.in",
- "i.bg",
- "muosat.no",
- "otoineppu.hokkaido.jp",
- "il.us",
- "dyndns-at-work.com",
- "yk.ca",
- "artanddesign.museum",
- "kiwa.mie.jp",
- "york.museum",
- "ostre-toten.no",
- "mi.th",
- "co.sz",
- "ia.us",
- "ind.tn",
- "rel.ht",
- "ind.br",
- "gob.hn",
- "numata.hokkaido.jp",
+ "sakado.saitama.jp",
+ "us.na",
+ "xz.cn",
+ "kariwa.niigata.jp",
+ "oji.nara.jp",
+ "orenburg.ru",
+ "fh.se",
+ "am.br",
+ "org.kg",
+ "gs.oslo.no",
+ "soma.fukushima.jp",
+ "selfip.info",
+ "asahi.toyama.jp",
+ "fm.br",
+ "kasai.hyogo.jp",
+ "yorkshire.museum",
+ "okinawa.jp",
+ "xn--45q11c",
+ "motegi.tochigi.jp",
+ "co.ba",
+ "ca.na",
+ "uji.kyoto.jp",
+ "qh.cn",
+ "randaberg.no",
+ "ak.us",
+ "nishiazai.shiga.jp",
+ "ah.cn",
+ "ngo.ph",
+ "cv.ua",
+ "shiiba.miyazaki.jp",
+ "kosei.shiga.jp",
+ "fuchu.hiroshima.jp",
+ "bl.uk",
+ "shikabe.hokkaido.jp",
+ "katashina.gunma.jp",
+ "mb.ca",
+ "stockholm.museum",
+ "nachikatsuura.wakayama.jp",
+ "kanna.gunma.jp",
+ "video.hu",
+ "kanra.gunma.jp",
+ "ec",
+ "cc",
+ "gov.co",
+ "edu.co",
+ "gov.cm",
+ "com.co",
+ "chofu.tokyo.jp",
+ "ac",
+ "ketrzyn.pl",
+ "koshu.yamanashi.jp",
+ "omasvuotna.no",
+ "gov.cl",
+ "gob.cl",
+ "sakuho.nagano.jp",
+ "actor",
+ "svizzera.museum",
+ "zp.ua",
+ "fudai.iwate.jp",
"int.co",
- "komforb.se",
- "int.tt",
+ "overhalla.no",
+ "hk.cn",
+ "shimamaki.hokkaido.jp",
+ "xj.cn",
+ "mi.th",
+ "abira.hokkaido.jp",
+ "gov.cd",
+ "xn--90a3ac",
+ "wi.us",
+ "monza.it",
+ "ako.hyogo.jp",
+ "minamiuonuma.niigata.jp",
+ "fuchu.toyama.jp",
+ "nishiarita.saga.jp",
+ "hofu.yamaguchi.jp",
+ "wy.us",
+ "ecn.br",
+ "urawa.saitama.jp",
+ "xn--d1acj3b",
+ "mc",
+ "edu.cw",
+ "org.sh",
+ "yamanashi.yamanashi.jp",
+ "xn--55qx5d",
+ "eco.br",
+ "fuchu.tokyo.jp",
+ "com.cw",
+ "fujisawa.kanagawa.jp",
+ "ikeda.hokkaido.jp",
+ "iwade.wakayama.jp",
+ "edu.ci",
+ "com.ci",
+ "academy",
+ "ck.ua",
+ "setagaya.tokyo.jp",
+ "makurazaki.kagoshima.jp",
+ "uk.com",
+ "meiwa.gunma.jp",
+ "k12.ky.us",
+ "xn--55qx5d.cn",
+ "namegawa.saitama.jp",
+ "wa.us",
+ "oizumi.gunma.jp",
"int.ci",
- "medio-campidano.it",
- "nativeamerican.museum",
- "higashimatsuyama.saitama.jp",
- "koya.wakayama.jp",
- "za.com",
- "onga.fukuoka.jp",
- "in.na",
- "fukui.fukui.jp",
- "media.aero",
- "theater.museum",
- "logistics.aero",
- "hashimoto.wakayama.jp",
- "achi.nagano.jp",
- "jobs",
- "ws",
- "defense.tn",
- "tm.se",
- "sande.xn--mre-og-romsdal-qqb.no",
- "imb.br",
- "saotome.st",
+ "sobetsu.hokkaido.jp",
+ "org.bh",
+ "wa.au",
+ "matsuyama.ehime.jp",
+ "ws.na",
+ "kanzaki.saga.jp",
+ "otsuki.kochi.jp",
+ "xn--io0a7i",
+ "izena.okinawa.jp",
+ "xn--slat-5na.no",
+ "kozagawa.wakayama.jp",
"wv.us",
- "arts.nf",
- "s3-website-sa-east-1.amazonaws.com",
- "crotone.it",
- "lebtimnetz.de",
- "nara.nara.jp",
- "arts.museum",
- "dyndns-home.com",
- "hioki.kagoshima.jp",
- "omuta.fukuoka.jp",
- "narvik.no",
- "int.tj",
- "aguni.okinawa.jp",
- "village.museum",
- "nagasaki.jp",
- "lecce.it",
- "hoylandet.no",
- "w.se",
- "sibenik.museum",
- "higashine.yamagata.jp",
- "hitachinaka.ibaraki.jp",
- "yn.cn",
+ "yamatotakada.nara.jp",
+ "xn--zfr164b",
+ "blogspot.be",
+ "iide.yamagata.jp",
+ "xn--p1ai",
+ "yamato.kanagawa.jp",
+ "gf",
+ "sakaki.nagano.jp",
+ "cf",
+ "kosai.shizuoka.jp",
+ "mk.ua",
"com.fr",
- "mil.hn",
- "sorfold.no",
- "cremona.it",
- "sagae.yamagata.jp",
- "shari.hokkaido.jp",
- "fujishiro.ibaraki.jp",
- "axis.museum",
- "bd.se",
- "asahi.nagano.jp",
- "mobi.tz",
- "ternopil.ua",
- "blogspot.co.nz",
- "akrehamn.no",
- "novosibirsk.ru",
- "brussels.museum",
- "kids.museum",
- "numazu.shizuoka.jp",
- "suisse.museum",
- "stjohn.museum",
- "kids.us",
- "lib.hi.us",
- "iron.museum",
- "go.dyndns.org",
- "jobs.tt",
- "wi.us",
- "toyoake.aichi.jp",
- "s3-website-us-west-1.amazonaws.com",
- "grosseto.it",
- "shimoichi.nara.jp",
- "dyndns-work.com",
- "hirono.iwate.jp",
- "finland.museum",
- "intl.tn",
- "shitara.aichi.jp",
- "ws.na",
- "shinshiro.aichi.jp",
- "campidano-medio.it",
- "farmers.museum",
- "kalmykia.ru",
- "iraq.museum",
- "w.bg",
- "artdeco.museum",
- "doshi.yamanashi.jp",
- "technology.museum",
- "blogspot.co.at",
- "aizuwakamatsu.fukushima.jp",
- "motoyama.kochi.jp",
- "city.nagoya.jp",
- "wa.us",
- "tateyama.toyama.jp",
- "oi.kanagawa.jp",
- "naka.ibaraki.jp",
- "osakasayama.osaka.jp",
- "tobishima.aichi.jp",
- "motosu.gifu.jp",
- "eidsberg.no",
- "vinnytsia.ua",
- "indian.museum",
- "chicago.museum",
- "from-hi.com",
- "omitama.ibaraki.jp",
- "blogspot.co.uk",
- "santafe.museum",
- "moroyama.saitama.jp",
- "blogspot.co.il",
- "kamchatka.ru",
- "kutno.pl",
- "nantan.kyoto.jp",
- "sakai.fukui.jp",
- "honai.ehime.jp",
- "otama.fukushima.jp",
- "higashi.okinawa.jp",
- "handson.museum",
- "nuernberg.museum",
- "fh.se",
- "arts.co",
- "songfest.om",
- "atlanta.museum",
- "net.sy",
- "ip6.arpa",
- "web.co",
- "higashikagura.hokkaido.jp",
- "seihi.nagasaki.jp",
- "glas.museum",
- "horonobe.hokkaido.jp",
- "tonsberg.no",
- "okuma.fukushima.jp",
- "grajewo.pl",
- "higashiyama.kyoto.jp",
- "niigata.jp",
- "bialystok.pl",
- "askvoll.no",
- "neues.museum",
- "here-for-more.info",
- "sveio.no",
- "kristiansund.no",
- "corporation.museum",
- "kai.yamanashi.jp",
- "iq",
- "dyndns-wiki.com",
- "takinoue.hokkaido.jp",
- "radio.br",
- "arts.ro",
- "lans.museum",
- "imageandsound.museum",
- "fudai.iwate.jp",
- "shakotan.hokkaido.jp",
- "rankoshi.hokkaido.jp",
- "id.lv",
- "traniandriabarletta.it",
- "narviika.no",
- "voronezh.ru",
- "in.rs",
- "ballooning.aero",
- "versailles.museum",
- "higashiagatsuma.gunma.jp",
- "web.tj",
- "i.ph",
- "gateway.museum",
- "notaires.km",
- "selfip.info",
- "ethnology.museum",
- "onomichi.hiroshima.jp",
- "nagano.jp",
- "kaminokawa.tochigi.jp",
- "flight.aero",
- "moriyoshi.akita.jp",
- "otake.hiroshima.jp",
- "flesberg.no",
- "moss.no",
- "stathelle.no",
- "takanabe.miyazaki.jp",
- "moriya.ibaraki.jp",
- "safety.aero",
- "wiki.br",
- "okawa.fukuoka.jp",
- "dyndns-mail.com",
- "astronomy.museum",
- "fukuoka.jp",
- "tsuga.tochigi.jp",
- "gifu.gifu.jp",
- "int.vn",
- "niikappu.hokkaido.jp",
- "shiroi.chiba.jp",
- "mosjoen.no",
+ "af",
+ "xn--io0a7i.cn",
+ "naka.hiroshima.jp",
+ "bf",
+ "kikugawa.shizuoka.jp",
+ "ks.us",
+ "aca.pro",
+ "askim.no",
"nesna.no",
- "balsan.it",
- "naha.okinawa.jp",
- "karasuyama.tochigi.jp",
- "s3-website-us-west-2.amazonaws.com",
- "airport.aero",
- "gonohe.aomori.jp",
- "eidsvoll.no",
- "alabama.museum",
- "kuriyama.hokkaido.jp",
- "shirakawa.gifu.jp",
- "shirakawa.fukushima.jp",
- "karmoy.no",
- "kepno.pl",
- "omi.niigata.jp",
- "historichouses.museum",
- "miyawaka.fukuoka.jp",
- "rovno.ua",
- "uz",
- "kristiansand.no",
- "manchester.museum",
- "gov.do",
- "gov.dm",
- "southcarolina.museum",
- "edu.do",
- "edu.dm",
- "com.do",
- "com.dm",
- "com.de",
- "gov.dz",
- "edu.dz",
- "nagasu.kumamoto.jp",
- "cc.mi.us",
- "com.dz",
+ "yokote.akita.jp",
+ "higashimatsushima.miyagi.jp",
+ "yurihonjo.akita.jp",
+ "orkdal.no",
+ "online.museum",
+ "asso.mc",
+ "family.museum",
+ "sakawa.kochi.jp",
+ "onna.okinawa.jp",
"go.id",
+ "xn--smla-hra.no",
+ "sannohe.aomori.jp",
"co.id",
- "ud.it",
- "dynathome.net",
- "taiji.wakayama.jp",
- "k12.fl.us",
- "halloffame.museum",
- "voss.no",
- "kosei.shiga.jp",
- "nord-aurdal.no",
- "uz.ua",
- "us",
- "obanazawa.yamagata.jp",
- "kishiwada.osaka.jp",
- "historical.museum",
- "art.do",
- "s3-website-ap-southeast-1.amazonaws.com",
- "lib.fl.us",
- "art.dz",
- "wy.us",
- "kasai.hyogo.jp",
- "shimotsuma.ibaraki.jp",
- "wroc.pl",
- "cc.wi.us",
- "kumiyama.kyoto.jp",
- "u.se",
- "reggio-calabria.it",
- "ut.us",
- "indianmarket.museum",
- "cc.vi.us",
- "forli-cesena.it",
- "railway.museum",
- "nsw.edu.au",
- "tamayu.shimane.jp",
- "hekinan.aichi.jp",
- "kashiwara.osaka.jp",
- "sandoy.no",
- "bomlo.no",
- "fukaya.saitama.jp",
- "illustration.museum",
- "asahi.chiba.jp",
- "video.hu",
- "arkhangelsk.ru",
- "higashimatsushima.miyagi.jp",
- "bunkyo.tokyo.jp",
- "starostwo.gov.pl",
- "bo.nordland.no",
- "is-a-nurse.com",
- "s3-website-ap-northeast-1.amazonaws.com",
- "sld.do",
- "asahi.yamagata.jp",
- "sor-fron.no",
- "tranoy.no",
- "ua",
- "hobby-site.com",
- "org.tw",
- "web.ve",
- "org.bw",
- "isla.pr",
- "happou.akita.jp",
- "us.na",
- "england.museum",
- "andriatranibarletta.it",
- "gob.do",
- "u.bg",
- "gallery.museum",
- "yono.saitama.jp",
- "vardo.no",
- "shimokawa.hokkaido.jp",
- "tarnobrzeg.pl",
- "tomiya.miyagi.jp",
- "nasu.tochigi.jp",
- "yaroslavl.ru",
- "finnoy.no",
- "hemsedal.no",
- "rodoy.no",
- "dyndns-free.com",
- "nago.okinawa.jp",
- "uk",
- "nakano.tokyo.jp",
- "massacarrara.it",
- "org.cw",
- "sejny.pl",
- "hadsel.no",
- "hitoyoshi.kumamoto.jp",
- "com.ro",
- "com.re",
- "go.kr",
- "co.kr",
- "seljord.no",
+ "rikuzentakata.iwate.jp",
+ "kyowa.akita.jp",
+ "id.ir",
+ "omi.nagano.jp",
+ "blogspot.bj",
"co.ir",
- "tynset.no",
- "go.cr",
- "ed.cr",
- "gov.rs",
- "co.cr",
- "edu.rs",
- "shinanomachi.nagano.jp",
- "dnsdojo.net",
- "is-a-llama.com",
- "nagatoro.saitama.jp",
- "yokkaichi.mie.jp",
- "nakano.nagano.jp",
- "naie.hokkaido.jp",
- "annefrank.museum",
- "cuneo.it",
- "yazu.tottori.jp",
- "es.kr",
- "california.museum",
- "averoy.no",
- "luroy.no",
- "fukuyama.hiroshima.jp",
- "mil.do",
- "sakai.osaka.jp",
- "re.kr",
- "nagiso.nagano.jp",
- "gov.ru",
+ "xn--seral-lra.no",
+ "co.mw",
+ "org.ph",
+ "naroy.no",
+ "xn--3bst00m",
+ "chuo.yamanashi.jp",
+ "xn--kpry57d",
+ "kr.com",
+ "info.ec",
+ "co.rw",
+ "uruma.okinawa.jp",
+ "yokohama.jp",
+ "sakata.yamagata.jp",
+ "mil.co",
+ "yamanakako.yamanashi.jp",
+ "vestby.no",
+ "honjo.saitama.jp",
+ "omsk.ru",
+ "co.in",
+ "komae.tokyo.jp",
+ "mil.cl",
+ "xn--skjk-soa.no",
+ "yokoze.saitama.jp",
+ "go.it",
+ "co.it",
+ "kakegawa.shizuoka.jp",
+ "cz.it",
+ "grong.no",
+ "xn--j1amh",
+ "contractors",
+ "yamashina.kyoto.jp",
+ "is.it",
+ "zgrad.ru",
+ "yomitan.okinawa.jp",
+ "gr.it",
+ "cs.it",
+ "shizuoka.jp",
+ "cr.it",
+ "ao.it",
"ae.org",
- "fermo.it",
- "edu.ru",
- "com.ru",
- "farmequipment.museum",
- "andoy.no",
- "shimosuwa.nagano.jp",
- "moriyama.shiga.jp",
- "tm.fr",
- "nakanojo.gunma.jp",
- "hatoyama.saitama.jp",
- "univ.sn",
- "nakasatsunai.hokkaido.jp",
- "nagi.okayama.jp",
- "niki.hokkaido.jp",
- "yamato.kumamoto.jp",
- "rishirifuji.hokkaido.jp",
- "kawai.iwate.jp",
- "stv.ru",
- "uvic.museum",
- "city.yokohama.jp",
- "s3-website-ap-southeast-2.amazonaws.com",
- "tottori.jp",
- "gov.mo",
- "gov.me",
- "ms.kr",
- "edu.mo",
- "edu.me",
- "gov.mk",
- "edu.mk",
- "com.mo",
- "miasta.pl",
- "com.mk",
- "gov.mg",
- "edu.mg",
- "radoy.no",
- "com.mg",
+ "cl.it",
+ "shishikui.tokushima.jp",
+ "brescia.it",
+ "ar.it",
+ "bo.it",
+ "xn--yer-zna.no",
+ "ky.us",
+ "bz.it",
+ "xn--rdal-poa.no",
+ "al.it",
+ "bs.it",
+ "br.it",
+ "fr.it",
+ "xn--od0alg.cn",
+ "bl.it",
+ "en.it",
+ "iwata.shizuoka.jp",
+ "cn.it",
+ "blogspot.cf",
+ "2000.hu",
+ "motorcycles",
+ "ge.it",
+ "an.it",
+ "itano.tokushima.jp",
+ "ce.it",
+ "rieti.it",
+ "xn--rland-uua.no",
+ "bn.it",
+ "ct.it",
+ "is-an-actress.com",
+ "aq.it",
+ "vagsoy.no",
+ "at.it",
+ "xn--mely-ira.no",
+ "fe.it",
+ "is-a-caterer.com",
+ "bt.it",
+ "nagahama.shiga.jp",
+ "cb.it",
+ "okutama.tokyo.jp",
+ "ks.ua",
+ "kr.ua",
+ "yonabaru.okinawa.jp",
"co.im",
- "gov.ma",
- "kms.ru",
- "tom.ru",
- "www.ck",
- "nedre-eiker.no",
- "web.nf",
- "s3-website-us-gov-west-1.amazonaws.com",
- "ozora.hokkaido.jp",
- "morioka.iwate.jp",
- "uri.arpa",
- "k12.de.us",
- "mitoyo.kagawa.jp",
- "reggio-emilia.it",
- "kounosu.saitama.jp",
- "money.museum",
- "seirou.niigata.jp",
- "urn.arpa",
- "osakikamijima.hiroshima.jp",
- "cc.hi.us",
- "kawanabe.kagoshima.jp",
- "kouyama.kagoshima.jp",
+ "roros.no",
+ "sanuki.kagawa.jp",
+ "omi.niigata.jp",
+ "xn--sr-aurdal-l8a.no",
+ "ci.it",
+ "us.org",
+ "kitanakagusuku.okinawa.jp",
+ "do",
+ "nakijin.okinawa.jp",
+ "dz",
+ "mo.it",
+ "yakumo.hokkaido.jp",
+ "ms.it",
+ "web.co",
+ "edu.sn",
+ "is-slick.com",
+ "com.sn",
+ "bi.it",
+ "xn--troms-zua.no",
+ "fi.it",
+ "hiratsuka.kanagawa.jp",
+ "ozu.ehime.jp",
+ "is-an-artist.com",
+ "coop",
+ "navigation.aero",
+ "xn--asky-ira.no",
+ "art.sn",
+ "feedback",
+ "koori.fukushima.jp",
+ "oshima.tokyo.jp",
+ "d.bg",
+ "grue.no",
+ "coop.mw",
+ "xn--rros-gra.no",
+ "d.se",
+ "ud.it",
+ "mn.it",
+ "dnp",
+ "ukiha.fukuoka.jp",
+ "omachi.nagano.jp",
+ "enterprises",
+ "zgora.pl",
+ "alta.no",
+ "de",
+ "im.it",
+ "k12.wy.us",
+ "sumoto.hyogo.jp",
+ "me.it",
+ "co.bw",
+ "arna.no",
+ "kamakura.kanagawa.jp",
+ "cloudcontrolled.com",
+ "mt.it",
+ "info.na",
+ "gov.tn",
+ "my.id",
+ "aure.no",
+ "com.tn",
+ "coop.br",
+ "xn--merker-kua.no",
+ "fm.it",
+ "xn--sr-odal-q1a.no",
+ "coop.py",
+ "horten.no",
+ "xn--i1b6b1a6a2e",
+ "xn--sknit-yqa.no",
+ "mb.it",
+ "info.nr",
+ "gran.no",
+ "fusa.no",
+ "ca.it",
+ "dep.no",
+ "mi.it",
+ "gov.in",
+ "edu.in",
"honefoss.no",
- "gov.mu",
- "rnd.ru",
- "snz.ru",
- "lib.de.us",
- "com.mu",
- "sa.cr",
- "nirasaki.yamanashi.jp",
- "k12.dc.us",
- "uba.ar",
- "otsuchi.iwate.jp",
- "station.museum",
- "kamioka.akita.jp",
- "sapporo.jp",
- "tm.km",
- "misconfused.org",
- "gov.iq",
- "edu.iq",
- "hakui.ishikawa.jp",
- "gov.mr",
+ "shingo.aomori.jp",
+ "etne.no",
+ "bodo.no",
+ "arq.br",
+ "xn--smna-gra.no",
+ "ba.it",
+ "xn--trgstad-r1a.no",
+ "za.org",
+ "risor.no",
+ "city.kobe.jp",
+ "mormon",
+ "starnberg.museum",
+ "is-a-painter.com",
+ "berg.no",
+ "istmein.de",
+ "yame.fukuoka.jp",
+ "iheya.okinawa.jp",
+ "ap.it",
+ "ens.tn",
+ "xn--risa-5na.no",
+ "arts.nf",
+ "km.ua",
+ "is-an-actor.com",
+ "av.it",
+ "dj",
+ "from-co.net",
+ "xn--mli-tla.no",
+ "moss.no",
+ "xn--linds-pra.no",
+ "from-la.net",
+ "xn--yfro4i67o",
+ "xn--55qx5d.hk",
+ "dm",
+ "hole.no",
"gov.mn",
- "com.iq",
+ "historisch.museum",
"edu.mn",
- "meloy.no",
- "lib.dc.us",
- "co.tm",
- "fi.cr",
- "ginan.gifu.jp",
- "unbi.ba",
- "archaeology.museum",
- "kui.hiroshima.jp",
- "yuki.ibaraki.jp",
- "bahcavuotna.no",
- "yokote.akita.jp",
- "narusawa.yamanashi.jp",
- "masoy.no",
- "sa.edu.au",
- "cc.ri.us",
- "tochio.niigata.jp",
- "gov.ml",
- "edu.ml",
- "askoy.no",
- "floro.no",
- "com.ml",
- "takayama.nagano.jp",
- "malatvuopmi.no",
- "textile.museum",
- "uy",
- "teledata.mz",
- "hachioji.tokyo.jp",
- "net.tw",
- "ivgu.no",
- "chichibu.saitama.jp",
- "higashikawa.hokkaido.jp",
- "unsa.ba",
- "massa-carrara.it",
- "zhitomir.ua",
- "tadaoka.osaka.jp",
- "yorkshire.museum",
- "toyotsu.fukuoka.jp",
- "tottori.tottori.jp",
- "nc",
- "ina.nagano.jp",
- "kameoka.kyoto.jp",
- "khv.ru",
- "indianapolis.museum",
- "arboretum.museum",
- "shimonita.gunma.jp",
- "stjordal.no",
- "memorial.museum",
- "varoy.no",
- "e-burg.ru",
- "jar.ru",
- "judaica.museum",
- "bir.ru",
- "net.cw",
- "takayama.gunma.jp",
- "my.id",
- "orskog.no",
- "kemerovo.ru",
- "kunstunddesign.museum",
- "zoological.museum",
- "kunstsammlung.museum",
- "tachikawa.tokyo.jp",
- "shikokuchuo.ehime.jp",
- "nc.us",
- "isen.kagoshima.jp",
- "int.is",
- "kostroma.ru",
- "yokoze.saitama.jp",
- "chelyabinsk.ru",
- "mil.ru",
- "uk.net",
- "soundandvision.museum",
- "foundation.museum",
- "fukushima.fukushima.jp",
- "vrn.ru",
- "shichinohe.aomori.jp",
- "naka.hiroshima.jp",
- "ogawa.saitama.jp",
- "kitahata.saga.jp",
- "malbork.pl",
- "louvre.museum",
- "sango.nara.jp",
- "msk.ru",
- "aerobatic.aero",
- "flanders.museum",
+ "info.nf",
+ "yakumo.shimane.jp",
+ "from-ma.com",
+ "gen.in",
+ "coop.mv",
+ "ind.tn",
+ "steigen.no",
+ "xn--risr-ira.no",
+ "from-ca.com",
+ "from-mo.com",
+ "rodoy.no",
+ "from-ri.com",
+ "berlin",
+ "from-mi.com",
+ "omachi.saga.jp",
+ "bergen.no",
+ "hammerfest.no",
+ "romsa.no",
+ "from-pa.com",
+ "suli.hu",
+ "from-or.com",
+ "swiebodzin.pl",
+ "from-az.net",
+ "from-ky.com",
+ "wf",
+ "fin.tn",
+ "from-ok.com",
+ "edu.an",
"ind.in",
- "k12.ri.us",
- "tsk.ru",
- "adachi.tokyo.jp",
- "istmein.de",
- "mizuho.tokyo.jp",
- "obama.fukui.jp",
- "shiroishi.saga.jp",
- "obira.hokkaido.jp",
- "kasuya.fukuoka.jp",
- "mil.mg",
- "kawahara.tottori.jp",
- "matera.it",
- "nogi.tochigi.jp",
- "children.museum",
- "modern.museum",
- "lib.ri.us",
- "chosei.chiba.jp",
- "broadcast.museum",
- "ug",
- "niihama.ehime.jp",
- "honjyo.akita.jp",
- "irkutsk.ru",
- "jolster.no",
- "bungotakada.oita.jp",
- "ashiya.hyogo.jp",
- "luzern.museum",
- "spb.ru",
- "ashiya.fukuoka.jp",
- "kanoya.kagoshima.jp",
- "takko.aomori.jp",
- "hiraya.nagano.jp",
- "awaji.hyogo.jp",
- "nagawa.nagano.jp",
- "samara.ru",
- "niigata.niigata.jp",
- "otobe.hokkaido.jp",
- "montreal.museum",
- "cmw.ru",
- "automotive.museum",
- "aomori.jp",
- "childrens.museum",
- "canada.museum",
- "asuke.aichi.jp",
- "ingatlan.hu",
- "building.museum",
- "ol.no",
- "british.museum",
- "obama.nagasaki.jp",
- "kasaoka.okayama.jp",
- "mil.iq",
- "brindisi.it",
- "nagano.nagano.jp",
- "nic.tr",
- "russia.museum",
- "nakanoto.ishikawa.jp",
- "tomioka.gunma.jp",
- "nic.ar",
- "k12.mo.us",
- "k12.me.us",
- "k12.md.us",
- "czest.pl",
- "machida.tokyo.jp",
- "k12.mi.us",
- "hs.kr",
- "australia.museum",
- "naganohara.gunma.jp",
- "omihachiman.shiga.jp",
- "aircraft.aero",
- "kongsvinger.no",
- "nagasaki.nagasaki.jp",
- "k12.ma.us",
- "kudoyama.wakayama.jp",
- "k12.ms.us",
- "higashikagawa.kagawa.jp",
- "yame.fukuoka.jp",
- "lib.mo.us",
- "lib.me.us",
- "lib.md.us",
+ "camp",
+ "com.an",
+ "iwaki.fukushima.jp",
+ "okegawa.saitama.jp",
+ "iwate.iwate.jp",
+ "merseine.nu",
+ "from-pr.com",
+ "amot.no",
+ "niki.hokkaido.jp",
+ "okayama.okayama.jp",
+ "xn--trany-yua.no",
+ "ch.it",
+ "kv.ua",
+ "community",
+ "from-al.com",
+ "gov.pn",
+ "from-mn.com",
+ "edu.pn",
+ "eniwa.hokkaido.jp",
+ "omaezaki.shizuoka.jp",
+ "agrar.hu",
+ "bialowieza.pl",
+ "gov.vn",
+ "edu.vn",
+ "homeunix.com",
+ "com.vn",
+ "nakasatsunai.hokkaido.jp",
+ "xn--io0a7i.hk",
+ "oxford.museum",
+ "firm.nf",
+ "aerodrome.aero",
+ "from-ar.com",
+ "gov.cu",
+ "edu.cu",
+ "is-a-socialist.com",
+ "cremona.it",
+ "com.cu",
+ "rygge.no",
"kofu.yamanashi.jp",
- "lib.mi.us",
- "kyoto.jp",
- "mochizuki.nagano.jp",
- "tanohata.iwate.jp",
- "chitose.hokkaido.jp",
- "arteducation.museum",
- "carrier.museum",
- "dnsdojo.org",
- "forsand.no",
- "tosashimizu.kochi.jp",
- "lib.ma.us",
- "tjeldsund.no",
- "dielddanuorri.no",
- "lib.ms.us",
- "yakutia.ru",
- "miners.museum",
- "yekaterinburg.ru",
- "nic.tj",
- "columbus.museum",
- "kicks-ass.net",
- "gets-it.net",
- "tochigi.jp",
- "utah.museum",
- "teramo.it",
- "iki.nagasaki.jp",
- "zhytomyr.ua",
- "badaddja.no",
- "fujioka.gunma.jp",
- "elburg.museum",
- "k12.mt.us",
- "am.br",
- "miyoshi.aichi.jp",
- "wakasa.tottori.jp",
- "shimoda.shizuoka.jp",
- "moscow.museum",
- "city.kobe.jp",
- "vestre-toten.no",
- "hattfjelldal.no",
- "dyroy.no",
- "k12.mn.us",
- "odate.akita.jp",
- "nogata.fukuoka.jp",
- "cinema.museum",
- "lib.mt.us",
- "federation.aero",
- "yamanashi.jp",
- "from-az.net",
- "kochi.jp",
- "brescia.it",
- "warabi.saitama.jp",
- "kobayashi.miyazaki.jp",
- "oregon.museum",
- "hachinohe.aomori.jp",
- "omura.nagasaki.jp",
- "lib.mn.us",
- "rifu.miyagi.jp",
+ "kunigami.okinawa.jp",
+ "folkebibl.no",
+ "xn--rennesy-v1a.no",
+ "from-ak.com",
+ "kagoshima.kagoshima.jp",
+ "motorcycle.museum",
+ "is-a-doctor.com",
+ "net.sy",
+ "from-wa.com",
+ "xn--bmlo-gra.no",
+ "coop.km",
+ "bo.telemark.no",
+ "fukui.fukui.jp",
+ "net.ly",
+ "homeunix.net",
+ "int.vn",
+ "from-wi.com",
+ "net.uy",
+ "radom.pl",
+ "from-wy.com",
+ "from-il.com",
+ "from-ia.com",
+ "sunagawa.hokkaido.jp",
+ "inf.cu",
+ "kh.ua",
+ "nakaniikawa.toyama.jp",
+ "rissa.no",
+ "dni.us",
+ "xn--rde-ula.no",
+ "otsuki.yamanashi.jp",
+ "shikokuchuo.ehime.jp",
+ "xn--hobl-ira.no",
+ "control.aero",
+ "osakasayama.osaka.jp",
+ "kasuga.hyogo.jp",
+ "ivgu.no",
+ "gob.hn",
+ "edu.hn",
+ "insurance.aero",
+ "com.hn",
+ "getmyip.com",
+ "dance",
+ "kaita.hiroshima.jp",
+ "donetsk.ua",
+ "onomichi.hiroshima.jp",
+ "xn--sandy-yua.no",
+ "dnsalias.com",
+ "grozny.ru",
+ "itoigawa.niigata.jp",
+ "from-in.com",
"beiarn.no",
- "sannohe.aomori.jp",
- "iveland.no",
- "higashiura.aichi.jp",
- "shimokitayama.nara.jp",
- "uda.nara.jp",
- "aomori.aomori.jp",
- "semboku.akita.jp",
- "stavropol.ru",
- "czeladz.pl",
- "web.id",
- "tv.br",
- "does-it.net",
- "ullensaker.no",
- "mansions.museum",
- "namie.fukushima.jp",
- "railroad.museum",
- "romsa.no",
- "chita.aichi.jp",
- "ueno.gunma.jp",
- "beardu.no",
- "fm.br",
- "bauern.museum",
- "usarts.museum",
- "touch.museum",
- "storfjord.no",
- "nakijin.okinawa.jp",
- "takahama.aichi.jp",
- "sakuho.nagano.jp",
- "aichi.jp",
- "florida.museum",
- "gs.st.no",
- "takaharu.miyazaki.jp",
- "repbody.aero",
- "co.mu",
- "catering.aero",
- "daisen.akita.jp",
- "com.uz",
- "com.ug",
- "yonabaru.okinawa.jp",
- "gov.ua",
- "edu.ua",
- "kg.kr",
- "com.ua",
- "fuossko.no",
+ "seoul.kr",
+ "xn--msy-ula0h.no",
+ "xn--4gbrim",
+ "batsfjord.no",
+ "dnsalias.net",
+ "xn--lcvr32d.hk",
+ "radoy.no",
+ "yonago.tottori.jp",
+ "artgallery.museum",
+ "in-the-band.net",
+ "yoshikawa.saitama.jp",
+ "historisches.museum",
"from-wv.com",
- "odawara.kanagawa.jp",
- "kanie.aichi.jp",
- "is-a-candidate.org",
- "beeldengeluid.museum",
- "trust.museum",
- "iizuna.nagano.jp",
- "cloudfront.net",
- "karpacz.pl",
- "ochi.kochi.jp",
- "gjerdrum.no",
- "mod.uk",
- "iwatsuki.saitama.jp",
- "kin.okinawa.jp",
- "alessandria.it",
- "higashitsuno.kochi.jp",
- "rzeszow.pl",
- "kunst.museum",
- "anthro.museum",
- "yasu.shiga.jp",
- "tatarstan.ru",
- "rissa.no",
- "hinohara.tokyo.jp",
- "rochester.museum",
- "yamatotakada.nara.jp",
- "sciencecenter.museum",
- "is-very-evil.org",
- "ayagawa.kagawa.jp",
- "hobby-site.org",
- "erimo.hokkaido.jp",
- "owani.aomori.jp",
- "kotohira.kagawa.jp",
- "from-wa.com",
- "ilawa.pl",
- "exchange.aero",
- "kumamoto.jp",
- "otaki.saitama.jp",
- "museum",
- "entertainment.aero",
- "ogawa.nagano.jp",
- "takehara.hiroshima.jp",
- "gs.ah.no",
- "konan.aichi.jp",
- "s3-fips-us-gov-west-1.amazonaws.com",
- "pm",
+ "rauma.no",
+ "from-fl.com",
+ "xn--od0alg.hk",
+ "from-ms.com",
+ "ninomiya.kanagawa.jp",
+ "cooking",
+ "xn--ngbc5azd",
+ "is-a-democrat.com",
+ "dk",
+ "webhop.biz",
+ "from-ks.com",
+ "dynalias.com",
+ "gov.kn",
+ "edu.kn",
+ "net.my",
+ "volyn.ua",
+ "halden.no",
+ "salzburg.museum",
+ "xn--vard-jra.no",
+ "kurogi.fukuoka.jp",
+ "xn--lrenskog-54a.no",
+ "xn--mjndalen-64a.no",
+ "elvendrell.museum",
+ "histoire.museum",
+ "mil.in",
+ "ambulance.aero",
+ "org.mx",
+ "frosinone.it",
+ "sopot.pl",
"sasayama.hyogo.jp",
- "itoman.okinawa.jp",
- "sciencecenters.museum",
- "ohira.miyagi.jp",
- "kitashiobara.fukushima.jp",
- "izhevsk.ru",
- "fed.us",
- "kitayama.wakayama.jp",
- "kouhoku.saga.jp",
- "trondheim.no",
- "pr",
- "pro",
- "iwanai.hokkaido.jp",
- "po.it",
- "pv.it",
- "pu.it",
- "pd.it",
- "malselv.no",
- "jet.uk",
- "museum.no",
- "pz.it",
- "shiroishi.miyagi.jp",
- "surgut.ru",
- "hongo.hiroshima.jp",
- "leirfjord.no",
- "gov.sx",
- "vestre-slidre.no",
- "encyclopedic.museum",
- "pt",
- "pro.az",
- "carbonia-iglesias.it",
- "pr.it",
- "brasil.museum",
- "ps",
- "workshop.museum",
- "toyooka.hyogo.jp",
- "usantiques.museum",
- "pe",
- "school.na",
- "hyogo.jp",
- "takaoka.toyama.jp",
- "pt.it",
- "museum.tt",
- "nf",
- "pe.it",
- "ogawara.miyagi.jp",
- "kamifurano.hokkaido.jp",
- "pr.us",
+ "dynalias.net",
+ "association.aero",
+ "holdings",
+ "otofuke.hokkaido.jp",
+ "belluno.it",
+ "act.au",
+ "co.je",
+ "is-a-rockstar.com",
+ "biz.vn",
+ "yokaichiba.chiba.jp",
+ "namegata.ibaraki.jp",
+ "yasuoka.nagano.jp",
+ "bahccavuotna.no",
+ "net.py",
+ "xn--lesund-hua.no",
+ "iamallama.com",
+ "nanmoku.gunma.jp",
+ "dyndns.tv",
+ "medecin.km",
+ "xn--hery-ira.nordland.no",
+ "magazine.aero",
+ "nakanoto.ishikawa.jp",
+ "drobak.no",
+ "balsfjord.no",
+ "messina.it",
+ "gx.cn",
+ "xn--od0aq3b.hk",
+ "brussel.museum",
+ "xn--rst-0na.no",
+ "funagata.yamagata.jp",
+ "frogans",
+ "gemological.museum",
+ "mjondalen.no",
+ "oshino.yamanashi.jp",
+ "here-for-more.info",
+ "com.gy",
+ "from-de.com",
+ "maison",
+ "iki.fi",
+ "xn--mgb2ddes",
+ "xn--80aswg",
+ "artdeco.museum",
+ "kasuga.fukuoka.jp",
+ "francaise.museum",
+ "gose.nara.jp",
+ "xn--lury-ira.no",
+ "international",
+ "wa.edu.au",
+ "from-oh.com",
+ "yamaga.kumamoto.jp",
+ "crotone.it",
+ "is-a-anarchist.com",
+ "siena.it",
+ "defense.tn",
+ "history.museum",
+ "k12.co.us",
+ "dielddanuorri.no",
+ "xn--zf0avx.hk",
+ "vt.us",
+ "rikubetsu.hokkaido.jp",
+ "stord.no",
+ "org.gr",
+ "eastcoast.museum",
+ "shinshinotsu.hokkaido.jp",
+ "midatlantic.museum",
+ "obihiro.hokkaido.jp",
+ "association.museum",
"raisa.no",
- "pe.ca",
- "p.se",
- "gov.cx",
- "snasa.no",
- "cbg.ru",
- "gs.of.no",
- "nf.ca",
- "fortmissoula.museum",
+ "store.ro",
+ "go.jp",
+ "kr.it",
+ "ed.jp",
+ "co.jp",
+ "sogne.no",
+ "org.gp",
+ "fishing",
+ "cloudcontrolapp.com",
+ "org.ge",
+ "shioya.tochigi.jp",
+ "store.st",
+ "gr.jp",
+ "vi.us",
"yoro.gifu.jp",
- "school.museum",
- "per.sg",
- "pro.tt",
- "stjordalshalsen.no",
- "yawata.kyoto.jp",
- "trysil.no",
- "takahagi.ibaraki.jp",
- "pn",
- "galsa.no",
- "iwaizumi.iwate.jp",
- "takayama.gifu.jp",
- "zushi.kanagawa.jp",
- "olbia-tempio.it",
- "frosinone.it",
- "pro.br",
- "pi.it",
- "glass.museum",
- "yuzawa.niigata.jp",
- "usenet.pl",
- "pn.it",
- "kuchinotsu.nagasaki.jp",
- "tarui.gifu.jp",
- "museum.mv",
- "izu.shizuoka.jp",
- "post",
+ "ando.nara.jp",
+ "ad.jp",
+ "countryestate.museum",
+ "encyclopedic.museum",
+ "yuki.ibaraki.jp",
+ "nishi.osaka.jp",
+ "hagi.yamaguchi.jp",
+ "murmansk.ru",
+ "chambagri.fr",
+ "xn--vgan-qoa.no",
+ "sorum.no",
+ "oumu.hokkaido.jp",
+ "giessen.museum",
+ "xn--zf0ao64a.tw",
+ "mil.hn",
+ "boston.museum",
+ "afjord.no",
+ "vikna.no",
+ "k12.ca.us",
+ "xn--uc0ay4a.hk",
+ "drammen.no",
+ "net.ky",
+ "valley.museum",
+ "wielun.pl",
+ "mallorca.museum",
+ "xn--b-5ga.nordland.no",
+ "amusement.aero",
+ "xn--muost-0qa.no",
+ "xn--karmy-yua.no",
+ "xn--mgbab2bd",
+ "ozu.kumamoto.jp",
+ "xn--osyro-wua.no",
+ "miki.hyogo.jp",
+ "florida.museum",
+ "birkenes.no",
+ "awaji.hyogo.jp",
+ "gloppen.no",
+ "stryn.no",
+ "moskenes.no",
+ "komforb.se",
+ "somna.no",
+ "orkanger.no",
+ "campobasso.it",
+ "mx.na",
+ "niimi.okayama.jp",
+ "org.gi",
+ "va.us",
+ "handson.museum",
+ "ino.kochi.jp",
+ "hobby-site.com",
+ "homeunix.org",
+ "xn--mlatvuopmi-s4a.no",
+ "hammarfeasta.no",
+ "va.no",
+ "saka.hiroshima.jp",
+ "nakagawa.nagano.jp",
+ "seljord.no",
+ "gniezno.pl",
+ "austin.museum",
+ "dyndns.org",
+ "vn.ua",
+ "snasa.no",
+ "eastafrica.museum",
+ "bristol.museum",
+ "berlin.museum",
+ "balsan.it",
+ "shiroishi.saga.jp",
+ "modern.museum",
+ "campidanomedio.it",
+ "radio.br",
+ "charter.aero",
+ "botanical.museum",
+ "ama.aichi.jp",
+ "xn--vg-yiab.no",
+ "sakuragawa.ibaraki.jp",
+ "kitagata.gifu.jp",
+ "shimokawa.hokkaido.jp",
+ "kyowa.hokkaido.jp",
+ "chiropractic.museum",
+ "costume.museum",
+ "nakagawa.hokkaido.jp",
+ "carrier.museum",
+ "shizuoka.shizuoka.jp",
+ "frei.no",
+ "asahi.nagano.jp",
+ "dnsalias.org",
+ "slask.pl",
+ "bauern.museum",
+ "desi",
+ "clinton.museum",
+ "gallery.museum",
+ "nakagawa.tokushima.jp",
+ "helsinki.museum",
+ "futsu.nagasaki.jp",
+ "shikama.miyagi.jp",
+ "k12.fl.us",
+ "dvrdns.org",
+ "xn--uc0atv.hk",
+ "hizen.saga.jp",
+ "garden.museum",
+ "smola.no",
+ "is-leet.com",
+ "xn--pgbs0dh",
+ "badajoz.museum",
+ "shonai.fukuoka.jp",
+ "xn--mot-tla.no",
+ "salat.no",
+ "deatnu.no",
+ "miasa.nagano.jp",
+ "mobi.na",
+ "inuyama.aichi.jp",
+ "sauda.no",
+ "divtasvuodna.no",
+ "is-a-green.com",
+ "dynalias.org",
+ "oppegard.no",
+ "corporation.museum",
+ "selbu.no",
+ "xn--6qq986b3xl",
+ "seirou.niigata.jp",
+ "mansion.museum",
+ "cechire.com",
+ "hattfjelldal.no",
+ "from-ga.com",
+ "from-mt.com",
+ "imari.saga.jp",
+ "from-ct.com",
+ "isshiki.aichi.jp",
+ "alabama.museum",
+ "okinawa.okinawa.jp",
+ "burghof.museum",
+ "castres.museum",
+ "shinagawa.tokyo.jp",
+ "naklo.pl",
+ "kamigori.hyogo.jp",
+ "community.museum",
+ "culture.museum",
+ "ushuaia.museum",
+ "astronomy.museum",
+ "cincinnati.museum",
+ "izumi.kagoshima.jp",
+ "farmers.museum",
+ "art.museum",
+ "yonezawa.yamagata.jp",
+ "xn--krager-gya.no",
+ "nakama.fukuoka.jp",
+ "skaun.no",
+ "nanbu.yamanashi.jp",
+ "annefrank.museum",
+ "massa-carrara.it",
+ "aarborte.no",
+ "vc",
+ "sanok.pl",
+ "osakikamijima.hiroshima.jp",
+ "xn--kfjord-iua.no",
+ "okinoshima.shimane.jp",
+ "oiso.kanagawa.jp",
+ "xn--koluokta-7ya57h.no",
+ "halloffame.museum",
+ "gets-it.net",
+ "gov.dz",
+ "edu.dz",
+ "ps",
+ "com.dz",
+ "pr",
+ "chino.nagano.jp",
+ "yasu.shiga.jp",
+ "is-a-personaltrainer.com",
+ "xn--1qqw23a",
+ "mihama.mie.jp",
"pl",
- "airguard.museum",
- "midori.gunma.jp",
- "sarufutsu.hokkaido.jp",
- "tgory.pl",
- "tabayama.yamanashi.jp",
- "motorcycle.museum",
- "harstad.no",
- "pa",
- "ito.shizuoka.jp",
- "gs.vf.no",
- "neat-url.com",
- "oguni.kumamoto.jp",
- "kuroiso.tochigi.jp",
- "computer.museum",
- "nonoichi.ishikawa.jp",
- "pl.ua",
- "okayama.jp",
- "pa.it",
- "fukudomi.saga.jp",
- "handa.aichi.jp",
- "leksvik.no",
- "square.museum",
+ "bus.museum",
+ "kvam.no",
+ "xn--vgsy-qoa0j.no",
+ "xn--bievt-0qa.no",
+ "mobi.ng",
+ "post",
+ "kurgan.ru",
+ "art.dz",
+ "kaufen",
+ "pub",
+ "hamburg.museum",
+ "pro",
+ "asahi.yamagata.jp",
+ "com.uz",
+ "historicalsociety.museum",
+ "mazowsze.pl",
+ "onga.fukuoka.jp",
+ "pro.om",
"p.bg",
- "nyny.museum",
- "sumida.tokyo.jp",
- "austrheim.no",
- "dni.us",
- "wake.okayama.jp",
- "lebork.pl",
- "wakkanai.hokkaido.jp",
- "engerdal.no",
- "masuda.shimane.jp",
- "heroy.nordland.no",
- "pa.us",
- "itabashi.tokyo.jp",
- "game-server.cc",
- "pub.sa",
- "oyabe.toyama.jp",
- "sa.au",
- "ph",
- "schlesisches.museum",
- "fukuchi.fukuoka.jp",
- "murayama.yamagata.jp",
- "pk",
- "yalta.ua",
- "algard.no",
- "priv.me",
- "toride.ibaraki.jp",
- "tsuno.miyazaki.jp",
- "sf.no",
- "sells-for-less.com",
- "okinawa.jp",
- "towada.aomori.jp",
+ "pn",
+ "p.se",
+ "groks-the.info",
+ "wildlife.museum",
+ "pe",
+ "nd.us",
+ "western.museum",
+ "air.museum",
+ "ikeda.nagano.jp",
+ "and.museum",
+ "dlugoleka.pl",
+ "arita.saga.jp",
+ "durham.museum",
+ "pt",
+ "agano.niigata.jp",
+ "yamada.fukuoka.jp",
+ "horonobe.hokkaido.jp",
+ "amli.no",
"yamato.fukushima.jp",
+ "nl.no",
+ "communication.museum",
+ "gov.bz",
+ "edu.bz",
+ "communications.museum",
+ "com.bz",
+ "xn--ystre-slidre-ujb.no",
"pro.ec",
- "pp.ua",
- "psi.br",
- "priv.at",
- "circus.museum",
- "homeftp.net",
- "sassari.it",
- "funahashi.toyama.jp",
- "is-a-linux-user.org",
- "nishihara.kumamoto.jp",
- "kaneyama.yamagata.jp",
- "co.hu",
- "izumiotsu.osaka.jp",
- "ogata.akita.jp",
- "shijonawate.osaka.jp",
- "iitate.fukushima.jp",
- "glogow.pl",
- "aquarium.museum",
- "og.ao",
- "yuzhno-sakhalinsk.ru",
- "sue.fukuoka.jp",
- "etnedal.no",
- "isernia.it",
- "helsinki.museum",
- "pro.na",
- "yamashina.kyoto.jp",
- "midori.chiba.jp",
- "kinko.kagoshima.jp",
- "yamato.kanagawa.jp",
- "arendal.no",
- "pri.ee",
- "perm.ru",
- "hjelmeland.no",
- "columbia.museum",
- "k12.ut.us",
- "nishiarita.saga.jp",
- "usui.fukuoka.jp",
- "krakow.pl",
- "urausu.hokkaido.jp",
- "tm.hu",
- "wakasa.fukui.jp",
- "ath.cx",
- "ushistory.museum",
- "ooshika.nagano.jp",
- "from-wy.com",
- "gojome.akita.jp",
- "izumisano.osaka.jp",
- "chesapeakebay.museum",
- "saito.miyazaki.jp",
- "lib.ut.us",
- "katori.chiba.jp",
- "sunndal.no",
- "upow.gov.pl",
- "jaworzno.pl",
- "higashichichibu.saitama.jp",
- "ohda.shimane.jp",
+ "xn--mgbaam7a8h",
+ "anan.nagano.jp",
+ "pub.sa",
+ "ne.tz",
+ "xn--wgbh1c",
+ "missile.museum",
+ "ne.us",
+ "ulm.museum",
"no.com",
- "cultural.museum",
- "wales.museum",
- "pisa.it",
- "ebino.miyazaki.jp",
- "arezzo.it",
- "software.aero",
- "urbino-pesaro.it",
- "pw",
- "kutchan.hokkaido.jp",
- "fujimi.saitama.jp",
- "blogspot.cf",
- "k12.tx.us",
- "graz.museum",
- "oe.yamagata.jp",
- "ustka.pl",
- "cambridge.museum",
- "vf.no",
- "midtre-gauldal.no",
- "dyndns-server.com",
- "oceanographique.museum",
- "yamatokoriyama.nara.jp",
- "hiroo.hokkaido.jp",
- "lib.tx.us",
- "otaki.nagano.jp",
- "rockart.museum",
- "eigersund.no",
- "university.museum",
- "nishimera.miyazaki.jp",
- "from-wi.com",
- "keisen.fukuoka.jp",
- "house.museum",
- "aizumi.tokushima.jp",
- "yamanakako.yamanashi.jp",
- "nanae.hokkaido.jp",
- "sakado.saitama.jp",
- "kaisei.kanagawa.jp",
- "sokndal.no",
- "kuzumaki.iwate.jp",
- "ebiz.tw",
- "portal.museum",
- "yamazoe.nara.jp",
- "coloradoplateau.museum",
- "ullensvang.no",
- "vladivostok.ru",
- "za.org",
- "hanno.saitama.jp",
- "komoro.nagano.jp",
- "idv.tw",
- "myoko.niigata.jp",
+ "unzen.nagasaki.jp",
+ "homebuilt.aero",
+ "funabashi.chiba.jp",
+ "pro.br",
+ "k12.tn.us",
+ "botanicalgarden.museum",
+ "yasugi.shimane.jp",
+ "dallas.museum",
+ "sklep.pl",
"py",
- "pilots.museum",
- "washingtondc.museum",
- "scientist.aero",
- "folldal.no",
- "kasahara.gifu.jp",
- "bajddar.no",
- "shimoji.okinawa.jp",
+ "for-the.biz",
"nt.no",
- "saltdal.no",
- "github.io",
- "prof.pr",
- "linz.museum",
- "hachijo.tokyo.jp",
- "kumamoto.kumamoto.jp",
- "atsuma.hokkaido.jp",
- "warmia.pl",
- "museum.mw",
- "hofu.yamaguchi.jp",
+ "nt.ro",
+ "per.la",
+ "nt.au",
+ "marburg.museum",
+ "pro.na",
+ "usa.museum",
"iida.nagano.jp",
- "toyama.jp",
- "name.vn",
- "fujimino.saitama.jp",
- "chino.nagano.jp",
- "yomitan.okinawa.jp",
- "pro.vn",
- "sakahogi.gifu.jp",
- "seiro.niigata.jp",
- "leitungsen.de",
- "or.th",
+ "presse.ml",
+ "xn--hcesuolo-7ya35b.no",
+ "rovno.ua",
+ "xn--uc0atv.tw",
+ "matsuno.ehime.jp",
+ "chirurgiens-dentistes.fr",
+ "pm",
+ "kustanai.ru",
+ "can.museum",
+ "prof.pr",
+ "k12.in.us",
+ "groks-this.info",
+ "casadelamoneda.museum",
+ "amami.kagoshima.jp",
+ "sport.hu",
+ "xn--wcvs22d.hk",
+ "skien.no",
+ "xn--trna-woa.no",
+ "dell-ogliastra.it",
+ "ny.us",
+ "hara.nagano.jp",
+ "xn--bearalvhki-y4a.no",
+ "presse.ci",
+ "ureshino.mie.jp",
+ "city.nagoya.jp",
+ "onjuku.chiba.jp",
+ "satsumasendai.kagoshima.jp",
+ "hioki.kagoshima.jp",
+ "shiga.jp",
+ "pa",
+ "nj.us",
+ "xn--drbak-wua.no",
+ "ritto.shiga.jp",
+ "gov.az",
+ "edu.az",
+ "kicks-ass.net",
+ "com.az",
+ "nm.us",
+ "parts",
+ "british.museum",
+ "xn--kprw13d",
+ "appspot.com",
+ "k12.mn.us",
+ "shiroishi.miyagi.jp",
+ "xn--wgbl6a",
+ "boutique",
+ "ne.kr",
+ "urbinopesaro.it",
+ "global.prod.fastly.net",
+ "heritage.museum",
+ "nakayama.yamagata.jp",
+ "ueda.nagano.jp",
+ "pink",
+ "dudinka.ru",
+ "wloclawek.pl",
+ "int.az",
+ "kamisunagawa.hokkaido.jp",
+ "arteducation.museum",
+ "pro.pr",
+ "nanbu.tottori.jp",
+ "presse.km",
+ "yamagata.jp",
+ "nishi.fukuoka.jp",
+ "plo.ps",
+ "higashiagatsuma.gunma.jp",
+ "pila.pl",
+ "hakui.ishikawa.jp",
+ "nanto.toyama.jp",
+ "nanae.hokkaido.jp",
+ "to",
+ "td",
"port.fr",
- "is-very-good.org",
- "williamsburg.museum",
- "kitahiroshima.hokkaido.jp",
- "melhus.no",
- "ostroleka.pl",
- "elverum.no",
- "inawashiro.fukushima.jp",
- "sakura.chiba.jp",
- "ashoro.hokkaido.jp",
- "takahashi.okayama.jp",
- "halsa.no",
- "obihiro.hokkaido.jp",
- "hasuda.saitama.jp",
- "anpachi.gifu.jp",
- "tajiri.osaka.jp",
- "kadoma.osaka.jp",
- "svizzera.museum",
- "openair.museum",
- "osaki.miyagi.jp",
- "tomari.hokkaido.jp",
- "labour.museum",
- "yokawa.hyogo.jp",
- "mobara.chiba.jp",
- "yamanouchi.nagano.jp",
- "mihama.mie.jp",
- "saroma.hokkaido.jp",
- "pp.az",
- "brumunddal.no",
- "s3-us-west-2.amazonaws.com",
- "nozawaonsen.nagano.jp",
- "nl.no",
- "stordal.no",
- "ikoma.nara.jp",
- "gov.km",
- "edu.km",
- "gov.ki",
- "com.km",
+ "tz",
+ "kiho.mie.jp",
+ "goto.nagasaki.jp",
+ "rishirifuji.hokkaido.jp",
+ "tr",
+ "nv.us",
+ "tl",
+ "rivne.ua",
+ "cosenza.it",
+ "nm.cn",
+ "yamal.ru",
+ "geology.museum",
+ "tools",
+ "mad.museum",
+ "matsumae.hokkaido.jp",
+ "ns.ca",
+ "t.bg",
+ "blogsite.org",
+ "tn",
+ "psc.br",
+ "t.se",
+ "oga.akita.jp",
+ "ph",
+ "pics",
+ "shichikashuku.miyagi.jp",
+ "aki.kochi.jp",
+ "nl.ca",
+ "sango.nara.jp",
+ "zoology.museum",
+ "pri.ee",
+ "nu.ca",
+ "psi.br",
+ "komono.mie.jp",
+ "per.nf",
+ "sejny.pl",
+ "tt",
+ "xn--srum-gra.no",
+ "akune.kagoshima.jp",
+ "photo",
+ "photos",
+ "seika.kyoto.jp",
+ "manno.kagawa.jp",
+ "otoineppu.hokkaido.jp",
+ "xn--80adxhks",
+ "interactive.museum",
+ "tromso.no",
+ "kumano.mie.jp",
+ "vs.it",
+ "partners",
+ "vr.it",
+ "org.gg",
+ "nt.ca",
+ "nh.us",
+ "go.ug",
+ "shimabara.nagasaki.jp",
+ "ppg.br",
+ "xn--vler-qoa.hedmark.no",
+ "co.ug",
+ "co.ag",
+ "tips",
+ "yaotsu.gifu.jp",
+ "hirono.iwate.jp",
+ "ibaraki.ibaraki.jp",
+ "chizu.tottori.jp",
+ "kirkenes.no",
+ "nango.fukushima.jp",
+ "nb.ca",
+ "tur.br",
+ "xn--rholt-mra.no",
+ "kisosaki.mie.jp",
+ "mil.tz",
+ "bokn.no",
+ "co.gg",
+ "california.museum",
+ "ve.it",
+ "pk",
"gov.kz",
- "edu.ki",
"edu.kz",
- "gov.kg",
- "com.ki",
- "edu.kg",
"com.kz",
- "com.kg",
- "imakane.hokkaido.jp",
- "krasnoyarsk.ru",
- "is-a-bruinsfan.org",
- "namdalseid.no",
- "ac.th",
- "gaivuotna.no",
- "plants.museum",
- "childrensgarden.museum",
- "pg",
+ "sandoy.no",
+ "vt.it",
+ "xn--mgbayh7gpa",
+ "tromsa.no",
+ "nishikawa.yamagata.jp",
+ "tj",
+ "kommune.no",
+ "biz.az",
+ "tm",
+ "trd.br",
+ "coldwar.museum",
+ "vb.it",
+ "teo.br",
+ "automotive.museum",
+ "troandin.no",
+ "vi.it",
+ "herokuapp.com",
+ "tel",
"eiheiji.fukui.jp",
- "tokai.ibaraki.jp",
- "blogdns.net",
- "ogori.fukuoka.jp",
- "okegawa.saitama.jp",
- "salzburg.museum",
- "stokke.no",
- "sanjo.niigata.jp",
- "kimitsu.chiba.jp",
- "pg.it",
- "southwest.museum",
- "ina.saitama.jp",
- "ass.km",
+ "yuzawa.niigata.jp",
+ "khmelnitskiy.ua",
+ "today",
+ "tienda",
+ "pistoia.it",
+ "catanzaro.it",
+ "elb.amazonaws.com",
+ "imizu.toyama.jp",
+ "tattoo",
+ "prd.km",
+ "ayase.kanagawa.jp",
+ "kakogawa.hyogo.jp",
+ "herokussl.com",
+ "sakura.tochigi.jp",
+ "palana.ru",
+ "notogawa.shiga.jp",
+ "xn--vhquv",
+ "gateway.museum",
+ "sveio.no",
+ "equipment.aero",
+ "iwakura.aichi.jp",
+ "voss.no",
+ "ookuwa.nagano.jp",
+ "tur.ar",
+ "nc",
+ "from-hi.com",
+ "tv",
+ "gov.cx",
+ "nom.co",
+ "act.edu.au",
+ "tmp.br",
+ "tysnes.no",
+ "mil.az",
+ "birdart.museum",
+ "shirahama.wakayama.jp",
+ "is-a-musician.com",
+ "rl.no",
+ "fineart.museum",
+ "yabuki.fukushima.jp",
+ "va.it",
+ "ryuoh.shiga.jp",
+ "pescara.it",
+ "dyndns.ws",
+ "tozsde.hu",
+ "net.co",
+ "ohkura.yamagata.jp",
+ "trader.aero",
+ "mine.nu",
+ "rebun.hokkaido.jp",
+ "war.museum",
+ "ro.com",
+ "palermo.it",
+ "portland.museum",
+ "karpacz.pl",
+ "vv.it",
+ "th",
+ "tottori.jp",
+ "vega.no",
+ "mulhouse.museum",
+ "washingtondc.museum",
+ "ru.com",
+ "chonan.chiba.jp",
+ "suita.osaka.jp",
+ "samukawa.kanagawa.jp",
+ "ath.cx",
+ "ri.us",
+ "safety.aero",
+ "trento.it",
+ "ooshika.nagano.jp",
+ "medio-campidano.it",
+ "plumbing",
+ "maritime.museum",
+ "hannan.osaka.jp",
+ "from-ut.com",
+ "kchr.ru",
+ "khmelnytskyi.ua",
+ "xn--mk0axi.hk",
+ "seiyo.ehime.jp",
+ "wada.nagano.jp",
+ "indian.museum",
+ "net.cw",
+ "miura.kanagawa.jp",
+ "andriatranibarletta.it",
+ "xn--klbu-woa.no",
+ "yamamoto.miyagi.jp",
+ "tk",
+ "shima.mie.jp",
+ "chihayaakasaka.osaka.jp",
+ "net.ci",
+ "re.kr",
+ "ogi.saga.jp",
+ "zushi.kanagawa.jp",
+ "workinggroup.aero",
+ "firenze.it",
+ "watchandclock.museum",
+ "vang.no",
+ "kameyama.mie.jp",
+ "valer.ostfold.no",
+ "xn--hpmir-xqa.no",
+ "satte.saitama.jp",
+ "teramo.it",
+ "pomorskie.pl",
+ "muenchen.museum",
+ "tysfjord.no",
+ "yugawa.fukushima.jp",
+ "vaga.no",
+ "mil.kz",
+ "public.museum",
+ "nf",
+ "plants.museum",
+ "homelinux.net",
+ "nom.fr",
+ "tra.kp",
+ "verran.no",
+ "tonsberg.no",
+ "xn--vrggt-xqad.no",
+ "pw",
+ "yamagata.nagano.jp",
+ "dating",
+ "tourism.tn",
+ "ichiba.tokushima.jp",
+ "homelinux.com",
+ "pasadena.museum",
+ "hatsukaichi.hiroshima.jp",
+ "divttasvuotna.no",
+ "ebina.kanagawa.jp",
+ "padova.it",
+ "dellogliastra.it",
+ "presidio.museum",
+ "kinko.kagoshima.jp",
+ "sanda.hyogo.jp",
+ "saiki.oita.jp",
+ "xn--leagaviika-52b.no",
+ "zakopane.pl",
+ "tingvoll.no",
+ "kiso.nagano.jp",
+ "portal.museum",
+ "nanao.ishikawa.jp",
+ "topology.museum",
+ "per.sg",
+ "veterinaire.fr",
+ "publ.pt",
+ "isa-geek.com",
+ "xn--j6w193g",
+ "xn--brum-voa.no",
+ "sakahogi.gifu.jp",
+ "environmentalconservation.museum",
+ "akiruno.tokyo.jp",
+ "chesapeakebay.museum",
+ "surrey.museum",
+ "isa-geek.net",
+ "no.it",
+ "higashikagawa.kagawa.jp",
+ "indianapolis.museum",
+ "ora.gunma.jp",
+ "otsu.shiga.jp",
+ "pilots.museum",
+ "ptz.ru",
+ "polkowice.pl",
+ "nu.it",
+ "yahiko.niigata.jp",
+ "dinosaur.museum",
+ "bo.nordland.no",
+ "starostwo.gov.pl",
+ "okuizumo.shimane.jp",
+ "indianmarket.museum",
+ "portlligat.museum",
+ "rs.ba",
+ "aguni.okinawa.jp",
+ "org.gh",
+ "express.aero",
+ "shiso.hyogo.jp",
+ "rv.ua",
+ "seiro.niigata.jp",
+ "preservation.museum",
+ "ota.gunma.jp",
+ "ichihara.chiba.jp",
+ "minamiashigara.kanagawa.jp",
+ "umi.fukuoka.jp",
+ "xn--ses554g",
+ "itayanagi.aomori.jp",
+ "nt.edu.au",
+ "xn--6frz82g",
+ "sabae.fukui.jp",
+ "soeda.fukuoka.jp",
+ "ternopil.ua",
+ "hamatonbetsu.hokkaido.jp",
+ "prd.mg",
+ "xn--3ds443g",
+ "productions",
+ "tom.ru",
+ "tarnobrzeg.pl",
+ "trentino.it",
+ "ichikawa.chiba.jp",
+ "sd.us",
+ "onagawa.miyagi.jp",
+ "bergbau.museum",
+ "kitakyushu.jp",
+ "sagamihara.kanagawa.jp",
+ "chicago.museum",
+ "pisa.it",
+ "ham-radio-op.net",
+ "sydney.museum",
+ "asaminami.hiroshima.jp",
+ "panama.museum",
+ "kumakogen.ehime.jp",
+ "ichinomiya.chiba.jp",
+ "tw",
+ "yamagata.ibaraki.jp",
+ "koebenhavn.museum",
+ "vibovalentia.it",
+ "virtuel.museum",
+ "selje.no",
+ "hachinohe.aomori.jp",
+ "skjak.no",
+ "na.it",
+ "paderborn.museum",
+ "venice.it",
+ "tourism.pl",
+ "oguchi.aichi.jp",
+ "virtual.museum",
+ "xn--krehamn-dxa.no",
+ "net.tn",
+ "st.no",
+ "xn--lrdal-sra.no",
+ "happou.akita.jp",
+ "xn--ygbi2ammx",
+ "sd.cn",
+ "torsken.no",
+ "kyonan.chiba.jp",
+ "tosu.saga.jp",
+ "xn--bod-2na.no",
+ "pyatigorsk.ru",
+ "se.com",
+ "net.in",
+ "coop.ht",
+ "yabu.hyogo.jp",
+ "sn.cn",
+ "production.aero",
+ "daejeon.kr",
+ "seki.gifu.jp",
+ "xn--rady-ira.no",
+ "virginia.museum",
+ "namie.fukushima.jp",
+ "medizinhistorisches.museum",
"tsu.mie.jp",
- "priv.no",
+ "saito.miyazaki.jp",
+ "transport.museum",
+ "name.na",
+ "vegarshei.no",
+ "ag.it",
+ "xn--xhq521b",
+ "bg.it",
+ "tsukumi.oita.jp",
+ "fg.it",
+ "kg.kr",
+ "pvt.k12.ma.us",
+ "net.an",
+ "sa.au",
+ "nat.tn",
+ "rec.co",
+ "tottori.tottori.jp",
+ "shiki.saitama.jp",
+ "kyotango.kyoto.jp",
+ "sor-odal.no",
+ "is-a-guru.com",
+ "verbania.it",
+ "net.pn",
+ "xn--s-1fa.no",
+ "k12.az.us",
+ "xn--l-1fa.no",
+ "toda.saitama.jp",
+ "net.vn",
+ "sa.com",
+ "kashima.ibaraki.jp",
+ "net.cu",
+ "sa.cr",
+ "xn--krjohka-hwab49j.no",
+ "xn--vestvgy-ixa6o.no",
+ "sb.ua",
+ "tara.saga.jp",
+ "podhale.pl",
+ "opole.pl",
+ "gov.gn",
+ "edu.gn",
+ "xn--nry-yla5g.no",
+ "com.gn",
+ "bedzin.pl",
+ "torino.it",
+ "kamoenai.hokkaido.jp",
+ "xn--sr-fron-q1a.no",
+ "shibukawa.gunma.jp",
+ "kunohe.iwate.jp",
+ "ro.it",
+ "isa-geek.org",
+ "name.ng",
+ "vision",
+ "net.hn",
+ "orsta.no",
"morimachi.shizuoka.jp",
- "priv.pl",
- "gov.kn",
- "edu.kn",
- "bruxelles.museum",
- "honjo.saitama.jp",
- "kitamoto.saitama.jp",
- "drammen.no",
- "per.nf",
- "traeumtgerade.de",
- "nic.im",
- "nishinoshima.shimane.jp",
- "environment.museum",
- "padova.it",
- "sa.gov.au",
+ "ogasawara.tokyo.jp",
+ "sm.ua",
+ "higashiura.aichi.jp",
+ "sakyo.kyoto.jp",
+ "uchihara.ibaraki.jp",
+ "rn.it",
+ "yamanouchi.nagano.jp",
+ "asakawa.fukushima.jp",
+ "tome.miyagi.jp",
+ "re.it",
+ "nic.in",
+ "isahaya.nagasaki.jp",
+ "tas.au",
+ "perm.ru",
+ "us-east-1.amazonaws.com",
+ "xn--gls-elac.no",
+ "oishida.yamagata.jp",
+ "sh.cn",
+ "kartuzy.pl",
+ "palmsprings.museum",
+ "ri.it",
+ "osaka.jp",
+ "teledata.mz",
+ "chikujo.fukuoka.jp",
+ "tosa.kochi.jp",
+ "net.kn",
+ "tonami.toyama.jp",
+ "plantation.museum",
+ "togane.chiba.jp",
"mishima.fukushima.jp",
+ "shari.hokkaido.jp",
+ "from-sd.com",
+ "pruszkow.pl",
+ "tenkawa.nara.jp",
+ "from-md.com",
+ "sc",
+ "aizubange.fukushima.jp",
+ "nyc.mn",
+ "nx.cn",
+ "rost.no",
+ "shizukuishi.iwate.jp",
+ "dnsdojo.org",
+ "rm.it",
+ "xn--rskog-uua.no",
+ "tadaoka.osaka.jp",
+ "act.gov.au",
+ "xn--vry-yla5g.no",
+ "yugawara.kanagawa.jp",
+ "xn--bjddar-pta.no",
+ "xn--lhppi-xqa.no",
+ "roan.no",
+ "tomari.hokkaido.jp",
+ "togura.nagano.jp",
+ "sch.lk",
+ "togo.aichi.jp",
+ "ra.it",
+ "rotorcraft.aero",
+ "television.museum",
+ "sch.uk",
+ "rnu.tn",
+ "norfolk.museum",
+ "bolzano.it",
+ "net.gy",
+ "itoman.okinawa.jp",
+ "xn--bdddj-mrabd.no",
+ "is-a-soxfan.org",
+ "imakane.hokkaido.jp",
+ "xn--h-2fa.no",
+ "rns.tn",
+ "sch.sa",
+ "showa.gunma.jp",
+ "namdalseid.no",
+ "from-id.com",
+ "date.hokkaido.jp",
+ "tone.ibaraki.jp",
+ "sch.ir",
+ "modelling.aero",
+ "trani-andria-barletta.it",
+ "res.in",
+ "yuasa.wakayama.jp",
+ "sch.qa",
+ "tahara.aichi.jp",
+ "hokuryu.hokkaido.jp",
+ "knowsitall.info",
+ "tananger.no",
+ "kasukabe.saitama.jp",
+ "is-a-hard-worker.com",
+ "training",
+ "sch.jo",
+ "homedns.org",
+ "tanabe.kyoto.jp",
+ "tuva.ru",
+ "ne.jp",
+ "coastaldefence.museum",
+ "sch.id",
+ "photography",
+ "rana.no",
+ "bologna.it",
+ "sk.ca",
+ "kainan.tokushima.jp",
+ "xn--bjarky-fya.no",
+ "yoita.niigata.jp",
+ "torino.museum",
+ "sekikawa.niigata.jp",
+ "tvedestrand.no",
+ "nara.nara.jp",
+ "xn--9dbhblg6di.museum",
+ "test.ru",
+ "hikari.yamaguchi.jp",
+ "management",
+ "xn--vads-jra.no",
+ "volkenkunde.museum",
+ "dyndns.info",
+ "tatarstan.ru",
+ "ohtawara.tochigi.jp",
+ "tomobe.ibaraki.jp",
+ "tokyo",
+ "alesund.no",
+ "embroidery.museum",
+ "xn--gmq050i.hk",
+ "blogdns.org",
+ "sch.ae",
+ "rade.no",
+ "chungnam.kr",
+ "is-a-blogger.com",
+ "store.nf",
+ "noda.iwate.jp",
+ "odate.akita.jp",
+ "showa.yamanashi.jp",
+ "yokawa.hyogo.jp",
+ "school.na",
+ "yakage.okayama.jp",
+ "research.aero",
+ "matsuzaki.shizuoka.jp",
+ "fetsund.no",
+ "yalta.ua",
+ "yn.cn",
+ "tula.ru",
+ "sakai.osaka.jp",
+ "emergency.aero",
+ "walbrzych.pl",
+ "samegawa.fukushima.jp",
+ "higashitsuno.kochi.jp",
+ "toshima.tokyo.jp",
+ "brumunddal.no",
+ "ogliastra.it",
+ "xn--rsta-fra.no",
+ "yonaguni.okinawa.jp",
+ "ringsaker.no",
+ "xn--givuotna-8ya.no",
+ "tsuyama.okayama.jp",
+ "so.it",
+ "tagajo.miyagi.jp",
+ "ss.it",
+ "sr.it",
"przeworsk.pl",
- "luxembourg.museum",
- "fujimi.nagano.jp",
- "caserta.it",
- "hamada.shimane.jp",
- "workinggroup.aero",
- "minamata.kumamoto.jp",
- "uslivinghistory.museum",
- "science.museum",
- "iyo.ehime.jp",
- "homeftp.org",
- "mashiko.tochigi.jp",
- "ogimi.okinawa.jp",
- "kitami.hokkaido.jp",
- "sondre-land.no",
- "odessa.ua",
- "bihoro.hokkaido.jp",
- "sakai.ibaraki.jp",
- "asahi.ibaraki.jp",
- "iruma.saitama.jp",
- "fredrikstad.no",
- "minamiise.mie.jp",
- "minami.tokushima.jp",
- "mihara.hiroshima.jp",
- "os.hordaland.no",
- "lyngdal.no",
- "takamori.kumamoto.jp",
- "yabu.hyogo.jp",
- "ham-radio-op.net",
- "palace.museum",
- "ac.se",
- "wada.nagano.jp",
- "nishikatsura.yamanashi.jp",
+ "hekinan.aichi.jp",
+ "forsand.no",
+ "hornindal.no",
+ "hitachiota.ibaraki.jp",
+ "traeumtgerade.de",
+ "oyodo.nara.jp",
+ "shingu.wakayama.jp",
+ "org.sy",
+ "xn--mxtq1m.hk",
+ "nabari.mie.jp",
+ "tver.ru",
+ "kunitachi.tokyo.jp",
+ "aurland.no",
+ "org.ly",
+ "sor-varanger.no",
+ "farsund.no",
+ "ravenna.it",
+ "org.uy",
+ "inazawa.aichi.jp",
+ "tochigi.jp",
+ "froland.no",
+ "trani-barletta-andria.it",
+ "dgca.aero",
+ "kalisz.pl",
+ "nanyo.yamagata.jp",
+ "si.it",
+ "shiogama.miyagi.jp",
+ "midsund.no",
+ "dali.museum",
+ "tateyama.toyama.jp",
+ "yorii.saitama.jp",
+ "nedre-eiker.no",
+ "hitachinaka.ibaraki.jp",
+ "uchinomi.kagawa.jp",
+ "kamimine.saga.jp",
+ "aizuwakamatsu.fukushima.jp",
+ "kuji.iwate.jp",
+ "research.museum",
+ "georgia.museum",
+ "nakagawa.fukuoka.jp",
+ "selfip.biz",
+ "olawa.pl",
+ "nagai.yamagata.jp",
+ "naamesjevuemie.no",
+ "gs.tr.no",
+ "gs.ol.no",
"gs.mr.no",
- "nic.in",
- "ac.sz",
- "plantation.museum",
- "kisofukushima.nagano.jp",
- "publ.pt",
- "hinode.tokyo.jp",
+ "taxi.br",
+ "niiza.saitama.jp",
+ "sund.no",
+ "gs.nl.no",
+ "gs.rl.no",
+ "nanjo.okinawa.jp",
+ "tsushima.aichi.jp",
+ "jo",
+ "jobs",
+ "org.my",
"saijo.ehime.jp",
- "manno.kagawa.jp",
- "gov.my",
- "ryazan.ru",
- "priv.hu",
- "edu.my",
- "national.museum",
- "from-vt.com",
- "com.my",
- "mihama.chiba.jp",
- "abiko.chiba.jp",
- "radom.pl",
- "kakuda.miyagi.jp",
- "nt.ro",
- "anthropology.museum",
- "yashio.saitama.jp",
- "palana.ru",
- "tawaramoto.nara.jp",
- "kazimierz-dolny.pl",
- "control.aero",
- "monzabrianza.it",
- "miyama.mie.jp",
- "yamanashi.yamanashi.jp",
- "tendo.yamagata.jp",
- "messina.it",
- "biz.ki",
- "yokosuka.kanagawa.jp",
- "ibaraki.jp",
- "nishihara.okinawa.jp",
- "otari.nagano.jp",
- "yoka.hyogo.jp",
- "okayama.okayama.jp",
- "agano.niigata.jp",
- "dazaifu.fukuoka.jp",
- "tonami.toyama.jp",
- "sondrio.it",
- "pordenone.it",
- "stalowa-wola.pl",
- "navuotna.no",
- "aland.fi",
- "otaki.chiba.jp",
- "kuromatsunai.hokkaido.jp",
- "gs.tr.no",
- "histoire.museum",
- "field.museum",
- "asago.hyogo.jp",
- "s3-us-west-1.amazonaws.com",
- "aisai.aichi.jp",
- "risor.no",
- "geometre-expert.fr",
- "sorum.no",
- "mil.km",
- "marumori.miyagi.jp",
- "kasama.ibaraki.jp",
- "gs.fm.no",
- "mil.kz",
- "sogndal.no",
- "mil.kg",
- "gov.lk",
- "edu.lk",
- "minami.kyoto.jp",
- "shichikashuku.miyagi.jp",
- "com.lk",
- "nishiawakura.okayama.jp",
- "on-the-web.tv",
- "bl.uk",
- "from-va.com",
- "gov.la",
- "edu.la",
- "com.la",
- "co.cl",
- "yoshikawa.saitama.jp",
- "bellevue.museum",
- "gov.lc",
- "edu.lc",
- "fujiyoshida.yamanashi.jp",
- "com.lc",
- "modum.no",
- "pila.pl",
- "poznan.pl",
- "gov.lb",
- "edu.lb",
- "oristano.it",
- "karikatur.museum",
- "com.lb",
- "amber.museum",
- "yugawa.fukushima.jp",
- "ppg.br",
- "yonezawa.yamagata.jp",
- "fukumitsu.toyama.jp",
- "minamiboso.chiba.jp",
+ "sa.it",
+ "gs.st.no",
+ "gov.st",
+ "net.dz",
+ "edu.st",
+ "gouv.rw",
+ "com.st",
+ "gouv.ml",
+ "vicenza.it",
"gov.lt",
- "livorno.it",
- "forum.hu",
- "mil.kr",
- "kariya.aichi.jp",
- "gs.tm.no",
- "stord.no",
- "gov.lr",
- "edu.lr",
- "mulhouse.museum",
- "iwate.jp",
- "com.lr",
- "naamesjevuemie.no",
- "co.pl",
- "shimodate.ibaraki.jp",
- "takamori.nagano.jp",
- "doomdns.org",
- "ltd.lk",
- "omiya.saitama.jp",
- "architecture.museum",
- "k12.ks.us",
- "cci.fr",
- "ulsan.kr",
- "entomology.museum",
- "uhren.museum",
- "co.nl",
- "mihama.wakayama.jp",
- "nishi.fukuoka.jp",
- "hikimi.shimane.jp",
- "society.museum",
- "hamura.tokyo.jp",
- "hamamatsu.shizuoka.jp",
- "tokai.aichi.jp",
- "lib.ks.us",
- "aarborte.no",
- "oishida.yamagata.jp",
- "computerhistory.museum",
- "asker.no",
- "cc.mo.us",
- "tamamura.gunma.jp",
- "veterinaire.km",
- "getmyip.com",
- "yoshioka.gunma.jp",
- "uozu.toyama.jp",
- "gov.kp",
- "edu.kp",
- "haboro.hokkaido.jp",
- "cc.co.us",
- "com.kp",
- "oamishirasato.chiba.jp",
- "monzaebrianza.it",
- "tm.pl",
- "noshiro.akita.jp",
- "qc.com",
- "miyada.nagano.jp",
- "magadan.ru",
- "so.gov.pl",
- "sayama.saitama.jp",
- "izena.okinawa.jp",
- "abeno.osaka.jp",
- "sr.gov.pl",
- "viterbo.it",
- "chijiwa.nagasaki.jp",
- "doesntexist.org",
- "org.hk",
- "kommune.no",
- "oregontrail.museum",
- "kurume.fukuoka.jp",
- "community.museum",
- "mil.my",
- "monza-brianza.it",
- "kunimi.fukushima.jp",
- "grp.lk",
- "mihama.fukui.jp",
- "askim.no",
- "steam.museum",
- "salerno.it",
- "heroy.more-og-romsdal.no",
- "nishikawa.yamagata.jp",
- "ishinomaki.miyagi.jp",
- "starachowice.pl",
- "s3-us-gov-west-1.amazonaws.com",
- "labor.museum",
- "taito.tokyo.jp",
- "yoita.niigata.jp",
- "academy.museum",
- "philately.museum",
- "otago.museum",
- "chiropractic.museum",
- "is-very-bad.org",
- "ueda.nagano.jp",
- "org.hu",
- "ako.hyogo.jp",
- "bv.nl",
- "kitadaito.okinawa.jp",
- "salem.museum",
- "leasing.aero",
- "blogdns.org",
- "org.ht",
- "meguro.tokyo.jp",
- "sortland.no",
- "hashima.gifu.jp",
- "org.hn",
- "barum.no",
- "okinoshima.shimane.jp",
- "takahata.yamagata.jp",
- "ritto.shiga.jp",
- "shacknet.nu",
- "powiat.pl",
- "settlers.museum",
- "tambov.ru",
- "or.id",
- "communication.museum",
- "if.ua",
- "daito.osaka.jp",
- "mordovia.ru",
+ "xn--mgba3a4fra",
+ "sp.it",
+ "gs.nt.no",
+ "yamakita.kanagawa.jp",
+ "net.uz",
+ "gouv.ci",
+ "j.bg",
+ "bygland.no",
+ "scotland.museum",
+ "stat.no",
+ "ichikawamisato.yamanashi.jp",
+ "xn--mgba3a4f16a",
+ "sa.edu.au",
+ "sv.it",
+ "je",
+ "slupsk.pl",
+ "date.fukushima.jp",
+ "repbody.aero",
"tohnosho.chiba.jp",
- "herad.no",
- "kashiwazaki.niigata.jp",
- "sayama.osaka.jp",
- "togura.nagano.jp",
- "grandrapids.museum",
- "jinsekikogen.hiroshima.jp",
- "ikeda.hokkaido.jp",
- "higashi.fukuoka.jp",
- "communications.museum",
- "okinawa.okinawa.jp",
- "yokaichiba.chiba.jp",
- "discovery.museum",
- "echizen.fukui.jp",
- "udine.it",
- "aya.miyazaki.jp",
- "philadelphia.museum",
- "toyama.toyama.jp",
- "ambulance.museum",
+ "kamijima.ehime.jp",
+ "sola.no",
+ "gov.tt",
+ "info.tz",
+ "edu.tt",
+ "org.py",
+ "aoki.nagano.jp",
+ "com.tt",
+ "iveland.no",
+ "xn--55qw42g",
+ "gouv.sn",
+ "pesarourbino.it",
+ "hobby-site.org",
"tateyama.chiba.jp",
- "topology.museum",
- "historisches.museum",
- "is-a-student.com",
- "kameyama.mie.jp",
- "congresodelalengua3.ar",
- "info",
- "simple-url.com",
- "gs.hm.no",
- "uryu.hokkaido.jp",
- "tra.kp",
- "ranzan.saitama.jp",
- "historisch.museum",
- "rep.kp",
- "k12.la.us",
- "hanamaki.iwate.jp",
- "info.mv",
- "ac.id",
- "shimofusa.chiba.jp",
- "edu.pe",
- "gov.pk",
- "lib.la.us",
- "edu.pk",
- "com.pe",
- "info.at",
- "com.pk",
- "gov.ge",
- "edu.ge",
- "bytom.pl",
- "inabe.mie.jp",
- "gov.gi",
- "ojiya.niigata.jp",
- "com.ge",
- "edu.gi",
- "co.gg",
- "gov.gg",
- "hurum.no",
- "com.gi",
- "nakhodka.ru",
- "edu.pa",
- "xxx",
- "cechire.com",
- "com.pa",
- "gov.ps",
- "edu.ps",
- "com.ps",
- "minamiizu.shizuoka.jp",
- "ibaraki.osaka.jp",
- "go.ug",
- "suzuka.mie.jp",
- "saigawa.fukuoka.jp",
- "co.ug",
- "nakatombetsu.hokkaido.jp",
- "chiyoda.tokyo.jp",
- "newhampshire.museum",
- "moseushi.hokkaido.jp",
- "gos.pk",
- "honjo.akita.jp",
- "homedns.org",
- "tarama.okinawa.jp",
- "is-a-caterer.com",
- "ostroda.pl",
- "mragowo.pl",
- "inf.br",
- "higashi.fukushima.jp",
- "raholt.no",
- "aso.kumamoto.jp",
- "googlecode.com",
+ "gov.bt",
+ "jor.br",
+ "telekommunikation.museum",
+ "edu.bt",
+ "sula.no",
+ "com.bt",
+ "shibuya.tokyo.jp",
+ "jet.uk",
+ "net.bz",
+ "tjeldsund.no",
+ "school.museum",
+ "gov.it",
+ "idrett.no",
+ "edu.it",
+ "gs.tm.no",
+ "int.tt",
+ "higashichichibu.saitama.jp",
+ "pisz.pl",
+ "intl.tn",
+ "nisshin.aichi.jp",
"info.tn",
- "edu.uy",
- "info.tt",
- "com.uy",
- "dnsdojo.com",
- "muroran.hokkaido.jp",
- "hachirogata.akita.jp",
- "mod.gi",
+ "ulan-ude.ru",
+ "shimosuwa.nagano.jp",
+ "tree.museum",
+ "azumino.nagano.jp",
+ "jus.br",
+ "gs.aa.no",
+ "sanjo.niigata.jp",
+ "xn--mgba3a4fra.ir",
+ "jm",
+ "photography.museum",
+ "edu.mt",
+ "com.mt",
+ "xn--mgba3a4f16a.ir",
+ "gs.fm.no",
+ "storfjord.no",
+ "chikugo.fukuoka.jp",
+ "hitachiomiya.ibaraki.jp",
+ "edunet.tn",
+ "tamano.okayama.jp",
+ "reggiocalabria.it",
+ "gouv.bj",
+ "songdalen.no",
+ "gs.bu.no",
+ "gs.hl.no",
+ "misugi.mie.jp",
+ "philadelphia.museum",
+ "net.az",
+ "higashi.fukuoka.jp",
+ "abu.yamaguchi.jp",
+ "yanagawa.fukuoka.jp",
+ "time.museum",
+ "toei.aichi.jp",
+ "jp",
+ "nichinan.tottori.jp",
+ "reggio-calabria.it",
+ "game.tw",
"gov.pt",
- "wf",
"edu.pt",
"com.pt",
- "x.se",
- "is-a-cpa.com",
- "imabari.ehime.jp",
- "edu.gt",
- "is-a-knight.org",
- "info.nr",
- "com.gt",
- "tm.mg",
- "info.bb",
- "gov.pr",
- "gov.pn",
- "gov.rw",
- "edu.pr",
- "inf.cu",
- "edu.pn",
- "edu.rw",
- "castle.museum",
- "com.pr",
- "shirosato.ibaraki.jp",
- "com.rw",
- "gov.gr",
- "gov.gn",
- "edu.gr",
- "edu.gn",
- "abu.yamaguchi.jp",
- "com.gr",
- "com.gn",
- "dyndns-pics.com",
- "overhalla.no",
- "gon.pk",
- "cyber.museum",
- "iwata.shizuoka.jp",
- "ltd.gi",
- "or.kr",
- "avellino.it",
- "gov.pl",
- "net.hk",
- "asakawa.fukushima.jp",
- "edu.pl",
- "aizumisato.fukushima.jp",
- "info.au",
+ "utazu.kagawa.jp",
+ "gouv.km",
+ "nyc.museum",
+ "sells-for-u.com",
+ "club.tw",
+ "omihachiman.shiga.jp",
+ "org.ky",
+ "gjerstad.no",
+ "yoka.hyogo.jp",
+ "jur.pro",
+ "yuza.yamagata.jp",
+ "int.pt",
+ "reggio-emilia.it",
+ "gs.ah.no",
+ "yk.ca",
+ "mosvik.no",
+ "jondal.no",
+ "gouv.fr",
+ "pg",
+ "sch.ng",
+ "skedsmokorset.no",
+ "flakstad.no",
+ "biz.tt",
+ "shop.pl",
+ "yaese.okinawa.jp",
+ "baghdad.museum",
+ "gjovik.no",
+ "udmurtia.ru",
+ "hakodate.hokkaido.jp",
+ "tsk.ru",
+ "edu.ht",
+ "com.ht",
+ "taxi.aero",
+ "taishi.osaka.jp",
+ "grimstad.no",
+ "sakai.fukui.jp",
+ "realestate.pl",
+ "gs.hm.no",
+ "gamvik.no",
+ "showa.fukushima.jp",
+ "mil.st",
+ "art.ht",
+ "usenet.pl",
+ "sasaguri.fukuoka.jp",
+ "sor-aurdal.no",
+ "ube.yamaguchi.jp",
+ "hasvik.no",
+ "tomiya.miyagi.jp",
+ "toride.ibaraki.jp",
+ "presse.fr",
+ "ne.ug",
+ "village.museum",
+ "muosat.no",
+ "higashi.fukushima.jp",
+ "settlement.museum",
+ "industries",
+ "otaki.saitama.jp",
+ "tondabayashi.osaka.jp",
+ "nantan.kyoto.jp",
+ "nagato.yamaguchi.jp",
+ "net.kz",
+ "sx.cn",
+ "sapporo.jp",
+ "biz.at",
+ "shika.ishikawa.jp",
+ "syzran.ru",
+ "tabayama.yamanashi.jp",
+ "oskol.ru",
+ "educator.aero",
+ "tank.museum",
+ "tas.edu.au",
+ "odesa.ua",
+ "smolensk.ru",
+ "kolobrzeg.pl",
+ "national.museum",
+ "hashima.gifu.jp",
+ "caserta.it",
+ "supplies",
+ "journalist.aero",
+ "tsumagoi.gunma.jp",
+ "salerno.it",
+ "univ.sn",
+ "jessheim.no",
+ "sciences.museum",
+ "sci.eg",
+ "buryatia.ru",
+ "xn--davvenjrga-y4a.no",
+ "tamamura.gunma.jp",
+ "scrapper-site.net",
+ "tsubame.niigata.jp",
+ "shingu.hyogo.jp",
+ "mashiko.tochigi.jp",
+ "med.ht",
+ "education",
+ "pvt.ge",
+ "ibigawa.gifu.jp",
+ "tg",
+ "hichiso.gifu.jp",
+ "tamayu.shimane.jp",
+ "malvik.no",
+ "nakagusuku.okinawa.jp",
+ "balestrand.no",
+ "utsunomiya.tochigi.jp",
+ "jolster.no",
+ "taku.saga.jp",
+ "trondheim.no",
+ "wakkanai.hokkaido.jp",
+ "xn--gjvik-wua.no",
+ "station.museum",
+ "chukotka.ru",
+ "jevnaker.no",
+ "or.tz",
+ "simple-url.com",
+ "yokosuka.kanagawa.jp",
+ "or.us",
+ "ninohe.iwate.jp",
"monza-e-della-brianza.it",
- "com.pl",
- "pescara.it",
- "med.pa",
- "sakuragawa.ibaraki.jp",
+ "oz.au",
+ "journalism.museum",
+ "forgot.her.name",
+ "ol.no",
+ "magnitka.ru",
+ "philadelphiaarea.museum",
+ "tarumizu.kagoshima.jp",
+ "or.mu",
+ "xn--gmqw5a.hk",
+ "sanfrancisco.museum",
+ "sibenik.museum",
+ "perugia.it",
+ "obama.fukui.jp",
+ "entertainment.aero",
+ "or.at",
+ "brand.se",
"or.cr",
- "chikusei.ibaraki.jp",
- "is-an-actress.com",
- "cc.ky.us",
- "nakaniikawa.toyama.jp",
- "is-a-guru.com",
- "lomza.pl",
- "cieszyn.pl",
- "rovigo.it",
- "info.sd",
- "horology.museum",
- "hirado.nagasaki.jp",
- "atm.pl",
- "biella.it",
- "sld.pa",
- "ikeda.nagano.jp",
- "gsm.pl",
- "sos.pl",
- "est.pr",
- "miasa.nagano.jp",
- "art.pl",
- "gob.pe",
- "sex.pl",
- "gob.pk",
- "is-an-artist.com",
- "miharu.fukushima.jp",
- "info.na",
- "x.bg",
- "microlight.aero",
- "aisho.shiga.jp",
- "paroch.k12.ma.us",
- "info.nf",
- "s3-website-eu-west-1.amazonaws.com",
- "gob.pa",
- "net.ht",
- "minami.fukuoka.jp",
- "cc.wy.us",
- "abo.pa",
- "oguni.yamagata.jp",
- "minamifurano.hokkaido.jp",
- "gov.mw",
- "pittsburgh.museum",
- "info.la",
- "edu.mw",
- "gop.pk",
- "iide.yamagata.jp",
- "com.mw",
- "net.hn",
- "info.ec",
- "co.ag",
- "dyndns-blog.com",
- "aid.pl",
- "yuza.yamagata.jp",
- "med.pl",
- "gok.pk",
- "hamar.no",
- "sc.kr",
- "ac.kr",
- "gub.uy",
- "ac.ir",
- "kotoura.tottori.jp",
- "ina.ibaraki.jp",
- "ac.cr",
- "iwamizawa.hokkaido.jp",
- "seaport.museum",
- "hamaroy.no",
- "notaires.fr",
- "cc.ny.us",
- "skanland.no",
- "freemasonry.museum",
- "potenza.it",
- "civilisation.museum",
- "koryo.nara.jp",
- "fam.pk",
- "gob.gt",
- "shirako.chiba.jp",
- "biz.pk",
- "embroidery.museum",
- "minamiaiki.nagano.jp",
- "bashkiria.ru",
- "lecco.it",
- "lincoln.museum",
- "onagawa.miyagi.jp",
- "amusement.aero",
- "hirara.okinawa.jp",
- "rec.ro",
- "gda.pl",
- "minamimaki.nagano.jp",
- "chiryu.aichi.jp",
- "yugawara.kanagawa.jp",
- "shioya.tochigi.jp",
- "merseine.nu",
- "ikata.ehime.jp",
- "vyatka.ru",
- "aquila.it",
- "xz.cn",
- "thruhere.net",
+ "kuroiso.tochigi.jp",
+ "odawara.kanagawa.jp",
+ "software.aero",
+ "support",
+ "shiwa.iwate.jp",
+ "yamagata.gifu.jp",
+ "omuta.fukuoka.jp",
+ "carbonia-iglesias.it",
+ "chikuho.fukuoka.jp",
+ "otaru.hokkaido.jp",
+ "fukuchiyama.kyoto.jp",
+ "kamitsue.oita.jp",
+ "is-a-geek.org",
+ "shingu.fukuoka.jp",
+ "forgot.his.name",
+ "or.kr",
+ "omiya.saitama.jp",
+ "ono.hyogo.jp",
+ "or.ci",
+ "flight.aero",
+ "tozawa.yamagata.jp",
+ "siracusa.it",
+ "takatori.nara.jp",
+ "otake.hiroshima.jp",
+ "museet.museum",
+ "tsushima.nagasaki.jp",
+ "od.ua",
+ "cargo.aero",
+ "info.tt",
+ "kasugai.aichi.jp",
+ "ozora.hokkaido.jp",
+ "is-a-photographer.com",
+ "tsukui.kanagawa.jp",
+ "group.aero",
+ "aero.tt",
+ "xn--rhqv96g",
+ "or.na",
+ "flights",
+ "waw.pl",
+ "jeju.kr",
+ "sagae.yamagata.jp",
+ "owani.aomori.jp",
+ "muenster.museum",
+ "mobi.tz",
+ "cmw.ru",
+ "ryugasaki.ibaraki.jp",
+ "nanporo.hokkaido.jp",
"daegu.kr",
- "mil.pe",
- "mil.ge",
- "rel.pl",
- "ikeda.fukui.jp",
- "agrar.hu",
- "tokyo.jp",
- "ono.fukui.jp",
- "homeunix.net",
- "philadelphiaarea.museum",
- "ac.pr",
- "uruma.okinawa.jp",
- "geisei.kochi.jp",
- "nagato.yamaguchi.jp",
- "oyama.tochigi.jp",
- "stockholm.museum",
- "cherkasy.ua",
- "dnsalias.net",
- "name.az",
- "gotemba.shizuoka.jp",
- "niimi.okayama.jp",
- "frankfurt.museum",
- "nishiokoppe.hokkaido.jp",
- "ac.im",
- "xj.cn",
- "biz.pr",
- "vevelstad.no",
- "stange.no",
- "urawa.saitama.jp",
- "koriyama.fukushima.jp",
- "haram.no",
- "ofunato.iwate.jp",
- "mazury.pl",
- "mil.uy",
- "harima.hyogo.jp",
- "shimotsuke.tochigi.jp",
- "choyo.kumamoto.jp",
- "setouchi.okayama.jp",
- "biz.pl",
- "mil.gt",
- "it.ao",
- "soo.kagoshima.jp",
- "for-our.info",
+ "sukagawa.fukushima.jp",
+ "illustration.museum",
+ "on.ca",
+ "jeonnam.kr",
+ "ojiya.niigata.jp",
+ "jar.ru",
+ "fujishiro.ibaraki.jp",
+ "tarama.okinawa.jp",
+ "agriculture.museum",
+ "taketa.oita.jp",
+ "otobe.hokkaido.jp",
+ "oh.us",
+ "or.bi",
+ "or.th",
+ "house.museum",
+ "dovre.no",
+ "glass.museum",
+ "noboribetsu.hokkaido.jp",
+ "writesthisblog.com",
+ "readmyblog.org",
+ "gorge.museum",
+ "hino.tottori.jp",
+ "kamo.niigata.jp",
+ "ichikawa.hyogo.jp",
"narashino.chiba.jp",
- "mil.rw",
- "is-an-entertainer.com",
- "googleapis.com",
- "public.museum",
- "homeunix.org",
- "edu.pf",
- "okaya.nagano.jp",
- "kawara.fukuoka.jp",
- "com.pf",
- "mamurogawa.yamagata.jp",
- "k12.pa.us",
- "tsukui.kanagawa.jp",
- "mil.pl",
- "info.co",
- "dnsalias.org",
- "k12.ga.us",
- "name.qa",
- "yoshida.saitama.jp",
- "nichinan.tottori.jp",
- "swinoujscie.pl",
- "tamaki.mie.jp",
- "nom.fr",
- "tokamachi.niigata.jp",
- "kaluga.ru",
- "lib.pa.us",
- "cargo.aero",
- "lib.ga.us",
- "ohira.tochigi.jp",
- "sykkylven.no",
- "paris.museum",
- "belau.pw",
- "info.pr",
- "omasvuotna.no",
- "biz.mw",
- "bjerkreim.no",
- "bardu.no",
- "k12.gu.us",
- "unnan.shimane.jp",
- "edu.gp",
- "kozaki.chiba.jp",
- "artsandcrafts.museum",
- "com.gp",
- "ono.fukushima.jp",
- "info.ro",
- "info.pl",
- "elk.pl",
- "naustdal.no",
- "bamble.no",
- "nesset.no",
- "birthplace.museum",
- "k12.pr.us",
- "ibaraki.ibaraki.jp",
- "minamiyamashiro.kyoto.jp",
- "info.pk",
- "lib.gu.us",
- "info.ht",
- "asakuchi.okayama.jp",
- "omotego.fukushima.jp",
- "gov.ph",
- "minamitane.kagoshima.jp",
- "edu.ph",
- "go.jp",
- "hanamigawa.chiba.jp",
- "ed.jp",
- "com.ph",
- "co.jp",
- "gov.gh",
- "edu.gh",
- "ad.jp",
- "kobierzyce.pl",
- "annaka.gunma.jp",
- "detroit.museum",
- "lib.pr.us",
- "com.gh",
- "kamikoani.akita.jp",
- "telekommunikation.museum",
- "dontexist.org",
- "yorii.saitama.jp",
- "geology.museum",
- "gr.jp",
- "ohi.fukui.jp",
- "higashishirakawa.gifu.jp",
- "is-a-green.com",
- "ikawa.akita.jp",
- "embaixada.st",
- "org.do",
- "org.dm",
- "amakusa.kumamoto.jp",
- "design.museum",
- "org.dz",
- "kosaka.akita.jp",
- "kembuchi.hokkaido.jp",
- "ichiba.tokushima.jp",
- "is-uberleet.com",
- "szkola.pl",
- "omachi.nagano.jp",
- "info.ki",
- "stuff-4-sale.us",
- "podhale.pl",
- "grozny.ru",
- "sakurai.nara.jp",
- "snillfjord.no",
- "lahppi.no",
- "tagami.niigata.jp",
- "design.aero",
- "civilaviation.aero",
- "is-found.org",
- "ukiha.fukuoka.jp",
- "hasami.nagasaki.jp",
- "endofinternet.net",
- "jur.pro",
- "miyama.fukuoka.jp",
- "med.pro",
- "zgorzelec.pl",
- "itayanagi.aomori.jp",
- "loyalist.museum",
- "info.hu",
- "kawaminami.miyazaki.jp",
- "bolzano.it",
- "minamiuonuma.niigata.jp",
- "is-a-painter.com",
- "kaneyama.fukushima.jp",
- "is-into-anime.com",
- "xn--j1amh",
- "kamikawa.saitama.jp",
- "xn--wgbl6a",
- "minamiminowa.nagano.jp",
- "hasama.oita.jp",
- "okagaki.fukuoka.jp",
- "fussa.tokyo.jp",
+ "toho.fukuoka.jp",
+ "oketo.hokkaido.jp",
+ "johana.toyama.jp",
+ "takamori.kumamoto.jp",
+ "is-a-bulls-fan.com",
+ "scienceandindustry.museum",
+ "hawaii.museum",
+ "field.museum",
+ "kitashiobara.fukushima.jp",
+ "komagane.nagano.jp",
+ "force.museum",
+ "ok.us",
+ "sande.xn--mre-og-romsdal-qqb.no",
+ "nichinan.miyazaki.jp",
+ "otama.fukushima.jp",
+ "swidnica.pl",
+ "cyber.museum",
+ "kainan.wakayama.jp",
+ "union.aero",
+ "tonaki.okinawa.jp",
+ "bible.museum",
+ "oyabe.toyama.jp",
+ "cymru.museum",
+ "amber.museum",
+ "sherbrooke.museum",
+ "suzuka.mie.jp",
+ "k12.ut.us",
+ "steinkjer.no",
+ "donna.no",
+ "sellsyourhome.org",
+ "kamifurano.hokkaido.jp",
+ "takaoka.toyama.jp",
+ "shacknet.nu",
+ "asuke.aichi.jp",
+ "takasaki.gunma.jp",
+ "obira.hokkaido.jp",
+ "dyroy.no",
+ "hino.tokyo.jp",
+ "railway.museum",
+ "sciencesnaturelles.museum",
+ "sakegawa.yamagata.jp",
+ "money.museum",
"tsurugashima.saitama.jp",
- "kartuzy.pl",
+ "works.aero",
+ "aisai.aichi.jp",
+ "org.co",
+ "educational.museum",
+ "tako.chiba.jp",
+ "basel.museum",
+ "rockart.museum",
+ "uozu.toyama.jp",
+ "tomakomai.hokkaido.jp",
+ "sciencehistory.museum",
+ "tsugaru.aomori.jp",
+ "yamagata.yamagata.jp",
+ "rochester.museum",
+ "tanohata.iwate.jp",
+ "space-to-rent.com",
+ "ls",
+ "lr",
+ "gob.sv",
+ "edu.sv",
+ "www.ro",
+ "com.sv",
+ "nishiaizu.fukushima.jp",
+ "shitara.aichi.jp",
+ "tomisato.chiba.jp",
+ "gov.lv",
+ "soni.nara.jp",
+ "edu.lv",
+ "com.lv",
+ "lu",
+ "k12.mt.us",
+ "l.bg",
+ "l.se",
+ "lom.no",
+ "asn.lv",
+ "joshkar-ola.ru",
+ "university.museum",
+ "lt",
+ "marketplace.aero",
+ "takamori.nagano.jp",
+ "org.cw",
+ "education.museum",
+ "itako.ibaraki.jp",
+ "lb",
+ "tanabe.wakayama.jp",
+ "bando.ibaraki.jp",
+ "xn--mgb9awbf",
+ "org.ci",
+ "li",
+ "other.nf",
+ "shimane.jp",
+ "limo",
+ "k12.vt.us",
+ "teshikaga.hokkaido.jp",
+ "net.gn",
+ "xn--aurskog-hland-jnb.no",
+ "seihi.nagasaki.jp",
+ "info.vn",
+ "ly",
+ "santafe.museum",
+ "luster.no",
+ "tajiri.osaka.jp",
+ "os.hedmark.no",
+ "technology",
+ "joso.ibaraki.jp",
+ "lunner.no",
+ "kunstunddesign.museum",
+ "okuma.fukushima.jp",
+ "handa.aichi.jp",
+ "chuo.tokyo.jp",
+ "ltd.lk",
+ "gov.mv",
+ "edu.mv",
+ "scienceandhistory.museum",
+ "com.mv",
+ "baths.museum",
+ "sweden.museum",
+ "expert",
+ "takayama.gunma.jp",
+ "lib.ee",
+ "xn--dyry-ira.no",
+ "naturhistorisches.museum",
+ "lebork.pl",
+ "farmstead.museum",
+ "shimoichi.nara.jp",
+ "tobetsu.hokkaido.jp",
+ "bungotakada.oita.jp",
+ "la",
+ "sue.fukuoka.jp",
+ "int.mv",
+ "leg.br",
+ "or.id",
+ "jefferson.museum",
+ "clock.museum",
+ "uhren.museum",
+ "sennan.osaka.jp",
+ "christmas",
+ "land",
+ "lierne.no",
+ "takayama.nagano.jp",
+ "lv",
+ "tas.gov.au",
+ "link",
+ "asahi.ibaraki.jp",
+ "anan.tokushima.jp",
+ "jeonbuk.kr",
+ "nishinoshima.shimane.jp",
+ "nankoku.kochi.jp",
+ "takahama.aichi.jp",
+ "mordovia.ru",
+ "lel.br",
+ "or.it",
+ "takazaki.miyazaki.jp",
+ "gdynia.pl",
+ "tokushima.jp",
+ "lerdal.no",
+ "ski.museum",
+ "limanowa.pl",
+ "ot.it",
+ "krokstadelva.no",
+ "shirosato.ibaraki.jp",
+ "xn--berlevg-jxa.no",
+ "mima.tokushima.jp",
+ "lapy.pl",
+ "yusui.kagoshima.jp",
+ "lindas.no",
+ "mil.lv",
+ "augustow.pl",
+ "kiev.ua",
+ "matsushige.tokushima.jp",
+ "tamatsukuri.ibaraki.jp",
+ "lib.or.us",
+ "dontexist.org",
+ "lugansk.ua",
+ "lib.dc.us",
+ "info.ve",
+ "kikuchi.kumamoto.jp",
+ "lib.ok.us",
+ "biz.mv",
+ "lib.sc.us",
+ "kiwi",
+ "institute",
+ "lib.de.us",
+ "tsukigata.hokkaido.jp",
+ "rokunohe.aomori.jp",
+ "lk",
"yoshino.nara.jp",
- "nissedal.no",
- "belluno.it",
- "mazowsze.pl",
- "aki.kochi.jp",
- "ena.gifu.jp",
- "nishio.aichi.jp",
- "xn--nnx388a",
- "xn--asky-ira.no",
- "kagamino.okayama.jp",
- "tsuchiura.ibaraki.jp",
- "newjersey.museum",
- "mantova.it",
- "heguri.nara.jp",
- "takamatsu.kagawa.jp",
- "spjelkavik.no",
- "aknoluokta.no",
- "fujikawa.shizuoka.jp",
- "yoshida.shizuoka.jp",
- "xn--skjk-soa.no",
- "nakatane.kagoshima.jp",
- "gs.bu.no",
- "missoula.museum",
- "planetarium.museum",
- "is-a-socialist.com",
- "id.ly",
- "kitakami.iwate.jp",
- "nagoya.jp",
- "shinonsen.hyogo.jp",
- "minoh.osaka.jp",
- "karumai.iwate.jp",
- "is-leet.com",
- "pskov.ru",
- "is-a-rockstar.com",
+ "lib.nj.us",
+ "lib.nm.us",
+ "chuvashia.ru",
+ "lib.nc.us",
+ "shinkamigoto.nagasaki.jp",
+ "rg.it",
+ "osen.no",
+ "takasu.hokkaido.jp",
+ "izumozaki.niigata.jp",
+ "lib.ne.us",
+ "keisen.fukuoka.jp",
+ "lib.sd.us",
+ "shimodate.ibaraki.jp",
+ "org.sn",
+ "odda.no",
+ "lib.la.us",
+ "beppu.oita.jp",
+ "fukushima.fukushima.jp",
+ "bryansk.ru",
+ "lebesby.no",
+ "lardal.no",
+ "mobi.tt",
+ "technology.museum",
+ "koge.tottori.jp",
+ "berlevag.no",
+ "takehara.hiroshima.jp",
"off.ai",
- "meraker.no",
- "cc.oh.us",
- "andria-barletta-trani.it",
- "oyodo.nara.jp",
- "kasumigaura.ibaraki.jp",
- "nationalheritage.museum",
- "xn--trgstad-r1a.no",
- "misaki.osaka.jp",
- "iwade.wakayama.jp",
- "pavia.it",
- "chikushino.fukuoka.jp",
- "org.ro",
- "monza.it",
- "dynalias.net",
- "turek.pl",
- "suzaka.nagano.jp",
- "parma.it",
- "macerata.it",
- "mil.ph",
- "padua.it",
- "or.mu",
- "mil.gh",
- "tsukumi.oita.jp",
- "homelinux.org",
- "org.rs",
- "kafjord.no",
- "xn--brum-voa.no",
- "bar.pro",
- "chiyoda.gunma.jp",
- "agrigento.it",
- "gov.ky",
- "tachiarai.fukuoka.jp",
- "edu.ky",
- "bedzin.pl",
- "com.ky",
- "kitakata.miyazaki.jp",
- "xn--snes-poa.no",
- "ikeda.osaka.jp",
- "historicalsociety.museum",
- "xn--andy-ira.no",
- "owariasahi.aichi.jp",
- "cpa.pro",
- "org.ru",
- "selbu.no",
- "xn--slat-5na.no",
- "ogawa.ibaraki.jp",
- "kamikawa.hokkaido.jp",
- "kawakami.nara.jp",
- "oceanographic.museum",
- "okawa.kochi.jp",
- "cc.nh.us",
- "kunohe.iwate.jp",
- "cherkassy.ua",
- "dynalias.org",
- "odesa.ua",
- "sande.vestfold.no",
- "shibukawa.gunma.jp",
- "cc.sc.us",
- "yoshimi.saitama.jp",
- "net.do",
- "net.dm",
- "chungbuk.kr",
- "decorativearts.museum",
- "chungnam.kr",
- "net.dz",
- "org.mo",
- "org.me",
- "org.mk",
- "isehara.kanagawa.jp",
- "minamisanriku.miyagi.jp",
- "org.mg",
- "afjord.no",
- "xn--snase-nra.no",
- "mitaka.tokyo.jp",
- "yura.wakayama.jp",
- "kahoku.yamagata.jp",
- "org.ma",
- "ac.mu",
- "us.com",
- "ibara.okayama.jp",
- "xn--bievt-0qa.no",
- "xn--stjrdal-s1a.no",
- "fukuroi.shizuoka.jp",
- "minakami.gunma.jp",
- "sanok.pl",
- "naklo.pl",
+ "wales.museum",
+ "lib.nd.us",
+ "koeln.museum",
+ "stjohn.museum",
+ "boldlygoingnowhere.org",
+ "chita.aichi.jp",
+ "mil.mv",
+ "ginan.gifu.jp",
+ "lib.il.us",
+ "xn--langevg-jxa.no",
+ "org.tn",
+ "prato.it",
+ "konan.aichi.jp",
+ "lib.ri.us",
+ "kasamatsu.gifu.jp",
+ "siljan.no",
+ "oslo.no",
+ "kunst.museum",
+ "marugame.kagawa.jp",
+ "lib.ms.us",
+ "lib.mo.us",
+ "lib.ia.us",
+ "lib.id.us",
+ "mantova.it",
+ "org.in",
+ "karasuyama.tochigi.jp",
+ "askvoll.no",
+ "xn--ggaviika-8ya47h.no",
+ "oyer.no",
+ "takaishi.osaka.jp",
+ "lipetsk.ru",
+ "koto.tokyo.jp",
+ "okawa.fukuoka.jp",
+ "lib.me.us",
+ "tsurugi.ishikawa.jp",
+ "voagat.no",
+ "lib.as.us",
+ "lib.ar.us",
+ "yosemite.museum",
+ "lib.ak.us",
+ "lyngdal.no",
+ "lib.ma.us",
+ "media.aero",
+ "gaivuotna.no",
+ "lib.md.us",
+ "lib.pr.us",
+ "lib.al.us",
"onojo.fukuoka.jp",
- "xn--bdddj-mrabd.no",
- "ujitawara.kyoto.jp",
- "xn--snsa-roa.no",
- "xn--smla-hra.no",
- "misugi.mie.jp",
- "tychy.pl",
- "karelia.ru",
- "org.mu",
- "toyohashi.aichi.jp",
- "sanfrancisco.museum",
- "minamioguni.kumamoto.jp",
- "hisayama.fukuoka.jp",
- "notodden.no",
- "iwaki.fukushima.jp",
- "yusui.kagoshima.jp",
- "toyokawa.aichi.jp",
- "klabu.no",
- "inami.toyama.jp",
- "izumi.kagoshima.jp",
- "org.iq",
- "nichinan.miyazaki.jp",
- "brandywinevalley.museum",
- "xn--seral-lra.no",
"org.mn",
- "modalen.no",
- "oz.au",
- "s3-sa-east-1.amazonaws.com",
+ "himi.toyama.jp",
+ "kyiv.ua",
+ "kawasaki.jp",
+ "ryazan.ru",
+ "minamitane.kagoshima.jp",
+ "org.an",
+ "ushistory.museum",
+ "lillesand.no",
+ "tachikawa.tokyo.jp",
"nakai.kanagawa.jp",
- "hidaka.saitama.jp",
- "omanmobile.om",
- "furukawa.miyagi.jp",
- "kolobrzeg.pl",
- "org.ml",
- "clock.museum",
- "zgrad.ru",
- "writesthisblog.com",
- "nesodden.no",
- "teaches-yoga.com",
- "tsukuba.ibaraki.jp",
- "est-mon-blogueur.com",
- "is-a-conservative.com",
- "guovdageaidnu.no",
- "khmelnitskiy.ua",
- "xn--xkc2dl3a5ee0h",
- "tsuruta.aomori.jp",
- "bydgoszcz.pl",
- "kanagawa.jp",
- "rahkkeravju.no",
- "trustee.museum",
- "is-an-actor.com",
- "flekkefjord.no",
- "xn--vard-jra.no",
- "cymru.museum",
- "nom.ro",
- "nom.re",
- "nishi.osaka.jp",
- "shingo.aomori.jp",
- "stargard.pl",
- "pc.it",
- "siellak.no",
- "zao.miyagi.jp",
- "shinyoshitomi.fukuoka.jp",
- "history.museum",
- "is-a-bulls-fan.com",
- "uk.com",
- "zamami.okinawa.jp",
- "xn--sknit-yqa.no",
- "endofinternet.org",
- "hirakata.osaka.jp",
- "gs.svalbard.no",
- "ne.kr",
- "law.pro",
- "seoul.kr",
- "xn--troms-zua.no",
- "giessen.museum",
- "nov.ru",
- "kiyama.saga.jp",
- "science-fiction.museum",
- "sch.uk",
- "takikawa.hokkaido.jp",
- "gov.ly",
- "edu.ly",
- "com.ly",
- "ashikaga.tochigi.jp",
- "oizumi.gunma.jp",
- "seiyo.ehime.jp",
- "oketo.hokkaido.jp",
- "isleofman.museum",
- "habikino.osaka.jp",
- "kawakami.nagano.jp",
- "nt.edu.au",
- "songdalen.no",
- "xn--trna-woa.no",
- "of.no",
- "sakaki.nagano.jp",
- "sanuki.kagawa.jp",
- "takahama.fukui.jp",
- "gov.mv",
- "edu.mv",
- "burghof.museum",
- "toyako.hokkaido.jp",
- "com.mv",
- "namsskogan.no",
- "hidaka.hokkaido.jp",
- "xn--vads-jra.no",
- "brussel.museum",
- "siedlce.pl",
- "nom.mg",
- "drangedal.no",
- "iglesias-carbonia.it",
- "joshkar-ola.ru",
- "unzen.nagasaki.jp",
- "kamikitayama.nara.jp",
- "naroy.no",
- "news.hu",
- "tsuiki.fukuoka.jp",
- "idv.hk",
- "art.museum",
- "ryuoh.shiga.jp",
- "psc.br",
- "oto.fukuoka.jp",
- "net.ru",
- "inatsuki.fukuoka.jp",
- "murakami.niigata.jp",
- "iwate.iwate.jp",
- "nishiwaki.hyogo.jp",
- "sakyo.kyoto.jp",
- "yufu.oita.jp",
- "is-a-personaltrainer.com",
- "gs.ol.no",
- "stuff-4-sale.org",
- "hidaka.wakayama.jp",
- "larsson.museum",
- "k12.ky.us",
- "oystre-slidre.no",
- "tomakomai.hokkaido.jp",
+ "klepp.no",
+ "ivanovo.ru",
+ "kita.tokyo.jp",
+ "lib.pa.us",
+ "austevoll.no",
+ "lib.mi.us",
+ "ogawara.miyagi.jp",
+ "org.pn",
+ "lib.va.us",
+ "takaharu.miyazaki.jp",
+ "nagakute.aichi.jp",
+ "org.vn",
+ "hiraizumi.iwate.jp",
+ "lanbib.se",
+ "accident-investigation.aero",
+ "takahagi.ibaraki.jp",
+ "org.cu",
+ "xn--hylandet-54a.no",
"gyokuto.kumamoto.jp",
- "kosuge.yamanashi.jp",
- "incheon.kr",
- "med.ly",
- "usuki.oita.jp",
- "net.mo",
- "net.me",
- "net.mk",
- "lib.ky.us",
- "xn--berlevg-jxa.no",
- "is-a-techie.com",
- "steigen.no",
- "xn--sr-aurdal-l8a.no",
- "ayase.kanagawa.jp",
- "bristol.museum",
- "and.museum",
- "is-a-doctor.com",
- "lg.jp",
- "net.ma",
- "air.museum",
- "xn--zf0avx.hk",
- "indiana.museum",
- "xn--vrggt-xqad.no",
- "xn--j6w193g",
- "eng.pro",
- "ddr.museum",
- "mjondalen.no",
- "yashiro.hyogo.jp",
- "gamagori.aichi.jp",
- "tokuyama.yamaguchi.jp",
- "yao.osaka.jp",
- "kahoku.ishikawa.jp",
- "minamidaito.okinawa.jp",
- "xn--55qx5d.cn",
- "sukumo.kochi.jp",
- "net.mu",
- "is-a-geek.org",
- "pyatigorsk.ru",
- "tonaki.okinawa.jp",
- "government.aero",
- "kharkov.ua",
- "kharkiv.ua",
- "net.iq",
- "gs.nl.no",
- "rotorcraft.aero",
- "miyagi.jp",
- "bus.museum",
- "daigo.ibaraki.jp",
- "yahaba.iwate.jp",
- "nkz.ru",
- "akiruno.tokyo.jp",
- "skjak.no",
- "is-a-hard-worker.com",
- "net.ml",
- "mad.museum",
- "chikuhoku.nagano.jp",
- "plc.co.im",
+ "perso.sn",
+ "saves-the-whales.com",
+ "legnica.pl",
+ "tokorozawa.saitama.jp",
+ "alto-adige.it",
+ "yaizu.shizuoka.jp",
+ "lib.vi.us",
+ "nakagyo.kyoto.jp",
+ "press.ma",
+ "swinoujscie.pl",
+ "co.lc",
+ "sakae.nagano.jp",
+ "luxe",
+ "ac.sz",
+ "ac.tz",
+ "org.hn",
+ "sykkylven.no",
+ "s3-sa-east-1.amazonaws.com",
+ "takahashi.okayama.jp",
+ "lib.ks.us",
+ "honbetsu.hokkaido.jp",
+ "daito.osaka.jp",
+ "ac.rs",
+ "kopervik.no",
+ "ac.mu",
+ "nyuzen.toyama.jp",
+ "nrw",
"ac.ru",
- "xn--s-1fa.no",
- "usdecorativearts.museum",
- "uy.com",
- "xn--smna-gra.no",
- "nsk.ru",
- "gloppen.no",
- "readmyblog.org",
- "in.th",
- "khmelnytskyi.ua",
- "doomdns.com",
- "ardal.no",
- "misaki.okayama.jp",
- "ichinomiya.chiba.jp",
- "nagai.yamagata.jp",
- "sekikawa.niigata.jp",
- "izunokuni.shizuoka.jp",
- "barrell-of-knowledge.info",
- "novara.it",
- "katagami.akita.jp",
- "kitagata.saga.jp",
- "can.museum",
- "ulan-ude.ru",
- "bando.ibaraki.jp",
- "inami.wakayama.jp",
- "biz.mv",
- "jamal.ru",
- "toyoura.hokkaido.jp",
- "xn--bmlo-gra.no",
- "nuoro.it",
+ "ac.se",
+ "yachimata.chiba.jp",
+ "ac.ae",
+ "qc.com",
+ "shimane.shimane.jp",
+ "lezajsk.pl",
+ "lib.hi.us",
+ "ac.at",
+ "ac.me",
+ "ac.gn",
+ "porsgrunn.no",
+ "ac.cr",
+ "labour.museum",
+ "kawahara.tottori.jp",
+ "tsuruoka.yamagata.jp",
+ "org.kn",
+ "yamada.iwate.jp",
+ "net.st",
+ "ac.cn",
+ "parma.it",
+ "kawaba.gunma.jp",
+ "iwama.ibaraki.jp",
+ "zhytomyr.ua",
+ "mombetsu.hokkaido.jp",
+ "namikata.ehime.jp",
+ "landes.museum",
+ "sumita.iwate.jp",
+ "nishigo.fukushima.jp",
+ "artanddesign.museum",
+ "media.museum",
+ "ac.kr",
+ "shichinohe.aomori.jp",
+ "perso.ht",
+ "ac.tj",
+ "terni.it",
+ "timekeeping.museum",
+ "tagami.niigata.jp",
+ "jetzt",
+ "net.tt",
+ "padua.it",
+ "ac.ci",
+ "land-4-sale.us",
+ "tochio.niigata.jp",
+ "tatebayashi.gunma.jp",
+ "gouv.ht",
+ "net.bt",
+ "xn--hery-ira.xn--mre-og-romsdal-qqb.no",
+ "obuse.nagano.jp",
+ "drangedal.no",
+ "nesset.no",
+ "nakatane.kagoshima.jp",
+ "yahaba.iwate.jp",
+ "ikeda.gifu.jp",
+ "cc.na",
+ "ac.ma",
+ "lighting",
+ "ouda.nara.jp",
+ "ogata.akita.jp",
+ "kudamatsu.yamaguchi.jp",
"moriguchi.osaka.jp",
+ "pittsburgh.museum",
+ "anamizu.ishikawa.jp",
+ "oe.yamagata.jp",
+ "jinsekikogen.hiroshima.jp",
+ "juif.museum",
+ "xn--gildeskl-g0a.no",
+ "or.jp",
+ "ontario.museum",
+ "gc.ca",
+ "qc.ca",
+ "net.mt",
+ "kisofukushima.nagano.jp",
+ "takizawa.iwate.jp",
+ "oregon.museum",
+ "bc.ca",
+ "ac.be",
+ "la-spezia.it",
+ "otari.nagano.jp",
+ "barlettatraniandria.it",
+ "doshi.yamanashi.jp",
+ "obu.aichi.jp",
+ "uchinada.ishikawa.jp",
+ "net.pt",
+ "leirvik.no",
+ "ac.th",
+ "essex.museum",
+ "miyazaki.jp",
+ "oshu.iwate.jp",
+ "mugi.tokushima.jp",
+ "furniture.museum",
+ "gangaviika.no",
+ "k12.nv.us",
+ "kochi.kochi.jp",
+ "barletta-trani-andria.it",
+ "gob.gt",
+ "edu.gt",
+ "takikawa.hokkaido.jp",
+ "com.gt",
+ "ebiz.tw",
+ "narvik.no",
+ "kawanishi.nara.jp",
+ "tomioka.gunma.jp",
+ "otaki.nagano.jp",
+ "tainai.niigata.jp",
+ "opoczno.pl",
+ "hoyanger.no",
+ "navuotna.no",
+ "is-saved.org",
+ "kuchinotsu.nagasaki.jp",
"oseto.nagasaki.jp",
- "xn--b-5ga.nordland.no",
- "horokanai.hokkaido.jp",
- "aerodrome.aero",
- "nalchik.ru",
- "mil.mv",
- "chikuma.nagano.jp",
- "beppu.oita.jp",
- "yamatsuri.fukushima.jp",
- "ski.museum",
- "kitagawa.kochi.jp",
- "palmsprings.museum",
- "for-more.biz",
- "nishinomiya.hyogo.jp",
- "xn--tn0ag.hk",
- "tas.gov.au",
- "org.uz",
- "tokigawa.saitama.jp",
- "oarai.ibaraki.jp",
- "org.ug",
- "oki.fukuoka.jp",
- "doesntexist.com",
- "nishitosa.kochi.jp",
- "is-a-blogger.com",
- "org.ua",
- "minokamo.gifu.jp",
- "vologda.ru",
- "pulawy.pl",
- "kadogawa.miyazaki.jp",
- "mykolaiv.ua",
- "nature.museum",
- "badajoz.museum",
- "usa.oita.jp",
- "isumi.chiba.jp",
- "tsuruoka.yamagata.jp",
- "malopolska.pl",
- "xn--55qx5d.hk",
- "xn--btsfjord-9za.no",
- "fjell.no",
- "is-a-hunter.com",
- "xn--srum-gra.no",
- "cc.md.us",
- "torahime.shiga.jp",
+ "net.ht",
+ "name.tj",
+ "tydal.no",
+ "targi.pl",
+ "shop.ht",
+ "if.ua",
+ "chikuzen.fukuoka.jp",
+ "tjome.no",
+ "olsztyn.pl",
+ "lib.wa.us",
+ "levanger.no",
+ "saigawa.fukuoka.jp",
+ "ind.gt",
+ "perso.tn",
+ "co.pl",
+ "trana.no",
+ "saku.nagano.jp",
+ "nakamichi.yamanashi.jp",
+ "nakatombetsu.hokkaido.jp",
+ "shinyoshitomi.fukuoka.jp",
+ "kaminokawa.tochigi.jp",
+ "co.pn",
"ogano.saitama.jp",
- "fujikawa.yamanashi.jp",
- "cc.id.us",
- "varggat.no",
- "minamiawaji.hyogo.jp",
- "mihara.kochi.jp",
- "basel.museum",
- "shimogo.fukushima.jp",
- "casadelamoneda.museum",
- "nasushiobara.tochigi.jp",
- "xn--sandy-yua.no",
- "webhop.net",
- "blogdns.com",
- "xn--zf0ao64a.tw",
- "gov.py",
- "edu.py",
- "office-on-the.net",
- "barrel-of-knowledge.info",
- "com.py",
- "nikaho.akita.jp",
- "isteingeek.de",
- "com.gy",
- "airtraffic.aero",
- "shell.museum",
- "xn--bjddar-pta.no",
- "urbinopesaro.it",
- "xn--vgan-qoa.no",
- "is-a-lawyer.com",
- "oygarden.no",
- "ivano-frankivsk.ua",
- "kunigami.okinawa.jp",
- "gs.hl.no",
- "kagamiishi.fukushima.jp",
- "imari.saga.jp",
- "kamikawa.hyogo.jp",
- "kitaura.miyazaki.jp",
- "omachi.saga.jp",
- "zoology.museum",
- "family.museum",
- "ogaki.gifu.jp",
- "works.aero",
- "hotel.tz",
- "western.museum",
- "xn--sr-odal-q1a.no",
- "cc.nd.us",
- "pf",
- "kikugawa.shizuoka.jp",
- "hotel.lk",
- "bologna.it",
- "tsuno.kochi.jp",
- "culturalcenter.museum",
- "environmentalconservation.museum",
- "nango.fukushima.jp",
- "xn--trany-yua.no",
- "kitagawa.miyazaki.jp",
- "gs.rl.no",
- "nishikata.tochigi.jp",
- "shingu.wakayama.jp",
- "izumi.osaka.jp",
- "hotel.hu",
- "xn--bhcavuotna-s4a.no",
+ "lib.wi.us",
+ "ogose.saitama.jp",
+ "de.us",
+ "freight.aero",
+ "turek.pl",
+ "xn--80asehdb",
+ "xn--45brj9c",
+ "xn--s9brj9c",
+ "latina.it",
+ "taishi.hyogo.jp",
+ "osaki.miyagi.jp",
+ "vinnytsia.ua",
+ "tolga.no",
+ "kamiizumi.saitama.jp",
+ "usculture.museum",
+ "report",
+ "de.com",
+ "xn--tysvr-vra.no",
+ "lavangen.no",
+ "tomsk.ru",
+ "kawakami.nara.jp",
+ "iwamizawa.hokkaido.jp",
+ "narviika.no",
+ "tamakawa.fukushima.jp",
+ "rnrt.tn",
+ "xn--q9jyb4c",
+ "gs.svalbard.no",
+ "oguni.kumamoto.jp",
+ "miyada.nagano.jp",
+ "taketomi.okinawa.jp",
+ "brandywinevalley.museum",
+ "oceanographique.museum",
+ "openair.museum",
+ "xn--loabt-0qa.no",
+ "xn--rdy-0nab.no",
+ "shinshiro.aichi.jp",
+ "iiyama.nagano.jp",
+ "takatsuki.osaka.jp",
+ "dr.na",
+ "ostre-toten.no",
+ "org.dz",
+ "dn.ua",
+ "mil.gt",
+ "miyota.nagano.jp",
+ "org.sz",
+ "krym.ua",
+ "org.uz",
+ "xn--nqv7f",
+ "obama.nagasaki.jp",
+ "kanie.aichi.jp",
+ "is-very-bad.org",
+ "omura.nagasaki.jp",
+ "ac.id",
+ "est-le-patron.com",
+ "tomika.gifu.jp",
+ "miyake.nara.jp",
+ "turen.tn",
+ "raholt.no",
+ "ac.ir",
+ "org.bz",
+ "xn--p1acf",
+ "ac.mw",
+ "xn--fl-zia.no",
+ "ac.rw",
+ "okaya.nagano.jp",
"ouchi.saga.jp",
- "xn--sandnessjen-ogb.no",
- "xn--io0a7i.cn",
- "bjarkoy.no",
- "uwajima.ehime.jp",
- "xn--vgsy-qoa0j.no",
- "kakegawa.shizuoka.jp",
- "yoshinogari.saga.jp",
- "kinokawa.wakayama.jp",
- "oshima.tokyo.jp",
- "carboniaiglesias.it",
- "sunagawa.hokkaido.jp",
- "nagaokakyo.kyoto.jp",
- "minami-alps.yamanashi.jp",
- "grong.no",
- "tahara.aichi.jp",
- "sagamihara.kanagawa.jp",
- "north.museum",
- "lavagis.no",
- "yawatahama.ehime.jp",
- "nanmoku.gunma.jp",
- "ohkura.yamagata.jp",
- "inagawa.hyogo.jp",
- "cc.or.us",
- "kumagaya.saitama.jp",
- "kawakita.ishikawa.jp",
+ "tychy.pl",
+ "nishikata.tochigi.jp",
+ "ac.in",
+ "turin.it",
+ "kibichuo.okayama.jp",
+ "xn--fiqz9s",
+ "ono.fukui.jp",
+ "fc.it",
+ "shimofusa.chiba.jp",
+ "xn--h2brj9c",
+ "pavia.it",
+ "xn--fjord-lra.no",
+ "sarpsborg.no",
+ "marketing",
+ "umaji.kochi.jp",
+ "plc.ly",
+ "xn--fiqs8s",
+ "dp.ua",
+ "likescandy.com",
+ "kakamigahara.gifu.jp",
+ "org.az",
+ "ogori.fukuoka.jp",
+ "niigata.jp",
+ "kiyose.tokyo.jp",
+ "rawa-maz.pl",
+ "tokashiki.okinawa.jp",
+ "mc.it",
+ "ac.im",
+ "gov.cn",
+ "edu.cn",
+ "com.cn",
+ "komvux.se",
+ "cci.fr",
+ "avocat.fr",
+ "barrell-of-knowledge.info",
+ "kesennuma.miyagi.jp",
+ "kawakami.nagano.jp",
+ "lib.oh.us",
+ "nsw.au",
+ "kawajima.saitama.jp",
+ "lodi.it",
+ "ohda.shimane.jp",
+ "est-a-la-maison.com",
+ "og.ao",
+ "operaunite.com",
+ "heimatunduhren.museum",
+ "est-a-la-masion.com",
+ "tranoy.no",
+ "shop.hu",
+ "lib.nh.us",
+ "or.ug",
+ "tenri.nara.jp",
+ "losangeles.museum",
+ "tagawa.fukuoka.jp",
+ "rel.ht",
+ "neues.museum",
+ "xn--frya-hra.no",
+ "democrat",
+ "kawanehon.shizuoka.jp",
+ "name.tt",
+ "rhcloud.com",
+ "nozawaonsen.nagano.jp",
+ "ftpaccess.cc",
"xn--ciqpn.hk",
- "inzai.chiba.jp",
- "dreamhosters.com",
- "uzhgorod.ua",
- "mihama.aichi.jp",
- "yaotsu.gifu.jp",
- "xn--xkc2al3hye2a",
- "itami.hyogo.jp",
- "hobol.no",
- "miyake.nara.jp",
- "iki.fi",
- "sklep.pl",
- "tochigi.tochigi.jp",
- "osteroy.no",
- "is-a-patsfan.org",
- "yokohama.jp",
- "net.uz",
- "wakayama.jp",
- "net.ua",
- "xn--bearalvhki-y4a.no",
- "shiogama.miyagi.jp",
- "furudono.fukushima.jp",
- "spy.museum",
- "kurogi.fukuoka.jp",
- "mil.py",
- "cc.pr.us",
- "parachuting.aero",
- "kanzaki.saga.jp",
- "nobeoka.miyazaki.jp",
- "nacion.ar",
- "setagaya.tokyo.jp",
- "skjervoy.no",
- "klepp.no",
- "atsugi.kanagawa.jp",
- "air-traffic-control.aero",
- "inagi.tokyo.jp",
- "nsn.us",
- "xn--io0a7i.hk",
- "nls.uk",
- "miyako.fukuoka.jp",
- "nel.uk",
- "fukagawa.hokkaido.jp",
- "samukawa.kanagawa.jp",
- "championship.aero",
- "vefsn.no",
- "tydal.no",
- "aogaki.hyogo.jp",
- "xn--sr-fron-q1a.no",
- "ariake.saga.jp",
- "kanegasaki.iwate.jp",
- "kamimine.saga.jp",
- "takagi.nagano.jp",
- "cc.ar.us",
- "assedic.fr",
- "is-very-sweet.org",
- "nt.au",
- "soc.lk",
- "fuefuki.yamanashi.jp",
- "kitakyushu.jp",
- "cc.nm.us",
- "ono.hyogo.jp",
- "nanporo.hokkaido.jp",
- "sakura.tochigi.jp",
- "kanuma.tochigi.jp",
- "xn--bod-2na.no",
- "of.by",
- "miyakonojo.miyazaki.jp",
- "mizumaki.fukuoka.jp",
- "nesseby.no",
- "nesoddtangen.no",
- "is-a-photographer.com",
- "is-a-player.com",
- "tv.sd",
- "principe.st",
- "kasuga.hyogo.jp",
- "ushuaia.museum",
- "koshu.yamanashi.jp",
- "kasuga.fukuoka.jp",
- "dnepropetrovsk.ua",
- "nanto.toyama.jp",
- "skydiving.aero",
- "ikeda.gifu.jp",
- "yaita.tochigi.jp",
- "izumozaki.niigata.jp",
- "isahaya.nagasaki.jp",
- "norddal.no",
- "timekeeping.museum",
- "ostrowwlkp.pl",
- "xn--bhccavuotna-k7a.no",
- "vadso.no",
- "nuremberg.museum",
- "kamakura.kanagawa.jp",
- "worse-than.tv",
- "leangaviika.no",
- "uchinomi.kagawa.jp",
- "dnipropetrovsk.ua",
- "kagami.kochi.jp",
- "kochi.kochi.jp",
- "suwalki.pl",
- "kopervik.no",
- "iheya.okinawa.jp",
- "iris.arpa",
+ "savannahga.museum",
+ "nishinomiya.hyogo.jp",
+ "xn--nnx388a",
+ "ohira.miyagi.jp",
+ "kawatana.nagasaki.jp",
+ "luxembourg.museum",
"togakushi.nagano.jp",
- "freight.aero",
- "kamigori.hyogo.jp",
- "is-lost.org",
- "jessheim.no",
- "tomigusuku.okinawa.jp",
- "sanagochi.tokushima.jp",
- "nishiaizu.fukushima.jp",
+ "ochi.kochi.jp",
+ "est-mon-blogueur.com",
+ "tranby.no",
+ "k12.wv.us",
+ "for-better.biz",
+ "org.kz",
+ "koya.wakayama.jp",
+ "dyn-o-saur.com",
+ "oto.fukuoka.jp",
+ "miyazaki.miyazaki.jp",
+ "surgut.ru",
+ "naval.museum",
+ "is-an-anarchist.com",
+ "yokkaichi.mie.jp",
+ "ranzan.saitama.jp",
+ "xn--tjme-hra.no",
+ "xn--srfold-bya.no",
+ "xn--brnnysund-m8ac.no",
+ "xn--aroport-bya.ci",
+ "is-a-liberal.com",
+ "is-a-landscaper.com",
+ "medecin.fr",
+ "tokushima.tokushima.jp",
+ "shimogo.fukushima.jp",
+ "on-the-web.tv",
+ "omitama.ibaraki.jp",
+ "assedic.fr",
+ "tateshina.nagano.jp",
+ "lodingen.no",
+ "tsuiki.fukuoka.jp",
+ "asso.nc",
+ "miyazu.kyoto.jp",
+ "xn--snase-nra.no",
+ "xn--nqv7fs00ema",
+ "go.pw",
+ "ed.pw",
+ "co.pw",
+ "xn--flor-jra.no",
+ "dyndns.biz",
+ "mil.cn",
+ "north.museum",
+ "xn--jrpeland-54a.no",
"buyshouses.net",
- "tozsde.hu",
+ "ono.fukushima.jp",
+ "kawaminami.miyazaki.jp",
"tsuru.yamanashi.jp",
- "jan-mayen.no",
- "minamiashigara.kanagawa.jp",
- "hatogaya.saitama.jp",
- "nordreisa.no",
- "museumcenter.museum",
- "xn--czrw28b.tw",
- "rhcloud.com",
- "xn--vg-yiab.no",
- "civilwar.museum",
- "sch.lk",
- "nachikatsuura.wakayama.jp",
- "szczecin.pl",
- "kawaguchi.saitama.jp",
- "yusuhara.kochi.jp",
- "id.ir",
- "gwangju.kr",
- "scotland.museum",
- "myphotos.cc",
- "yurihonjo.akita.jp",
- "org.km",
- "maryland.museum",
- "org.ki",
- "org.kz",
- "org.kg",
- "nemuro.hokkaido.jp",
- "nakadomari.aomori.jp",
- "takanezawa.tochigi.jp",
- "urakawa.hokkaido.jp",
- "kitagata.gifu.jp",
- "xn--stjrdalshalsen-sqb.no",
- "shingu.hyogo.jp",
- "xn--aurskog-hland-jnb.no",
- "dyndns-office.com",
- "ozu.kumamoto.jp",
- "shingu.fukuoka.jp",
- "nabari.mie.jp",
- "pb.ao",
- "tsurugi.ishikawa.jp",
- "xn--vler-qoa.hedmark.no",
- "nagaoka.niigata.jp",
- "or.ug",
- "org.kn",
- "tsushima.aichi.jp",
- "xn--vestvgy-ixa6o.no",
- "uchinada.ishikawa.jp",
- "castres.museum",
- "hokuryu.hokkaido.jp",
- "chofu.tokyo.jp",
- "hikari.yamaguchi.jp",
- "kiyokawa.kanagawa.jp",
- "yoichi.hokkaido.jp",
- "nowaruda.pl",
- "izumo.shimane.jp",
- "webhop.org",
- "choshi.chiba.jp",
- "its.me",
- "izumizaki.fukushima.jp",
- "int.ru",
- "web.do",
- "dontexist.com",
- "kasamatsu.gifu.jp",
- "naturalhistory.museum",
- "nakayama.yamagata.jp",
- "utsunomiya.tochigi.jp",
- "missile.museum",
- "mansion.museum",
- "sc.ug",
- "ac.ug",
- "other.nf",
- "osoyro.no",
- "nakatsugawa.gifu.jp",
- "cc.gu.us",
- "org.my",
- "kozagawa.wakayama.jp",
- "warszawa.pl",
- "naturbruksgymn.se",
- "sec.ps",
- "obuse.nagano.jp",
- "olecko.pl",
- "hichiso.gifu.jp",
- "nerima.tokyo.jp",
- "nt.gov.au",
- "nanjo.okinawa.jp",
- "veterinaire.fr",
- "xn--wcvs22d.hk",
- "is-a-democrat.com",
- "shimonoseki.yamaguchi.jp",
- "nom.km",
- "naturalhistorymuseum.museum",
- "esashi.hokkaido.jp",
- "ac.ng",
- "union.aero",
- "ogose.saitama.jp",
- "hakodate.hokkaido.jp",
- "org.lk",
- "brand.se",
- "org.la",
- "nawrastelecom.om",
- "nordre-land.no",
- "vegarshei.no",
- "org.ls",
- "kakogawa.hyogo.jp",
- "org.lc",
- "org.lb",
- "net.ki",
- "net.kz",
- "net.kg",
- "xn--nry-yla5g.no",
- "shinkamigoto.nagasaki.jp",
- "vossevangen.no",
- "iz.hr",
- "taishi.osaka.jp",
- "iwama.ibaraki.jp",
- "shibuya.tokyo.jp",
- "chikuzen.fukuoka.jp",
- "org.lr",
- "sch.gg",
- "akishima.tokyo.jp",
- "xn--tysvr-vra.no",
- "wa.edu.au",
- "susaki.kochi.jp",
- "skierva.no",
- "xn--bjarky-fya.no",
- "homeunix.com",
- "net.kn",
- "hayakawa.yamanashi.jp",
- "dnsalias.com",
- "wakuya.miyagi.jp",
- "yamanobe.yamagata.jp",
- "org.kp",
- "homelinux.com",
+ "xn--jlster-bya.no",
+ "mochizuki.nagano.jp",
+ "servebbs.com",
+ "xn--srreisa-q1a.no",
+ "jelenia-gora.pl",
+ "net.lv",
+ "conference.aero",
+ "taiki.mie.jp",
"is-an-accountant.com",
- "nagahama.shiga.jp",
- "abashiri.hokkaido.jp",
- "is-into-cars.com",
- "kawagoe.saitama.jp",
- "kudamatsu.yamaguchi.jp",
- "batsfjord.no",
- "omanpost.om",
- "xn--45brj9c",
- "natori.miyagi.jp",
- "is-a-teacher.com",
- "costume.museum",
- "is-a-anarchist.com",
- "podlasie.pl",
- "xn--s9brj9c",
- "is-by.us",
- "xn--vry-yla5g.no",
- "komaki.aichi.jp",
- "vagsoy.no",
- "coastaldefence.museum",
- "onjuku.chiba.jp",
- "ibestad.no",
- "nishiizu.shizuoka.jp",
- "otsuki.yamanashi.jp",
- "kujukuri.chiba.jp",
- "or.jp",
- "is-a-musician.com",
- "net.my",
- "hirogawa.wakayama.jp",
- "nakamura.kochi.jp",
- "gov.lv",
- "youth.museum",
- "edu.lv",
- "is-an-anarchist.com",
- "com.lv",
- "funagata.yamagata.jp",
- "kawamata.fukushima.jp",
- "balsfjord.no",
+ "is-a-player.com",
+ "oregontrail.museum",
+ "lans.museum",
+ "from-sc.com",
+ "ohi.fukui.jp",
+ "sado.niigata.jp",
+ "servebbs.net",
+ "higashishirakawa.gifu.jp",
+ "valer.hedmark.no",
+ "is-a-libertarian.com",
+ "store.bb",
+ "xn--snsa-roa.no",
+ "council.aero",
+ "vanylven.no",
+ "xn--rmskog-bya.no",
+ "is-uberleet.com",
+ "from-dc.com",
+ "xn--vegrshei-c0a.no",
+ "takahama.fukui.jp",
+ "paragliding.aero",
+ "kayabe.hokkaido.jp",
+ "leksvik.no",
+ "takagi.nagano.jp",
+ "betainabox.com",
+ "ogawa.saitama.jp",
+ "okoppe.hokkaido.jp",
+ "for-our.info",
+ "googlecode.com",
+ "takasago.hyogo.jp",
+ "manx.museum",
+ "net.mv",
+ "dnsdojo.net",
+ "shiriuchi.hokkaido.jp",
+ "nnov.ru",
+ "kawazu.shizuoka.jp",
+ "dyndns-remote.com",
+ "xn--snes-poa.no",
+ "takayama.gifu.jp",
+ "dnsdojo.com",
+ "xn--lgrd-poac.no",
+ "pr.us",
+ "agency",
+ "xn--dnna-gra.no",
+ "hayakawa.yamanashi.jp",
+ "xn--finny-yua.no",
+ "pskov.ru",
"ujiie.tochigi.jp",
- "is-into-cartoons.com",
- "nayoro.hokkaido.jp",
- "nishigo.fukushima.jp",
- "is-a-landscaper.com",
+ "academy.museum",
+ "name.vn",
+ "tsuno.miyazaki.jp",
+ "judygarland.museum",
+ "living.museum",
+ "dyndns-pics.com",
+ "kiyama.saga.jp",
+ "from-ny.net",
+ "suwalki.pl",
+ "s3-fips-us-gov-west-1.amazonaws.com",
+ "pb.ao",
"tajimi.gifu.jp",
- "net.lk",
- "net.la",
- "is-certified.com",
- "oppegard.no",
- "qld.gov.au",
+ "xn--ksnes-uua.no",
"ac.jp",
- "shishikui.tokushima.jp",
- "net.lc",
- "tsushima.nagasaki.jp",
- "culture.museum",
- "windmill.museum",
- "sakegawa.yamagata.jp",
- "dontexist.net",
- "net.lb",
- "xn--wgbh1c",
- "yasuoka.nagano.jp",
- "itano.tokushima.jp",
- "whaling.museum",
- "asn.lv",
- "us.org",
- "org.pe",
- "otofuke.hokkaido.jp",
- "org.pk",
- "net.lr",
- "udm.ru",
- "org.ge",
- "org.gi",
- "nishinoomote.kagoshima.jp",
- "org.gg",
- "org.pa",
- "org.ps",
- "nanao.ishikawa.jp",
- "ambulance.aero",
- "virtuel.museum",
- "marylhurst.museum",
- "virtual.museum",
- "bialowieza.pl",
- "org.uy",
- "oguchi.aichi.jp",
- "utsira.no",
- "org.pt",
- "aca.pro",
- "org.gt",
- "org.pr",
- "org.pn",
- "hembygdsforbund.museum",
- "pro.ht",
- "org.gr",
- "org.gn",
- "promocion.ar",
- "nagara.chiba.jp",
- "is-a-liberal.com",
- "settlement.museum",
- "org.pl",
- "aeroport.fr",
- "id.au",
- "elasticbeanstalk.com",
- "chirurgiens-dentistes.fr",
- "isa.us",
- "mil.lv",
- "udono.mie.jp",
- "namerikawa.toyama.jp",
- "gs.sf.no",
- "dynalias.com",
- "xn--blt-elab.no",
- "bieszczady.pl",
+ "dyndns-home.com",
+ "takarazuka.hyogo.jp",
+ "birthplace.museum",
+ "takata.fukuoka.jp",
+ "os.hordaland.no",
+ "is-very-evil.org",
+ "stavern.no",
+ "fujikawaguchiko.yamanashi.jp",
+ "mibu.tochigi.jp",
"xn--slt-elab.no",
- "est-le-patron.com",
- "hidaka.kochi.jp",
- "kumakogen.ehime.jp",
- "org.mw",
- "pol.ht",
- "baghdad.museum",
- "is-a-geek.com",
- "newmexico.museum",
- "xn--bidr-5nac.no",
- "kashiwa.chiba.jp",
- "homelinux.net",
- "www.ro",
- "cc.ok.us",
- "huissier-justice.fr",
- "isshiki.aichi.jp",
- "info.vn",
- "info.ve",
- "nom.pe",
- "presse.ci",
- "phoenix.museum",
- "gjesdal.no",
- "nom.pa",
- "is-a-soxfan.org",
- "norfolk.museum",
- "porsangu.no",
- "nordkapp.no",
- "nieruchomosci.pl",
- "kawagoe.mie.jp",
- "valer.ostfold.no",
- "presse.km",
- "napoli.it",
- "taishi.hyogo.jp",
- "consulado.st",
- "gausdal.no",
- "net.pe",
- "ne.ug",
- "net.pk",
- "kakamigahara.gifu.jp",
- "net.ge",
- "oxford.museum",
- "net.gg",
- "net.pa",
- "net.ps",
- "undersea.museum",
- "iglesiascarbonia.it",
- "akashi.hyogo.jp",
- "nom.pl",
- "org.pf",
- "prd.fr",
- "net.uy",
- "net.pt",
- "pilot.aero",
- "net.gt",
- "schokoladen.museum",
- "presse.ml",
- "net.pr",
- "net.pn",
- "net.rw",
- "net.gr",
- "net.gn",
- "ora.gunma.jp",
- "cc.ak.us",
- "poltava.ua",
- "nishiazai.shiga.jp",
- "pp.se",
- "ota.gunma.jp",
- "net.pl",
- "org.gp",
- "pistoia.it",
- "xn--sr-varanger-ggb.no",
- "valer.hedmark.no",
- "kasukabe.saitama.jp",
- "org.ph",
- "is-a-republican.com",
- "wa.au",
- "org.gh",
- "project.museum",
- "marburg.museum",
- "ngo.lk",
- "yamada.toyama.jp",
- "wakayama.wakayama.jp",
- "is-a-libertarian.com",
- "issmarterthanyou.com",
- "is-a-nascarfan.com",
- "oskol.ru",
- "parliament.uk",
+ "tokyo.jp",
+ "endofinternet.net",
+ "bato.tochigi.jp",
+ "skanit.no",
+ "culturalcenter.museum",
+ "intelligence.museum",
+ "isteingeek.de",
+ "company",
+ "sarufutsu.hokkaido.jp",
+ "government.aero",
"localhistory.museum",
- "net.mw",
- "cc.fl.us",
- "namikata.ehime.jp",
- "inuyama.aichi.jp",
- "gemological.museum",
- "xn--brnnysund-m8ac.no",
- "cc.il.us",
- "nankoku.kochi.jp",
- "museumvereniging.museum",
- "xn--node",
- "is-a-therapist.com",
- "scrapper-site.net",
- "nakama.fukuoka.jp",
- "sodegaura.chiba.jp",
- "yanaizu.fukushima.jp",
- "namsos.no",
- "hanggliding.aero",
- "tcm.museum",
- "munakata.fukuoka.jp",
- "yakumo.shimane.jp",
- "act.gov.au",
- "consultant.aero",
- "bifuka.hokkaido.jp",
- "xn--nmesjevuemie-tcba.no",
- "xn--sndre-land-0cb.no",
- "is-a-designer.com",
- "ise.mie.jp",
- "xn--vegrshei-c0a.no",
- "imperia.it",
- "nikolaev.ua",
- "is-a-geek.net",
- "vaksdal.no",
- "newport.museum",
- "cc.al.us",
- "okoppe.hokkaido.jp",
- "xn--sknland-fxa.no",
- "fuchu.hiroshima.jp",
- "ichinomiya.aichi.jp",
- "kitakata.fukushima.jp",
- "xn--comunicaes-v6a2o.museum",
- "xn--jlster-bya.no",
- "sch.ly",
- "kamogawa.chiba.jp",
- "oryol.ru",
- "udmurtia.ru",
+ "xn--lgbbat1ad8j",
+ "haga.tochigi.jp",
+ "pulawy.pl",
+ "pe.kr",
+ "xn--blt-elab.no",
+ "lib.tx.us",
+ "ascolipiceno.it",
+ "pa.us",
+ "from-nv.com",
+ "pl.ua",
+ "blogdns.net",
+ "pp.az",
+ "oki.fukuoka.jp",
+ "museumcenter.museum",
+ "vibo-valentia.it",
+ "stavropol.ru",
+ "from-nj.com",
+ "bahcavuotna.no",
+ "services.aero",
+ "vf.no",
+ "blogdns.com",
+ "matsudo.chiba.jp",
+ "daiwa.hiroshima.jp",
+ "graphics",
+ "karuizawa.nagano.jp",
+ "tokke.no",
+ "domains",
+ "tamba.hyogo.jp",
+ "pp.ru",
+ "pp.se",
+ "sevastopol.ua",
+ "sebastopol.ua",
+ "lacaixa",
+ "is-an-entertainer.com",
"is-gone.com",
- "yakumo.hokkaido.jp",
- "net.gp",
- "ne.jp",
- "equipment.aero",
- "iijima.nagano.jp",
- "ogasawara.tokyo.jp",
- "preservation.museum",
- "org.ky",
- "suifu.ibaraki.jp",
- "nagareyama.chiba.jp",
- "is-an-engineer.com",
- "judygarland.museum",
- "net.ph",
- "tsuruga.fukui.jp",
- "is-with-theband.com",
- "schweiz.museum",
- "omigawa.chiba.jp",
- "navigation.aero",
- "presse.fr",
- "paleo.museum",
- "hamburg.museum",
+ "ogimi.okinawa.jp",
+ "vladivostok.ru",
+ "yuu.yamaguchi.jp",
+ "oshima.yamaguchi.jp",
+ "dyndns-mail.com",
+ "from-nm.com",
+ "tr.no",
+ "pe.ca",
+ "sannan.hyogo.jp",
+ "tn.us",
+ "malatvuopmi.no",
+ "servebbs.org",
+ "katsuyama.fukui.jp",
+ "uryu.hokkaido.jp",
+ "ltd.gi",
+ "og.it",
+ "red.sv",
+ "toki.gifu.jp",
+ "olbia-tempio.it",
+ "kiyosu.aichi.jp",
"xn--brnny-wuac.no",
- "xn--tjme-hra.no",
- "kiryu.gunma.jp",
- "pol.dz",
- "piacenza.it",
- "vic.gov.au",
- "nyuzen.toyama.jp",
+ "from-ne.com",
+ "pp.ua",
+ "xn--mosjen-eya.no",
+ "nasushiobara.tochigi.jp",
+ "xn--mgbbh1a71e",
+ "is-a-designer.com",
+ "xn--mgberp4a5d4ar",
+ "owariasahi.aichi.jp",
+ "tm.no",
+ "tm.ro",
+ "bremanger.no",
+ "tohma.hokkaido.jp",
+ "tm.se",
+ "dyndns-ip.com",
+ "flatanger.no",
+ "gratangen.no",
+ "xn--sgne-gra.no",
+ "from-nh.com",
+ "tm.fr",
+ "campidano-medio.it",
+ "tv.sd",
+ "tv.tz",
+ "nc.us",
+ "is-a-bookkeeper.com",
+ "xn--lns-qla.museum",
+ "shirakawa.fukushima.jp",
+ "yamatsuri.fukushima.jp",
+ "tj.cn",
+ "lib.ga.us",
+ "te.ua",
"xn--o3cw4h",
- "interactive.museum",
- "in-addr.arpa",
- "motegi.tochigi.jp",
- "nakamichi.yamanashi.jp",
- "tamakawa.fukushima.jp",
- "hirokawa.fukuoka.jp",
- "is-a-celticsfan.org",
- "xn--9dbhblg6di.museum",
- "kawaue.gifu.jp",
- "fauske.no",
- "usgarden.museum",
- "xn--srfold-bya.no",
- "matsusaka.mie.jp",
- "inderoy.no",
- "wassamu.hokkaido.jp",
- "norilsk.ru",
- "ichinohe.iwate.jp",
- "is-into-games.com",
- "tarumizu.kagoshima.jp",
- "wa.gov.au",
- "boldlygoingnowhere.org",
- "webhop.biz",
- "xn--skjervy-v1a.no",
- "pruszkow.pl",
- "tomika.gifu.jp",
- "ngo.pl",
- "hanyu.saitama.jp",
- "pe.kr",
- "oshima.yamaguchi.jp",
- "shiso.hyogo.jp",
- "olsztyn.pl",
- "wolomin.pl",
- "uenohara.yamanashi.jp",
- "is-very-nice.org",
- "yamada.fukuoka.jp",
- "miyako.iwate.jp",
- "xn--jrpeland-54a.no",
- "is-a-financialadvisor.com",
- "umi.fukuoka.jp",
- "ptz.ru",
- "int.lk",
- "utazas.hu",
- "fuchu.toyama.jp",
- "org.ly",
- "edu.mx",
+ "tonosho.kagawa.jp",
+ "org.gn",
+ "xn--mgbqly7cvafr",
+ "xn--ygarden-p1a.no",
+ "tenei.fukushima.jp",
"xn--skierv-uta.no",
- "int.la",
- "com.mx",
- "ikusaka.nagano.jp",
- "yawara.ibaraki.jp",
- "matsue.shimane.jp",
- "prd.mg",
- "tokorozawa.saitama.jp",
- "org.mv",
- "yamamoto.miyagi.jp",
- "net.ky",
- "chikugo.fukuoka.jp",
- "nyc.mn",
- "otaru.hokkaido.jp",
- "prato.it",
- "is-a-bookkeeper.com",
- "lajolla.museum",
- "shisui.chiba.jp",
- "walbrzych.pl",
- "ninohe.iwate.jp",
- "ichinoseki.iwate.jp",
- "emergency.aero",
- "alaska.museum",
- "modelling.aero",
- "xn--sgne-gra.no",
- "consulting.aero",
- "ninomiya.kanagawa.jp",
- "nikko.tochigi.jp",
- "wielun.pl",
- "nic.uk",
- "yuu.yamaguchi.jp",
- "komagane.nagano.jp",
- "isesaki.gunma.jp",
- "gob.mx",
- "chikujo.fukuoka.jp",
- "yaese.okinawa.jp",
- "is-a-chef.org",
- "watari.miyagi.jp",
- "mitake.gifu.jp",
- "xn--b-5ga.telemark.no",
- "matsubara.osaka.jp",
- "kamagaya.chiba.jp",
- "sasaguri.fukuoka.jp",
- "katsuragi.nara.jp",
- "sologne.museum",
- "nosegawa.nara.jp",
- "wajima.ishikawa.jp",
- "kommunalforbund.se",
- "trolley.museum",
- "yachimata.chiba.jp",
- "pomorskie.pl",
- "sosnowiec.pl",
- "matsuzaki.shizuoka.jp",
- "info.az",
- "xn--tnsberg-q1a.no",
- "web.lk",
- "xn--srreisa-q1a.no",
- "samegawa.fukushima.jp",
- "ngo.ph",
- "pasadena.museum",
- "iiyama.nagano.jp",
- "midsund.no",
- "fetsund.no",
- "aurskog-holand.no",
- "sekigahara.gifu.jp",
- "net.ly",
- "jfk.museum",
- "info.tz",
- "alesund.no",
- "ishikawa.jp",
- "zaporizhzhia.ua",
- "net.mv",
- "civilization.museum",
- "yuasa.wakayama.jp",
- "photography.museum",
- "lucerne.museum",
- "farsund.no",
- "org.py",
- "unjarga.no",
- "group.aero",
- "zachpomor.pl",
+ "nsw.edu.au",
+ "takino.hyogo.jp",
+ "okagaki.fukuoka.jp",
+ "aeroclub.aero",
+ "is-a-student.com",
+ "oyamazaki.kyoto.jp",
+ "miyoshi.saitama.jp",
+ "state.museum",
+ "miyakonojo.miyazaki.jp",
+ "stadt.museum",
+ "olkusz.pl",
+ "yamaguchi.jp",
+ "livinghistory.museum",
+ "miyashiro.saitama.jp",
+ "joetsu.niigata.jp",
"mitou.yamaguchi.jp",
- "xn--od0alg.cn",
- "matsubushi.saitama.jp",
- "watchandclock.museum",
- "accident-investigation.aero",
- "xn--ygbi2ammx",
+ "is-a-financialadvisor.com",
+ "aerobatic.aero",
+ "database.museum",
+ "steam.museum",
+ "niigata.niigata.jp",
+ "botanicgarden.museum",
+ "sch.ly",
+ "xn--laheadju-7ya.no",
+ "denmark.museum",
+ "tm.hu",
+ "xn--skjervy-v1a.no",
+ "jamal.ru",
+ "penza.ru",
+ "is-certified.com",
+ "pf",
+ "tm.km",
+ "gliding.aero",
+ "shimonita.gunma.jp",
+ "dyndns-at-home.com",
+ "tv.bo",
+ "tv.na",
+ "usdecorativearts.museum",
+ "tc",
+ "tv.br",
+ "xn--b-5ga.telemark.no",
+ "airline.aero",
+ "yekaterinburg.ru",
+ "xn--unup4y",
+ "taito.tokyo.jp",
+ "agematsu.nagano.jp",
+ "heroy.more-og-romsdal.no",
+ "lorenskog.no",
+ "andria-barletta-trani.it",
+ "togitsu.nagasaki.jp",
+ "caltanissetta.it",
+ "prd.fr",
+ "huissier-justice.fr",
+ "shell.museum",
+ "ballangen.no",
+ "yamanobe.yamagata.jp",
+ "kawaue.gifu.jp",
+ "westfalen.museum",
+ "serveftp.net",
+ "xn--mlselv-iua.no",
+ "space.museum",
+ "xn--frna-woa.no",
+ "vc.it",
+ "yukuhashi.fukuoka.jp",
+ "tokigawa.saitama.jp",
+ "tadotsu.kagawa.jp",
+ "po.it",
+ "pd.it",
+ "pz.it",
+ "shimizu.shizuoka.jp",
+ "dominic.ua",
+ "pr.it",
+ "salvadordali.museum",
+ "ac.ug",
+ "sowa.ibaraki.jp",
"wallonie.museum",
- "wegrow.pl",
- "ind.gt",
- "int.pt",
- "xn--yfro4i67o",
- "ibigawa.gifu.jp",
+ "pu.it",
+ "kobierzyce.pl",
+ "kiyosato.hokkaido.jp",
+ "pn.it",
+ "ddr.museum",
+ "pe.it",
+ "gs.jan-mayen.no",
+ "pt.it",
+ "does-it.net",
+ "taiki.hokkaido.jp",
+ "kawasaki.miyagi.jp",
+ "skole.museum",
+ "salem.museum",
+ "pi.it",
+ "suifu.ibaraki.jp",
+ "net.gt",
+ "taira.toyama.jp",
+ "medical.museum",
+ "shiranuka.hokkaido.jp",
+ "hayashima.okayama.jp",
+ "sanagochi.tokushima.jp",
+ "sodegaura.chiba.jp",
+ "is-a-conservative.com",
+ "tf",
+ "christiansburg.museum",
+ "leangaviika.no",
+ "nf.ca",
+ "lavagis.no",
+ "watch-and-clock.museum",
+ "royrvik.no",
"xn--vre-eiker-k8a.no",
- "namegawa.saitama.jp",
- "parti.se",
- "endoftheinternet.org",
- "int.rw",
- "xn--aroport-bya.ci",
- "xn--ystre-slidre-ujb.no",
- "niiza.saitama.jp",
- "chikuho.fukuoka.jp",
- "webhop.info",
- "nanbu.tottori.jp",
- "xn--ygarden-p1a.no",
- "sukagawa.fukushima.jp",
- "xn--osyro-wua.no",
- "press.ma",
- "georgia.museum",
- "uonuma.niigata.jp",
- "press.museum",
- "tanagura.fukushima.jp",
- "int.mw",
- "yokoshibahikari.chiba.jp",
+ "pa.it",
+ "plc.co.im",
+ "kawagoe.mie.jp",
+ "issmarterthanyou.com",
+ "omotego.fukushima.jp",
+ "pv.it",
+ "takatsuki.shiga.jp",
+ "podlasie.pl",
"pesaro-urbino.it",
- "mitsue.nara.jp",
- "naval.museum",
- "nahari.kochi.jp",
- "xn--avery-yua.no",
- "xn--od0alg.hk",
- "katsushika.tokyo.jp",
- "otsuki.kochi.jp",
- "jewelry.museum",
- "nrw.museum",
- "takarazuka.hyogo.jp",
- "matsuura.nagasaki.jp",
- "romskog.no",
- "ino.kochi.jp",
- "panama.museum",
- "web.pk",
- "um.gov.pl",
- "namegata.ibaraki.jp",
- "isa-hockeynut.com",
- "xn--eveni-0qa01ga.no",
- "marugame.kagawa.jp",
- "is-saved.org",
- "experts-comptables.fr",
- "paderborn.museum",
- "net.py",
- "net.gy",
- "komvux.se",
- "zakopane.pl",
- "torsken.no",
- "isa-geek.net",
- "matsukawa.nagano.jp",
- "eidskog.no",
- "ontario.museum",
- "fujikawaguchiko.yamanashi.jp",
- "makurazaki.kagoshima.jp",
- "isa.kagoshima.jp",
- "isa-geek.org",
- "ascolipiceno.it",
- "xn--hobl-ira.no",
- "notogawa.shiga.jp",
- "kasugai.aichi.jp",
- "fuchu.tokyo.jp",
- "mutsu.aomori.jp",
- "matsumoto.nagano.jp",
- "nanyo.yamagata.jp",
- "umaji.kochi.jp",
- "nakagawa.tokushima.jp",
- "konskowola.pl",
- "kursk.ru",
- "ivanovo.ru",
- "presidio.museum",
- "ishikari.hokkaido.jp",
- "yachiyo.ibaraki.jp",
- "tomsk.ru",
- "nakagawa.nagano.jp",
- "westfalen.museum",
- "gotsu.shimane.jp",
- "uto.kumamoto.jp",
- "wajiki.tokushima.jp",
- "neyagawa.osaka.jp",
- "yamagata.jp",
- "pesarourbino.it",
- "xn--nvuotna-hwa.no",
- "matsushige.tokushima.jp",
- "production.aero",
- "ing.pa",
- "polkowice.pl",
- "xn--90a3ac",
- "nakagawa.hokkaido.jp",
- "uw.gov.pl",
- "ube.yamaguchi.jp",
- "wazuka.kyoto.jp",
- "wodzislaw.pl",
- "yasuda.kochi.jp",
- "xn--vler-qoa.xn--stfold-9xa.no",
- "mitsuke.niigata.jp",
- "niyodogawa.kochi.jp",
- "pharmacy.museum",
- "waw.pl",
- "zaporizhzhe.ua",
- "xn--yer-zna.no",
- "ascoli-piceno.it",
- "yasaka.nagano.jp",
+ "miyagi.jp",
+ "nayoro.hokkaido.jp",
+ "is-a-lawyer.com",
+ "airport.aero",
+ "air-surveillance.aero",
+ "to.it",
+ "ts.it",
+ "tgory.pl",
+ "tr.it",
+ "delaware.museum",
+ "xn--xkc2dl3a5ee0h",
+ "taka.hyogo.jp",
+ "xn--sknland-fxa.no",
+ "tw.cn",
+ "carboniaiglesias.it",
+ "supply",
+ "tn.it",
+ "takashima.shiga.jp",
+ "te.it",
+ "shinanomachi.nagano.jp",
+ "lib.gu.us",
+ "boleslawiec.pl",
+ "kawara.fukuoka.jp",
+ "pro.vn",
+ "takahata.yamagata.jp",
+ "kawakita.ishikawa.jp",
+ "kawanishi.hyogo.jp",
+ "dyndns-web.com",
+ "oguni.yamagata.jp",
+ "kashiwa.chiba.jp",
+ "shimizu.hokkaido.jp",
+ "shakotan.hokkaido.jp",
+ "achi.nagano.jp",
+ "xn--hbmer-xqa.no",
+ "tt.im",
+ "takko.aomori.jp",
+ "org.st",
+ "serveftp.org",
+ "is-a-geek.net",
+ "pordenone.it",
+ "xn--xkc2al3hye2a",
+ "miyoshi.hiroshima.jp",
+ "shijonawate.osaka.jp",
+ "otsuchi.iwate.jp",
+ "yoshinogari.saga.jp",
+ "ta.it",
+ "is-a-geek.com",
+ "news.hu",
+ "org.tt",
+ "accident-prevention.aero",
+ "tp.it",
+ "yazu.tottori.jp",
+ "time.no",
+ "artcenter.museum",
+ "tv.it",
+ "is-a-nurse.com",
+ "org.bt",
+ "detroit.museum",
+ "okazaki.aichi.jp",
+ "masaki.ehime.jp",
+ "moka.tochigi.jp",
+ "tinn.no",
+ "xn--sr-varanger-ggb.no",
+ "poznan.pl",
+ "katowice.pl",
+ "kawagoe.saitama.jp",
+ "youth.museum",
+ "dyndns-at-work.com",
+ "z-2.compute-1.amazonaws.com",
+ "ichinomiya.aichi.jp",
+ "whaling.museum",
+ "org.mt",
"xn--holtlen-hxa.no",
- "xn--fl-zia.no",
- "yonago.tottori.jp",
- "naturhistorisches.museum",
- "pp.ru",
- "in-the-band.net",
- "xn--fiqs8s",
- "slask.pl",
- "xn--hpmir-xqa.no",
- "pomorze.pl",
- "szczytno.pl",
- "wanouchi.gifu.jp",
- "inf.mk",
- "matsumoto.kagoshima.jp",
- "historyofscience.museum",
- "yosemite.museum",
+ "palace.museum",
+ "newmexico.museum",
+ "tv.im",
+ "tana.no",
+ "indiana.museum",
+ "xn--node",
+ "dyndns-wiki.com",
+ "kvanangen.no",
+ "delmenhorst.museum",
+ "tyumen.ru",
+ "sc.tz",
+ "org.pt",
+ "sc.us",
+ "net.cn",
+ "piacenza.it",
+ "kyotanabe.kyoto.jp",
+ "miyoshi.tokushima.jp",
+ "porsangu.no",
+ "yawata.kyoto.jp",
+ "dynathome.net",
+ "shirakawa.gifu.jp",
+ "echizen.fukui.jp",
+ "org.ht",
+ "sc.cn",
+ "voyage",
+ "oamishirasato.chiba.jp",
+ "xn--rhkkervju-01af.no",
+ "daisen.akita.jp",
+ "sc.kr",
+ "is-very-good.org",
+ "tx.us",
+ "toba.mie.jp",
+ "dyndns-work.com",
+ "xn--bidr-5nac.no",
+ "urayasu.chiba.jp",
+ "pharmacy.museum",
+ "xn--bhcavuotna-s4a.no",
+ "sf.no",
+ "linz.museum",
+ "tanagura.fukushima.jp",
+ "sor-fron.no",
+ "loten.no",
"minamiechizen.fukui.jp",
- "uki.kumamoto.jp",
- "lutsk.ua",
- "yamaga.kumamoto.jp",
- "matsuno.ehime.jp",
- "prd.km",
- "xn--fiqz9s",
- "monzaedellabrianza.it",
- "xn--hery-ira.nordland.no",
- "shizuoka.jp",
- "pisz.pl",
- "satsumasendai.kagoshima.jp",
- "matsushima.miyagi.jp",
- "yahiko.niigata.jp",
- "ug.gov.pl",
- "yasugi.shimane.jp",
- "itako.ibaraki.jp",
- "xn--3e0b707e",
- "s3-eu-west-1.amazonaws.com",
- "ishikawa.okinawa.jp",
- "iizuka.fukuoka.jp",
- "ikaruga.nara.jp",
- "insurance.aero",
- "yukuhashi.fukuoka.jp",
- "matsuyama.ehime.jp",
- "itakura.gunma.jp",
- "katsuragi.wakayama.jp",
- "yamal.ru",
- "vanylven.no",
- "yabuki.fukushima.jp",
- "nanbu.yamanashi.jp",
- "xn--h-2fa.no",
- "int.mv",
- "yatomi.aichi.jp",
- "wroclaw.pl",
- "xn--flor-jra.no",
- "wlocl.pl",
- "xn--mgb2ddes",
- "xn--frna-woa.no",
+ "skierva.no",
+ "trolley.museum",
+ "yawara.ibaraki.jp",
+ "thruhere.net",
+ "lecco.it",
+ "nowaruda.pl",
+ "uscountryestate.museum",
+ "ne.pw",
+ "rc.it",
+ "bryne.no",
+ "miyama.fukuoka.jp",
+ "lecce.it",
+ "luroy.no",
+ "ogawa.nagano.jp",
+ "taiji.wakayama.jp",
+ "takamatsu.kagawa.jp",
+ "shikatsu.aichi.jp",
+ "xn--ldingen-q1a.no",
+ "tado.mie.jp",
+ "phoenix.museum",
+ "decorativearts.museum",
+ "hitachi.ibaraki.jp",
+ "kawanishi.yamagata.jp",
+ "tono.iwate.jp",
+ "tendo.yamagata.jp",
+ "xn--c1avg",
+ "skjervoy.no",
+ "lucca.it",
+ "ichinohe.iwate.jp",
+ "exchange.aero",
+ "miyako.fukuoka.jp",
+ "parliament.uk",
+ "naturalsciences.museum",
+ "shibata.niigata.jp",
+ "shibetsu.hokkaido.jp",
+ "properties",
+ "tomigusuku.okinawa.jp",
+ "trustee.museum",
+ "pol.dz",
+ "co.ve",
+ "dontexist.net",
+ "theater.museum",
+ "kawai.nara.jp",
+ "dontexist.com",
+ "nasu.tochigi.jp",
+ "kawamata.fukushima.jp",
+ "co.vi",
+ "hu.net",
+ "js.cn",
+ "xn--h1aegh.museum",
+ "jl.cn",
+ "zgorzelec.pl",
+ "pharmaciens.km",
+ "pro.az",
+ "xn--sandnessjen-ogb.no",
+ "niepce.museum",
+ "gb.net",
+ "tranibarlettaandria.it",
+ "xn--tn0ag.hk",
+ "potenza.it",
+ "otago.museum",
+ "tempioolbia.it",
+ "sakai.ibaraki.jp",
+ "traniandriabarletta.it",
+ "xn--andy-ira.no",
+ "sekigahara.gifu.jp",
+ "nikko.tochigi.jp",
+ "iglesiascarbonia.it",
+ "szczytno.pl",
+ "arkhangelsk.ru",
+ "endofinternet.org",
+ "xn--mgbc0a9azcg",
+ "miyawaka.fukuoka.jp",
+ "xn--unjrga-rta.no",
+ "is-a-hunter.com",
+ "is-an-engineer.com",
+ "shimotsuma.ibaraki.jp",
+ "sayama.osaka.jp",
+ "paroch.k12.ma.us",
+ "tobe.ehime.jp",
+ "za.net",
+ "tsukuba.ibaraki.jp",
+ "from-nd.com",
+ "toon.ehime.jp",
+ "is-a-chef.org",
+ "otoyo.kochi.jp",
+ "trainer.aero",
+ "lubin.pl",
+ "xn--porsgu-sta26f.no",
+ "diamonds",
+ "org.sv",
+ "kihoku.ehime.jp",
"org.lv",
- "yamaguchi.jp",
- "nationalfirearms.museum",
- "per.la",
- "chippubetsu.hokkaido.jp",
- "xn--od0aq3b.hk",
- "s3.amazonaws.com",
- "xn--fjord-lra.no",
- "kisarazu.chiba.jp",
- "palermo.it",
+ "sayama.saitama.jp",
+ "ichinoseki.iwate.jp",
+ "tamaki.mie.jp",
+ "oharu.aichi.jp",
+ "oarai.ibaraki.jp",
"tatsuno.hyogo.jp",
- "nakagusuku.okinawa.jp",
- "ushiku.ibaraki.jp",
- "watarai.mie.jp",
- "xn--hcesuolo-7ya35b.no",
- "cc.sd.us",
- "yamagata.nagano.jp",
- "war.museum",
- "national-library-scotland.uk",
- "po.gov.pl",
- "uchihara.ibaraki.jp",
- "newyork.museum",
- "otoyo.kochi.jp",
- "portland.museum",
- "xn--rland-uua.no",
- "okazaki.aichi.jp",
- "xn--frya-hra.no",
- "pa.gov.pl",
- "xn--mely-ira.no",
- "pharmacien.fr",
- "xn--finny-yua.no",
- "xn--rady-ira.no",
- "ulvik.no",
- "yamagata.ibaraki.jp",
- "net.lv",
- "xn--rdal-poa.no",
- "xn--risr-ira.no",
- "yonaguni.okinawa.jp",
- "kouzushima.tokyo.jp",
- "is-not-certified.com",
- "ishigaki.okinawa.jp",
- "tatsuno.nagano.jp",
- "is-a-chef.com",
+ "tabuse.yamaguchi.jp",
+ "org.mv",
+ "doomdns.org",
+ "uk.net",
+ "xn--ostery-fya.no",
+ "is-a-celticsfan.org",
+ "gs.sf.no",
+ "gs.of.no",
"xn--hnefoss-q1a.no",
- "shizuoka.shizuoka.jp",
- "yamada.iwate.jp",
- "pvt.ge",
- "xn--stre-toten-zcb.no",
- "futsu.nagasaki.jp",
- "xn--mk0axi.hk",
- "xn--merker-kua.no",
- "accident-prevention.aero",
- "kihoku.ehime.jp",
- "itoigawa.niigata.jp",
- "xn--risa-5na.no",
- "pro.pr",
- "ide.kyoto.jp",
- "prochowice.pl",
- "plo.ps",
- "yamakita.kanagawa.jp",
- "masaki.ehime.jp",
- "naoshima.kagawa.jp",
- "xn--rennesy-v1a.no",
- "ulm.museum",
- "penza.ru",
- "ine.kyoto.jp",
- "xn--mgbaam7a8h",
- "usa.museum",
- "xn--muost-0qa.no",
+ "ap-northeast-1.compute.amazonaws.com",
+ "omaha.museum",
+ "stuff-4-sale.us",
+ "nogi.tochigi.jp",
+ "pomorze.pl",
+ "xn--mgberp4a5d4a87g",
+ "misconfused.org",
+ "xn--kranghke-b0a.no",
+ "tm.mg",
+ "schlesisches.museum",
+ "at-band-camp.net",
+ "lib.ny.us",
+ "xn--bhccavuotna-k7a.no",
+ "xn--krdsherad-m8a.no",
+ "satx.museum",
+ "artsandcrafts.museum",
+ "adygeya.ru",
+ "sosnowiec.pl",
+ "kimitsu.chiba.jp",
+ "izumizaki.fukushima.jp",
+ "textile.museum",
+ "eu.int",
+ "yaita.tochigi.jp",
+ "sells-for-less.com",
+ "servegame.org",
+ "xn--stjrdal-s1a.no",
+ "jgora.pl",
+ "jpn.com",
+ "tomi.nagano.jp",
+ "england.museum",
+ "finland.museum",
+ "s3.amazonaws.com",
+ "myphotos.cc",
+ "sano.tochigi.jp",
+ "tsukiyono.gunma.jp",
"mutsuzawa.chiba.jp",
- "porsanger.no",
- "xn--mjndalen-64a.no",
- "naturalsciences.museum",
- "xn--drbak-wua.no",
- "iwanuma.miyagi.jp",
- "xn--indery-fya.no",
- "xn--dnna-gra.no",
+ "xn--hgebostad-g3a.no",
+ "luxury",
+ "from-tx.com",
+ "pg.it",
+ "schoenbrunn.museum",
+ "xn--oppegrd-ixa.no",
+ "olbiatempio.it",
+ "lib.ky.us",
+ "tsuwano.shimane.jp",
+ "from-tn.com",
+ "eu-west-1.compute.amazonaws.com",
+ "nakatsugawa.gifu.jp",
+ "xn--vler-qoa.xn--stfold-9xa.no",
+ "taiwa.miyagi.jp",
+ "tsuruga.fukui.jp",
+ "xn--rlingen-mxa.no",
+ "xn--lten-gra.no",
+ "design.aero",
+ "schokoladen.museum",
+ "lutsk.ua",
+ "us-west-2.compute.amazonaws.com",
+ "dagestan.ru",
+ "chippubetsu.hokkaido.jp",
+ "lesja.no",
+ "us-west-1.compute.amazonaws.com",
+ "computer",
+ "kawai.iwate.jp",
+ "sciencecenter.museum",
+ "ln.cn",
+ "sciencecenters.museum",
+ "ap-southeast-2.compute.amazonaws.com",
+ "of.no",
+ "journal.aero",
+ "jorpeland.no",
+ "ap-southeast-1.compute.amazonaws.com",
+ "juedisches.museum",
+ "guovdageaidnu.no",
+ "la.us",
+ "szex.hu",
+ "kiyokawa.kanagawa.jp",
+ "science.museum",
+ "jx.cn",
+ "donostia.museum",
+ "davvesiida.no",
+ "lt.ua",
+ "yachiyo.ibaraki.jp",
+ "lib.wy.us",
+ "hembygdsforbund.museum",
+ "cc.sd.us",
+ "cc.az.us",
+ "k12.ct.us",
+ "cc.as.us",
+ "cc.ar.us",
+ "org.gt",
+ "cc.or.us",
+ "cc.mo.us",
+ "cc.md.us",
+ "cc.al.us",
+ "cc.ms.us",
+ "project.museum",
+ "samnanger.no",
+ "cc.nd.us",
+ "okawa.kochi.jp",
+ "neyagawa.osaka.jp",
+ "cc.tn.us",
+ "tosashimizu.kochi.jp",
+ "lakas.hu",
+ "shirako.chiba.jp",
+ "judaica.museum",
+ "cc.gu.us",
+ "cc.mn.us",
+ "cc.co.us",
+ "cc.de.us",
+ "cc.ut.us",
+ "cc.me.us",
+ "ichikai.tochigi.jp",
+ "dazaifu.fukuoka.jp",
+ "cc.ne.us",
+ "cc.mt.us",
+ "tokoname.aichi.jp",
+ "cc.fl.us",
+ "xn--stjrdalshalsen-sqb.no",
+ "um.gov.pl",
+ "atlanta.museum",
+ "lv.ua",
+ "oyama.tochigi.jp",
+ "cc.mi.us",
+ "cc.ri.us",
+ "cc.ct.us",
+ "lc",
+ "design.museum",
+ "cc.ks.us",
+ "is-a-techie.com",
+ "www.ck",
+ "of.by",
+ "computer.museum",
+ "cc.ny.us",
+ "lukow.pl",
+ "cc.nj.us",
+ "cc.nm.us",
+ "jerusalem.museum",
+ "tachiarai.fukuoka.jp",
+ "cc.la.us",
+ "lomza.pl",
+ "cc.ma.us",
+ "coop.tt",
+ "schweiz.museum",
+ "cc.ga.us",
+ "sc.ug",
+ "barrel-of-knowledge.info",
+ "sande.more-og-romsdal.no",
+ "anpachi.gifu.jp",
+ "cc.ky.us",
+ "cc.nv.us",
+ "cc.ca.us",
+ "isumi.chiba.jp",
+ "pharmacien.fr",
+ "go.dyndns.org",
+ "cc.oh.us",
+ "cc.hi.us",
+ "cc.nh.us",
+ "shibata.miyagi.jp",
+ "is-into-anime.com",
+ "fukuchi.fukuoka.jp",
+ "taki.mie.jp",
+ "inzai.chiba.jp",
+ "cc.ak.us",
+ "cc.ok.us",
+ "depot.museum",
+ "dolls.museum",
+ "wa.gov.au",
+ "spydeberg.no",
+ "iwafune.tochigi.jp",
"taishin.fukushima.jp",
- "matsuda.kanagawa.jp",
- "noboribetsu.hokkaido.jp",
- "yamagata.gifu.jp",
- "katsuura.chiba.jp",
- "yakage.okayama.jp",
- "pharmaciens.km",
- "is-a-chef.net",
- "plaza.museum",
- "xn--msy-ula0h.no",
- "pvt.k12.ma.us",
- "xn--hylandet-54a.no",
- "scrapping.cc",
- "xn--uc0atv.hk",
- "xn--rskog-uua.no",
- "urayasu.chiba.jp",
- "kaszuby.pl",
- "xn--rholt-mra.no",
- "xn--uc0atv.tw",
- "xn--mlatvuopmi-s4a.no",
- "xn--mgba3a4fra",
- "kaizuka.osaka.jp",
- "xn--mgba3a4f16a",
- "irc.pl",
- "xn--rst-0na.no",
- "watch-and-clock.museum",
- "xn--rde-ula.no",
- "xn--mgba3a4fra.ir",
- "xn--mgba3a4f16a.ir",
+ "lo.it",
+ "lib.co.us",
+ "ohira.tochigi.jp",
+ "student.aero",
+ "pro.tt",
+ "lu.it",
+ "s3-us-west-1.amazonaws.com",
+ "s3-us-west-2.amazonaws.com",
+ "asahi.chiba.jp",
+ "le.it",
+ "takanabe.miyazaki.jp",
+ "lt.it",
+ "lib.ca.us",
+ "iwakuni.yamaguchi.jp",
+ "s3-eu-west-1.amazonaws.com",
+ "org.cn",
+ "ltd.co.im",
+ "li.it",
+ "abiko.chiba.jp",
+ "london",
+ "seaport.museum",
+ "jogasz.hu",
+ "kiwa.mie.jp",
+ "lund.no",
+ "priv.pl",
+ "uw.gov.pl",
+ "tsuchiura.ibaraki.jp",
+ "starachowice.pl",
+ "lier.no",
+ "music.museum",
+ "from-va.com",
+ "lib.fl.us",
+ "pro.ht",
+ "cc.id.us",
+ "lebtimnetz.de",
+ "cc.il.us",
+ "tobishima.aichi.jp",
+ "shirataka.yamagata.jp",
+ "or.pw",
+ "cc.in.us",
+ "cc.wi.us",
+ "travel",
+ "architecture.museum",
+ "trogstad.no",
+ "kuwana.mie.jp",
+ "teaches-yoga.com",
+ "cc.wy.us",
+ "computerhistory.museum",
+ "lyngen.no",
+ "pol.ht",
"ostrowiec.pl",
- "xn--rros-gra.no",
- "xn--h2brj9c",
- "chizu.tottori.jp",
- "org.mx",
- "urasoe.okinawa.jp",
- "xn--mgb9awbf",
- "xn--mot-tla.no",
- "yamagata.yamagata.jp",
- "uscountryestate.museum",
- "uji.kyoto.jp",
- "xn--mgbayh7gpa",
- "portlligat.museum",
- "inashiki.ibaraki.jp",
- "oharu.aichi.jp",
- "maizuru.kyoto.jp",
- "isa-geek.com",
- "xn--nttery-byae.no",
- "xn--dyry-ira.no",
- "nyc.museum",
- "ichihara.chiba.jp",
- "xn--rlingen-mxa.no",
- "matsumae.hokkaido.jp",
- "pro.mv",
- "iamallama.com",
- "net.mx",
- "xn--kprw13d",
- "xn--kpry57d",
- "nagakute.aichi.jp",
- "s3-ap-northeast-1.amazonaws.com",
- "pubol.museum",
- "usculture.museum",
- "perugia.it",
- "xn--unjrga-rta.no",
- "xn--davvenjrga-y4a.no",
- "shizukuishi.iwate.jp",
- "s3-ap-southeast-1.amazonaws.com",
+ "jamison.museum",
+ "daigo.ibaraki.jp",
+ "tynset.no",
+ "cc.wa.us",
+ "travel.pl",
+ "tatsuno.nagano.jp",
+ "joboji.iwate.jp",
+ "travel.tt",
+ "test.tj",
+ "livorno.it",
+ "cc.wv.us",
+ "xn--ryken-vua.no",
+ "cc.ia.us",
+ "lindesnes.no",
+ "priv.me",
+ "shunan.yamaguchi.jp",
+ "lib.tn.us",
+ "treviso.it",
"press.aero",
"press.se",
- "wildlife.museum",
- "xn--hery-ira.xn--mre-og-romsdal-qqb.no",
- "xn--krehamn-dxa.no",
- "xn--hyanger-q1a.no",
- "xn--lury-ira.no",
- "xn--mli-tla.no",
- "posts-and-telecommunications.museum",
- "perso.tn",
- "iwakura.aichi.jp",
- "pippu.hokkaido.jp",
- "nakagyo.kyoto.jp",
- "xn--p1ai",
- "xn--klbu-woa.no",
- "xn--hbmer-xqa.no",
- "wloclawek.pl",
- "xn--linds-pra.no",
- "nakagawa.fukuoka.jp",
+ "scrapping.cc",
+ "leirfjord.no",
+ "tysvar.no",
+ "lib.in.us",
+ "harvestcelebration.museum",
+ "lib.mn.us",
+ "laquila.it",
+ "taranto.it",
+ "tsunan.niigata.jp",
+ "lahppi.no",
+ "bruxelles.museum",
+ "london.museum",
+ "xn--avery-yua.no",
+ "xn--ryrvik-bya.no",
+ "obanazawa.yamagata.jp",
+ "leitungsen.de",
+ "lincoln.museum",
+ "pilot.aero",
+ "parti.se",
+ "larsson.museum",
+ "cc.tx.us",
+ "press.museum",
+ "dc.us",
+ "luzern.museum",
+ "pubol.museum",
+ "ac.pr",
+ "towada.aomori.jp",
+ "oceanographic.museum",
+ "laakesvuemie.no",
+ "z-1.compute-1.amazonaws.com",
+ "monzaedellabrianza.it",
+ "for-more.biz",
+ "stuff-4-sale.org",
+ "tsaritsyn.ru",
+ "trieste.it",
+ "for-some.biz",
+ "xn--3e0b707e",
+ "priv.at",
+ "torahime.shiga.jp",
+ "from-vt.com",
+ "turystyka.pl",
+ "ac.pa",
+ "se.net",
+ "planetarium.museum",
+ "miyama.mie.jp",
+ "homeftp.org",
+ "omigawa.chiba.jp",
+ "xn--fiq64b",
+ "museumvereniging.museum",
+ "s3-ap-northeast-1.amazonaws.com",
+ "paleo.museum",
+ "trust.museum",
+ "toga.toyama.jp",
+ "xn--kvnangen-k0a.no",
+ "office-on-the.net",
+ "lancashire.museum",
+ "ogaki.gifu.jp",
+ "tsuno.kochi.jp",
+ "praxi",
+ "vaapste.no",
+ "pro.mv",
"s3-ap-southeast-2.amazonaws.com",
- "xn--lesund-hua.no",
- "perso.sn",
- "xn--kfjord-iua.no",
- "xn--fpcrj9c3d",
- "perso.ht",
- "xn--krdsherad-m8a.no",
- "xn--clchc0ea0b2g2a9gcd",
- "xn--oppegrd-ixa.no",
- "xn--pgbs0dh",
- "ishikawa.fukushima.jp",
- "xn--hgebostad-g3a.no",
- "utashinai.hokkaido.jp",
- "xn--lrenskog-54a.no",
- "xn--lrdal-sra.no",
- "xn--54b7fta0cc",
- "pc.pl",
- "appspot.com",
- "iwafune.tochigi.jp",
- "yatsushiro.kumamoto.jp",
- "yotsukaido.chiba.jp",
- "xn--lten-gra.no",
+ "s3-ap-southeast-1.amazonaws.com",
+ "tochigi.tochigi.jp",
+ "tama.tokyo.jp",
+ "ogawa.ibaraki.jp",
+ "kawanabe.kagoshima.jp",
+ "xn--fiq228c5hs",
+ "touch.museum",
+ "discovery.museum",
+ "s3-us-gov-west-1.amazonaws.com",
+ "leka.no",
+ "newyork.museum",
+ "trysil.no",
+ "lajolla.museum",
+ "isa-hockeynut.com",
+ "tsuruta.aomori.jp",
+ "sayo.hyogo.jp",
+ "poltava.ua",
+ "podzone.org",
+ "lg.ua",
+ "lib.az.us",
+ "sa-east-1.compute.amazonaws.com",
+ "xn--btsfjord-9za.no",
+ "newspaper.museum",
+ "ug.gov.pl",
+ "likes-pie.com",
+ "paris.museum",
+ "takinoue.hokkaido.jp",
+ "lillehammer.no",
+ "bellevue.museum",
+ "nrw.museum",
+ "tambov.ru",
+ "texas.museum",
+ "is-a-republican.com",
+ "miyako.iwate.jp",
+ "tawaramoto.nara.jp",
+ "forli-cesena.it",
+ "philately.museum",
+ "s3-website-us-east-1.amazonaws.com",
+ "tarui.gifu.jp",
+ "s3-website-sa-east-1.amazonaws.com",
+ "xn--cg4bki",
+ "sologne.museum",
+ "game-server.cc",
+ "doesntexist.org",
+ "xn--kvfjord-nxa.no",
+ "town.museum",
+ "parachuting.aero",
+ "gs.va.no",
+ "tokuyama.yamaguchi.jp",
+ "newhampshire.museum",
+ "florence.it",
+ "tsubetsu.hokkaido.jp",
+ "from-nc.com",
+ "tokamachi.niigata.jp",
+ "miyoshi.aichi.jp",
+ "xn--ogbpf8fl",
+ "xn--mgbqly7c0a67fbc",
+ "historyofscience.museum",
+ "oryol.ru",
+ "so.gov.pl",
+ "toyama.jp",
+ "sr.gov.pl",
+ "dyndns-server.com",
+ "is-a-chef.net",
+ "tm.mc",
+ "xn--czr694b",
+ "nationalheritage.museum",
+ "xn--czrs0t",
+ "bievat.no",
+ "is-a-chef.com",
+ "xn--mgbtf8fl",
+ "pippu.hokkaido.jp",
+ "elasticbeanstalk.com",
+ "s3-website-ap-southeast-2.amazonaws.com",
+ "xn--comunicaes-v6a2o.museum",
+ "oi.kanagawa.jp",
+ "toyama.toyama.jp",
+ "takanezawa.tochigi.jp",
+ "s3-website-ap-southeast-1.amazonaws.com",
+ "sa.gov.au",
+ "xn--czru2d",
+ "s3-website-ap-northeast-1.amazonaws.com",
+ "toyooka.hyogo.jp",
+ "toyone.aichi.jp",
+ "doomdns.com",
+ "toyo.kochi.jp",
+ "tsuga.tochigi.jp",
+ "s3-website-us-west-2.amazonaws.com",
+ "shinonsen.hyogo.jp",
+ "xn--moreke-jua.no",
+ "tokai.aichi.jp",
+ "toyota.aichi.jp",
+ "s3-website-us-west-1.amazonaws.com",
+ "is-very-sweet.org",
+ "xn--hyanger-q1a.no",
+ "kawachinagano.osaka.jp",
+ "toyono.osaka.jp",
+ "nishitosa.kochi.jp",
+ "tokai.ibaraki.jp",
+ "pc.it",
+ "xn--nvuotna-hwa.no",
+ "sande.vestfold.no",
+ "jobs.tt",
+ "xn--kvitsy-fya.no",
+ "royken.no",
+ "tm.pl",
+ "xn--eveni-0qa01ga.no",
+ "nishinoomote.kagoshima.jp",
+ "kommunalforbund.se",
+ "xn--nmesjevuemie-tcba.no",
+ "priv.hu",
+ "suwa.nagano.jp",
+ "toyako.hokkaido.jp",
+ "toyonaka.osaka.jp",
+ "toyokawa.aichi.jp",
+ "egyptian.museum",
+ "yokoshibahikari.chiba.jp",
+ "toyotomi.hokkaido.jp",
+ "lg.jp",
+ "plaza.museum",
+ "shimonoseki.yamaguchi.jp",
+ "principe.st",
+ "kongsvinger.no",
+ "toyoura.hokkaido.jp",
+ "newjersey.museum",
+ "prochowice.pl",
+ "tsubata.ishikawa.jp",
+ "lenvik.no",
+ "society.museum",
"is-a-cubicle-slave.com",
- "xn--karmy-yua.no",
- "xn--gls-elac.no",
- "ichikawa.hyogo.jp",
- "xn--l-1fa.no",
- "xn--krager-gya.no",
- "xn--koluokta-7ya57h.no",
- "xn--ostery-fya.no",
- "xn--mgbbh1a71e",
- "xn--uc0ay4a.hk",
- "xn--langevg-jxa.no",
- "hatsukaichi.hiroshima.jp",
- "katsuyama.fukui.jp",
- "ichikawamisato.yamanashi.jp",
- "xn--h1aegh.museum",
- "xn--gmqw5a.hk",
- "nisshin.aichi.jp",
- "xn--rdy-0nab.no",
- "xn--lhppi-xqa.no",
- "natuurwetenschappen.museum",
- "xn--givuotna-8ya.no",
- "xn--gjvik-wua.no",
- "yanagawa.fukuoka.jp",
- "xn--leagaviika-52b.no",
- "xn--krjohka-hwab49j.no",
+ "dreamhosters.com",
+ "xn--gecrj9c",
+ "larvik.no",
+ "lib.ut.us",
+ "law.pro",
+ "dnepropetrovsk.ua",
+ "loabat.no",
+ "niyodogawa.kochi.jp",
+ "lib.mt.us",
+ "uchiko.ehime.jp",
+ "porsanger.no",
+ "lib.vt.us",
+ "louvre.museum",
+ "toya.hokkaido.jp",
+ "dnipropetrovsk.ua",
+ "tempio-olbia.it",
+ "vossevangen.no",
+ "ac.vn",
+ "xn--sndre-land-0cb.no",
+ "yanaizu.fukushima.jp",
+ "tcm.museum",
+ "trapani.it",
"xn--frde-gra.no",
- "xn--rsta-fra.no",
- "xn--gildeskl-g0a.no",
- "xn--mgbc0a9azcg",
- "xn--lcvr32d.hk",
- "xn--mgberp4a5d4ar",
- "la-spezia.it",
- "xn--mlselv-iua.no",
- "xn--moreke-jua.no",
- "paragliding.aero",
- "podzone.net",
+ "kawaguchi.saitama.jp",
+ "skiptvet.no",
+ "trading.aero",
+ "xn--tnsberg-q1a.no",
+ "sakae.chiba.jp",
+ "loppa.no",
+ "spy.museum",
+ "labor.museum",
+ "dyndns-blog.com",
+ "is-a-nascarfan.com",
+ "saskatchewan.museum",
+ "yawatahama.ehime.jp",
+ "joyo.kyoto.jp",
+ "lviv.ua",
+ "dyndns-free.com",
+ "xn--czrw28b.tw",
+ "otaki.chiba.jp",
+ "dyndns-office.com",
+ "ruovat.no",
+ "xn--lt-liac.no",
+ "jewish.museum",
"yachiyo.chiba.jp",
- "xn--ldingen-q1a.no",
- "xn--mgbqly7cvafr",
- "xn--lns-qla.museum",
- "yatsuka.shimane.jp",
- "iwakuni.yamaguchi.jp",
- "xn--rmskog-bya.no",
- "xn--rhkkervju-01af.no",
- "xn--gmq050i.hk",
- "xn--ggaviika-8ya47h.no",
- "plc.ly",
- "inazawa.aichi.jp",
- "ichikawa.chiba.jp",
- "xn--fzc2c9e2c",
+ "lib.nv.us",
+ "jewishart.museum",
+ "langevag.no",
+ "jan-mayen.no",
+ "homeftp.net",
+ "directory",
+ "loyalist.museum",
+ "natuurwetenschappen.museum",
+ "is-a-teacher.com",
+ "s3-website-us-gov-west-1.amazonaws.com",
+ "is-not-certified.com",
+ "cc.sc.us",
+ "science-fiction.museum",
+ "cc.dc.us",
+ "cc.nc.us",
+ "is-into-cars.com",
+ "is-into-cartoons.com",
+ "podzone.net",
+ "ofunato.iwate.jp",
+ "doesntexist.com",
+ "is-a-therapist.com",
+ "nationalfirearms.museum",
+ "toyosato.shiga.jp",
+ "cc.pr.us",
+ "lc.it",
+ "national-library-scotland.uk",
+ "cc.pa.us",
+ "is-with-theband.com",
+ "davvenjarga.no",
+ "priv.no",
+ "convent.museum",
+ "xn--indery-fya.no",
+ "po.gov.pl",
+ "pa.gov.pl",
+ "compute.amazonaws.com",
+ "compute-1.amazonaws.com",
+ "experts-comptables.fr",
+ "leasing.aero",
+ "xn--54b7fta0cc",
+ "is-very-nice.org",
+ "xn--fpcrj9c3d",
+ "jfk.museum",
+ "leikanger.no",
+ "lucerne.museum",
+ "jp.net",
"xn--mtta-vrjjat-k7af.no",
+ "gs.vf.no",
+ "laspezia.it",
+ "is-into-games.com",
+ "resistance.museum",
+ "pc.pl",
+ "scientist.aero",
+ "s3-website-eu-west-1.amazonaws.com",
+ "xn--hmmrfeasta-s4ac.no",
+ "newport.museum",
+ "stavanger.no",
+ "toyoake.aichi.jp",
+ "jewelry.museum",
+ "cc.vt.us",
+ "cc.vi.us",
+ "toyota.yamaguchi.jp",
+ "cc.va.us",
+ "hoylandet.no",
+ "corvette.museum",
+ "toyohashi.aichi.jp",
+ "lib.ct.us",
+ "air-traffic-control.aero",
+ "us-gov-west-1.compute.amazonaws.com",
+ "jaworzno.pl",
+ "posts-and-telecommunications.museum",
+ "powiat.pl",
"passenger-association.aero",
- "ureshino.mie.jp",
- "xn--mgberp4a5d4a87g",
- "xn--mosjen-eya.no",
- "podzone.org",
- "xn--correios-e-telecomunicaes-ghc29a.museum",
- "xn--ogbpf8fl",
- "xn--loabt-0qa.no",
- "matsudo.chiba.jp",
- "xn--lgbbat1ad8j",
+ "logistics.aero",
+ "lewismiller.museum",
+ "xn--stre-toten-zcb.no",
+ "toyotsu.fukuoka.jp",
"pacific.museum",
- "xn--lgrd-poac.no",
- "xn--ksnes-uua.no",
- "xn--gecrj9c",
- "xn--ryken-vua.no",
- "intelligence.museum",
- "xn--hmmrfeasta-s4ac.no",
- "xn--kvfjord-nxa.no",
- "xn--ryrvik-bya.no",
- "xn--lt-liac.no",
- "newspaper.museum",
- "porsgrunn.no",
- "is-slick.com",
- "xn--laheadju-7ya.no",
- "ichikai.tochigi.jp",
- "xn--mgbtf8fl",
- "xn--kvnangen-k0a.no",
- "xn--kranghke-b0a.no",
- "yaizu.shizuoka.jp",
- "imizu.toyama.jp",
- "xn--mgbqly7c0a67fbc",
- "xn--porsgu-sta26f.no",
- "xn--mxtq1m.hk",
- "unazuki.toyama.jp",
- "xn--kvitsy-fya.no",
- "utazu.kagawa.jp",
- "uchiko.ehime.jp"
+ "xn--nttery-byae.no",
+ "shimotsuke.tochigi.jp",
+ "geometre-expert.fr",
+ "endoftheinternet.org",
+ "skydiving.aero",
+ "xn--correios-e-telecomunicaes-ghc29a.museum",
+ "lowicz.pl",
+ "xn--clchc0ea0b2g2a9gcd",
+ "xn--fzc2c9e2c"
};
#define stringpool ((const char *) &stringpool_contents)
const struct DomainRule *
@@ -12448,17477 +12991,19667 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
{
static const struct DomainRule wordlist[] =
{
-#line 1877 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str0, 2},
-#line 1351 "effective_tld_names.gperf"
+#line 2409 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str0, 0},
+#line 1822 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1, 0},
-#line 1610 "effective_tld_names.gperf"
+#line 1709 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2, 0},
-#line 1715 "effective_tld_names.gperf"
+#line 2272 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3, 0},
-#line 802 "effective_tld_names.gperf"
+#line 1246 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4, 0},
-#line 1033 "effective_tld_names.gperf"
+#line 846 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5, 0},
-#line 1028 "effective_tld_names.gperf"
+#line 1800 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6, 0},
-#line 1656 "effective_tld_names.gperf"
+#line 729 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str7, 0},
-#line 694 "effective_tld_names.gperf"
+#line 1107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str8, 0},
-#line 1171 "effective_tld_names.gperf"
+#line 1849 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str9, 0},
-#line 4961 "effective_tld_names.gperf"
+#line 910 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str10, 0},
-#line 5094 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, 2},
-#line 5062 "effective_tld_names.gperf"
+#line 1780 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str11, 0},
+#line 1897 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str12, 0},
-#line 208 "effective_tld_names.gperf"
+#line 1270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str13, 0},
-#line 4752 "effective_tld_names.gperf"
+#line 1848 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str14, 0},
-#line 328 "effective_tld_names.gperf"
+#line 1958 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str15, 0},
-#line 794 "effective_tld_names.gperf"
+#line 2419 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str16, 0},
-#line 76 "effective_tld_names.gperf"
+#line 1318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str17, 0},
-#line 4558 "effective_tld_names.gperf"
+#line 1414 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str18, 0},
-#line 4580 "effective_tld_names.gperf"
+#line 1269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str19, 0},
-#line 1040 "effective_tld_names.gperf"
+#line 939 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str20, 0},
-#line 4950 "effective_tld_names.gperf"
+#line 1935 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str21, 0},
-#line 862 "effective_tld_names.gperf"
+#line 2412 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str22, 0},
-#line 165 "effective_tld_names.gperf"
+#line 2237 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str23, 0},
-#line 5110 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, 0},
-#line 1819 "effective_tld_names.gperf"
+#line 1410 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str24, 2},
+#line 990 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str25, 0},
-#line 1817 "effective_tld_names.gperf"
+#line 938 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str26, 0},
-#line 356 "effective_tld_names.gperf"
+#line 1079 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str27, 0},
-#line 1267 "effective_tld_names.gperf"
+#line 212 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str28, 0},
-#line 1266 "effective_tld_names.gperf"
+#line 1907 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str29, 0},
-#line 1728 "effective_tld_names.gperf"
+#line 79 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str30, 0},
-#line 1727 "effective_tld_names.gperf"
+#line 365 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str31, 0},
-#line 1036 "effective_tld_names.gperf"
+#line 1331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str32, 0},
-#line 1183 "effective_tld_names.gperf"
+#line 1014 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str33, 0},
-#line 1182 "effective_tld_names.gperf"
+#line 1750 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str34, 0},
-#line 5104 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, 0},
-#line 1717 "effective_tld_names.gperf"
+#line 2306 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str35, 2},
+#line 1003 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str36, 0},
-#line 350 "effective_tld_names.gperf"
+#line 1912 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str37, 0},
-#line 968 "effective_tld_names.gperf"
+#line 826 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str38, 0},
-#line 966 "effective_tld_names.gperf"
+#line 2213 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str39, 0},
-#line 877 "effective_tld_names.gperf"
+#line 271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str40, 0},
-#line 876 "effective_tld_names.gperf"
+#line 1878 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str41, 0},
-#line 1733 "effective_tld_names.gperf"
+#line 1336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str42, 0},
-#line 1181 "effective_tld_names.gperf"
+#line 1911 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str43, 0},
-#line 1830 "effective_tld_names.gperf"
+#line 1302 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str44, 0},
-#line 1328 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str45, 2},
-#line 1187 "effective_tld_names.gperf"
+#line 230 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str45, 0},
+#line 548 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str46, 0},
-#line 1722 "effective_tld_names.gperf"
+#line 1335 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str47, 0},
-#line 1015 "effective_tld_names.gperf"
+#line 1008 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str48, 0},
-#line 1177 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str49, 0},
-#line 875 "effective_tld_names.gperf"
+#line 416 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str49, 2},
+#line 622 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str50, 0},
-#line 827 "effective_tld_names.gperf"
+#line 1528 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str51, 0},
-#line 1664 "effective_tld_names.gperf"
+#line 973 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str52, 0},
-#line 5011 "effective_tld_names.gperf"
+#line 1007 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str53, 0},
-#line 882 "effective_tld_names.gperf"
+#line 252 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str54, 0},
-#line 223 "effective_tld_names.gperf"
+#line 1983 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str55, 2},
-#line 866 "effective_tld_names.gperf"
+#line 255 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str56, 0},
-#line 821 "effective_tld_names.gperf"
+#line 2240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str57, 0},
-#line 871 "effective_tld_names.gperf"
+#line 1434 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str58, 0},
-#line 4963 "effective_tld_names.gperf"
+#line 1876 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str59, 0},
-#line 5095 "effective_tld_names.gperf"
+#line 1059 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str60, 0},
-#line 209 "effective_tld_names.gperf"
+#line 1044 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str61, 0},
-#line 342 "effective_tld_names.gperf"
+#line 1993 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str62, 0},
-#line 2786 "effective_tld_names.gperf"
+#line 152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str63, 0},
-#line 1801 "effective_tld_names.gperf"
+#line 1094 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str64, 0},
-#line 865 "effective_tld_names.gperf"
+#line 1300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str65, 0},
-#line 4559 "effective_tld_names.gperf"
+#line 593 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str66, 0},
-#line 2945 "effective_tld_names.gperf"
+#line 1875 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str67, 0},
-#line 1041 "effective_tld_names.gperf"
+#line 1299 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str68, 0},
-#line 1252 "effective_tld_names.gperf"
+#line 568 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str69, 0},
-#line 1723 "effective_tld_names.gperf"
+#line 971 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str70, 0},
-#line 1808 "effective_tld_names.gperf"
+#line 1877 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str71, 0},
-#line 1178 "effective_tld_names.gperf"
+#line 1916 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str72, 0},
-#line 4552 "effective_tld_names.gperf"
+#line 1551 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str73, 0},
-#line 1259 "effective_tld_names.gperf"
+#line 1301 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str74, 0},
-#line 949 "effective_tld_names.gperf"
+#line 970 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str75, 0},
-#line 1876 "effective_tld_names.gperf"
+#line 1339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str76, 0},
-#line 1344 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str77, 2},
-#line 872 "effective_tld_names.gperf"
+#line 937 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str77, 4},
+#line 972 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str78, 0},
-#line 1730 "effective_tld_names.gperf"
+#line 1012 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str79, 0},
-#line 962 "effective_tld_names.gperf"
+#line 1683 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str80, 0},
-#line 957 "effective_tld_names.gperf"
+#line 2251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str81, 0},
-#line 1185 "effective_tld_names.gperf"
+#line 2006 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str82, 0},
-#line 1720 "effective_tld_names.gperf"
+#line 1226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str83, 0},
-#line 810 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str84, 4},
-#line 5017 "effective_tld_names.gperf"
+#line 21 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str84, 0},
+#line 16 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str85, 0},
-#line 318 "effective_tld_names.gperf"
+#line 335 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str86, 0},
-#line 1809 "effective_tld_names.gperf"
+#line 25 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str87, 0},
-#line 1832 "effective_tld_names.gperf"
+#line 24 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str88, 0},
-#line 879 "effective_tld_names.gperf"
+#line 23 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str89, 0},
-#line 1260 "effective_tld_names.gperf"
+#line 20 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str90, 0},
-#line 2855 "effective_tld_names.gperf"
+#line 19 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str91, 0},
-#line 1016 "effective_tld_names.gperf"
+#line 624 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str92, 0},
-#line 846 "effective_tld_names.gperf"
+#line 4640 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str93, 0},
-#line 1034 "effective_tld_names.gperf"
+#line 18 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str94, 0},
-#line 5013 "effective_tld_names.gperf"
+#line 15 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str95, 0},
-#line 958 "effective_tld_names.gperf"
+#line 1763 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str96, 0},
-#line 225 "effective_tld_names.gperf"
+#line 2320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str97, 0},
-#line 1852 "effective_tld_names.gperf"
+#line 2186 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str98, 0},
-#line 1332 "effective_tld_names.gperf"
+#line 2386 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str99, 0},
-#line 4585 "effective_tld_names.gperf"
+#line 1684 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str100, 0},
-#line 1716 "effective_tld_names.gperf"
+#line 2253 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str101, 0},
-#line 4951 "effective_tld_names.gperf"
+#line 2007 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str102, 0},
-#line 1805 "effective_tld_names.gperf"
+#line 1227 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str103, 0},
-#line 1762 "effective_tld_names.gperf"
+#line 14 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str104, 0},
-#line 1172 "effective_tld_names.gperf"
+#line 840 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str105, 0},
-#line 1761 "effective_tld_names.gperf"
+#line 1956 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str106, 0},
-#line 1256 "effective_tld_names.gperf"
+#line 1002 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str107, 0},
-#line 1214 "effective_tld_names.gperf"
+#line 269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str108, 0},
-#line 264 "effective_tld_names.gperf"
+#line 626 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str109, 0},
-#line 1615 "effective_tld_names.gperf"
+#line 1896 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str110, 0},
-#line 1281 "effective_tld_names.gperf"
+#line 1317 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str111, 0},
-#line 4578 "effective_tld_names.gperf"
+#line 543 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str112, 0},
-#line 863 "effective_tld_names.gperf"
+#line 989 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str113, 0},
-#line 954 "effective_tld_names.gperf"
+#line 26 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str114, 0},
-#line 983 "effective_tld_names.gperf"
+#line 349 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str115, 0},
-#line 912 "effective_tld_names.gperf"
+#line 1439 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str116, 0},
-#line 4755 "effective_tld_names.gperf"
+#line 266 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str117, 0},
-#line 83 "effective_tld_names.gperf"
+#line 1714 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str118, 0},
-#line 1724 "effective_tld_names.gperf"
+#line 2282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str119, 0},
-#line 4501 "effective_tld_names.gperf"
+#line 2355 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str120, 0},
-#line 1878 "effective_tld_names.gperf"
+#line 1360 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str121, 0},
-#line 1026 "effective_tld_names.gperf"
+#line 2191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str122, 0},
-#line 1179 "effective_tld_names.gperf"
+#line 190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str123, 0},
-#line 848 "effective_tld_names.gperf"
+#line 28 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str124, 0},
-#line 320 "effective_tld_names.gperf"
+#line 2233 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str125, 0},
-#line 1017 "effective_tld_names.gperf"
+#line 2228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str126, 0},
-#line 4754 "effective_tld_names.gperf"
+#line 1782 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str127, 0},
-#line 873 "effective_tld_names.gperf"
+#line 369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str128, 0},
-#line 2857 "effective_tld_names.gperf"
+#line 1275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str129, 0},
-#line 1807 "effective_tld_names.gperf"
+#line 368 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str130, 0},
-#line 2924 "effective_tld_names.gperf"
+#line 944 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str131, 0},
-#line 1258 "effective_tld_names.gperf"
+#line 1934 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str132, 0},
-#line 357 "effective_tld_names.gperf"
+#line 2411 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str133, 0},
-#line 2787 "effective_tld_names.gperf"
+#line 1451 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str134, 0},
-#line 956 "effective_tld_names.gperf"
+#line 1982 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str135, 0},
-#line 1025 "effective_tld_names.gperf"
+#line 2521 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str136, 0},
-#line 3419 "effective_tld_names.gperf"
+#line 2239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str137, 0},
-#line 3518 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str138, 0},
-#line 3487 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str139, 0},
-#line 3201 "effective_tld_names.gperf"
+#line 1427 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str138, 2},
+#line 546 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str139, 2},
+#line 1851 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str140, 0},
-#line 5015 "effective_tld_names.gperf"
+#line 1781 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str141, 0},
-#line 1616 "effective_tld_names.gperf"
+#line 370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str142, 0},
-#line 3415 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str143, 2},
-#line 3529 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str144, 2},
-#line 2706 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str145, 2},
-#line 695 "effective_tld_names.gperf"
+#line 86 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str143, 0},
+#line 1272 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str144, 0},
+#line 1452 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str145, 0},
+#line 1924 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str146, 0},
-#line 1806 "effective_tld_names.gperf"
+#line 1752 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str147, 0},
-#line 1257 "effective_tld_names.gperf"
+#line 1920 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str148, 0},
-#line 86 "effective_tld_names.gperf"
+#line 941 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str149, 0},
-#line 4502 "effective_tld_names.gperf"
+#line 1346 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str150, 0},
-#line 3520 "effective_tld_names.gperf"
+#line 1922 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str151, 0},
-#line 226 "effective_tld_names.gperf"
+#line 89 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str152, 0},
-#line 955 "effective_tld_names.gperf"
+#line 1344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str153, 0},
-#line 2858 "effective_tld_names.gperf"
+#line 1345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str154, 0},
-#line 5273 "effective_tld_names.gperf"
+#line 1021 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str155, 0},
-#line 5438 "effective_tld_names.gperf"
+#line 1910 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str156, 0},
-#line 1721 "effective_tld_names.gperf"
+#line 1018 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str157, 0},
-#line 1276 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str158, 1},
-#line 5218 "effective_tld_names.gperf"
+#line 1019 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str158, 0},
+#line 226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str159, 0},
-#line 3114 "effective_tld_names.gperf"
+#line 2394 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str160, 0},
-#line 3100 "effective_tld_names.gperf"
+#line 1334 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str161, 0},
-#line 1176 "effective_tld_names.gperf"
+#line 1913 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str162, 0},
-#line 5259 "effective_tld_names.gperf"
+#line 2373 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str163, 0},
-#line 5457 "effective_tld_names.gperf"
+#line 418 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str164, 0},
-#line 3476 "effective_tld_names.gperf"
+#line 325 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str165, 0},
-#line 869 "effective_tld_names.gperf"
+#line 1337 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str166, 0},
-#line 1587 "effective_tld_names.gperf"
+#line 1006 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str167, 0},
-#line 1152 "effective_tld_names.gperf"
+#line 735 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str168, 0},
-#line 1738 "effective_tld_names.gperf"
+#line 1009 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str169, 0},
-#line 1736 "effective_tld_names.gperf"
+#line 347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str170, 0},
-#line 1734 "effective_tld_names.gperf"
+#line 2501 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str171, 0},
-#line 4568 "effective_tld_names.gperf"
+#line 1874 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str172, 0},
-#line 1190 "effective_tld_names.gperf"
+#line 899 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str173, 0},
-#line 600 "effective_tld_names.gperf"
+#line 2360 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str174, 0},
-#line 3422 "effective_tld_names.gperf"
+#line 1298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str175, 0},
-#line 1820 "effective_tld_names.gperf"
+#line 1852 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str176, 0},
-#line 4595 "effective_tld_names.gperf"
+#line 310 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str177, 0},
-#line 1027 "effective_tld_names.gperf"
+#line 1273 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str178, 0},
-#line 27 "effective_tld_names.gperf"
+#line 595 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str179, 0},
-#line 1268 "effective_tld_names.gperf"
+#line 969 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str180, 0},
-#line 1731 "effective_tld_names.gperf"
+#line 942 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str181, 0},
-#line 885 "effective_tld_names.gperf"
+#line 2365 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str182, 0},
-#line 4478 "effective_tld_names.gperf"
+#line 1921 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str183, 0},
-#line 1188 "effective_tld_names.gperf"
+#line 2371 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str184, 0},
-#line 1186 "effective_tld_names.gperf"
+#line 1837 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str185, 0},
-#line 969 "effective_tld_names.gperf"
+#line 1836 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str186, 0},
-#line 883 "effective_tld_names.gperf"
+#line 1835 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str187, 0},
-#line 880 "effective_tld_names.gperf"
+#line 1778 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str188, 0},
-#line 5365 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str189, 2},
-#line 3092 "effective_tld_names.gperf"
+#line 1927 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str189, 0},
+#line 1261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str190, 0},
-#line 2465 "effective_tld_names.gperf"
+#line 1260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str191, 0},
-#line 1434 "effective_tld_names.gperf"
+#line 1259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str192, 0},
-#line 3484 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str193, 2},
-#line 5274 "effective_tld_names.gperf"
+#line 1834 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str193, 0},
+#line 1349 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str194, 0},
-#line 5441 "effective_tld_names.gperf"
+#line 2364 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str195, 0},
-#line 3076 "effective_tld_names.gperf"
+#line 1258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str196, 0},
-#line 3101 "effective_tld_names.gperf"
+#line 928 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str197, 0},
-#line 2464 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str198, 2},
-#line 1429 "effective_tld_names.gperf"
+#line 927 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str198, 0},
+#line 926 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str199, 0},
-#line 265 "effective_tld_names.gperf"
+#line 6382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str200, 0},
-#line 997 "effective_tld_names.gperf"
+#line 1024 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str201, 0},
-#line 2868 "effective_tld_names.gperf"
+#line 925 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str202, 0},
-#line 1633 "effective_tld_names.gperf"
+#line 1733 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str203, 0},
-#line 1818 "effective_tld_names.gperf"
+#line 1831 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str204, 0},
-#line 2495 "effective_tld_names.gperf"
+#line 1418 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str205, 0},
-#line 766 "effective_tld_names.gperf"
+#line 442 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str206, 0},
-#line 1812 "effective_tld_names.gperf"
+#line 1425 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str207, 0},
-#line 1729 "effective_tld_names.gperf"
+#line 805 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str208, 0},
-#line 4910 "effective_tld_names.gperf"
+#line 1255 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str209, 0},
-#line 1263 "effective_tld_names.gperf"
+#line 1862 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str210, 0},
-#line 87 "effective_tld_names.gperf"
+#line 1864 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str211, 0},
-#line 111 "effective_tld_names.gperf"
+#line 1863 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str212, 0},
-#line 1184 "effective_tld_names.gperf"
+#line 84 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str213, 0},
-#line 3479 "effective_tld_names.gperf"
+#line 1287 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str214, 0},
-#line 5430 "effective_tld_names.gperf"
+#line 1288 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str215, 0},
-#line 3094 "effective_tld_names.gperf"
+#line 922 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str216, 0},
-#line 967 "effective_tld_names.gperf"
+#line 82 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str217, 0},
-#line 844 "effective_tld_names.gperf"
+#line 3564 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str218, 0},
-#line 1175 "effective_tld_names.gperf"
+#line 960 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str219, 0},
-#line 963 "effective_tld_names.gperf"
+#line 961 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str220, 0},
-#line 878 "effective_tld_names.gperf"
+#line 3341 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str221, 0},
-#line 81 "effective_tld_names.gperf"
+#line 959 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str222, 0},
-#line 1658 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str223, 0},
-#line 3204 "effective_tld_names.gperf"
+#line 3682 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str223, 2},
+#line 1736 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str224, 0},
-#line 1456 "effective_tld_names.gperf"
+#line 414 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str225, 0},
-#line 868 "effective_tld_names.gperf"
+#line 958 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str226, 0},
-#line 5366 "effective_tld_names.gperf"
+#line 2400 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str227, 0},
-#line 796 "effective_tld_names.gperf"
+#line 424 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str228, 0},
-#line 79 "effective_tld_names.gperf"
+#line 986 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str229, 0},
-#line 4954 "effective_tld_names.gperf"
+#line 115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str230, 0},
-#line 3115 "effective_tld_names.gperf"
+#line 6358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str231, 0},
-#line 186 "effective_tld_names.gperf"
+#line 254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str232, 0},
-#line 3485 "effective_tld_names.gperf"
+#line 3631 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str233, 0},
-#line 2869 "effective_tld_names.gperf"
+#line 1074 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str234, 0},
-#line 3423 "effective_tld_names.gperf"
+#line 1548 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str235, 0},
-#line 1711 "effective_tld_names.gperf"
+#line 3628 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str236, 0},
-#line 3203 "effective_tld_names.gperf"
+#line 2372 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str237, 0},
-#line 1431 "effective_tld_names.gperf"
+#line 6359 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str238, 0},
-#line 3093 "effective_tld_names.gperf"
+#line 1894 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str239, 0},
-#line 1099 "effective_tld_names.gperf"
+#line 3586 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str240, 0},
-#line 2725 "effective_tld_names.gperf"
+#line 1909 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str241, 0},
-#line 767 "effective_tld_names.gperf"
+#line 1333 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str242, 0},
-#line 1262 "effective_tld_names.gperf"
+#line 449 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str243, 0},
-#line 1088 "effective_tld_names.gperf"
+#line 1623 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str244, 0},
-#line 5014 "effective_tld_names.gperf"
+#line 1472 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str245, 0},
-#line 4911 "effective_tld_names.gperf"
+#line 3559 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str246, 0},
-#line 1149 "effective_tld_names.gperf"
+#line 2393 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str247, 0},
-#line 3480 "effective_tld_names.gperf"
+#line 1479 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str248, 0},
-#line 4532 "effective_tld_names.gperf"
+#line 1005 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str249, 0},
-#line 961 "effective_tld_names.gperf"
+#line 733 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str250, 0},
-#line 3095 "effective_tld_names.gperf"
+#line 311 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str251, 0},
-#line 308 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str252, 0},
-#line 1816 "effective_tld_names.gperf"
+#line 1809 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str252, 4},
+#line 1906 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str253, 0},
-#line 314 "effective_tld_names.gperf"
+#line 1330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str254, 0},
-#line 3079 "effective_tld_names.gperf"
+#line 2359 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str255, 0},
-#line 1306 "effective_tld_names.gperf"
+#line 1509 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str256, 0},
-#line 3205 "effective_tld_names.gperf"
+#line 2358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str257, 0},
-#line 1457 "effective_tld_names.gperf"
+#line 2000 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str258, 0},
-#line 2789 "effective_tld_names.gperf"
+#line 1738 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str259, 0},
-#line 798 "effective_tld_names.gperf"
+#line 1860 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str260, 0},
-#line 1719 "effective_tld_names.gperf"
+#line 1001 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str261, 0},
-#line 187 "effective_tld_names.gperf"
+#line 2370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str262, 0},
-#line 1174 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str263, 0},
-#line 1001 "effective_tld_names.gperf"
+#line 1104 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str263, 2},
+#line 2389 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str264, 0},
-#line 4553 "effective_tld_names.gperf"
+#line 3639 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str265, 0},
-#line 5449 "effective_tld_names.gperf"
+#line 845 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str266, 0},
-#line 1714 "effective_tld_names.gperf"
+#line 498 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str267, 0},
-#line 1000 "effective_tld_names.gperf"
+#line 2352 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str268, 0},
-#line 5253 "effective_tld_names.gperf"
+#line 1517 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str269, 0},
-#line 5400 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str270, 0},
-#line 867 "effective_tld_names.gperf"
+#line 625 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str270, 4},
+#line 308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str271, 0},
-#line 831 "effective_tld_names.gperf"
+#line 2392 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str272, 0},
-#line 325 "effective_tld_names.gperf"
+#line 3256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str273, 0},
-#line 3218 "effective_tld_names.gperf"
+#line 5767 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str274, 0},
-#line 2447 "effective_tld_names.gperf"
+#line 3561 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str275, 0},
-#line 1649 "effective_tld_names.gperf"
+#line 3257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str276, 0},
-#line 1669 "effective_tld_names.gperf"
+#line 617 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str277, 0},
-#line 5219 "effective_tld_names.gperf"
+#line 1830 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str278, 0},
-#line 306 "effective_tld_names.gperf"
+#line 1866 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str279, 0},
-#line 2976 "effective_tld_names.gperf"
+#line 1254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str280, 0},
-#line 787 "effective_tld_names.gperf"
+#line 5730 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str281, 0},
-#line 842 "effective_tld_names.gperf"
+#line 1290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str282, 0},
-#line 3096 "effective_tld_names.gperf"
+#line 1547 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str283, 0},
-#line 4943 "effective_tld_names.gperf"
+#line 921 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str284, 0},
-#line 1712 "effective_tld_names.gperf"
+#line 962 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str285, 0},
-#line 3121 "effective_tld_names.gperf"
+#line 902 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str286, 0},
-#line 148 "effective_tld_names.gperf"
+#line 1761 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str287, 0},
-#line 1739 "effective_tld_names.gperf"
+#line 2310 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str288, 0},
-#line 3486 "effective_tld_names.gperf"
+#line 2184 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str289, 0},
-#line 1191 "effective_tld_names.gperf"
+#line 3344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str290, 0},
-#line 1811 "effective_tld_names.gperf"
+#line 1499 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str291, 0},
-#line 799 "effective_tld_names.gperf"
+#line 838 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str292, 0},
-#line 1261 "effective_tld_names.gperf"
+#line 2399 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str293, 0},
-#line 886 "effective_tld_names.gperf"
+#line 2089 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str294, 0},
-#line 960 "effective_tld_names.gperf"
+#line 1889 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str295, 0},
-#line 3217 "effective_tld_names.gperf"
+#line 1888 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str296, 0},
-#line 247 "effective_tld_names.gperf"
+#line 1310 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str297, 0},
-#line 1411 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str298, 2},
-#line 5116 "effective_tld_names.gperf"
+#line 979 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str298, 0},
+#line 1495 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str299, 0},
-#line 528 "effective_tld_names.gperf"
+#line 3627 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str300, 0},
-#line 5395 "effective_tld_names.gperf"
+#line 1685 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str301, 0},
-#line 2947 "effective_tld_names.gperf"
+#line 1466 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str302, 0},
-#line 404 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str303, 2},
-#line 3482 "effective_tld_names.gperf"
+#line 3636 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str303, 0},
+#line 3580 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str304, 0},
-#line 4533 "effective_tld_names.gperf"
+#line 169 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str305, 0},
-#line 5220 "effective_tld_names.gperf"
+#line 489 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str306, 0},
-#line 524 "effective_tld_names.gperf"
+#line 3370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str307, 0},
-#line 1589 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str308, 0},
-#line 596 "effective_tld_names.gperf"
+#line 1503 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str308, 2},
+#line 1926 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str309, 0},
-#line 1376 "effective_tld_names.gperf"
+#line 3379 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str310, 0},
-#line 601 "effective_tld_names.gperf"
+#line 1885 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str311, 0},
-#line 3207 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str312, 0},
-#line 788 "effective_tld_names.gperf"
+#line 534 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str312, 4},
+#line 2281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str313, 0},
-#line 4615 "effective_tld_names.gperf"
+#line 1348 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str314, 0},
-#line 1815 "effective_tld_names.gperf"
+#line 1795 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str315, 0},
-#line 149 "effective_tld_names.gperf"
+#line 1307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str316, 0},
-#line 5263 "effective_tld_names.gperf"
+#line 2198 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str317, 0},
-#line 1265 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str318, 0},
-#line 1063 "effective_tld_names.gperf"
+#line 518 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str318, 4},
+#line 1023 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str319, 0},
-#line 965 "effective_tld_names.gperf"
+#line 977 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str320, 0},
-#line 1707 "effective_tld_names.gperf"
+#line 544 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str321, 0},
-#line 253 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str322, 0},
-#line 547 "effective_tld_names.gperf"
+#line 537 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str322, 4},
+#line 1523 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str323, 0},
-#line 3416 "effective_tld_names.gperf"
+#line 1886 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str324, 0},
-#line 5394 "effective_tld_names.gperf"
+#line 455 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str325, 0},
-#line 1364 "effective_tld_names.gperf"
+#line 5667 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str326, 0},
-#line 1737 "effective_tld_names.gperf"
+#line 1308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str327, 0},
-#line 529 "effective_tld_names.gperf"
+#line 978 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str328, 0},
-#line 3001 "effective_tld_names.gperf"
+#line 1883 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str329, 0},
-#line 1189 "effective_tld_names.gperf"
+#line 332 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str330, 0},
-#line 998 "effective_tld_names.gperf"
+#line 5668 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str331, 0},
-#line 597 "effective_tld_names.gperf"
+#line 1305 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str332, 0},
-#line 4713 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str333, 0},
-#line 884 "effective_tld_names.gperf"
+#line 533 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str333, 4},
+#line 1712 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str334, 0},
-#line 602 "effective_tld_names.gperf"
+#line 2341 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str335, 0},
-#line 1085 "effective_tld_names.gperf"
+#line 808 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str336, 0},
-#line 88 "effective_tld_names.gperf"
+#line 1393 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str337, 0},
-#line 4621 "effective_tld_names.gperf"
+#line 2366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str338, 0},
-#line 302 "effective_tld_names.gperf"
+#line 162 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str339, 0},
-#line 3245 "effective_tld_names.gperf"
+#line 3660 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str340, 0},
-#line 5270 "effective_tld_names.gperf"
+#line 122 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str341, 0},
-#line 4479 "effective_tld_names.gperf"
+#line 844 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str342, 0},
-#line 1586 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str343, 0},
-#line 1151 "effective_tld_names.gperf"
+#line 530 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str343, 4},
+#line 1488 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str344, 0},
-#line 21 "effective_tld_names.gperf"
+#line 1686 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str345, 0},
-#line 16 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str346, 0},
-#line 1672 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str347, 0},
-#line 15 "effective_tld_names.gperf"
+#line 900 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str346, 4},
+#line 541 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str347, 4},
+#line 2514 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str348, 0},
-#line 25 "effective_tld_names.gperf"
+#line 2073 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str349, 0},
-#line 574 "effective_tld_names.gperf"
+#line 627 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str350, 0},
-#line 24 "effective_tld_names.gperf"
+#line 4641 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str351, 0},
-#line 598 "effective_tld_names.gperf"
+#line 664 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str352, 0},
-#line 23 "effective_tld_names.gperf"
+#line 1827 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str353, 0},
-#line 20 "effective_tld_names.gperf"
+#line 632 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str354, 0},
-#line 19 "effective_tld_names.gperf"
+#line 1777 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str355, 0},
-#line 18 "effective_tld_names.gperf"
+#line 1251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str356, 0},
-#line 826 "effective_tld_names.gperf"
+#line 1365 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str357, 0},
-#line 4594 "effective_tld_names.gperf"
+#line 917 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str358, 0},
-#line 14 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str359, 0},
-#line 26 "effective_tld_names.gperf"
+#line 3579 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str359, 1},
+#line 5712 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str360, 0},
-#line 4477 "effective_tld_names.gperf"
+#line 1621 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str361, 0},
-#line 5651 "effective_tld_names.gperf"
+#line 1823 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str362, 0},
-#line 549 "effective_tld_names.gperf"
+#line 90 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str363, 0},
-#line 3417 "effective_tld_names.gperf"
+#line 1247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str364, 0},
-#line 630 "effective_tld_names.gperf"
+#line 911 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str365, 0},
-#line 1389 "effective_tld_names.gperf"
+#line 1482 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str366, 0},
-#line 5432 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str367, 0},
-#line 5385 "effective_tld_names.gperf"
+#line 512 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str367, 4},
+#line 1527 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str368, 0},
-#line 3002 "effective_tld_names.gperf"
+#line 1257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str369, 0},
-#line 151 "effective_tld_names.gperf"
+#line 1933 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str370, 0},
-#line 1745 "effective_tld_names.gperf"
+#line 1882 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str371, 0},
-#line 572 "effective_tld_names.gperf"
+#line 372 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str372, 0},
-#line 634 "effective_tld_names.gperf"
+#line 2354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str373, 0},
-#line 1197 "effective_tld_names.gperf"
+#line 650 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str374, 0},
-#line 1045 "effective_tld_names.gperf"
+#line 395 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str375, 0},
-#line 1735 "effective_tld_names.gperf"
+#line 924 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str376, 0},
-#line 893 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str377, 0},
-#line 406 "effective_tld_names.gperf"
+#line 531 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str377, 4},
+#line 3663 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str378, 0},
-#line 5271 "effective_tld_names.gperf"
+#line 1903 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str379, 0},
-#line 3414 "effective_tld_names.gperf"
+#line 1902 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str380, 0},
-#line 828 "effective_tld_names.gperf"
+#line 1826 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str381, 0},
-#line 1746 "effective_tld_names.gperf"
+#line 3353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str382, 0},
-#line 4583 "effective_tld_names.gperf"
+#line 1327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str383, 0},
-#line 575 "effective_tld_names.gperf"
+#line 1326 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str384, 0},
-#line 2494 "effective_tld_names.gperf"
+#line 309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str385, 0},
-#line 1198 "effective_tld_names.gperf"
+#line 1249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str386, 0},
-#line 3521 "effective_tld_names.gperf"
+#line 473 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str387, 0},
-#line 1828 "effective_tld_names.gperf"
+#line 658 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str388, 0},
-#line 769 "effective_tld_names.gperf"
+#line 998 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str389, 0},
-#line 3504 "effective_tld_names.gperf"
+#line 997 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str390, 0},
-#line 894 "effective_tld_names.gperf"
+#line 4649 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str391, 0},
-#line 5442 "effective_tld_names.gperf"
+#line 915 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str392, 0},
-#line 5652 "effective_tld_names.gperf"
+#line 1824 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str393, 0},
-#line 1590 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str394, 0},
-#line 1004 "effective_tld_names.gperf"
+#line 6381 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str394, 2},
+#line 1424 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str395, 0},
-#line 30 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str396, 0},
-#line 604 "effective_tld_names.gperf"
+#line 536 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str396, 4},
+#line 467 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str397, 0},
-#line 2474 "effective_tld_names.gperf"
+#line 3675 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str398, 0},
-#line 1391 "effective_tld_names.gperf"
+#line 5713 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str399, 0},
-#line 3209 "effective_tld_names.gperf"
+#line 1899 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str400, 0},
-#line 5258 "effective_tld_names.gperf"
+#line 1788 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str401, 0},
-#line 3247 "effective_tld_names.gperf"
+#line 1457 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str402, 0},
-#line 4714 "effective_tld_names.gperf"
+#line 1323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str403, 0},
-#line 4557 "effective_tld_names.gperf"
+#line 1801 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str404, 0},
-#line 472 "effective_tld_names.gperf"
+#line 1100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str405, 0},
-#line 573 "effective_tld_names.gperf"
+#line 995 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str406, 0},
-#line 1065 "effective_tld_names.gperf"
+#line 835 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str407, 0},
-#line 1887 "effective_tld_names.gperf"
+#line 1046 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str408, 0},
-#line 1199 "effective_tld_names.gperf"
+#line 6380 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str409, 0},
-#line 806 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str410, 0},
-#line 311 "effective_tld_names.gperf"
+#line 2209 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str410, 4},
+#line 2387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str411, 0},
-#line 3122 "effective_tld_names.gperf"
+#line 1900 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str412, 0},
-#line 2902 "effective_tld_names.gperf"
+#line 3656 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str413, 0},
-#line 895 "effective_tld_names.gperf"
+#line 2316 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str414, 0},
-#line 830 "effective_tld_names.gperf"
+#line 1928 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str415, 0},
-#line 1632 "effective_tld_names.gperf"
+#line 1324 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str416, 0},
-#line 3418 "effective_tld_names.gperf"
+#line 1049 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str417, 0},
-#line 5233 "effective_tld_names.gperf"
+#line 1796 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str418, 0},
-#line 704 "effective_tld_names.gperf"
+#line 1351 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str419, 0},
-#line 5646 "effective_tld_names.gperf"
+#line 1385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str420, 0},
-#line 1002 "effective_tld_names.gperf"
+#line 2252 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str421, 0},
-#line 4808 "effective_tld_names.gperf"
+#line 996 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str422, 0},
-#line 1744 "effective_tld_names.gperf"
+#line 1787 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str423, 0},
-#line 1454 "effective_tld_names.gperf"
+#line 1028 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str424, 0},
-#line 849 "effective_tld_names.gperf"
+#line 1320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str425, 0},
-#line 2854 "effective_tld_names.gperf"
+#line 1981 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str426, 0},
-#line 1196 "effective_tld_names.gperf"
+#line 992 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str427, 0},
-#line 1022 "effective_tld_names.gperf"
+#line 293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str428, 0},
-#line 292 "effective_tld_names.gperf"
+#line 1805 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str429, 0},
-#line 5002 "effective_tld_names.gperf"
+#line 1758 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str430, 0},
-#line 217 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str431, 0},
-#line 785 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str432, 2},
-#line 892 "effective_tld_names.gperf"
+#line 3560 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str431, 2},
+#line 1892 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str432, 0},
+#line 651 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str433, 0},
-#line 4924 "effective_tld_names.gperf"
+#line 1929 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str434, 0},
-#line 1348 "effective_tld_names.gperf"
+#line 1313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str435, 0},
-#line 2948 "effective_tld_names.gperf"
+#line 259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str436, 0},
-#line 5272 "effective_tld_names.gperf"
+#line 1352 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str437, 0},
-#line 361 "effective_tld_names.gperf"
+#line 4648 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str438, 0},
-#line 5583 "effective_tld_names.gperf"
+#line 983 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str439, 0},
-#line 1826 "effective_tld_names.gperf"
+#line 1029 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str440, 0},
-#line 1275 "effective_tld_names.gperf"
+#line 481 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str441, 0},
-#line 2491 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str442, 0},
-#line 5649 "effective_tld_names.gperf"
+#line 6360 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str442, 2},
+#line 5765 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str443, 0},
-#line 979 "effective_tld_names.gperf"
+#line 2532 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str444, 0},
-#line 825 "effective_tld_names.gperf"
+#line 188 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str445, 0},
-#line 801 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str446, 0},
-#line 2715 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str447, 2},
-#line 705 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str448, 0},
-#line 3120 "effective_tld_names.gperf"
+#line 519 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str446, 4},
+#line 1759 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str447, 0},
+#line 2432 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str448, 4},
+#line 3349 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str449, 0},
-#line 4536 "effective_tld_names.gperf"
+#line 639 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str450, 0},
-#line 3426 "effective_tld_names.gperf"
+#line 1786 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str451, 0},
-#line 5648 "effective_tld_names.gperf"
+#line 987 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str452, 0},
-#line 2973 "effective_tld_names.gperf"
+#line 1319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str453, 0},
-#line 1321 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str454, 0},
-#line 5117 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str455, 0},
-#line 1407 "effective_tld_names.gperf"
+#line 538 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str454, 4},
+#line 516 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str455, 4},
+#line 1711 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str456, 0},
-#line 194 "effective_tld_names.gperf"
+#line 2245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str457, 0},
-#line 434 "effective_tld_names.gperf"
+#line 991 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str458, 0},
-#line 5584 "effective_tld_names.gperf"
+#line 600 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str459, 0},
-#line 4556 "effective_tld_names.gperf"
+#line 168 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str460, 0},
-#line 4566 "effective_tld_names.gperf"
+#line 3357 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str461, 0},
-#line 3197 "effective_tld_names.gperf"
+#line 315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str462, 0},
-#line 5115 "effective_tld_names.gperf"
+#line 3358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str463, 0},
-#line 2946 "effective_tld_names.gperf"
+#line 485 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str464, 0},
-#line 456 "effective_tld_names.gperf"
+#line 2011 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str465, 0},
-#line 525 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str466, 0},
-#line 5223 "effective_tld_names.gperf"
+#line 535 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str466, 4},
+#line 1678 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str467, 0},
-#line 4925 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str468, 0},
-#line 526 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str469, 2},
-#line 1089 "effective_tld_names.gperf"
+#line 525 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str468, 4},
+#line 1505 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str469, 0},
+#line 3612 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str470, 0},
-#line 2449 "effective_tld_names.gperf"
+#line 3350 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str471, 0},
-#line 786 "effective_tld_names.gperf"
+#line 3258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str472, 0},
-#line 987 "effective_tld_names.gperf"
+#line 287 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str473, 0},
-#line 1527 "effective_tld_names.gperf"
+#line 2396 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str474, 0},
-#line 3474 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str475, 0},
-#line 1116 "effective_tld_names.gperf"
+#line 510 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str475, 4},
+#line 5958 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str476, 0},
-#line 3196 "effective_tld_names.gperf"
+#line 3348 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str477, 0},
-#line 5650 "effective_tld_names.gperf"
+#line 919 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str478, 0},
-#line 3123 "effective_tld_names.gperf"
+#line 3665 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str479, 0},
-#line 435 "effective_tld_names.gperf"
+#line 5959 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str480, 0},
-#line 458 "effective_tld_names.gperf"
+#line 1455 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str481, 0},
-#line 850 "effective_tld_names.gperf"
+#line 1732 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str482, 0},
-#line 2441 "effective_tld_names.gperf"
+#line 741 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str483, 0},
-#line 1363 "effective_tld_names.gperf"
+#line 312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str484, 0},
-#line 1791 "effective_tld_names.gperf"
+#line 331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str485, 0},
-#line 1239 "effective_tld_names.gperf"
+#line 4650 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str486, 0},
-#line 2716 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str487, 0},
-#line 2815 "effective_tld_names.gperf"
+#line 515 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str487, 4},
+#line 476 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str488, 0},
-#line 527 "effective_tld_names.gperf"
+#line 3626 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str489, 0},
-#line 986 "effective_tld_names.gperf"
+#line 1832 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str490, 0},
-#line 937 "effective_tld_names.gperf"
+#line 459 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str491, 0},
-#line 133 "effective_tld_names.gperf"
+#line 956 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str492, 0},
-#line 819 "effective_tld_names.gperf"
+#line 1987 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str493, 0},
-#line 1416 "effective_tld_names.gperf"
+#line 1689 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str494, 0},
-#line 2950 "effective_tld_names.gperf"
+#line 545 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str495, 0},
-#line 3244 "effective_tld_names.gperf"
+#line 2381 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str496, 0},
-#line 3097 "effective_tld_names.gperf"
+#line 3416 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str497, 0},
-#line 5609 "effective_tld_names.gperf"
+#line 1442 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str498, 0},
-#line 1611 "effective_tld_names.gperf"
+#line 1859 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str499, 0},
-#line 3412 "effective_tld_names.gperf"
+#line 914 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str500, 0},
-#line 935 "effective_tld_names.gperf"
+#line 2280 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str501, 0},
-#line 1896 "effective_tld_names.gperf"
+#line 1283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str502, 0},
-#line 603 "effective_tld_names.gperf"
+#line 3429 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str503, 0},
-#line 4753 "effective_tld_names.gperf"
+#line 1497 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str504, 0},
-#line 1670 "effective_tld_names.gperf"
+#line 954 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str505, 0},
-#line 5245 "effective_tld_names.gperf"
+#line 1394 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str506, 0},
-#line 5635 "effective_tld_names.gperf"
+#line 448 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str507, 0},
-#line 1890 "effective_tld_names.gperf"
+#line 3671 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str508, 0},
-#line 845 "effective_tld_names.gperf"
+#line 2053 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str509, 0},
-#line 1713 "effective_tld_names.gperf"
+#line 427 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str510, 0},
-#line 2482 "effective_tld_names.gperf"
+#line 5669 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str511, 0},
-#line 3427 "effective_tld_names.gperf"
+#line 1228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str512, 0},
-#line 5364 "effective_tld_names.gperf"
+#line 2090 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str513, 0},
-#line 5105 "effective_tld_names.gperf"
+#line 3285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str514, 0},
-#line 5257 "effective_tld_names.gperf"
+#line 1441 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str515, 0},
-#line 1044 "effective_tld_names.gperf"
+#line 3389 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str516, 0},
-#line 3074 "effective_tld_names.gperf"
+#line 1395 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str517, 0},
-#line 3274 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str518, 0},
-#line 1433 "effective_tld_names.gperf"
+#line 527 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str518, 4},
+#line 2247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str519, 0},
-#line 3211 "effective_tld_names.gperf"
+#line 3402 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str520, 0},
-#line 5610 "effective_tld_names.gperf"
+#line 2018 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str521, 0},
-#line 459 "effective_tld_names.gperf"
+#line 585 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str522, 0},
-#line 3318 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str523, 0},
-#line 3317 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str524, 0},
-#line 1667 "effective_tld_names.gperf"
+#line 526 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str523, 4},
+#line 505 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str524, 4},
+#line 1030 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str525, 0},
-#line 1305 "effective_tld_names.gperf"
+#line 1429 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str526, 0},
-#line 3280 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str527, 0},
-#line 1169 "effective_tld_names.gperf"
+#line 582 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str527, 4},
+#line 3449 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str528, 0},
-#line 1354 "effective_tld_names.gperf"
+#line 3499 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str529, 0},
-#line 362 "effective_tld_names.gperf"
+#line 318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str530, 0},
-#line 836 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str531, 0},
-#line 477 "effective_tld_names.gperf"
+#line 509 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str531, 4},
+#line 1478 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str532, 0},
-#line 3276 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str533, 0},
-#line 3320 "effective_tld_names.gperf"
+#line 528 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str533, 4},
+#line 3401 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str534, 0},
-#line 1424 "effective_tld_names.gperf"
+#line 1500 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str535, 0},
-#line 1287 "effective_tld_names.gperf"
+#line 1229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str536, 0},
-#line 4524 "effective_tld_names.gperf"
+#line 3400 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str537, 0},
-#line 3278 "effective_tld_names.gperf"
+#line 2380 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str538, 0},
-#line 1415 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str539, 2},
-#line 3310 "effective_tld_names.gperf"
+#line 1431 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str539, 0},
+#line 477 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str540, 0},
-#line 3413 "effective_tld_names.gperf"
+#line 3315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str541, 0},
-#line 4923 "effective_tld_names.gperf"
+#line 466 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str542, 0},
-#line 3279 "effective_tld_names.gperf"
+#line 3430 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str543, 0},
-#line 402 "effective_tld_names.gperf"
+#line 3462 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str544, 0},
-#line 5215 "effective_tld_names.gperf"
+#line 2057 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str545, 0},
-#line 1856 "effective_tld_names.gperf"
+#line 3460 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str546, 0},
-#line 363 "effective_tld_names.gperf"
+#line 3461 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str547, 0},
-#line 5636 "effective_tld_names.gperf"
+#line 37 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str548, 0},
-#line 4555 "effective_tld_names.gperf"
+#line 1682 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str549, 0},
-#line 3210 "effective_tld_names.gperf"
+#line 1690 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str550, 0},
-#line 359 "effective_tld_names.gperf"
+#line 2180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str551, 0},
-#line 5611 "effective_tld_names.gperf"
+#line 601 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str552, 0},
-#line 469 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str553, 0},
-#line 1388 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str554, 0},
-#line 3275 "effective_tld_names.gperf"
+#line 517 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str553, 4},
+#line 824 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str554, 2},
+#line 1476 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str555, 0},
-#line 457 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str556, 4},
-#line 3296 "effective_tld_names.gperf"
+#line 1869 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str556, 0},
+#line 583 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str557, 0},
-#line 2994 "effective_tld_names.gperf"
+#line 1293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str558, 0},
-#line 1086 "effective_tld_names.gperf"
+#line 118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str559, 0},
-#line 5558 "effective_tld_names.gperf"
+#line 965 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str560, 0},
-#line 3082 "effective_tld_names.gperf"
+#line 3374 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str561, 0},
-#line 5203 "effective_tld_names.gperf"
+#line 3424 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str562, 0},
-#line 5214 "effective_tld_names.gperf"
+#line 3423 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str563, 0},
-#line 1336 "effective_tld_names.gperf"
+#line 3385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str564, 0},
-#line 5073 "effective_tld_names.gperf"
+#line 1704 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str565, 0},
-#line 309 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str566, 0},
-#line 164 "effective_tld_names.gperf"
+#line 1507 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str566, 2},
+#line 2506 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str567, 0},
-#line 1468 "effective_tld_names.gperf"
+#line 3438 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str568, 0},
-#line 4940 "effective_tld_names.gperf"
+#line 1871 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str569, 0},
-#line 3421 "effective_tld_names.gperf"
+#line 5951 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str570, 0},
-#line 1790 "effective_tld_names.gperf"
+#line 5696 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str571, 0},
-#line 3175 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str572, 0},
-#line 286 "effective_tld_names.gperf"
+#line 513 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str572, 4},
+#line 1295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str573, 0},
-#line 4565 "effective_tld_names.gperf"
+#line 1825 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str574, 0},
-#line 599 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str575, 4},
-#line 450 "effective_tld_names.gperf"
+#line 966 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str575, 0},
+#line 1248 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str576, 0},
-#line 207 "effective_tld_names.gperf"
+#line 912 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str577, 0},
-#line 1353 "effective_tld_names.gperf"
+#line 484 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str578, 0},
-#line 3429 "effective_tld_names.gperf"
+#line 458 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str579, 0},
-#line 1115 "effective_tld_names.gperf"
+#line 3456 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str580, 0},
-#line 1792 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str581, 0},
-#line 2992 "effective_tld_names.gperf"
+#line 514 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str581, 4},
+#line 3356 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str582, 0},
-#line 1240 "effective_tld_names.gperf"
+#line 346 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str583, 0},
-#line 5559 "effective_tld_names.gperf"
+#line 396 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str584, 0},
-#line 938 "effective_tld_names.gperf"
+#line 303 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str585, 0},
-#line 300 "effective_tld_names.gperf"
+#line 3454 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str586, 0},
-#line 5602 "effective_tld_names.gperf"
+#line 1668 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str587, 0},
-#line 835 "effective_tld_names.gperf"
+#line 1453 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str588, 0},
-#line 1367 "effective_tld_names.gperf"
+#line 1321 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str589, 0},
-#line 1286 "effective_tld_names.gperf"
+#line 482 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str590, 0},
-#line 5444 "effective_tld_names.gperf"
+#line 993 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str591, 0},
-#line 5557 "effective_tld_names.gperf"
+#line 3355 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str592, 0},
-#line 1673 "effective_tld_names.gperf"
+#line 1630 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str593, 0},
-#line 5085 "effective_tld_names.gperf"
+#line 5727 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str594, 0},
-#line 479 "effective_tld_names.gperf"
+#line 5878 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str595, 0},
-#line 433 "effective_tld_names.gperf"
+#line 1366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str596, 0},
-#line 388 "effective_tld_names.gperf"
+#line 5879 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str597, 0},
-#line 3285 "effective_tld_names.gperf"
+#line 483 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str598, 0},
-#line 5239 "effective_tld_names.gperf"
+#line 244 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str599, 0},
-#line 5579 "effective_tld_names.gperf"
+#line 2414 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str600, 0},
-#line 5269 "effective_tld_names.gperf"
+#line 3391 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str601, 0},
-#line 291 "effective_tld_names.gperf"
+#line 3422 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str602, 0},
-#line 4905 "effective_tld_names.gperf"
+#line 3439 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str603, 0},
-#line 5388 "effective_tld_names.gperf"
+#line 5913 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str604, 0},
-#line 2492 "effective_tld_names.gperf"
+#line 480 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str605, 0},
-#line 1676 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str606, 0},
-#line 3067 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str607, 0},
-#line 2925 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str608, 0},
-#line 1534 "effective_tld_names.gperf"
+#line 507 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str606, 4},
+#line 1631 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str607, 4},
+#line 1798 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str608, 4},
+#line 584 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str609, 0},
-#line 1597 "effective_tld_names.gperf"
+#line 3436 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str610, 0},
-#line 4959 "effective_tld_names.gperf"
+#line 2345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str611, 0},
-#line 5561 "effective_tld_names.gperf"
+#line 1077 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str612, 0},
-#line 1675 "effective_tld_names.gperf"
+#line 3661 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str613, 0},
-#line 4955 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str614, 0},
-#line 1399 "effective_tld_names.gperf"
+#line 523 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str614, 4},
+#line 1433 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str615, 0},
-#line 1888 "effective_tld_names.gperf"
+#line 652 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str616, 0},
-#line 301 "effective_tld_names.gperf"
+#line 3354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str617, 0},
-#line 1588 "effective_tld_names.gperf"
+#line 3463 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str618, 0},
-#line 3314 "effective_tld_names.gperf"
+#line 6239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str619, 0},
-#line 3281 "effective_tld_names.gperf"
+#line 3557 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str620, 0},
-#line 1702 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str621, 4},
-#line 1035 "effective_tld_names.gperf"
+#line 5915 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str621, 0},
+#line 2178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str622, 0},
-#line 3206 "effective_tld_names.gperf"
+#line 1529 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str623, 0},
-#line 803 "effective_tld_names.gperf"
+#line 589 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str624, 0},
-#line 348 "effective_tld_names.gperf"
+#line 3298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str625, 0},
-#line 4586 "effective_tld_names.gperf"
+#line 3583 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str626, 0},
-#line 1689 "effective_tld_names.gperf"
+#line 392 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str627, 0},
-#line 2473 "effective_tld_names.gperf"
+#line 2410 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str628, 0},
-#line 5386 "effective_tld_names.gperf"
+#line 1471 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str629, 0},
-#line 5634 "effective_tld_names.gperf"
+#line 2319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str630, 0},
-#line 1725 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str631, 0},
-#line 2496 "effective_tld_names.gperf"
+#line 508 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str631, 4},
+#line 1514 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str632, 0},
-#line 1718 "effective_tld_names.gperf"
+#line 433 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str633, 0},
-#line 5582 "effective_tld_names.gperf"
+#line 126 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str634, 0},
-#line 1173 "effective_tld_names.gperf"
+#line 3420 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str635, 0},
-#line 2500 "effective_tld_names.gperf"
+#line 1868 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str636, 0},
-#line 1356 "effective_tld_names.gperf"
+#line 1292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str637, 0},
-#line 864 "effective_tld_names.gperf"
+#line 2179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str638, 0},
-#line 468 "effective_tld_names.gperf"
+#line 5924 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str639, 0},
-#line 4540 "effective_tld_names.gperf"
+#line 3417 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str640, 0},
-#line 1387 "effective_tld_names.gperf"
+#line 964 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str641, 0},
-#line 2485 "effective_tld_names.gperf"
+#line 3375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str642, 0},
-#line 2933 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str643, 2},
-#line 5254 "effective_tld_names.gperf"
+#line 1744 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str643, 4},
+#line 5918 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str644, 0},
-#line 2792 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str645, 2},
-#line 2540 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str646, 0},
-#line 5060 "effective_tld_names.gperf"
+#line 496 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str645, 0},
+#line 5690 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str646, 2},
+#line 747 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str647, 0},
-#line 3277 "effective_tld_names.gperf"
+#line 2226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str648, 0},
-#line 2499 "effective_tld_names.gperf"
+#line 3419 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str649, 0},
-#line 1392 "effective_tld_names.gperf"
+#line 5949 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str650, 0},
-#line 245 "effective_tld_names.gperf"
+#line 5942 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str651, 0},
-#line 2489 "effective_tld_names.gperf"
+#line 5932 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str652, 0},
-#line 1824 "effective_tld_names.gperf"
+#line 3418 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str653, 0},
-#line 2456 "effective_tld_names.gperf"
+#line 647 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str654, 0},
-#line 1273 "effective_tld_names.gperf"
+#line 5944 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str655, 0},
-#line 1382 "effective_tld_names.gperf"
+#line 1369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str656, 0},
-#line 3003 "effective_tld_names.gperf"
+#line 1531 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str657, 0},
-#line 976 "effective_tld_names.gperf"
+#line 1748 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str658, 0},
-#line 2731 "effective_tld_names.gperf"
+#line 3452 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str659, 0},
-#line 1412 "effective_tld_names.gperf"
+#line 3284 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str660, 0},
-#line 4757 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str661, 4},
-#line 3007 "effective_tld_names.gperf"
+#line 3466 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str661, 0},
+#line 3269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str662, 0},
-#line 310 "effective_tld_names.gperf"
+#line 3376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str663, 0},
-#line 977 "effective_tld_names.gperf"
+#line 2318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str664, 0},
-#line 3326 "effective_tld_names.gperf"
+#line 3450 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str665, 0},
-#line 5016 "effective_tld_names.gperf"
+#line 828 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str666, 0},
-#line 1018 "effective_tld_names.gperf"
+#line 1557 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str667, 0},
-#line 1408 "effective_tld_names.gperf"
+#line 298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str668, 0},
-#line 5248 "effective_tld_names.gperf"
+#line 2037 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str669, 0},
-#line 3116 "effective_tld_names.gperf"
+#line 665 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str670, 0},
-#line 2917 "effective_tld_names.gperf"
+#line 3467 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str671, 0},
-#line 1605 "effective_tld_names.gperf"
+#line 3664 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str672, 0},
-#line 3048 "effective_tld_names.gperf"
+#line 1722 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str673, 0},
-#line 4519 "effective_tld_names.gperf"
+#line 375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str674, 0},
-#line 4567 "effective_tld_names.gperf"
+#line 2415 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str675, 0},
-#line 3235 "effective_tld_names.gperf"
+#line 1511 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str676, 0},
-#line 2539 "effective_tld_names.gperf"
+#line 1084 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str677, 0},
-#line 2965 "effective_tld_names.gperf"
+#line 3469 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str678, 0},
-#line 4770 "effective_tld_names.gperf"
+#line 1705 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str679, 0},
-#line 5593 "effective_tld_names.gperf"
+#line 195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str680, 0},
-#line 5392 "effective_tld_names.gperf"
+#line 3316 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str681, 0},
-#line 3006 "effective_tld_names.gperf"
+#line 598 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str682, 0},
-#line 4987 "effective_tld_names.gperf"
+#line 3581 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str683, 0},
-#line 3316 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str684, 0},
-#line 1320 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str685, 0},
-#line 3519 "effective_tld_names.gperf"
+#line 1810 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str684, 4},
+#line 520 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str685, 4},
+#line 1367 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str686, 0},
-#line 1823 "effective_tld_names.gperf"
+#line 243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str687, 0},
-#line 2123 "effective_tld_names.gperf"
+#line 836 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str688, 0},
-#line 1272 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str689, 0},
-#line 2072 "effective_tld_names.gperf"
+#line 540 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str689, 4},
+#line 5914 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str690, 0},
-#line 5637 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str691, 0},
-#line 4977 "effective_tld_names.gperf"
+#line 2451 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str691, 4},
+#line 2554 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str692, 0},
-#line 975 "effective_tld_names.gperf"
+#line 2170 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str693, 0},
-#line 3075 "effective_tld_names.gperf"
+#line 430 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str694, 0},
-#line 3284 "effective_tld_names.gperf"
+#line 5897 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str695, 0},
-#line 3428 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str696, 0},
-#line 5447 "effective_tld_names.gperf"
+#line 524 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str696, 4},
+#line 2258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str697, 0},
-#line 3489 "effective_tld_names.gperf"
+#line 2203 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str698, 0},
-#line 2502 "effective_tld_names.gperf"
+#line 1463 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str699, 0},
-#line 2120 "effective_tld_names.gperf"
+#line 5726 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str700, 0},
-#line 3047 "effective_tld_names.gperf"
+#line 3307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str701, 0},
-#line 1842 "effective_tld_names.gperf"
+#line 127 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str702, 0},
-#line 3080 "effective_tld_names.gperf"
+#line 381 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str703, 0},
-#line 4919 "effective_tld_names.gperf"
+#line 179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str704, 0},
-#line 2484 "effective_tld_names.gperf"
+#line 511 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str705, 4},
-#line 723 "effective_tld_names.gperf"
+#line 3595 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str706, 0},
-#line 3155 "effective_tld_names.gperf"
+#line 1988 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str707, 0},
-#line 5330 "effective_tld_names.gperf"
+#line 399 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str708, 0},
-#line 2501 "effective_tld_names.gperf"
+#line 1426 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str709, 0},
-#line 2122 "effective_tld_names.gperf"
+#line 5953 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str710, 0},
-#line 444 "effective_tld_names.gperf"
+#line 5769 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str711, 0},
-#line 837 "effective_tld_names.gperf"
+#line 618 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str712, 0},
-#line 2541 "effective_tld_names.gperf"
+#line 5917 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str713, 0},
-#line 3283 "effective_tld_names.gperf"
+#line 657 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str714, 0},
-#line 5238 "effective_tld_names.gperf"
+#line 631 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str715, 0},
-#line 2498 "effective_tld_names.gperf"
+#line 3074 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str716, 0},
-#line 473 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str717, 0},
-#line 118 "effective_tld_names.gperf"
+#line 834 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str717, 4},
+#line 1095 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str718, 0},
-#line 3288 "effective_tld_names.gperf"
+#line 734 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str719, 0},
-#line 5020 "effective_tld_names.gperf"
+#line 2982 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str720, 0},
-#line 1453 "effective_tld_names.gperf"
+#line 667 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str721, 0},
-#line 3009 "effective_tld_names.gperf"
+#line 1908 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str722, 0},
-#line 3436 "effective_tld_names.gperf"
+#line 1332 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str723, 0},
-#line 1891 "effective_tld_names.gperf"
+#line 587 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str724, 0},
-#line 3501 "effective_tld_names.gperf"
+#line 1004 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str725, 0},
-#line 1037 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str726, 2},
-#line 1369 "effective_tld_names.gperf"
+#line 3442 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str726, 0},
+#line 3441 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str727, 0},
-#line 5106 "effective_tld_names.gperf"
+#line 5919 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str728, 0},
-#line 5096 "effective_tld_names.gperf"
+#line 795 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str729, 0},
-#line 3441 "effective_tld_names.gperf"
+#line 1109 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str730, 0},
-#line 4809 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str731, 0},
-#line 109 "effective_tld_names.gperf"
+#line 2919 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str731, 2},
+#line 2991 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str732, 0},
-#line 4539 "effective_tld_names.gperf"
+#line 2321 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str733, 0},
-#line 1726 "effective_tld_names.gperf"
+#line 2618 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str734, 0},
-#line 1709 "effective_tld_names.gperf"
+#line 5916 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str735, 0},
-#line 1180 "effective_tld_names.gperf"
+#line 2916 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str736, 0},
-#line 2463 "effective_tld_names.gperf"
+#line 2619 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str737, 0},
-#line 874 "effective_tld_names.gperf"
+#line 478 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str738, 0},
-#line 3008 "effective_tld_names.gperf"
+#line 3630 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str739, 0},
-#line 1023 "effective_tld_names.gperf"
+#line 1997 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str740, 0},
-#line 1398 "effective_tld_names.gperf"
+#line 1102 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str741, 0},
-#line 3167 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str742, 0},
-#line 3287 "effective_tld_names.gperf"
+#line 2830 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str742, 2},
+#line 1931 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str743, 0},
-#line 1343 "effective_tld_names.gperf"
+#line 2398 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str744, 0},
-#line 4687 "effective_tld_names.gperf"
+#line 1354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str745, 0},
-#line 3049 "effective_tld_names.gperf"
+#line 1032 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str746, 0},
-#line 5437 "effective_tld_names.gperf"
+#line 5925 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str747, 0},
-#line 1825 "effective_tld_names.gperf"
+#line 1914 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str748, 0},
-#line 2934 "effective_tld_names.gperf"
+#line 356 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str749, 0},
-#line 2497 "effective_tld_names.gperf"
+#line 1338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str750, 0},
-#line 305 "effective_tld_names.gperf"
+#line 285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str751, 0},
-#line 1274 "effective_tld_names.gperf"
+#line 1010 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str752, 0},
-#line 3005 "effective_tld_names.gperf"
+#line 908 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str753, 0},
-#line 3110 "effective_tld_names.gperf"
+#line 1412 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str754, 0},
-#line 978 "effective_tld_names.gperf"
+#line 1082 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str755, 0},
-#line 1355 "effective_tld_names.gperf"
+#line 1739 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str756, 0},
-#line 1810 "effective_tld_names.gperf"
+#line 2990 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str757, 0},
-#line 1280 "effective_tld_names.gperf"
+#line 616 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str758, 0},
-#line 3146 "effective_tld_names.gperf"
+#line 1413 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str759, 0},
-#line 4956 "effective_tld_names.gperf"
+#line 336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str760, 0},
-#line 959 "effective_tld_names.gperf"
+#line 811 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str761, 0},
-#line 422 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str762, 0},
-#line 605 "effective_tld_names.gperf"
+#line 529 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str762, 4},
+#line 217 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str763, 0},
-#line 3013 "effective_tld_names.gperf"
+#line 573 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str764, 0},
-#line 395 "effective_tld_names.gperf"
+#line 1025 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str765, 0},
-#line 1898 "effective_tld_names.gperf"
+#line 1986 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str766, 0},
-#line 5576 "effective_tld_names.gperf"
+#line 218 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str767, 0},
-#line 2506 "effective_tld_names.gperf"
+#line 1895 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str768, 0},
-#line 3356 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str769, 4},
-#line 3465 "effective_tld_names.gperf"
+#line 1316 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str769, 0},
+#line 2849 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str770, 0},
-#line 2503 "effective_tld_names.gperf"
+#line 988 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str771, 0},
-#line 852 "effective_tld_names.gperf"
+#line 2862 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str772, 0},
-#line 590 "effective_tld_names.gperf"
+#line 1941 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str773, 0},
-#line 3004 "effective_tld_names.gperf"
+#line 634 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str774, 0},
-#line 5589 "effective_tld_names.gperf"
+#line 1477 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str775, 0},
-#line 5054 "effective_tld_names.gperf"
+#line 1853 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str776, 0},
-#line 409 "effective_tld_names.gperf"
+#line 1274 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str777, 0},
-#line 3159 "effective_tld_names.gperf"
+#line 1745 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str778, 0},
-#line 1465 "effective_tld_names.gperf"
+#line 2163 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str779, 0},
-#line 3158 "effective_tld_names.gperf"
+#line 3265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str780, 0},
-#line 5064 "effective_tld_names.gperf"
+#line 943 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str781, 0},
-#line 1608 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str782, 4},
-#line 340 "effective_tld_names.gperf"
+#line 160 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str782, 0},
+#line 313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str783, 0},
-#line 449 "effective_tld_names.gperf"
+#line 1087 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str784, 0},
-#line 1401 "effective_tld_names.gperf"
+#line 3501 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str785, 0},
-#line 3305 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str786, 0},
-#line 3522 "effective_tld_names.gperf"
+#line 6388 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str786, 2},
+#line 3378 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str787, 0},
-#line 606 "effective_tld_names.gperf"
+#line 3063 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str788, 0},
-#line 4709 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str789, 0},
-#line 2074 "effective_tld_names.gperf"
+#line 5922 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str789, 4},
+#line 3369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str790, 0},
-#line 1397 "effective_tld_names.gperf"
+#line 1943 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str791, 0},
-#line 1829 "effective_tld_names.gperf"
+#line 1053 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str792, 0},
-#line 426 "effective_tld_names.gperf"
+#line 468 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str793, 0},
-#line 1851 "effective_tld_names.gperf"
+#line 2630 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str794, 0},
-#line 184 "effective_tld_names.gperf"
+#line 1438 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str795, 0},
-#line 2935 "effective_tld_names.gperf"
+#line 1440 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str796, 0},
-#line 4516 "effective_tld_names.gperf"
+#line 382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str797, 0},
-#line 219 "effective_tld_names.gperf"
+#line 5902 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str798, 0},
-#line 3010 "effective_tld_names.gperf"
+#line 831 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str799, 0},
-#line 3117 "effective_tld_names.gperf"
+#line 3672 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str800, 0},
-#line 332 "effective_tld_names.gperf"
+#line 2913 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str801, 0},
-#line 2745 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str802, 0},
-#line 5194 "effective_tld_names.gperf"
+#line 1099 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str802, 4},
+#line 662 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str803, 0},
-#line 4582 "effective_tld_names.gperf"
+#line 3571 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str804, 0},
-#line 2926 "effective_tld_names.gperf"
+#line 1392 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str805, 0},
-#line 3156 "effective_tld_names.gperf"
+#line 1890 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str806, 0},
-#line 371 "effective_tld_names.gperf"
+#line 441 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str807, 0},
-#line 807 "effective_tld_names.gperf"
+#line 5678 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str808, 0},
-#line 1535 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str809, 4},
-#line 4932 "effective_tld_names.gperf"
+#line 981 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str809, 0},
+#line 645 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str810, 0},
-#line 220 "effective_tld_names.gperf"
+#line 670 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str811, 0},
-#line 4529 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str812, 1},
-#line 5331 "effective_tld_names.gperf"
+#line 2021 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str812, 0},
+#line 5741 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str813, 0},
-#line 627 "effective_tld_names.gperf"
+#line 668 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str814, 0},
-#line 5387 "effective_tld_names.gperf"
+#line 420 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str815, 0},
-#line 1987 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str816, 0},
-#line 2549 "effective_tld_names.gperf"
+#line 2356 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str816, 4},
+#line 1804 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str817, 0},
-#line 464 "effective_tld_names.gperf"
+#line 732 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str818, 0},
-#line 1710 "effective_tld_names.gperf"
+#line 167 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str819, 0},
-#line 540 "effective_tld_names.gperf"
+#line 1666 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str820, 0},
-#line 372 "effective_tld_names.gperf"
+#line 3613 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str821, 0},
-#line 1386 "effective_tld_names.gperf"
+#line 5901 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str822, 0},
-#line 3108 "effective_tld_names.gperf"
+#line 457 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str823, 0},
-#line 2548 "effective_tld_names.gperf"
+#line 209 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str824, 0},
-#line 181 "effective_tld_names.gperf"
+#line 3569 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str825, 0},
-#line 1081 "effective_tld_names.gperf"
+#line 351 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str826, 0},
-#line 307 "effective_tld_names.gperf"
+#line 3313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str827, 0},
-#line 5382 "effective_tld_names.gperf"
+#line 1037 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str828, 0},
-#line 4791 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str829, 4},
-#line 4579 "effective_tld_names.gperf"
+#line 1681 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str829, 0},
+#line 1828 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str830, 0},
-#line 1074 "effective_tld_names.gperf"
+#line 2503 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str831, 0},
-#line 3475 "effective_tld_names.gperf"
+#line 581 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str832, 0},
-#line 999 "effective_tld_names.gperf"
+#line 1252 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str833, 0},
-#line 423 "effective_tld_names.gperf"
+#line 3289 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str834, 0},
-#line 3056 "effective_tld_names.gperf"
+#line 918 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str835, 0},
-#line 1360 "effective_tld_names.gperf"
+#line 4651 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str836, 0},
-#line 3507 "effective_tld_names.gperf"
+#line 1884 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str837, 0},
-#line 1156 "effective_tld_names.gperf"
+#line 5697 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str838, 0},
-#line 1897 "effective_tld_names.gperf"
+#line 1306 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str839, 0},
-#line 2632 "effective_tld_names.gperf"
+#line 976 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str840, 0},
-#line 3055 "effective_tld_names.gperf"
+#line 3648 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str841, 0},
-#line 4527 "effective_tld_names.gperf"
+#line 1225 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str842, 0},
-#line 1417 "effective_tld_names.gperf"
+#line 2981 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str843, 0},
-#line 1523 "effective_tld_names.gperf"
+#line 407 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str844, 0},
-#line 591 "effective_tld_names.gperf"
+#line 2143 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str845, 0},
-#line 5594 "effective_tld_names.gperf"
+#line 810 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str846, 0},
-#line 1372 "effective_tld_names.gperf"
+#line 299 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str847, 0},
-#line 1053 "effective_tld_names.gperf"
+#line 1521 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str848, 0},
-#line 5431 "effective_tld_names.gperf"
+#line 198 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str849, 0},
-#line 2530 "effective_tld_names.gperf"
+#line 1400 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str850, 0},
-#line 2527 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str851, 0},
-#line 2526 "effective_tld_names.gperf"
+#line 542 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str851, 4},
+#line 2753 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str852, 0},
-#line 4572 "effective_tld_names.gperf"
+#line 3380 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str853, 0},
-#line 710 "effective_tld_names.gperf"
+#line 646 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str854, 0},
-#line 1359 "effective_tld_names.gperf"
+#line 913 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str855, 0},
-#line 936 "effective_tld_names.gperf"
+#line 2328 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str856, 0},
-#line 1405 "effective_tld_names.gperf"
+#line 5705 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str857, 0},
-#line 4785 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str858, 2},
-#line 2969 "effective_tld_names.gperf"
+#line 436 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str858, 0},
+#line 3304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str859, 0},
-#line 5081 "effective_tld_names.gperf"
+#line 2201 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str860, 0},
-#line 838 "effective_tld_names.gperf"
+#line 1380 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str861, 0},
-#line 180 "effective_tld_names.gperf"
+#line 3502 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str862, 0},
-#line 532 "effective_tld_names.gperf"
+#line 3279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str863, 0},
-#line 1630 "effective_tld_names.gperf"
+#line 2085 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str864, 0},
-#line 1282 "effective_tld_names.gperf"
+#line 6370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str865, 0},
-#line 2128 "effective_tld_names.gperf"
+#line 2159 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str866, 0},
-#line 2483 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str867, 4},
-#line 703 "effective_tld_names.gperf"
+#line 5746 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str867, 0},
+#line 761 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str868, 0},
-#line 2068 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str869, 0},
-#line 4807 "effective_tld_names.gperf"
+#line 444 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str869, 4},
+#line 4645 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str870, 0},
-#line 95 "effective_tld_names.gperf"
+#line 655 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str871, 0},
-#line 1464 "effective_tld_names.gperf"
+#line 1484 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str872, 0},
-#line 3038 "effective_tld_names.gperf"
+#line 1797 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str873, 0},
-#line 3035 "effective_tld_names.gperf"
+#line 5907 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str874, 0},
-#line 3034 "effective_tld_names.gperf"
+#line 756 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str875, 0},
-#line 3327 "effective_tld_names.gperf"
+#line 88 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str876, 0},
-#line 2525 "effective_tld_names.gperf"
+#line 491 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str877, 0},
-#line 246 "effective_tld_names.gperf"
+#line 1542 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str878, 0},
-#line 1349 "effective_tld_names.gperf"
+#line 576 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str879, 0},
-#line 3071 "effective_tld_names.gperf"
+#line 738 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str880, 0},
-#line 5384 "effective_tld_names.gperf"
+#line 1549 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str881, 0},
-#line 822 "effective_tld_names.gperf"
+#line 3371 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str882, 0},
-#line 2713 "effective_tld_names.gperf"
+#line 3662 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str883, 0},
-#line 4492 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str884, 0},
-#line 2927 "effective_tld_names.gperf"
+#line 2839 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str884, 2},
+#line 3617 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str885, 0},
-#line 96 "effective_tld_names.gperf"
+#line 150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str886, 0},
-#line 4530 "effective_tld_names.gperf"
+#line 6371 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str887, 0},
-#line 454 "effective_tld_names.gperf"
+#line 5676 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str888, 0},
-#line 3258 "effective_tld_names.gperf"
+#line 5706 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str889, 0},
-#line 1708 "effective_tld_names.gperf"
+#line 1089 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str890, 0},
-#line 4792 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str891, 4},
-#line 183 "effective_tld_names.gperf"
+#line 1372 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str891, 0},
+#line 3455 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str892, 0},
-#line 375 "effective_tld_names.gperf"
+#line 5950 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str893, 0},
-#line 280 "effective_tld_names.gperf"
+#line 1368 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str894, 0},
-#line 4480 "effective_tld_names.gperf"
+#line 353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str895, 0},
-#line 3033 "effective_tld_names.gperf"
+#line 2659 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str896, 0},
-#line 303 "effective_tld_names.gperf"
+#line 2043 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str897, 0},
-#line 1623 "effective_tld_names.gperf"
+#line 2628 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str898, 0},
-#line 1153 "effective_tld_names.gperf"
+#line 3403 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str899, 0},
-#line 3323 "effective_tld_names.gperf"
+#line 3498 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str900, 0},
-#line 562 "effective_tld_names.gperf"
+#line 2658 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str901, 0},
-#line 5249 "effective_tld_names.gperf"
+#line 2663 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str902, 0},
-#line 1409 "effective_tld_names.gperf"
+#line 388 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str903, 0},
-#line 1603 "effective_tld_names.gperf"
+#line 3655 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str904, 0},
-#line 2867 "effective_tld_names.gperf"
+#line 178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str905, 0},
-#line 419 "effective_tld_names.gperf"
+#line 1375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str906, 0},
-#line 3243 "effective_tld_names.gperf"
+#line 2330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str907, 0},
-#line 1083 "effective_tld_names.gperf"
+#line 2629 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str908, 0},
-#line 3107 "effective_tld_names.gperf"
+#line 5760 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str909, 0},
-#line 1451 "effective_tld_names.gperf"
+#line 305 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str910, 0},
-#line 1406 "effective_tld_names.gperf"
+#line 6377 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str911, 0},
-#line 3234 "effective_tld_names.gperf"
+#line 182 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str912, 0},
-#line 2545 "effective_tld_names.gperf"
+#line 2966 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str913, 0},
-#line 1120 "effective_tld_names.gperf"
+#line 2988 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str914, 0},
-#line 1418 "effective_tld_names.gperf"
+#line 2653 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str915, 0},
-#line 5243 "effective_tld_names.gperf"
+#line 2654 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str916, 0},
-#line 5448 "effective_tld_names.gperf"
+#line 2340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str917, 0},
-#line 3322 "effective_tld_names.gperf"
+#line 605 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str918, 0},
-#line 2996 "effective_tld_names.gperf"
+#line 2649 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str919, 0},
-#line 4953 "effective_tld_names.gperf"
+#line 1803 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str920, 0},
-#line 5078 "effective_tld_names.gperf"
+#line 1396 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str921, 0},
-#line 2866 "effective_tld_names.gperf"
+#line 1054 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str922, 0},
-#line 698 "effective_tld_names.gperf"
+#line 654 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str923, 0},
-#line 1066 "effective_tld_names.gperf"
+#line 322 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str924, 0},
-#line 5619 "effective_tld_names.gperf"
+#line 2651 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str925, 0},
-#line 470 "effective_tld_names.gperf"
+#line 1086 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str926, 0},
-#line 1020 "effective_tld_names.gperf"
+#line 159 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str927, 0},
-#line 765 "effective_tld_names.gperf"
+#line 3448 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str928, 0},
-#line 448 "effective_tld_names.gperf"
+#line 419 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str929, 0},
-#line 1413 "effective_tld_names.gperf"
+#line 2082 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str930, 0},
-#line 1122 "effective_tld_names.gperf"
+#line 2640 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str931, 0},
-#line 809 "effective_tld_names.gperf"
+#line 3531 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str932, 0},
-#line 3358 "effective_tld_names.gperf"
+#line 5740 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str933, 0},
-#line 1969 "effective_tld_names.gperf"
+#line 3512 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str934, 0},
-#line 3000 "effective_tld_names.gperf"
+#line 749 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str935, 0},
-#line 1384 "effective_tld_names.gperf"
+#line 1050 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str936, 0},
-#line 360 "effective_tld_names.gperf"
+#line 2313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str937, 0},
-#line 1279 "effective_tld_names.gperf"
+#line 1407 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str938, 0},
-#line 102 "effective_tld_names.gperf"
+#line 3431 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str939, 0},
-#line 4560 "effective_tld_names.gperf"
+#line 3263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str940, 0},
-#line 5074 "effective_tld_names.gperf"
+#line 229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str941, 0},
-#line 5592 "effective_tld_names.gperf"
+#line 1790 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str942, 0},
-#line 4526 "effective_tld_names.gperf"
+#line 3276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str943, 0},
-#line 5027 "effective_tld_names.gperf"
+#line 2668 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str944, 0},
-#line 5573 "effective_tld_names.gperf"
+#line 2144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str945, 0},
-#line 792 "effective_tld_names.gperf"
+#line 2650 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str946, 0},
-#line 2931 "effective_tld_names.gperf"
+#line 497 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str947, 0},
-#line 2529 "effective_tld_names.gperf"
+#line 1867 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str948, 0},
-#line 1835 "effective_tld_names.gperf"
+#line 292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str949, 0},
-#line 1154 "effective_tld_names.gperf"
+#line 602 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str950, 0},
-#line 345 "effective_tld_names.gperf"
+#line 1291 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str951, 0},
-#line 617 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str952, 0},
-#line 2891 "effective_tld_names.gperf"
+#line 818 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str952, 1},
+#line 963 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str953, 0},
-#line 2865 "effective_tld_names.gperf"
+#line 1556 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str954, 0},
-#line 5446 "effective_tld_names.gperf"
+#line 2833 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str955, 0},
-#line 3313 "effective_tld_names.gperf"
+#line 2636 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str956, 0},
-#line 5343 "effective_tld_names.gperf"
+#line 661 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str957, 0},
-#line 5453 "effective_tld_names.gperf"
+#line 3410 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str958, 0},
-#line 5455 "effective_tld_names.gperf"
+#line 3295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str959, 0},
-#line 2546 "effective_tld_names.gperf"
+#line 2662 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str960, 0},
-#line 2960 "effective_tld_names.gperf"
+#line 344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str961, 0},
-#line 2971 "effective_tld_names.gperf"
+#line 611 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str962, 0},
-#line 2718 "effective_tld_names.gperf"
+#line 1669 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str963, 0},
-#line 4576 "effective_tld_names.gperf"
+#line 2987 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str964, 0},
-#line 1054 "effective_tld_names.gperf"
+#line 3570 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str965, 0},
-#line 431 "effective_tld_names.gperf"
+#line 2647 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str966, 0},
-#line 566 "effective_tld_names.gperf"
+#line 2646 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str967, 0},
-#line 5053 "effective_tld_names.gperf"
+#line 2634 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str968, 0},
-#line 346 "effective_tld_names.gperf"
+#line 2635 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str969, 0},
-#line 3037 "effective_tld_names.gperf"
+#line 787 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str970, 0},
-#line 2544 "effective_tld_names.gperf"
+#line 1734 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str971, 0},
-#line 3466 "effective_tld_names.gperf"
+#line 180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str972, 0},
-#line 4904 "effective_tld_names.gperf"
+#line 3270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str973, 0},
-#line 5369 "effective_tld_names.gperf"
+#line 391 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str974, 0},
-#line 1986 "effective_tld_names.gperf"
+#line 2643 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str975, 0},
-#line 5595 "effective_tld_names.gperf"
+#line 3504 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str976, 0},
-#line 329 "effective_tld_names.gperf"
+#line 3445 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str977, 0},
-#line 182 "effective_tld_names.gperf"
+#line 2912 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str978, 0},
-#line 2125 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str979, 4},
-#line 2075 "effective_tld_names.gperf"
+#line 773 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str979, 0},
+#line 1513 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str980, 0},
-#line 432 "effective_tld_names.gperf"
+#line 3594 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str981, 0},
-#line 4902 "effective_tld_names.gperf"
+#line 2623 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str982, 0},
-#line 244 "effective_tld_names.gperf"
+#line 2622 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str983, 0},
-#line 3053 "effective_tld_names.gperf"
+#line 1675 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str984, 0},
-#line 1014 "effective_tld_names.gperf"
+#line 736 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str985, 0},
-#line 1410 "effective_tld_names.gperf"
+#line 464 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str986, 0},
-#line 5251 "effective_tld_names.gperf"
+#line 905 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str987, 0},
-#line 1578 "effective_tld_names.gperf"
+#line 2165 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str988, 0},
-#line 2086 "effective_tld_names.gperf"
+#line 744 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str989, 0},
-#line 1357 "effective_tld_names.gperf"
+#line 462 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str990, 0},
-#line 3052 "effective_tld_names.gperf"
+#line 1952 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str991, 0},
-#line 5607 "effective_tld_names.gperf"
+#line 2620 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str992, 0},
-#line 4975 "effective_tld_names.gperf"
+#line 755 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str993, 0},
-#line 5072 "effective_tld_names.gperf"
+#line 2002 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str994, 0},
-#line 1979 "effective_tld_names.gperf"
+#line 2641 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str995, 0},
-#line 376 "effective_tld_names.gperf"
+#line 2901 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str996, 0},
-#line 5083 "effective_tld_names.gperf"
+#line 2642 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str997, 0},
-#line 230 "effective_tld_names.gperf"
+#line 2661 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str998, 0},
-#line 417 "effective_tld_names.gperf"
+#line 2621 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str999, 0},
-#line 4918 "effective_tld_names.gperf"
+#line 397 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1000, 0},
-#line 370 "effective_tld_names.gperf"
+#line 183 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1001, 0},
-#line 2070 "effective_tld_names.gperf"
+#line 1467 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1002, 0},
-#line 1585 "effective_tld_names.gperf"
+#line 3054 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1003, 0},
-#line 2113 "effective_tld_names.gperf"
+#line 3278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1004, 0},
-#line 1313 "effective_tld_names.gperf"
+#line 2761 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1005, 0},
-#line 800 "effective_tld_names.gperf"
+#line 603 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1006, 0},
-#line 2936 "effective_tld_names.gperf"
+#line 2202 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1007, 0},
-#line 3325 "effective_tld_names.gperf"
+#line 3382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1008, 0},
-#line 1293 "effective_tld_names.gperf"
+#line 3394 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1009, 0},
-#line 4658 "effective_tld_names.gperf"
+#line 181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1010, 0},
-#line 1395 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1011, 0},
-#line 2547 "effective_tld_names.gperf"
+#line 5923 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1011, 4},
+#line 1430 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1012, 0},
-#line 160 "effective_tld_names.gperf"
+#line 2329 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1013, 0},
-#line 1899 "effective_tld_names.gperf"
+#line 3047 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1014, 0},
-#line 1880 "effective_tld_names.gperf"
+#line 423 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1015, 0},
-#line 857 "effective_tld_names.gperf"
+#line 1379 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1016, 0},
-#line 2984 "effective_tld_names.gperf"
+#line 2259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1017, 0},
-#line 711 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1018, 0},
-#line 3087 "effective_tld_names.gperf"
+#line 817 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1018, 1},
+#line 2012 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1019, 0},
-#line 2909 "effective_tld_names.gperf"
+#line 753 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1020, 0},
-#line 3526 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1021, 4},
-#line 3488 "effective_tld_names.gperf"
+#line 1103 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1021, 0},
+#line 1051 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1022, 0},
-#line 2875 "effective_tld_names.gperf"
+#line 2845 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1023, 0},
-#line 793 "effective_tld_names.gperf"
+#line 341 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1024, 0},
-#line 993 "effective_tld_names.gperf"
+#line 2660 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1025, 0},
-#line 632 "effective_tld_names.gperf"
+#line 2701 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1026, 0},
-#line 1968 "effective_tld_names.gperf"
+#line 1915 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1027, 0},
-#line 5252 "effective_tld_names.gperf"
+#line 358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1028, 0},
-#line 3077 "effective_tld_names.gperf"
+#line 2644 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1029, 0},
-#line 4948 "effective_tld_names.gperf"
+#line 1011 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1030, 0},
-#line 3054 "effective_tld_names.gperf"
+#line 1550 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1031, 0},
-#line 4922 "effective_tld_names.gperf"
+#line 2617 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1032, 0},
-#line 2958 "effective_tld_names.gperf"
+#line 1717 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1033, 0},
-#line 1646 "effective_tld_names.gperf"
+#line 148 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1034, 0},
-#line 2475 "effective_tld_names.gperf"
+#line 81 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1035, 0},
-#line 2747 "effective_tld_names.gperf"
+#line 750 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1036, 0},
-#line 5456 "effective_tld_names.gperf"
+#line 197 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1037, 0},
-#line 2089 "effective_tld_names.gperf"
+#line 2667 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1038, 0},
-#line 2082 "effective_tld_names.gperf"
+#line 5941 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1039, 0},
-#line 2832 "effective_tld_names.gperf"
+#line 5937 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1040, 0},
-#line 2493 "effective_tld_names.gperf"
+#line 3283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1041, 0},
-#line 4903 "effective_tld_names.gperf"
+#line 3327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1042, 0},
-#line 2069 "effective_tld_names.gperf"
+#line 2382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1043, 0},
-#line 347 "effective_tld_names.gperf"
+#line 823 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1044, 0},
-#line 5572 "effective_tld_names.gperf"
+#line 1544 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1045, 0},
-#line 5193 "effective_tld_names.gperf"
+#line 359 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1046, 0},
-#line 5326 "effective_tld_names.gperf"
+#line 3399 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1047, 0},
-#line 3060 "effective_tld_names.gperf"
+#line 3397 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1048, 0},
-#line 5454 "effective_tld_names.gperf"
+#line 1376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1049, 0},
-#line 1396 "effective_tld_names.gperf"
+#line 2992 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1050, 0},
-#line 4677 "effective_tld_names.gperf"
+#line 2757 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1051, 0},
-#line 4917 "effective_tld_names.gperf"
+#line 2153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1052, 0},
-#line 3241 "effective_tld_names.gperf"
+#line 3523 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1053, 0},
-#line 5590 "effective_tld_names.gperf"
+#line 1485 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1054, 0},
-#line 3420 "effective_tld_names.gperf"
+#line 3651 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1055, 0},
-#line 3133 "effective_tld_names.gperf"
+#line 1558 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1056, 0},
-#line 4493 "effective_tld_names.gperf"
+#line 3552 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1057, 0},
-#line 5323 "effective_tld_names.gperf"
+#line 1833 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1058, 0},
-#line 3119 "effective_tld_names.gperf"
+#line 1397 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1059, 0},
-#line 5037 "effective_tld_names.gperf"
+#line 1256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1060, 0},
-#line 4949 "effective_tld_names.gperf"
+#line 2293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1061, 0},
-#line 4521 "effective_tld_names.gperf"
+#line 3625 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1062, 0},
-#line 5100 "effective_tld_names.gperf"
+#line 2669 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1063, 0},
-#line 2818 "effective_tld_names.gperf"
+#line 923 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1064, 0},
-#line 1617 "effective_tld_names.gperf"
+#line 334 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1065, 0},
-#line 533 "effective_tld_names.gperf"
+#line 1408 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1066, 0},
-#line 5620 "effective_tld_names.gperf"
+#line 904 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1067, 0},
-#line 4484 "effective_tld_names.gperf"
+#line 383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1068, 0},
-#line 3193 "effective_tld_names.gperf"
+#line 3673 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1069, 0},
-#line 1634 "effective_tld_names.gperf"
+#line 1619 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1070, 0},
-#line 537 "effective_tld_names.gperf"
+#line 2312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1071, 0},
-#line 2703 "effective_tld_names.gperf"
+#line 3396 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1072, 0},
-#line 1613 "effective_tld_names.gperf"
+#line 751 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1073, 0},
-#line 1003 "effective_tld_names.gperf"
+#line 2559 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1074, 0},
-#line 1536 "effective_tld_names.gperf"
+#line 3514 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1075, 0},
-#line 315 "effective_tld_names.gperf"
+#line 2515 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1076, 0},
-#line 5189 "effective_tld_names.gperf"
+#line 2954 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1077, 0},
-#line 5276 "effective_tld_names.gperf"
+#line 3487 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1078, 0},
-#line 3230 "effective_tld_names.gperf"
+#line 2357 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1079, 0},
-#line 1975 "effective_tld_names.gperf"
+#line 5868 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1080, 0},
-#line 4544 "effective_tld_names.gperf"
+#line 3591 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1081, 0},
-#line 2593 "effective_tld_names.gperf"
+#line 3527 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1082, 0},
-#line 2990 "effective_tld_names.gperf"
+#line 463 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1083, 0},
-#line 369 "effective_tld_names.gperf"
+#line 2061 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1084, 0},
-#line 608 "effective_tld_names.gperf"
+#line 3525 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1085, 0},
-#line 227 "effective_tld_names.gperf"
+#line 5866 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1086, 0},
-#line 2130 "effective_tld_names.gperf"
+#line 2638 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1087, 0},
-#line 1146 "effective_tld_names.gperf"
+#line 2477 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1088, 4},
-#line 5623 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1089, 0},
-#line 2577 "effective_tld_names.gperf"
+#line 3062 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1089, 2},
+#line 3513 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1090, 0},
-#line 1277 "effective_tld_names.gperf"
+#line 3333 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1091, 0},
-#line 3064 "effective_tld_names.gperf"
+#line 5875 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1092, 0},
-#line 4490 "effective_tld_names.gperf"
+#line 1045 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1093, 0},
-#line 4706 "effective_tld_names.gperf"
+#line 3497 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1094, 0},
-#line 3062 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1095, 4},
-#line 1902 "effective_tld_names.gperf"
+#line 3405 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1095, 0},
+#line 1808 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1096, 0},
-#line 2878 "effective_tld_names.gperf"
+#line 1811 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1097, 0},
-#line 1921 "effective_tld_names.gperf"
+#line 2077 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1098, 0},
-#line 994 "effective_tld_names.gperf"
+#line 5770 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1099, 0},
-#line 4992 "effective_tld_names.gperf"
+#line 5854 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1100, 0},
-#line 193 "effective_tld_names.gperf"
+#line 1052 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1101, 0},
-#line 163 "effective_tld_names.gperf"
+#line 3404 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1102, 0},
-#line 5282 "effective_tld_names.gperf"
+#line 752 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1103, 0},
-#line 1893 "effective_tld_names.gperf"
+#line 3440 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1104, 0},
-#line 1699 "effective_tld_names.gperf"
+#line 3528 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1105, 0},
-#line 1147 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1106, 4},
-#line 3367 "effective_tld_names.gperf"
+#line 5797 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1106, 0},
+#line 1245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1107, 0},
-#line 2477 "effective_tld_names.gperf"
+#line 2103 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1108, 0},
-#line 2470 "effective_tld_names.gperf"
+#line 754 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1109, 0},
-#line 4781 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1110, 4},
-#line 561 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1111, 4},
-#line 4674 "effective_tld_names.gperf"
+#line 2248 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1110, 0},
+#line 2332 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1111, 0},
+#line 1083 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1112, 0},
-#line 5109 "effective_tld_names.gperf"
+#line 5723 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1113, 0},
-#line 101 "effective_tld_names.gperf"
+#line 206 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1114, 0},
-#line 2087 "effective_tld_names.gperf"
+#line 2989 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1115, 0},
-#line 1570 "effective_tld_names.gperf"
+#line 3293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1116, 0},
-#line 6110 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1117, 2},
-#line 2528 "effective_tld_names.gperf"
+#line 1456 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1117, 0},
+#line 2034 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1118, 0},
-#line 1755 "effective_tld_names.gperf"
+#line 203 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1119, 0},
-#line 1754 "effective_tld_names.gperf"
+#line 3565 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1120, 0},
-#line 1638 "effective_tld_names.gperf"
+#line 3412 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1121, 0},
-#line 1107 "effective_tld_names.gperf"
+#line 187 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1122, 0},
-#line 909 "effective_tld_names.gperf"
+#line 2752 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1123, 0},
-#line 5608 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1124, 0},
-#line 195 "effective_tld_names.gperf"
+#line 532 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1124, 4},
+#line 2993 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1125, 0},
-#line 2885 "effective_tld_names.gperf"
+#line 307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1126, 0},
-#line 1660 "effective_tld_names.gperf"
+#line 3478 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1127, 0},
-#line 4984 "effective_tld_names.gperf"
+#line 2953 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1128, 0},
-#line 4686 "effective_tld_names.gperf"
+#line 1491 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1129, 0},
-#line 1166 "effective_tld_names.gperf"
+#line 2244 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1130, 0},
-#line 1759 "effective_tld_names.gperf"
+#line 5825 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1131, 0},
-#line 811 "effective_tld_names.gperf"
+#line 1898 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1132, 0},
-#line 1212 "effective_tld_names.gperf"
+#line 1405 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1133, 0},
-#line 2479 "effective_tld_names.gperf"
+#line 1322 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1134, 0},
-#line 3036 "effective_tld_names.gperf"
+#line 3516 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1135, 0},
-#line 911 "effective_tld_names.gperf"
+#line 994 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1136, 0},
-#line 1084 "effective_tld_names.gperf"
+#line 6383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1137, 0},
-#line 2695 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1138, 2},
-#line 513 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1139, 4},
-#line 3383 "effective_tld_names.gperf"
+#line 790 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1138, 0},
+#line 3061 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1139, 0},
+#line 1701 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1140, 0},
-#line 518 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1141, 4},
-#line 3059 "effective_tld_names.gperf"
+#line 1793 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1141, 0},
+#line 469 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1142, 0},
-#line 512 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1143, 4},
-#line 447 "effective_tld_names.gperf"
+#line 202 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1143, 0},
+#line 5853 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1144, 0},
-#line 1048 "effective_tld_names.gperf"
+#line 1746 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1145, 0},
-#line 2884 "effective_tld_names.gperf"
+#line 3496 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1146, 0},
-#line 522 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1147, 4},
-#line 5322 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1148, 0},
-#line 2930 "effective_tld_names.gperf"
+#line 492 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1147, 0},
+#line 814 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1148, 1},
+#line 5802 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1149, 0},
-#line 2929 "effective_tld_names.gperf"
+#line 5796 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1150, 0},
-#line 6114 "effective_tld_names.gperf"
+#line 2149 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1151, 0},
-#line 1296 "effective_tld_names.gperf"
+#line 1671 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1152, 0},
-#line 3161 "effective_tld_names.gperf"
+#line 361 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1153, 0},
-#line 2630 "effective_tld_names.gperf"
+#line 1377 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1154, 0},
-#line 107 "effective_tld_names.gperf"
+#line 5818 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1155, 0},
-#line 500 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1156, 4},
-#line 1459 "effective_tld_names.gperf"
+#line 2066 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1156, 0},
+#line 3515 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1157, 0},
-#line 6088 "effective_tld_names.gperf"
+#line 1417 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1158, 0},
-#line 1760 "effective_tld_names.gperf"
+#line 2755 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1159, 0},
-#line 1213 "effective_tld_names.gperf"
+#line 774 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1160, 0},
-#line 4625 "effective_tld_names.gperf"
+#line 5905 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1161, 0},
-#line 2893 "effective_tld_names.gperf"
+#line 2015 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1162, 0},
-#line 167 "effective_tld_names.gperf"
+#line 1716 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1163, 0},
-#line 851 "effective_tld_names.gperf"
+#line 2915 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1164, 0},
-#line 5092 "effective_tld_names.gperf"
+#line 3321 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1165, 0},
-#line 2823 "effective_tld_names.gperf"
+#line 1048 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1166, 0},
-#line 3202 "effective_tld_names.gperf"
+#line 3470 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1167, 0},
-#line 5391 "effective_tld_names.gperf"
+#line 2523 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1168, 0},
-#line 2480 "effective_tld_names.gperf"
+#line 2505 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1169, 0},
-#line 517 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1170, 4},
-#line 4633 "effective_tld_names.gperf"
+#line 236 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1170, 0},
+#line 5771 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1171, 0},
-#line 1758 "effective_tld_names.gperf"
+#line 3572 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1172, 0},
-#line 1756 "effective_tld_names.gperf"
+#line 3314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1173, 0},
-#line 1210 "effective_tld_names.gperf"
+#line 2798 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1174, 0},
-#line 5226 "effective_tld_names.gperf"
+#line 3260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1175, 0},
-#line 4870 "effective_tld_names.gperf"
+#line 2926 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1176, 0},
-#line 3373 "effective_tld_names.gperf"
+#line 3457 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1177, 0},
-#line 3065 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1178, 0},
-#line 4491 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1179, 1},
-#line 3359 "effective_tld_names.gperf"
+#line 3679 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1178, 4},
+#line 748 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1179, 0},
+#line 5863 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1180, 0},
-#line 1963 "effective_tld_names.gperf"
+#line 1502 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1181, 0},
-#line 519 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1182, 4},
-#line 1894 "effective_tld_names.gperf"
+#line 321 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1182, 0},
+#line 3518 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1183, 0},
-#line 1583 "effective_tld_names.gperf"
+#line 2972 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1184, 0},
-#line 2904 "effective_tld_names.gperf"
+#line 1656 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1185, 0},
-#line 1070 "effective_tld_names.gperf"
+#line 5805 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1186, 0},
-#line 4973 "effective_tld_names.gperf"
+#line 5851 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1187, 0},
-#line 4663 "effective_tld_names.gperf"
+#line 799 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1188, 0},
-#line 515 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1189, 4},
-#line 1703 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1190, 4},
-#line 5317 "effective_tld_names.gperf"
+#line 2500 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1189, 0},
+#line 461 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1190, 0},
+#line 3367 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1191, 0},
-#line 542 "effective_tld_names.gperf"
+#line 409 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1192, 0},
-#line 2127 "effective_tld_names.gperf"
+#line 3033 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1193, 0},
-#line 3090 "effective_tld_names.gperf"
+#line 235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1194, 0},
-#line 5336 "effective_tld_names.gperf"
+#line 2102 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1195, 0},
-#line 2458 "effective_tld_names.gperf"
+#line 5816 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1196, 0},
-#line 717 "effective_tld_names.gperf"
+#line 374 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1197, 0},
-#line 1394 "effective_tld_names.gperf"
+#line 3409 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1198, 0},
-#line 5030 "effective_tld_names.gperf"
+#line 822 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1199, 0},
-#line 6089 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1200, 2},
-#line 509 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1201, 4},
-#line 386 "effective_tld_names.gperf"
+#line 2003 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1200, 0},
+#line 2848 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1201, 0},
+#line 1629 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1202, 0},
-#line 2782 "effective_tld_names.gperf"
+#line 5809 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1203, 0},
-#line 2081 "effective_tld_names.gperf"
+#line 1720 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1204, 0},
-#line 760 "effective_tld_names.gperf"
+#line 801 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1205, 0},
-#line 1140 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1206, 4},
-#line 1547 "effective_tld_names.gperf"
+#line 2416 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1206, 0},
+#line 3473 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1207, 0},
-#line 3259 "effective_tld_names.gperf"
+#line 2038 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1208, 0},
-#line 2603 "effective_tld_names.gperf"
+#line 633 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1209, 0},
-#line 4795 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1210, 4},
-#line 4699 "effective_tld_names.gperf"
+#line 746 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1210, 0},
+#line 134 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1211, 0},
-#line 1019 "effective_tld_names.gperf"
+#line 3479 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1212, 0},
-#line 507 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1213, 4},
-#line 1648 "effective_tld_names.gperf"
+#line 5848 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1213, 0},
+#line 5739 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1214, 0},
-#line 1316 "effective_tld_names.gperf"
+#line 1680 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1215, 0},
-#line 6087 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1216, 0},
-#line 1461 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1217, 0},
-#line 1973 "effective_tld_names.gperf"
+#line 5947 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1216, 4},
+#line 578 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1217, 1},
+#line 580 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1218, 0},
-#line 1705 "effective_tld_names.gperf"
+#line 791 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1219, 0},
-#line 4996 "effective_tld_names.gperf"
+#line 240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1220, 0},
-#line 4525 "effective_tld_names.gperf"
+#line 3051 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1221, 0},
-#line 2459 "effective_tld_names.gperf"
+#line 2844 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1222, 0},
-#line 2609 "effective_tld_names.gperf"
+#line 2854 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1223, 0},
-#line 5088 "effective_tld_names.gperf"
+#line 2707 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1224, 0},
-#line 1059 "effective_tld_names.gperf"
+#line 5857 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1225, 0},
-#line 5630 "effective_tld_names.gperf"
+#line 3055 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1226, 0},
-#line 1326 "effective_tld_names.gperf"
+#line 2946 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1227, 0},
-#line 1317 "effective_tld_names.gperf"
+#line 3038 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1228, 0},
-#line 2066 "effective_tld_names.gperf"
+#line 5810 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1229, 0},
-#line 3260 "effective_tld_names.gperf"
+#line 1755 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1230, 0},
-#line 4802 "effective_tld_names.gperf"
+#line 2744 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1231, 0},
-#line 3225 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1232, 1},
-#line 5383 "effective_tld_names.gperf"
+#line 6364 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1232, 0},
+#line 2063 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1233, 0},
-#line 236 "effective_tld_names.gperf"
+#line 3488 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1234, 0},
-#line 3370 "effective_tld_names.gperf"
+#line 1370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1235, 0},
-#line 621 "effective_tld_names.gperf"
+#line 5803 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1236, 0},
-#line 3468 "effective_tld_names.gperf"
+#line 267 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1237, 0},
-#line 2859 "effective_tld_names.gperf"
+#line 3317 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1238, 0},
-#line 2586 "effective_tld_names.gperf"
+#line 3521 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1239, 0},
-#line 1892 "effective_tld_names.gperf"
+#line 785 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1240, 0},
-#line 2047 "effective_tld_names.gperf"
+#line 5840 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1241, 0},
-#line 715 "effective_tld_names.gperf"
+#line 3451 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1242, 0},
-#line 3270 "effective_tld_names.gperf"
+#line 1545 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1243, 0},
-#line 508 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1244, 4},
-#line 1584 "effective_tld_names.gperf"
+#line 2671 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1244, 0},
+#line 400 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1245, 0},
-#line 6113 "effective_tld_names.gperf"
+#line 5842 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1246, 0},
-#line 1368 "effective_tld_names.gperf"
+#line 897 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1247, 0},
-#line 1123 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1248, 4},
-#line 3371 "effective_tld_names.gperf"
+#line 3615 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1248, 0},
+#line 3393 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1249, 0},
-#line 762 "effective_tld_names.gperf"
+#line 2872 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1250, 0},
-#line 484 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1251, 4},
-#line 1571 "effective_tld_names.gperf"
+#line 2968 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1251, 0},
+#line 2413 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1252, 0},
-#line 506 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1253, 4},
-#line 1620 "effective_tld_names.gperf"
+#line 2417 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1253, 0},
+#line 560 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1254, 0},
-#line 4494 "effective_tld_names.gperf"
+#line 1751 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1255, 0},
-#line 501 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1256, 4},
-#line 751 "effective_tld_names.gperf"
+#line 2013 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1256, 0},
+#line 5815 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1257, 0},
-#line 460 "effective_tld_names.gperf"
+#line 5906 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1258, 0},
-#line 485 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1259, 4},
-#line 516 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1260, 4},
-#line 3368 "effective_tld_names.gperf"
+#line 3614 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1259, 0},
+#line 1562 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1260, 0},
+#line 5806 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1261, 0},
-#line 4830 "effective_tld_names.gperf"
+#line 1232 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1262, 0},
-#line 511 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1263, 4},
-#line 5380 "effective_tld_names.gperf"
+#line 5790 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1263, 0},
+#line 174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1264, 0},
-#line 162 "effective_tld_names.gperf"
+#line 1563 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1265, 0},
-#line 514 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1266, 4},
-#line 2799 "effective_tld_names.gperf"
+#line 2104 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1266, 0},
+#line 239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1267, 0},
-#line 1600 "effective_tld_names.gperf"
+#line 775 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1268, 0},
-#line 1283 "effective_tld_names.gperf"
+#line 238 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1269, 0},
-#line 2968 "effective_tld_names.gperf"
+#line 246 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1270, 0},
-#line 716 "effective_tld_names.gperf"
+#line 2551 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1271, 0},
-#line 510 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1272, 4},
-#line 1575 "effective_tld_names.gperf"
+#line 2827 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1272, 0},
+#line 599 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1273, 0},
-#line 3072 "effective_tld_names.gperf"
+#line 440 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1274, 0},
-#line 521 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1275, 4},
-#line 3399 "effective_tld_names.gperf"
+#line 2294 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1275, 0},
+#line 2672 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1276, 0},
-#line 4692 "effective_tld_names.gperf"
+#line 304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1277, 0},
-#line 3493 "effective_tld_names.gperf"
+#line 2843 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1278, 0},
-#line 4798 "effective_tld_names.gperf"
+#line 3589 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1279, 0},
-#line 3293 "effective_tld_names.gperf"
+#line 144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1280, 0},
-#line 700 "effective_tld_names.gperf"
+#line 1443 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1281, 0},
-#line 2629 "effective_tld_names.gperf"
+#line 2072 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1282, 0},
-#line 4875 "effective_tld_names.gperf"
+#line 3511 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1283, 0},
-#line 4793 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1284, 4},
-#line 5162 "effective_tld_names.gperf"
+#line 33 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1284, 0},
+#line 3555 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1285, 0},
-#line 2704 "effective_tld_names.gperf"
+#line 228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1286, 0},
-#line 4786 "effective_tld_names.gperf"
+#line 2978 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1287, 0},
-#line 1284 "effective_tld_names.gperf"
+#line 2772 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1288, 0},
-#line 2918 "effective_tld_names.gperf"
+#line 5689 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1289, 0},
-#line 3361 "effective_tld_names.gperf"
+#line 4023 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1290, 0},
-#line 2605 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1291, 0},
-#line 297 "effective_tld_names.gperf"
+#line 4108 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1291, 2},
+#line 821 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1292, 0},
-#line 622 "effective_tld_names.gperf"
+#line 2146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1293, 0},
-#line 1548 "effective_tld_names.gperf"
+#line 4077 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1294, 0},
-#line 2993 "effective_tld_names.gperf"
+#line 1918 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1295, 0},
-#line 5390 "effective_tld_names.gperf"
+#line 2511 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1296, 0},
-#line 6108 "effective_tld_names.gperf"
+#line 3654 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1297, 0},
-#line 3220 "effective_tld_names.gperf"
+#line 4045 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1298, 0},
-#line 2757 "effective_tld_names.gperf"
+#line 4016 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1299, 0},
-#line 1696 "effective_tld_names.gperf"
+#line 2879 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1300, 0},
-#line 2876 "effective_tld_names.gperf"
+#line 2160 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1301, 0},
-#line 4650 "effective_tld_names.gperf"
+#line 2303 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1302, 0},
-#line 5283 "effective_tld_names.gperf"
+#line 1445 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1303, 0},
-#line 610 "effective_tld_names.gperf"
+#line 2869 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1304, 0},
-#line 5333 "effective_tld_names.gperf"
+#line 4091 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1305, 0},
-#line 1579 "effective_tld_names.gperf"
+#line 205 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1306, 0},
-#line 2967 "effective_tld_names.gperf"
+#line 3611 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1307, 0},
-#line 3410 "effective_tld_names.gperf"
+#line 5808 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1308, 0},
-#line 2754 "effective_tld_names.gperf"
+#line 3683 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1309, 0},
-#line 2883 "effective_tld_names.gperf"
+#line 1939 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1310, 0},
-#line 1105 "effective_tld_names.gperf"
+#line 4044 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1311, 0},
-#line 1157 "effective_tld_names.gperf"
+#line 3684 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1312, 0},
-#line 2755 "effective_tld_names.gperf"
+#line 2930 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1313, 0},
-#line 3224 "effective_tld_names.gperf"
+#line 3067 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1314, 0},
-#line 4865 "effective_tld_names.gperf"
+#line 3035 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1315, 0},
-#line 4872 "effective_tld_names.gperf"
+#line 901 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1316, 0},
-#line 3070 "effective_tld_names.gperf"
+#line 4082 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1317, 0},
-#line 4505 "effective_tld_names.gperf"
+#line 3815 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1318, 0},
-#line 2567 "effective_tld_names.gperf"
+#line 3835 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1319, 0},
-#line 4794 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1320, 4},
-#line 4900 "effective_tld_names.gperf"
+#line 5720 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1320, 0},
+#line 2923 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1321, 0},
-#line 5178 "effective_tld_names.gperf"
+#line 3861 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1322, 0},
-#line 201 "effective_tld_names.gperf"
+#line 4037 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1323, 0},
-#line 3294 "effective_tld_names.gperf"
+#line 3909 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1324, 0},
-#line 6116 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1325, 2},
-#line 3154 "effective_tld_names.gperf"
+#line 3860 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1325, 0},
+#line 3930 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1326, 0},
-#line 2511 "effective_tld_names.gperf"
+#line 2533 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1327, 0},
-#line 2030 "effective_tld_names.gperf"
+#line 4046 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1328, 0},
-#line 5101 "effective_tld_names.gperf"
+#line 3925 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1329, 0},
-#line 1970 "effective_tld_names.gperf"
+#line 3892 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1330, 0},
-#line 1121 "effective_tld_names.gperf"
+#line 3924 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1331, 0},
-#line 330 "effective_tld_names.gperf"
+#line 3495 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1332, 0},
-#line 4542 "effective_tld_names.gperf"
+#line 4646 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1333, 0},
-#line 333 "effective_tld_names.gperf"
+#line 3060 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1334, 0},
-#line 2510 "effective_tld_names.gperf"
+#line 3890 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1335, 0},
-#line 2738 "effective_tld_names.gperf"
+#line 3005 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1336, 0},
-#line 4499 "effective_tld_names.gperf"
+#line 4070 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1337, 0},
-#line 1732 "effective_tld_names.gperf"
+#line 3889 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1338, 0},
-#line 881 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1339, 0},
-#line 4901 "effective_tld_names.gperf"
+#line 4019 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1339, 1},
+#line 3891 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1340, 0},
-#line 3019 "effective_tld_names.gperf"
+#line 3929 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1341, 0},
-#line 3353 "effective_tld_names.gperf"
+#line 4064 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1342, 0},
-#line 2740 "effective_tld_names.gperf"
+#line 4035 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1343, 0},
-#line 761 "effective_tld_names.gperf"
+#line 909 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1344, 0},
-#line 3496 "effective_tld_names.gperf"
+#line 3261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1345, 0},
-#line 153 "effective_tld_names.gperf"
+#line 3908 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1346, 0},
-#line 4837 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1347, 0},
-#line 3372 "effective_tld_names.gperf"
+#line 3966 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1347, 2},
+#line 3297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1348, 0},
-#line 1814 "effective_tld_names.gperf"
+#line 820 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1349, 0},
-#line 1264 "effective_tld_names.gperf"
+#line 5710 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1350, 0},
-#line 964 "effective_tld_names.gperf"
+#line 2929 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1351, 0},
-#line 3018 "effective_tld_names.gperf"
+#line 5776 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1352, 0},
-#line 2118 "effective_tld_names.gperf"
+#line 1068 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1353, 0},
-#line 1860 "effective_tld_names.gperf"
+#line 3483 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1354, 0},
-#line 5001 "effective_tld_names.gperf"
+#line 3532 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1355, 0},
-#line 523 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1356, 4},
-#line 2675 "effective_tld_names.gperf"
+#line 1458 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1356, 0},
+#line 3593 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1357, 0},
-#line 4871 "effective_tld_names.gperf"
+#line 3863 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1358, 0},
-#line 4945 "effective_tld_names.gperf"
+#line 2790 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1359, 0},
-#line 298 "effective_tld_names.gperf"
+#line 2080 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1360, 0},
-#line 5196 "effective_tld_names.gperf"
+#line 3937 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1361, 0},
-#line 2734 "effective_tld_names.gperf"
+#line 3934 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1362, 0},
-#line 2797 "effective_tld_names.gperf"
+#line 3935 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1363, 0},
-#line 4796 "effective_tld_names.gperf"
+#line 2732 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1364, 0},
-#line 1008 "effective_tld_names.gperf"
+#line 2909 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1365, 0},
-#line 2804 "effective_tld_names.gperf"
+#line 3923 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1366, 0},
-#line 4986 "effective_tld_names.gperf"
+#line 3926 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1367, 0},
-#line 2921 "effective_tld_names.gperf"
+#line 465 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1368, 0},
-#line 4972 "effective_tld_names.gperf"
+#line 2069 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1369, 0},
-#line 4803 "effective_tld_names.gperf"
+#line 3888 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1370, 0},
-#line 3143 "effective_tld_names.gperf"
+#line 237 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1371, 0},
-#line 505 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1372, 4},
-#line 336 "effective_tld_names.gperf"
+#line 1487 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1372, 0},
+#line 2044 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1373, 0},
-#line 313 "effective_tld_names.gperf"
+#line 3852 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1374, 0},
-#line 2841 "effective_tld_names.gperf"
+#line 3851 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1375, 0},
-#line 2843 "effective_tld_names.gperf"
+#line 3850 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1376, 0},
-#line 364 "effective_tld_names.gperf"
+#line 3940 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1377, 0},
-#line 5586 "effective_tld_names.gperf"
+#line 3849 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1378, 0},
-#line 4915 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1379, 1},
-#line 1657 "effective_tld_names.gperf"
+#line 380 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1379, 0},
+#line 3847 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1380, 0},
-#line 4990 "effective_tld_names.gperf"
+#line 4090 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1381, 0},
-#line 5179 "effective_tld_names.gperf"
+#line 3878 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1382, 0},
-#line 2513 "effective_tld_names.gperf"
+#line 3880 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1383, 0},
-#line 2842 "effective_tld_names.gperf"
+#line 3879 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1384, 0},
-#line 4571 "effective_tld_names.gperf"
+#line 614 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1385, 0},
-#line 577 "effective_tld_names.gperf"
+#line 3876 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1386, 0},
-#line 3086 "effective_tld_names.gperf"
+#line 3474 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1387, 0},
-#line 5292 "effective_tld_names.gperf"
+#line 2336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1388, 0},
-#line 4978 "effective_tld_names.gperf"
+#line 1785 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1389, 0},
-#line 2451 "effective_tld_names.gperf"
+#line 1314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1390, 0},
-#line 1470 "effective_tld_names.gperf"
+#line 1792 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1391, 0},
-#line 5066 "effective_tld_names.gperf"
+#line 984 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1392, 0},
-#line 1912 "effective_tld_names.gperf"
+#line 3268 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1393, 0},
-#line 2886 "effective_tld_names.gperf"
+#line 2001 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1394, 0},
-#line 3382 "effective_tld_names.gperf"
+#line 635 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1395, 0},
#line 452 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1396, 0},
-#line 2568 "effective_tld_names.gperf"
+#line 2680 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1397, 0},
-#line 2512 "effective_tld_names.gperf"
+#line 3922 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1398, 0},
-#line 4864 "effective_tld_names.gperf"
+#line 5900 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1399, 0},
-#line 3021 "effective_tld_names.gperf"
+#line 3016 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1400, 0},
-#line 1644 "effective_tld_names.gperf"
+#line 5877 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1401, 0},
-#line 1005 "effective_tld_names.gperf"
+#line 3920 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1402, 0},
-#line 1404 "effective_tld_names.gperf"
+#line 314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1403, 0},
-#line 3352 "effective_tld_names.gperf"
+#line 2792 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1404, 0},
-#line 2574 "effective_tld_names.gperf"
+#line 2362 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1405, 0},
-#line 6091 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1406, 4},
-#line 3020 "effective_tld_names.gperf"
+#line 3509 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1406, 0},
+#line 2788 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1407, 0},
-#line 5362 "effective_tld_names.gperf"
+#line 2023 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1408, 0},
-#line 5034 "effective_tld_names.gperf"
+#line 4106 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1409, 0},
-#line 718 "effective_tld_names.gperf"
+#line 3635 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1410, 0},
-#line 697 "effective_tld_names.gperf"
+#line 3685 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1411, 0},
-#line 1010 "effective_tld_names.gperf"
+#line 3475 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1412, 0},
-#line 1573 "effective_tld_names.gperf"
+#line 2133 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1413, 0},
-#line 1841 "effective_tld_names.gperf"
+#line 3846 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1414, 0},
-#line 2937 "effective_tld_names.gperf"
+#line 3882 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1415, 0},
-#line 3354 "effective_tld_names.gperf"
+#line 5936 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1416, 0},
-#line 2744 "effective_tld_names.gperf"
+#line 3950 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1417, 0},
-#line 4541 "effective_tld_names.gperf"
+#line 3742 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1418, 0},
-#line 1337 "effective_tld_names.gperf"
+#line 3471 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1419, 0},
-#line 5321 "effective_tld_names.gperf"
+#line 5814 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1420, 0},
-#line 5416 "effective_tld_names.gperf"
+#line 3899 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1421, 0},
-#line 4468 "effective_tld_names.gperf"
+#line 2771 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1422, 0},
-#line 169 "effective_tld_names.gperf"
+#line 3875 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1423, 0},
-#line 5191 "effective_tld_names.gperf"
+#line 5683 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1424, 0},
-#line 3223 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1425, 0},
-#line 5190 "effective_tld_names.gperf"
+#line 4076 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1425, 2},
+#line 3780 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1426, 0},
-#line 3222 "effective_tld_names.gperf"
+#line 3753 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1427, 0},
-#line 281 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1428, 0},
-#line 1873 "effective_tld_names.gperf"
+#line 3825 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1428, 1},
+#line 3939 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1429, 0},
-#line 808 "effective_tld_names.gperf"
+#line 3897 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1430, 0},
-#line 4979 "effective_tld_names.gperf"
+#line 3881 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1431, 0},
-#line 4838 "effective_tld_names.gperf"
+#line 5871 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1432, 0},
-#line 1866 "effective_tld_names.gperf"
+#line 3762 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1433, 0},
-#line 4467 "effective_tld_names.gperf"
+#line 3746 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1434, 0},
-#line 2560 "effective_tld_names.gperf"
+#line 2895 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1435, 0},
-#line 5564 "effective_tld_names.gperf"
+#line 385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1436, 0},
-#line 2611 "effective_tld_names.gperf"
+#line 3898 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1437, 0},
-#line 312 "effective_tld_names.gperf"
+#line 3896 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1438, 0},
-#line 5102 "effective_tld_names.gperf"
+#line 234 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1439, 0},
-#line 1599 "effective_tld_names.gperf"
+#line 3749 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1440, 0},
-#line 2563 "effective_tld_names.gperf"
+#line 4043 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1441, 0},
-#line 3271 "effective_tld_names.gperf"
+#line 4042 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1442, 0},
-#line 2481 "effective_tld_names.gperf"
+#line 3012 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1443, 0},
-#line 1602 "effective_tld_names.gperf"
+#line 3843 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1444, 0},
-#line 85 "effective_tld_names.gperf"
+#line 3836 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1445, 0},
-#line 5348 "effective_tld_names.gperf"
+#line 5911 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1446, 0},
-#line 80 "effective_tld_names.gperf"
+#line 3747 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1447, 0},
-#line 3328 "effective_tld_names.gperf"
+#line 4033 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1448, 0},
-#line 5359 "effective_tld_names.gperf"
+#line 1496 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1449, 0},
-#line 4926 "effective_tld_names.gperf"
+#line 3752 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1450, 0},
-#line 4634 "effective_tld_names.gperf"
+#line 3895 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1451, 0},
-#line 4675 "effective_tld_names.gperf"
+#line 245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1452, 0},
-#line 1489 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1453, 4},
-#line 4952 "effective_tld_names.gperf"
+#line 2828 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1453, 0},
+#line 3917 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1454, 0},
-#line 1863 "effective_tld_names.gperf"
+#line 3916 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1455, 0},
-#line 5055 "effective_tld_names.gperf"
+#line 3841 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1456, 0},
-#line 4694 "effective_tld_names.gperf"
+#line 3309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1457, 0},
-#line 1574 "effective_tld_names.gperf"
+#line 3837 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1458, 0},
-#line 4497 "effective_tld_names.gperf"
+#line 3743 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1459, 0},
-#line 4472 "effective_tld_names.gperf"
+#line 4041 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1460, 0},
-#line 1056 "effective_tld_names.gperf"
+#line 3913 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1461, 0},
-#line 2665 "effective_tld_names.gperf"
+#line 2545 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1462, 0},
-#line 4520 "effective_tld_names.gperf"
+#line 2880 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1463, 0},
-#line 5204 "effective_tld_names.gperf"
+#line 403 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1464, 0},
-#line 190 "effective_tld_names.gperf"
+#line 3914 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1465, 0},
-#line 5434 "effective_tld_names.gperf"
+#line 3943 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1466, 0},
-#line 3515 "effective_tld_names.gperf"
+#line 3911 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1467, 0},
-#line 5025 "effective_tld_names.gperf"
+#line 2874 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1468, 0},
-#line 3499 "effective_tld_names.gperf"
+#line 3014 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1469, 0},
-#line 4759 "effective_tld_names.gperf"
+#line 4072 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1470, 0},
-#line 3364 "effective_tld_names.gperf"
+#line 3903 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1471, 0},
-#line 5591 "effective_tld_names.gperf"
+#line 3944 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1472, 0},
-#line 420 "effective_tld_names.gperf"
+#line 421 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1473, 0},
-#line 4647 "effective_tld_names.gperf"
+#line 2558 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1474, 0},
-#line 763 "effective_tld_names.gperf"
+#line 1665 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1475, 0},
-#line 5077 "effective_tld_names.gperf"
+#line 1729 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1476, 0},
-#line 1695 "effective_tld_names.gperf"
+#line 1361 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1477, 0},
-#line 4537 "effective_tld_names.gperf"
+#line 2938 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1478, 0},
-#line 294 "effective_tld_names.gperf"
+#line 740 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1479, 0},
-#line 2825 "effective_tld_names.gperf"
+#line 3023 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1480, 0},
-#line 3445 "effective_tld_names.gperf"
+#line 1858 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1481, 0},
-#line 4705 "effective_tld_names.gperf"
+#line 2883 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1482, 0},
-#line 4784 "effective_tld_names.gperf"
+#line 1281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1483, 0},
-#line 1598 "effective_tld_names.gperf"
+#line 3906 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1484, 0},
-#line 2998 "effective_tld_names.gperf"
+#line 951 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1485, 0},
-#line 5306 "effective_tld_names.gperf"
+#line 3910 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1486, 0},
-#line 4498 "effective_tld_names.gperf"
+#line 2194 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1487, 0},
-#line 744 "effective_tld_names.gperf"
+#line 2842 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1488, 0},
-#line 2452 "effective_tld_names.gperf"
+#line 98 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1489, 0},
-#line 2892 "effective_tld_names.gperf"
+#line 6238 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1490, 0},
-#line 1104 "effective_tld_names.gperf"
+#line 172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1491, 0},
-#line 5098 "effective_tld_names.gperf"
+#line 1730 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1492, 0},
-#line 3470 "effective_tld_names.gperf"
+#line 1994 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1493, 0},
-#line 5057 "effective_tld_names.gperf"
+#line 446 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1494, 0},
-#line 5601 "effective_tld_names.gperf"
+#line 5849 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1495, 0},
-#line 5019 "effective_tld_names.gperf"
+#line 2081 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1496, 0},
-#line 5445 "effective_tld_names.gperf"
+#line 3748 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1497, 0},
-#line 4475 "effective_tld_names.gperf"
+#line 1280 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1498, 0},
-#line 5588 "effective_tld_names.gperf"
+#line 1854 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1499, 0},
-#line 2084 "effective_tld_names.gperf"
+#line 950 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1500, 0},
-#line 2922 "effective_tld_names.gperf"
+#line 1276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1501, 0},
-#line 4773 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1502, 4},
-#line 5562 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1503, 0},
-#line 3492 "effective_tld_names.gperf"
+#line 1560 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1502, 0},
+#line 3970 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1503, 1},
+#line 946 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1504, 0},
-#line 2932 "effective_tld_names.gperf"
+#line 5755 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1505, 0},
-#line 613 "effective_tld_names.gperf"
+#line 2841 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1506, 0},
-#line 425 "effective_tld_names.gperf"
+#line 2175 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1507, 0},
-#line 1948 "effective_tld_names.gperf"
+#line 5946 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1508, 0},
-#line 1971 "effective_tld_names.gperf"
+#line 5718 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1509, 0},
-#line 2085 "effective_tld_names.gperf"
+#line 2689 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1510, 0},
-#line 1853 "effective_tld_names.gperf"
+#line 111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1511, 0},
-#line 2469 "effective_tld_names.gperf"
+#line 211 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1512, 0},
-#line 3282 "effective_tld_names.gperf"
+#line 3840 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1513, 0},
-#line 1929 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1514, 0},
-#line 5160 "effective_tld_names.gperf"
+#line 3969 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1514, 1},
+#line 3968 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1515, 0},
-#line 1838 "effective_tld_names.gperf"
+#line 3872 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1516, 0},
-#line 504 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1517, 4},
-#line 4676 "effective_tld_names.gperf"
+#line 4012 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1517, 0},
+#line 2374 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1518, 0},
-#line 5417 "effective_tld_names.gperf"
+#line 3264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1519, 0},
-#line 2780 "effective_tld_names.gperf"
+#line 3744 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1520, 0},
-#line 2683 "effective_tld_names.gperf"
+#line 4068 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1521, 0},
-#line 159 "effective_tld_names.gperf"
+#line 345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1522, 0},
-#line 3315 "effective_tld_names.gperf"
+#line 3606 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1523, 0},
-#line 5163 "effective_tld_names.gperf"
+#line 4010 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1524, 0},
-#line 22 "effective_tld_names.gperf"
+#line 2062 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1525, 0},
-#line 4929 "effective_tld_names.gperf"
+#line 3503 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1526, 0},
-#line 4883 "effective_tld_names.gperf"
+#line 4039 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1527, 0},
-#line 3369 "effective_tld_names.gperf"
+#line 2980 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1528, 0},
-#line 175 "effective_tld_names.gperf"
+#line 3945 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1529, 0},
-#line 2450 "effective_tld_names.gperf"
+#line 2961 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1530, 0},
-#line 390 "effective_tld_names.gperf"
+#line 2657 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1531, 0},
-#line 520 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1532, 4},
-#line 2807 "effective_tld_names.gperf"
+#line 1731 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1532, 0},
+#line 2986 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1533, 0},
-#line 2802 "effective_tld_names.gperf"
+#line 2677 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1534, 0},
-#line 4814 "effective_tld_names.gperf"
+#line 4053 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1535, 0},
-#line 1443 "effective_tld_names.gperf"
+#line 106 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1536, 0},
-#line 4775 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1537, 4},
-#line 3106 "effective_tld_names.gperf"
+#line 3384 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1537, 0},
+#line 3294 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1538, 0},
-#line 4939 "effective_tld_names.gperf"
+#line 3491 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1539, 0},
-#line 5158 "effective_tld_names.gperf"
+#line 3709 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1540, 0},
-#line 1958 "effective_tld_names.gperf"
+#line 1856 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1541, 0},
-#line 5256 "effective_tld_names.gperf"
+#line 5812 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1542, 0},
-#line 3102 "effective_tld_names.gperf"
+#line 1278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1543, 0},
-#line 1012 "effective_tld_names.gperf"
+#line 2150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1544, 0},
-#line 1312 "effective_tld_names.gperf"
+#line 948 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1545, 0},
-#line 1685 "effective_tld_names.gperf"
+#line 2652 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1546, 0},
-#line 2756 "effective_tld_names.gperf"
+#line 4741 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1547, 0},
-#line 631 "effective_tld_names.gperf"
+#line 3510 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1548, 0},
-#line 1642 "effective_tld_names.gperf"
+#line 1742 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1549, 0},
-#line 5598 "effective_tld_names.gperf"
+#line 5684 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1550, 0},
-#line 5171 "effective_tld_names.gperf"
+#line 4764 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1551, 0},
-#line 1444 "effective_tld_names.gperf"
+#line 2683 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1552, 0},
-#line 5354 "effective_tld_names.gperf"
+#line 3831 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1553, 0},
-#line 1442 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1554, 4},
-#line 5352 "effective_tld_names.gperf"
+#line 5841 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1554, 0},
+#line 1416 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1555, 0},
-#line 3198 "effective_tld_names.gperf"
+#line 3838 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1556, 0},
-#line 1106 "effective_tld_names.gperf"
+#line 4766 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1557, 0},
-#line 5240 "effective_tld_names.gperf"
+#line 3778 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1558, 0},
-#line 2758 "effective_tld_names.gperf"
+#line 3608 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1559, 0},
-#line 2131 "effective_tld_names.gperf"
+#line 2882 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1560, 0},
-#line 5640 "effective_tld_names.gperf"
+#line 3806 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1561, 0},
-#line 2813 "effective_tld_names.gperf"
+#line 780 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1562, 0},
-#line 4855 "effective_tld_names.gperf"
+#line 2769 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1563, 0},
-#line 5176 "effective_tld_names.gperf"
+#line 4652 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1564, 0},
#line 2746 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1565, 0},
-#line 4707 "effective_tld_names.gperf"
+#line 4653 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1566, 0},
-#line 5374 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1567, 0},
-#line 1075 "effective_tld_names.gperf"
+#line 522 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1567, 4},
+#line 3476 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1568, 0},
-#line 2901 "effective_tld_names.gperf"
+#line 3506 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1569, 0},
-#line 5597 "effective_tld_names.gperf"
+#line 5719 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1570, 0},
-#line 5373 "effective_tld_names.gperf"
+#line 2555 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1571, 0},
-#line 2636 "effective_tld_names.gperf"
+#line 3833 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1572, 0},
-#line 1469 "effective_tld_names.gperf"
+#line 3003 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1573, 0},
-#line 2721 "effective_tld_names.gperf"
+#line 4675 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1574, 0},
-#line 5638 "effective_tld_names.gperf"
+#line 138 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1575, 0},
-#line 3085 "effective_tld_names.gperf"
+#line 302 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1576, 0},
-#line 1476 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1577, 4},
-#line 1145 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1578, 4},
-#line 2488 "effective_tld_names.gperf"
+#line 4696 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1577, 0},
+#line 4748 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1578, 0},
+#line 2196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1579, 0},
-#line 2638 "effective_tld_names.gperf"
+#line 2858 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1580, 0},
-#line 3406 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1581, 0},
-#line 5065 "effective_tld_names.gperf"
+#line 813 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1581, 1},
+#line 4710 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1582, 0},
-#line 4789 "effective_tld_names.gperf"
+#line 4769 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1583, 0},
-#line 1381 "effective_tld_names.gperf"
+#line 4055 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1584, 0},
-#line 1458 "effective_tld_names.gperf"
+#line 3010 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1585, 0},
-#line 2779 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1586, 0},
-#line 770 "effective_tld_names.gperf"
+#line 2204 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1586, 4},
+#line 5762 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1587, 0},
-#line 1881 "effective_tld_names.gperf"
+#line 5787 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1588, 0},
-#line 5372 "effective_tld_names.gperf"
+#line 2899 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1589, 0},
-#line 3088 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1590, 0},
-#line 100 "effective_tld_names.gperf"
+#line 539 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1590, 4},
+#line 4054 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1591, 0},
-#line 5168 "effective_tld_names.gperf"
+#line 1667 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1592, 0},
-#line 2979 "effective_tld_names.gperf"
+#line 4687 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1593, 0},
-#line 3272 "effective_tld_names.gperf"
+#line 283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1594, 0},
-#line 5132 "effective_tld_names.gperf"
+#line 3779 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1595, 0},
-#line 756 "effective_tld_names.gperf"
+#line 3884 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1596, 0},
-#line 1847 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1597, 0},
-#line 3460 "effective_tld_names.gperf"
+#line 521 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1597, 4},
+#line 2529 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1598, 0},
-#line 5180 "effective_tld_names.gperf"
+#line 5757 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1599, 0},
-#line 1967 "effective_tld_names.gperf"
+#line 2035 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1600, 0},
-#line 2700 "effective_tld_names.gperf"
+#line 2139 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1601, 0},
-#line 2471 "effective_tld_names.gperf"
+#line 105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1602, 0},
-#line 2021 "effective_tld_names.gperf"
+#line 1459 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1603, 0},
-#line 5009 "effective_tld_names.gperf"
+#line 770 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1604, 0},
-#line 2860 "effective_tld_names.gperf"
+#line 4702 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1605, 0},
-#line 3528 "effective_tld_names.gperf"
+#line 783 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1606, 0},
-#line 3424 "effective_tld_names.gperf"
+#line 2017 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1607, 0},
-#line 1103 "effective_tld_names.gperf"
+#line 3578 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1608, 0},
-#line 2894 "effective_tld_names.gperf"
+#line 4699 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1609, 0},
-#line 3440 "effective_tld_names.gperf"
+#line 1381 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1610, 0},
-#line 1882 "effective_tld_names.gperf"
+#line 5820 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1611, 0},
-#line 2805 "effective_tld_names.gperf"
+#line 5933 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1612, 0},
-#line 1941 "effective_tld_names.gperf"
+#line 4066 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1613, 0},
-#line 2900 "effective_tld_names.gperf"
+#line 2509 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1614, 0},
-#line 17 "effective_tld_names.gperf"
+#line 3645 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1615, 0},
-#line 2701 "effective_tld_names.gperf"
+#line 4056 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1616, 0},
-#line 4698 "effective_tld_names.gperf"
+#line 3432 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1617, 0},
-#line 2870 "effective_tld_names.gperf"
+#line 355 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1618, 0},
-#line 4471 "effective_tld_names.gperf"
+#line 2223 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1619, 0},
-#line 176 "effective_tld_names.gperf"
+#line 95 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1620, 0},
-#line 5028 "effective_tld_names.gperf"
+#line 2045 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1621, 0},
-#line 6109 "effective_tld_names.gperf"
+#line 2706 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1622, 0},
-#line 1492 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1623, 4},
-#line 1435 "effective_tld_names.gperf"
+#line 5934 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1623, 0},
+#line 5817 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1624, 0},
-#line 2959 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1625, 4},
-#line 3127 "effective_tld_names.gperf"
+#line 2117 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1625, 0},
+#line 5831 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1626, 0},
-#line 1581 "effective_tld_names.gperf"
+#line 2994 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1627, 0},
-#line 2699 "effective_tld_names.gperf"
+#line 5759 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1628, 0},
-#line 476 "effective_tld_names.gperf"
+#line 2725 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1629, 0},
-#line 1837 "effective_tld_names.gperf"
+#line 4071 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1630, 0},
-#line 2798 "effective_tld_names.gperf"
+#line 3020 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1631, 0},
-#line 4836 "effective_tld_names.gperf"
+#line 2884 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1632, 0},
-#line 1641 "effective_tld_names.gperf"
+#line 3308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1633, 0},
-#line 4631 "effective_tld_names.gperf"
+#line 3413 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1634, 0},
-#line 1595 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1635, 4},
-#line 5299 "effective_tld_names.gperf"
+#line 2148 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1635, 0},
+#line 4684 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1636, 0},
-#line 104 "effective_tld_names.gperf"
+#line 1657 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1637, 0},
-#line 4550 "effective_tld_names.gperf"
+#line 2853 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1638, 0},
-#line 2938 "effective_tld_names.gperf"
+#line 2363 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1639, 0},
-#line 1883 "effective_tld_names.gperf"
+#line 3763 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1640, 0},
-#line 1944 "effective_tld_names.gperf"
+#line 5821 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1641, 0},
-#line 1505 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1642, 4},
-#line 5311 "effective_tld_names.gperf"
+#line 5717 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1642, 0},
+#line 1741 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1643, 0},
-#line 4659 "effective_tld_names.gperf"
+#line 3052 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1644, 0},
-#line 4684 "effective_tld_names.gperf"
+#line 760 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1645, 0},
-#line 389 "effective_tld_names.gperf"
+#line 3921 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1646, 0},
-#line 215 "effective_tld_names.gperf"
+#line 3823 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1647, 0},
-#line 2692 "effective_tld_names.gperf"
+#line 2563 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1648, 0},
-#line 1622 "effective_tld_names.gperf"
+#line 3011 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1649, 0},
-#line 5288 "effective_tld_names.gperf"
+#line 2710 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1650, 0},
-#line 5409 "effective_tld_names.gperf"
+#line 2832 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1651, 0},
-#line 2806 "effective_tld_names.gperf"
+#line 2959 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1652, 0},
-#line 585 "effective_tld_names.gperf"
+#line 4047 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1653, 0},
-#line 701 "effective_tld_names.gperf"
+#line 3043 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1654, 0},
-#line 2906 "effective_tld_names.gperf"
+#line 3948 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1655, 0},
-#line 3490 "effective_tld_names.gperf"
+#line 4747 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1656, 0},
-#line 4862 "effective_tld_names.gperf"
+#line 2027 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1657, 0},
-#line 4899 "effective_tld_names.gperf"
+#line 3947 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1658, 0},
-#line 2552 "effective_tld_names.gperf"
+#line 3658 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1659, 0},
-#line 4824 "effective_tld_names.gperf"
+#line 4681 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1660, 0},
-#line 106 "effective_tld_names.gperf"
+#line 4775 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1661, 0},
-#line 2940 "effective_tld_names.gperf"
+#line 3927 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1662, 0},
-#line 563 "effective_tld_names.gperf"
+#line 4723 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1663, 0},
-#line 1545 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1664, 0},
-#line 5004 "effective_tld_names.gperf"
+#line 2425 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1664, 4},
+#line 2709 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1665, 0},
-#line 2551 "effective_tld_names.gperf"
+#line 3802 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1666, 0},
-#line 4941 "effective_tld_names.gperf"
+#line 3017 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1667, 0},
-#line 4788 "effective_tld_names.gperf"
+#line 6368 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1668, 0},
-#line 440 "effective_tld_names.gperf"
+#line 2225 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1669, 0},
-#line 3442 "effective_tld_names.gperf"
+#line 1794 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1670, 0},
-#line 2717 "effective_tld_names.gperf"
+#line 5859 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1671, 0},
-#line 399 "effective_tld_names.gperf"
+#line 2942 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1672, 0},
-#line 2751 "effective_tld_names.gperf"
+#line 557 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1673, 0},
-#line 2785 "effective_tld_names.gperf"
+#line 3045 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1674, 0},
-#line 5381 "effective_tld_names.gperf"
+#line 3907 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1675, 0},
-#line 1334 "effective_tld_names.gperf"
+#line 737 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1676, 0},
-#line 1918 "effective_tld_names.gperf"
+#line 3828 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1677, 0},
-#line 429 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1678, 4},
-#line 2058 "effective_tld_names.gperf"
+#line 2775 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1678, 0},
+#line 130 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1679, 0},
-#line 3329 "effective_tld_names.gperf"
+#line 3864 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1680, 0},
-#line 5286 "effective_tld_names.gperf"
+#line 2875 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1681, 0},
-#line 3250 "effective_tld_names.gperf"
+#line 4695 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1682, 0},
-#line 3058 "effective_tld_names.gperf"
+#line 5750 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1683, 0},
-#line 383 "effective_tld_names.gperf"
+#line 2197 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1684, 0},
-#line 2023 "effective_tld_names.gperf"
+#line 1555 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1685, 0},
-#line 3360 "effective_tld_names.gperf"
+#line 3677 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1686, 0},
-#line 1057 "effective_tld_names.gperf"
+#line 2260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1687, 0},
-#line 4863 "effective_tld_names.gperf"
+#line 5888 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1688, 0},
-#line 4626 "effective_tld_names.gperf"
+#line 2684 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1689, 0},
-#line 3400 "effective_tld_names.gperf"
+#line 812 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1690, 0},
-#line 4767 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1691, 0},
-#line 2957 "effective_tld_names.gperf"
+#line 1588 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1691, 4},
+#line 2748 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1692, 0},
-#line 755 "effective_tld_names.gperf"
+#line 1649 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1693, 0},
-#line 4933 "effective_tld_names.gperf"
+#line 4040 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1694, 0},
-#line 2532 "effective_tld_names.gperf"
+#line 3901 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1695, 0},
-#line 2619 "effective_tld_names.gperf"
+#line 2795 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1696, 0},
-#line 2095 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1697, 4},
-#line 531 "effective_tld_names.gperf"
+#line 2778 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1697, 0},
+#line 1652 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1698, 0},
-#line 5406 "effective_tld_names.gperf"
+#line 2760 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1699, 0},
-#line 4623 "effective_tld_names.gperf"
+#line 4781 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1700, 0},
-#line 1072 "effective_tld_names.gperf"
+#line 6367 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1701, 0},
-#line 5051 "effective_tld_names.gperf"
+#line 4073 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1702, 0},
-#line 5621 "effective_tld_names.gperf"
+#line 4701 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1703, 0},
-#line 5297 "effective_tld_names.gperf"
+#line 4032 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1704, 0},
-#line 4920 "effective_tld_names.gperf"
+#line 2016 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1705, 0},
-#line 4916 "effective_tld_names.gperf"
+#line 2132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1706, 0},
-#line 2696 "effective_tld_names.gperf"
+#line 3693 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1707, 0},
-#line 2029 "effective_tld_names.gperf"
+#line 5836 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1708, 0},
-#line 3040 "effective_tld_names.gperf"
+#line 2794 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1709, 0},
-#line 2610 "effective_tld_names.gperf"
+#line 5891 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1710, 0},
-#line 3128 "effective_tld_names.gperf"
+#line 3599 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1711, 0},
-#line 5401 "effective_tld_names.gperf"
+#line 1486 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1712, 0},
-#line 374 "effective_tld_names.gperf"
+#line 5153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1713, 0},
-#line 4538 "effective_tld_names.gperf"
+#line 4941 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1714, 0},
-#line 1688 "effective_tld_names.gperf"
+#line 5308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1715, 0},
-#line 212 "effective_tld_names.gperf"
+#line 4034 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1716, 0},
-#line 5356 "effective_tld_names.gperf"
+#line 3844 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1717, 0},
-#line 570 "effective_tld_names.gperf"
+#line 5206 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1718, 0},
-#line 2801 "effective_tld_names.gperf"
+#line 215 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1719, 0},
-#line 2556 "effective_tld_names.gperf"
+#line 4051 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1720, 0},
-#line 4928 "effective_tld_names.gperf"
+#line 5135 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1721, 0},
-#line 3409 "effective_tld_names.gperf"
+#line 4700 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1722, 0},
-#line 2995 "effective_tld_names.gperf"
+#line 2289 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1723, 0},
-#line 5007 "effective_tld_names.gperf"
+#line 3048 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1724, 0},
-#line 4682 "effective_tld_names.gperf"
+#line 3596 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1725, 0},
-#line 2591 "effective_tld_names.gperf"
+#line 5256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1726, 0},
-#line 2088 "effective_tld_names.gperf"
+#line 3330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1727, 0},
-#line 2956 "effective_tld_names.gperf"
+#line 5165 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1728, 0},
-#line 3147 "effective_tld_names.gperf"
+#line 1632 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1729, 0},
-#line 3136 "effective_tld_names.gperf"
+#line 2130 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1730, 0},
-#line 4042 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1731, 2},
-#line 99 "effective_tld_names.gperf"
+#line 2059 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1731, 0},
+#line 4782 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1732, 0},
-#line 5050 "effective_tld_names.gperf"
+#line 1638 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1733, 0},
-#line 381 "effective_tld_names.gperf"
+#line 5146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1734, 0},
-#line 1821 "effective_tld_names.gperf"
+#line 5828 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1735, 0},
-#line 1269 "effective_tld_names.gperf"
+#line 4783 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1736, 0},
-#line 216 "effective_tld_names.gperf"
+#line 4683 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1737, 0},
-#line 970 "effective_tld_names.gperf"
+#line 4705 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1738, 0},
-#line 1047 "effective_tld_names.gperf"
+#line 4716 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1739, 0},
-#line 331 "effective_tld_names.gperf"
+#line 3600 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1740, 0},
-#line 1425 "effective_tld_names.gperf"
+#line 4944 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1741, 0},
-#line 870 "effective_tld_names.gperf"
+#line 3517 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1742, 0},
-#line 3401 "effective_tld_names.gperf"
+#line 3839 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1743, 0},
-#line 2988 "effective_tld_names.gperf"
+#line 3530 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1744, 0},
-#line 1659 "effective_tld_names.gperf"
+#line 5212 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1745, 0},
-#line 564 "effective_tld_names.gperf"
+#line 4659 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1746, 0},
-#line 4823 "effective_tld_names.gperf"
+#line 3486 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1747, 0},
-#line 5302 "effective_tld_names.gperf"
+#line 1633 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1748, 0},
-#line 5632 "effective_tld_names.gperf"
+#line 2837 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1749, 0},
-#line 708 "effective_tld_names.gperf"
+#line 5850 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1750, 0},
-#line 4088 "effective_tld_names.gperf"
+#line 5138 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1751, 0},
-#line 3967 "effective_tld_names.gperf"
+#line 2129 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1752, 0},
-#line 5227 "effective_tld_names.gperf"
+#line 4903 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1753, 0},
-#line 5435 "effective_tld_names.gperf"
+#line 5867 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1754, 0},
-#line 3439 "effective_tld_names.gperf"
+#line 800 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1755, 0},
-#line 4255 "effective_tld_names.gperf"
+#line 4647 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1756, 0},
-#line 2478 "effective_tld_names.gperf"
+#line 102 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1757, 0},
-#line 1565 "effective_tld_names.gperf"
+#line 5102 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1758, 0},
-#line 543 "effective_tld_names.gperf"
+#line 5209 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1759, 0},
-#line 5170 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1760, 0},
-#line 136 "effective_tld_names.gperf"
+#line 2450 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1760, 4},
+#line 2866 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1761, 0},
-#line 4097 "effective_tld_names.gperf"
+#line 5756 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1762, 0},
-#line 398 "effective_tld_names.gperf"
+#line 1404 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1763, 0},
-#line 5198 "effective_tld_names.gperf"
+#line 2826 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1764, 0},
-#line 2887 "effective_tld_names.gperf"
+#line 3605 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1765, 0},
-#line 3954 "effective_tld_names.gperf"
+#line 4697 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1766, 0},
-#line 439 "effective_tld_names.gperf"
+#line 4725 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1767, 0},
-#line 1192 "effective_tld_names.gperf"
+#line 2704 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1768, 0},
-#line 887 "effective_tld_names.gperf"
+#line 5303 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1769, 0},
-#line 1562 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1770, 0},
-#line 607 "effective_tld_names.gperf"
+#line 3710 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1770, 2},
+#line 2010 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1771, 0},
-#line 1114 "effective_tld_names.gperf"
+#line 5170 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1772, 0},
-#line 1538 "effective_tld_names.gperf"
+#line 5889 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1773, 0},
-#line 2588 "effective_tld_names.gperf"
+#line 5148 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1774, 0},
-#line 3973 "effective_tld_names.gperf"
+#line 5142 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1775, 0},
-#line 391 "effective_tld_names.gperf"
+#line 5151 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1776, 0},
-#line 5626 "effective_tld_names.gperf"
+#line 2665 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1777, 0},
-#line 4635 "effective_tld_names.gperf"
+#line 5140 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1778, 0},
-#line 5164 "effective_tld_names.gperf"
+#line 4095 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1779, 0},
-#line 4968 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1780, 0},
-#line 189 "effective_tld_names.gperf"
+#line 3822 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1780, 4},
+#line 2550 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1781, 0},
-#line 1161 "effective_tld_names.gperf"
+#line 3700 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1782, 0},
-#line 142 "effective_tld_names.gperf"
+#line 2918 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1783, 0},
-#line 636 "effective_tld_names.gperf"
+#line 4059 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1784, 0},
-#line 4715 "effective_tld_names.gperf"
+#line 5248 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1785, 0},
-#line 37 "effective_tld_names.gperf"
+#line 4803 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1786, 0},
-#line 2697 "effective_tld_names.gperf"
+#line 2891 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1787, 0},
-#line 1978 "effective_tld_names.gperf"
+#line 5188 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1788, 0},
-#line 546 "effective_tld_names.gperf"
+#line 3408 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1789, 0},
-#line 4063 "effective_tld_names.gperf"
+#line 3826 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1790, 0},
-#line 3233 "effective_tld_names.gperf"
+#line 4959 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1791, 0},
-#line 5570 "effective_tld_names.gperf"
+#line 3059 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1792, 0},
-#line 5184 "effective_tld_names.gperf"
+#line 2933 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1793, 0},
-#line 4651 "effective_tld_names.gperf"
+#line 3621 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1794, 0},
-#line 1278 "effective_tld_names.gperf"
+#line 5291 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1795, 0},
-#line 117 "effective_tld_names.gperf"
+#line 1639 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1796, 0},
-#line 2026 "effective_tld_names.gperf"
+#line 3740 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1797, 0},
-#line 51 "effective_tld_names.gperf"
+#line 1362 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1798, 0},
-#line 1379 "effective_tld_names.gperf"
+#line 4057 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1799, 0},
-#line 4092 "effective_tld_names.gperf"
+#line 5157 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1800, 0},
-#line 4818 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1801, 0},
-#line 4500 "effective_tld_names.gperf"
+#line 2484 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1801, 4},
+#line 2065 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1802, 0},
-#line 858 "effective_tld_names.gperf"
+#line 5764 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1803, 0},
-#line 1609 "effective_tld_names.gperf"
+#line 5682 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1804, 0},
-#line 2607 "effective_tld_names.gperf"
+#line 3883 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1805, 0},
-#line 545 "effective_tld_names.gperf"
+#line 5172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1806, 0},
-#line 4720 "effective_tld_names.gperf"
+#line 4773 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1807, 0},
-#line 3953 "effective_tld_names.gperf"
+#line 2889 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1808, 0},
-#line 2690 "effective_tld_names.gperf"
+#line 5190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1809, 0},
-#line 2913 "effective_tld_names.gperf"
+#line 3032 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1810, 0},
-#line 3199 "effective_tld_names.gperf"
+#line 4015 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1811, 0},
-#line 5086 "effective_tld_names.gperf"
+#line 3697 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1812, 0},
-#line 2997 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1813, 0},
-#line 4833 "effective_tld_names.gperf"
+#line 27 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1813, 4},
+#line 2121 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1814, 0},
-#line 5161 "effective_tld_names.gperf"
+#line 4815 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1815, 0},
-#line 4777 "effective_tld_names.gperf"
+#line 2721 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1816, 0},
-#line 2027 "effective_tld_names.gperf"
+#line 3712 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1817, 0},
-#line 5216 "effective_tld_names.gperf"
+#line 116 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1818, 0},
-#line 2974 "effective_tld_names.gperf"
+#line 1644 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1819, 0},
-#line 5079 "effective_tld_names.gperf"
+#line 4096 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1820, 0},
-#line 4637 "effective_tld_names.gperf"
+#line 5693 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1821, 0},
-#line 3105 "effective_tld_names.gperf"
+#line 2964 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1822, 0},
-#line 3131 "effective_tld_names.gperf"
+#line 6373 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1823, 0},
-#line 3200 "effective_tld_names.gperf"
+#line 2784 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1824, 0},
-#line 1285 "effective_tld_names.gperf"
+#line 1662 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1825, 0},
-#line 241 "effective_tld_names.gperf"
+#line 4771 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1826, 0},
-#line 2975 "effective_tld_names.gperf"
+#line 4719 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1827, 0},
-#line 1362 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1828, 0},
-#line 1164 "effective_tld_names.gperf"
+#line 5921 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1828, 4},
+#line 4998 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1829, 0},
-#line 4083 "effective_tld_names.gperf"
+#line 2108 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1830, 0},
-#line 1302 "effective_tld_names.gperf"
+#line 4737 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1831, 0},
-#line 4964 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1832, 0},
-#line 5174 "effective_tld_names.gperf"
+#line 4970 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1832, 4},
+#line 4855 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1833, 0},
-#line 73 "effective_tld_names.gperf"
+#line 3301 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1834, 0},
-#line 2615 "effective_tld_names.gperf"
+#line 1661 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1835, 0},
-#line 56 "effective_tld_names.gperf"
+#line 5173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1836, 0},
-#line 1375 "effective_tld_names.gperf"
+#line 1382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1837, 0},
-#line 855 "effective_tld_names.gperf"
+#line 456 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1838, 0},
-#line 2039 "effective_tld_names.gperf"
+#line 5090 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1839, 0},
-#line 4839 "effective_tld_names.gperf"
+#line 5115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1840, 0},
-#line 559 "effective_tld_names.gperf"
+#line 5139 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1841, 0},
-#line 1614 "effective_tld_names.gperf"
+#line 5893 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1842, 0},
-#line 4508 "effective_tld_names.gperf"
+#line 3829 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1843, 0},
-#line 1621 "effective_tld_names.gperf"
+#line 2714 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1844, 0},
-#line 1346 "effective_tld_names.gperf"
+#line 2974 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1845, 0},
-#line 4827 "effective_tld_names.gperf"
+#line 2963 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1846, 0},
-#line 666 "effective_tld_names.gperf"
+#line 2682 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1847, 0},
-#line 115 "effective_tld_names.gperf"
+#line 4662 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1848, 0},
-#line 64 "effective_tld_names.gperf"
+#line 2766 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1849, 0},
-#line 3999 "effective_tld_names.gperf"
+#line 5211 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1850, 0},
-#line 2025 "effective_tld_names.gperf"
+#line 5177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1851, 0},
-#line 4016 "effective_tld_names.gperf"
+#line 2105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1852, 0},
-#line 4507 "effective_tld_names.gperf"
+#line 3657 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1853, 0},
-#line 2044 "effective_tld_names.gperf"
+#line 2120 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1854, 0},
-#line 2048 "effective_tld_names.gperf"
+#line 4756 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1855, 0},
-#line 4059 "effective_tld_names.gperf"
+#line 5116 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1856, 0},
-#line 1061 "effective_tld_names.gperf"
+#line 4752 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1857, 0},
-#line 571 "effective_tld_names.gperf"
+#line 2675 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1858, 0},
-#line 586 "effective_tld_names.gperf"
+#line 3042 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1859, 0},
-#line 3063 "effective_tld_names.gperf"
+#line 3698 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1860, 0},
-#line 2691 "effective_tld_names.gperf"
+#line 4063 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1861, 0},
-#line 5277 "effective_tld_names.gperf"
+#line 4754 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1862, 0},
-#line 5045 "effective_tld_names.gperf"
+#line 5267 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1863, 0},
-#line 3319 "effective_tld_names.gperf"
+#line 2971 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1864, 0},
-#line 4095 "effective_tld_names.gperf"
+#line 5113 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1865, 0},
-#line 403 "effective_tld_names.gperf"
+#line 5108 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1866, 0},
-#line 4971 "effective_tld_names.gperf"
+#line 2896 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1867, 0},
-#line 4834 "effective_tld_names.gperf"
+#line 3798 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1868, 0},
-#line 4577 "effective_tld_names.gperf"
+#line 3406 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1869, 0},
-#line 5580 "effective_tld_names.gperf"
+#line 3928 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1870, 0},
-#line 4093 "effective_tld_names.gperf"
+#line 2126 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1871, 0},
-#line 4817 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1872, 0},
-#line 52 "effective_tld_names.gperf"
+#line 4962 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1872, 4},
+#line 3030 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1873, 0},
-#line 2109 "effective_tld_names.gperf"
+#line 3022 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1874, 0},
-#line 112 "effective_tld_names.gperf"
+#line 2738 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1875, 0},
-#line 1964 "effective_tld_names.gperf"
+#line 5747 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1876, 0},
-#line 5581 "effective_tld_names.gperf"
+#line 5306 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1877, 0},
-#line 5107 "effective_tld_names.gperf"
+#line 4811 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1878, 0},
-#line 1163 "effective_tld_names.gperf"
+#line 3694 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1879, 0},
-#line 2592 "effective_tld_names.gperf"
+#line 5781 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1880, 0},
-#line 5571 "effective_tld_names.gperf"
+#line 3644 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1881, 0},
-#line 5089 "effective_tld_names.gperf"
+#line 2112 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1882, 0},
-#line 39 "effective_tld_names.gperf"
+#line 4768 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1883, 0},
-#line 54 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1884, 0},
-#line 1331 "effective_tld_names.gperf"
+#line 4964 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1884, 4},
+#line 4028 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1885, 0},
-#line 4476 "effective_tld_names.gperf"
+#line 5276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1886, 0},
-#line 2621 "effective_tld_names.gperf"
+#line 5282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1887, 0},
-#line 5125 "effective_tld_names.gperf"
+#line 2632 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1888, 0},
-#line 4721 "effective_tld_names.gperf"
+#line 3933 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1889, 0},
-#line 3506 "effective_tld_names.gperf"
+#line 4949 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1890, 0},
-#line 5344 "effective_tld_names.gperf"
+#line 360 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1891, 0},
-#line 2461 "effective_tld_names.gperf"
+#line 2786 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1892, 0},
-#line 4835 "effective_tld_names.gperf"
+#line 3832 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1893, 0},
-#line 4515 "effective_tld_names.gperf"
+#line 5163 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1894, 0},
-#line 4729 "effective_tld_names.gperf"
+#line 2717 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1895, 0},
-#line 2064 "effective_tld_names.gperf"
+#line 3848 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1896, 0},
-#line 2711 "effective_tld_names.gperf"
+#line 5293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1897, 0},
-#line 1330 "effective_tld_names.gperf"
+#line 3305 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1898, 0},
-#line 1537 "effective_tld_names.gperf"
+#line 5249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1899, 0},
-#line 4730 "effective_tld_names.gperf"
+#line 5241 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1900, 0},
-#line 4726 "effective_tld_names.gperf"
+#line 2702 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1901, 0},
-#line 4725 "effective_tld_names.gperf"
+#line 3772 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1902, 0},
-#line 2103 "effective_tld_names.gperf"
+#line 2699 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1903, 0},
-#line 1549 "effective_tld_names.gperf"
+#line 4061 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1904, 0},
-#line 44 "effective_tld_names.gperf"
+#line 3797 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1905, 0},
-#line 709 "effective_tld_names.gperf"
+#line 1428 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1906, 0},
-#line 47 "effective_tld_names.gperf"
+#line 4899 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1907, 0},
-#line 1989 "effective_tld_names.gperf"
+#line 5187 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1908, 0},
-#line 4588 "effective_tld_names.gperf"
+#line 1387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1909, 0},
-#line 4716 "effective_tld_names.gperf"
+#line 1791 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1910, 0},
-#line 2726 "effective_tld_names.gperf"
+#line 4006 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1911, 0},
-#line 42 "effective_tld_names.gperf"
+#line 2928 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1912, 0},
-#line 4906 "effective_tld_names.gperf"
+#line 5176 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1913, 0},
-#line 4718 "effective_tld_names.gperf"
+#line 4727 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1914, 0},
-#line 65 "effective_tld_names.gperf"
+#line 4896 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1915, 0},
-#line 2028 "effective_tld_names.gperf"
+#line 3974 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1916, 0},
-#line 4881 "effective_tld_names.gperf"
+#line 157 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1917, 0},
-#line 3273 "effective_tld_names.gperf"
+#line 1953 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1918, 0},
-#line 4738 "effective_tld_names.gperf"
+#line 210 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1919, 0},
-#line 1438 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1920, 4},
-#line 4229 "effective_tld_names.gperf"
+#line 3325 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1920, 0},
+#line 4990 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1921, 0},
-#line 2570 "effective_tld_names.gperf"
+#line 186 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1922, 0},
-#line 3324 "effective_tld_names.gperf"
+#line 3610 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1923, 0},
-#line 4776 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1924, 4},
-#line 1697 "effective_tld_names.gperf"
+#line 5106 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1924, 0},
+#line 2124 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1925, 0},
-#line 588 "effective_tld_names.gperf"
+#line 2135 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1926, 0},
-#line 67 "effective_tld_names.gperf"
+#line 1737 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1927, 0},
-#line 5378 "effective_tld_names.gperf"
+#line 2507 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1928, 0},
-#line 274 "effective_tld_names.gperf"
+#line 4779 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1929, 0},
-#line 5049 "effective_tld_names.gperf"
+#line 2113 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1930, 0},
-#line 5614 "effective_tld_names.gperf"
+#line 2284 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1931, 0},
-#line 5428 "effective_tld_names.gperf"
+#line 2525 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1932, 0},
-#line 2912 "effective_tld_names.gperf"
+#line 3786 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1933, 0},
-#line 4101 "effective_tld_names.gperf"
+#line 1640 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1934, 0},
-#line 5157 "effective_tld_names.gperf"
+#line 3745 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1935, 0},
-#line 1640 "effective_tld_names.gperf"
+#line 3977 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1936, 0},
-#line 1052 "effective_tld_names.gperf"
+#line 4751 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1937, 0},
-#line 4011 "effective_tld_names.gperf"
+#line 3318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1938, 0},
-#line 38 "effective_tld_names.gperf"
+#line 2893 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1939, 0},
-#line 5199 "effective_tld_names.gperf"
+#line 5704 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1940, 0},
-#line 407 "effective_tld_names.gperf"
+#line 1446 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1941, 0},
-#line 594 "effective_tld_names.gperf"
+#line 2101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1942, 0},
-#line 4868 "effective_tld_names.gperf"
+#line 3028 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1943, 0},
-#line 2836 "effective_tld_names.gperf"
+#line 5132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1944, 0},
-#line 1058 "effective_tld_names.gperf"
+#line 3912 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1945, 0},
-#line 2561 "effective_tld_names.gperf"
+#line 3286 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1946, 0},
-#line 2581 "effective_tld_names.gperf"
+#line 4890 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1947, 0},
-#line 1946 "effective_tld_names.gperf"
+#line 1634 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1948, 0},
-#line 277 "effective_tld_names.gperf"
+#line 6241 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1949, 0},
-#line 1915 "effective_tld_names.gperf"
+#line 6242 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1950, 0},
-#line 2601 "effective_tld_names.gperf"
+#line 4880 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1951, 0},
-#line 1937 "effective_tld_names.gperf"
+#line 2773 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1952, 0},
-#line 1908 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1953, 0},
-#line 1653 "effective_tld_names.gperf"
+#line 6305 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1953, 2},
+#line 5238 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1954, 0},
-#line 593 "effective_tld_names.gperf"
+#line 5119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1955, 0},
-#line 720 "effective_tld_names.gperf"
+#line 3985 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1956, 0},
-#line 5404 "effective_tld_names.gperf"
+#line 2692 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1957, 0},
-#line 2090 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1958, 4},
-#line 2035 "effective_tld_names.gperf"
+#line 6341 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1958, 0},
+#line 5124 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1959, 0},
-#line 5375 "effective_tld_names.gperf"
+#line 1636 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1960, 0},
-#line 2666 "effective_tld_names.gperf"
+#line 5752 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1961, 0},
-#line 4081 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1962, 0},
-#line 1917 "effective_tld_names.gperf"
+#line 1757 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1962, 4},
+#line 3505 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1963, 0},
-#line 5341 "effective_tld_names.gperf"
+#line 1855 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1964, 0},
-#line 58 "effective_tld_names.gperf"
+#line 1277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1965, 0},
-#line 5376 "effective_tld_names.gperf"
+#line 173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1966, 0},
-#line 2633 "effective_tld_names.gperf"
+#line 2305 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1967, 0},
-#line 4031 "effective_tld_names.gperf"
+#line 947 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1968, 0},
-#line 199 "effective_tld_names.gperf"
+#line 5205 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1969, 0},
-#line 191 "effective_tld_names.gperf"
+#line 2719 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1970, 0},
-#line 177 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1971, 0},
-#line 161 "effective_tld_names.gperf"
+#line 2852 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1971, 4},
+#line 4718 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1972, 0},
-#line 4230 "effective_tld_names.gperf"
+#line 4711 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1973, 0},
-#line 5303 "effective_tld_names.gperf"
+#line 4692 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1974, 0},
-#line 3397 "effective_tld_names.gperf"
+#line 2686 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1975, 0},
-#line 6101 "effective_tld_names.gperf"
+#line 5258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1976, 0},
-#line 4762 "effective_tld_names.gperf"
+#line 5111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1977, 0},
-#line 5411 "effective_tld_names.gperf"
+#line 2711 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1978, 0},
-#line 5389 "effective_tld_names.gperf"
+#line 2231 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1979, 0},
-#line 5310 "effective_tld_names.gperf"
+#line 4882 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1980, 0},
-#line 2899 "effective_tld_names.gperf"
+#line 1693 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1981, 0},
-#line 4746 "effective_tld_names.gperf"
+#line 2679 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1982, 0},
-#line 4528 "effective_tld_names.gperf"
+#line 5715 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1983, 0},
-#line 5141 "effective_tld_names.gperf"
+#line 1449 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1984, 0},
-#line 1448 "effective_tld_names.gperf"
+#line 4852 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1985, 0},
-#line 4712 "effective_tld_names.gperf"
+#line 2688 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1986, 0},
-#line 5149 "effective_tld_names.gperf"
+#line 1635 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1987, 0},
-#line 4589 "effective_tld_names.gperf"
+#line 4026 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1988, 0},
-#line 4102 "effective_tld_names.gperf"
+#line 3015 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1989, 0},
-#line 3981 "effective_tld_names.gperf"
+#line 5215 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1990, 0},
-#line 4247 "effective_tld_names.gperf"
+#line 1641 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1991, 0},
-#line 4215 "effective_tld_names.gperf"
+#line 2019 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1992, 0},
-#line 4213 "effective_tld_names.gperf"
+#line 4722 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1993, 0},
-#line 168 "effective_tld_names.gperf"
+#line 1098 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1994, 0},
-#line 4117 "effective_tld_names.gperf"
+#line 3805 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1995, 0},
-#line 4116 "effective_tld_names.gperf"
+#line 2512 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1996, 0},
-#line 4104 "effective_tld_names.gperf"
+#line 3699 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1997, 0},
-#line 4790 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str1998, 4},
-#line 4115 "effective_tld_names.gperf"
+#line 4050 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str1998, 0},
+#line 2728 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str1999, 0},
-#line 4122 "effective_tld_names.gperf"
+#line 140 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2000, 0},
-#line 4107 "effective_tld_names.gperf"
+#line 5255 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2001, 0},
-#line 4111 "effective_tld_names.gperf"
+#line 1673 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2002, 0},
-#line 124 "effective_tld_names.gperf"
+#line 5121 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2003, 0},
-#line 4106 "effective_tld_names.gperf"
+#line 769 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2004, 0},
-#line 1652 "effective_tld_names.gperf"
+#line 100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2005, 0},
-#line 1629 "effective_tld_names.gperf"
+#line 3044 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2006, 0},
-#line 5624 "effective_tld_names.gperf"
+#line 5832 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2007, 0},
-#line 3491 "effective_tld_names.gperf"
+#line 2136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2008, 0},
-#line 702 "effective_tld_names.gperf"
+#line 2950 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2009, 0},
-#line 4195 "effective_tld_names.gperf"
+#line 2138 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2010, 0},
-#line 93 "effective_tld_names.gperf"
+#line 220 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2011, 0},
-#line 4112 "effective_tld_names.gperf"
+#line 1470 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2012, 0},
-#line 4208 "effective_tld_names.gperf"
+#line 2156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2013, 0},
-#line 4203 "effective_tld_names.gperf"
+#line 3702 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2014, 0},
-#line 4202 "effective_tld_names.gperf"
+#line 5823 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2015, 0},
-#line 5370 "effective_tld_names.gperf"
+#line 3711 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2016, 0},
-#line 4119 "effective_tld_names.gperf"
+#line 3303 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2017, 0},
-#line 4240 "effective_tld_names.gperf"
+#line 2890 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2018, 0},
-#line 4211 "effective_tld_names.gperf"
+#line 3007 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2019, 0},
-#line 3970 "effective_tld_names.gperf"
+#line 6369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2020, 0},
-#line 4204 "effective_tld_names.gperf"
+#line 3696 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2021, 0},
-#line 4703 "effective_tld_names.gperf"
+#line 609 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2022, 0},
-#line 4103 "effective_tld_names.gperf"
+#line 1698 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2023, 0},
-#line 4199 "effective_tld_names.gperf"
+#line 3799 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2024, 0},
-#line 724 "effective_tld_names.gperf"
+#line 3708 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2025, 0},
-#line 4153 "effective_tld_names.gperf"
+#line 2290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2026, 0},
-#line 4152 "effective_tld_names.gperf"
+#line 5273 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2027, 0},
-#line 1319 "effective_tld_names.gperf"
+#line 3827 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2028, 0},
-#line 4590 "effective_tld_names.gperf"
+#line 1677 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2029, 0},
-#line 4051 "effective_tld_names.gperf"
+#line 4995 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2030, 0},
-#line 4113 "effective_tld_names.gperf"
+#line 5152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2031, 0},
-#line 4201 "effective_tld_names.gperf"
+#line 4866 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2032, 0},
-#line 4067 "effective_tld_names.gperf"
+#line 3785 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2033, 0},
-#line 2587 "effective_tld_names.gperf"
+#line 3988 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2034, 0},
-#line 198 "effective_tld_names.gperf"
+#line 5824 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2035, 0},
-#line 90 "effective_tld_names.gperf"
+#line 5272 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2036, 0},
-#line 4200 "effective_tld_names.gperf"
+#line 2151 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2037, 0},
-#line 3505 "effective_tld_names.gperf"
+#line 567 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2038, 0},
-#line 5208 "effective_tld_names.gperf"
+#line 5262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2039, 0},
-#line 2812 "effective_tld_names.gperf"
+#line 1110 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2040, 0},
-#line 5290 "effective_tld_names.gperf"
+#line 3526 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2041, 0},
-#line 4110 "effective_tld_names.gperf"
+#line 5105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2042, 0},
-#line 4861 "effective_tld_names.gperf"
+#line 4824 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2043, 0},
-#line 4125 "effective_tld_names.gperf"
+#line 1672 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2044, 0},
-#line 4216 "effective_tld_names.gperf"
+#line 5940 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2045, 0},
-#line 4123 "effective_tld_names.gperf"
+#line 2758 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2046, 0},
-#line 4120 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2047, 0},
-#line 773 "effective_tld_names.gperf"
+#line 4965 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2047, 4},
+#line 1946 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2048, 0},
-#line 4829 "effective_tld_names.gperf"
+#line 5200 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2049, 0},
-#line 2606 "effective_tld_names.gperf"
+#line 288 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2050, 0},
-#line 764 "effective_tld_names.gperf"
+#line 5699 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2051, 0},
-#line 5242 "effective_tld_names.gperf"
+#line 2865 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2052, 0},
-#line 4214 "effective_tld_names.gperf"
+#line 219 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2053, 0},
-#line 4209 "effective_tld_names.gperf"
+#line 2026 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2054, 0},
-#line 4118 "effective_tld_names.gperf"
+#line 5131 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2055, 0},
-#line 4109 "effective_tld_names.gperf"
+#line 4864 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2056, 0},
-#line 5185 "effective_tld_names.gperf"
+#line 5904 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2057, 0},
-#line 6096 "effective_tld_names.gperf"
+#line 3554 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2058, 0},
-#line 60 "effective_tld_names.gperf"
+#line 2190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2059, 0},
-#line 5565 "effective_tld_names.gperf"
+#line 1643 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2060, 0},
-#line 5284 "effective_tld_names.gperf"
+#line 5150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2061, 0},
-#line 4207 "effective_tld_names.gperf"
+#line 4686 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2062, 0},
-#line 988 "effective_tld_names.gperf"
+#line 559 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2063, 0},
-#line 5340 "effective_tld_names.gperf"
+#line 1721 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2064, 0},
-#line 4108 "effective_tld_names.gperf"
+#line 3006 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2065, 0},
-#line 1564 "effective_tld_names.gperf"
+#line 5295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2066, 0},
-#line 699 "effective_tld_names.gperf"
+#line 1947 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2067, 0},
-#line 557 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2068, 1},
-#line 4126 "effective_tld_names.gperf"
+#line 3026 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2068, 0},
+#line 301 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2069, 0},
-#line 4509 "effective_tld_names.gperf"
+#line 5225 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2070, 0},
-#line 4206 "effective_tld_names.gperf"
+#line 1655 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2071, 0},
-#line 1528 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2072, 4},
-#line 4701 "effective_tld_names.gperf"
+#line 4994 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2072, 0},
+#line 2091 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2073, 0},
-#line 5127 "effective_tld_names.gperf"
+#line 638 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2074, 0},
-#line 4212 "effective_tld_names.gperf"
+#line 4685 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2075, 0},
-#line 3132 "effective_tld_names.gperf"
+#line 158 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2076, 0},
-#line 4124 "effective_tld_names.gperf"
+#line 2793 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2077, 0},
-#line 2642 "effective_tld_names.gperf"
+#line 3704 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2078, 0},
-#line 430 "effective_tld_names.gperf"
+#line 22 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2079, 0},
-#line 6102 "effective_tld_names.gperf"
+#line 3433 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2080, 0},
-#line 178 "effective_tld_names.gperf"
+#line 3706 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2081, 0},
-#line 2796 "effective_tld_names.gperf"
+#line 3037 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2082, 0},
-#line 1700 "effective_tld_names.gperf"
+#line 214 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2083, 0},
-#line 4228 "effective_tld_names.gperf"
+#line 3414 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2084, 0},
-#line 4257 "effective_tld_names.gperf"
+#line 3737 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2085, 0},
-#line 5296 "effective_tld_names.gperf"
+#line 2161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2086, 0},
-#line 4132 "effective_tld_names.gperf"
+#line 1522 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2087, 0},
-#line 1338 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2088, 4},
-#line 4014 "effective_tld_names.gperf"
+#line 1538 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2088, 0},
+#line 5885 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2089, 0},
-#line 40 "effective_tld_names.gperf"
+#line 2859 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2090, 0},
-#line 4133 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2091, 0},
-#line 4134 "effective_tld_names.gperf"
+#line 4974 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2091, 2},
+#line 2687 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2092, 0},
-#line 4514 "effective_tld_names.gperf"
+#line 3695 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2093, 0},
-#line 2623 "effective_tld_names.gperf"
+#line 242 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2094, 0},
-#line 1339 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2095, 4},
-#line 4131 "effective_tld_names.gperf"
+#line 4867 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2095, 0},
+#line 165 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2096, 0},
-#line 4226 "effective_tld_names.gperf"
+#line 784 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2097, 0},
-#line 242 "effective_tld_names.gperf"
+#line 2249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2098, 0},
-#line 4473 "effective_tld_names.gperf"
+#line 2736 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2099, 0},
-#line 4078 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2100, 4},
-#line 3503 "effective_tld_names.gperf"
+#line 3058 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2100, 0},
+#line 5235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2101, 0},
-#line 2772 "effective_tld_names.gperf"
+#line 2119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2102, 0},
-#line 3061 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2103, 4},
-#line 179 "effective_tld_names.gperf"
+#line 2155 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2103, 0},
+#line 1565 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2104, 0},
-#line 2963 "effective_tld_names.gperf"
+#line 1942 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2105, 0},
-#line 1885 "effective_tld_names.gperf"
+#line 4816 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2106, 0},
-#line 3867 "effective_tld_names.gperf"
+#line 2088 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2107, 0},
-#line 3935 "effective_tld_names.gperf"
+#line 4865 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2108, 0},
-#line 427 "effective_tld_names.gperf"
+#line 3468 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2109, 0},
-#line 4182 "effective_tld_names.gperf"
+#line 797 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2110, 0},
-#line 4008 "effective_tld_names.gperf"
+#line 907 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2111, 0},
-#line 3952 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2112, 2},
-#line 4506 "effective_tld_names.gperf"
+#line 4081 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2112, 0},
+#line 280 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2113, 0},
-#line 3232 "effective_tld_names.gperf"
+#line 3624 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2114, 0},
-#line 3890 "effective_tld_names.gperf"
+#line 110 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2115, 0},
-#line 4181 "effective_tld_names.gperf"
+#line 3338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2116, 0},
-#line 4816 "effective_tld_names.gperf"
+#line 4105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2117, 0},
-#line 3877 "effective_tld_names.gperf"
+#line 3553 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2118, 0},
-#line 3921 "effective_tld_names.gperf"
+#line 4876 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2119, 0},
-#line 3869 "effective_tld_names.gperf"
+#line 2633 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2120, 0},
-#line 3937 "effective_tld_names.gperf"
+#line 2246 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2121, 0},
-#line 3878 "effective_tld_names.gperf"
+#line 2068 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2122, 0},
-#line 4907 "effective_tld_names.gperf"
+#line 1991 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2123, 0},
-#line 2736 "effective_tld_names.gperf"
+#line 3796 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2124, 0},
-#line 3936 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2125, 0},
-#line 1954 "effective_tld_names.gperf"
+#line 29 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2125, 4},
+#line 2887 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2126, 0},
-#line 3663 "effective_tld_names.gperf"
+#line 621 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2127, 0},
-#line 3944 "effective_tld_names.gperf"
+#line 1506 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2128, 0},
-#line 3662 "effective_tld_names.gperf"
+#line 3477 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2129, 0},
-#line 3865 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2130, 0},
-#line 2827 "effective_tld_names.gperf"
+#line 371 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2130, 4},
+#line 2115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2131, 0},
-#line 2650 "effective_tld_names.gperf"
+#line 1990 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2132, 0},
-#line 583 "effective_tld_names.gperf"
+#line 3783 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2133, 0},
-#line 3929 "effective_tld_names.gperf"
+#line 2036 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2134, 0},
-#line 4828 "effective_tld_names.gperf"
+#line 2694 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2135, 0},
-#line 1637 "effective_tld_names.gperf"
+#line 3978 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2136, 0},
-#line 1295 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2137, 4},
-#line 2803 "effective_tld_names.gperf"
+#line 3002 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2137, 0},
+#line 5677 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2138, 0},
-#line 3923 "effective_tld_names.gperf"
+#line 2900 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2139, 0},
-#line 240 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2140, 0},
-#line 1352 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2141, 4},
-#line 4280 "effective_tld_names.gperf"
+#line 1091 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2140, 1},
+#line 83 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2141, 0},
+#line 3707 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2142, 0},
-#line 3683 "effective_tld_names.gperf"
+#line 4660 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2143, 0},
-#line 4581 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2144, 4},
-#line 3531 "effective_tld_names.gperf"
+#line 493 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2144, 0},
+#line 200 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2145, 0},
-#line 3880 "effective_tld_names.gperf"
+#line 2726 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2146, 0},
-#line 3782 "effective_tld_names.gperf"
+#line 6343 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2147, 0},
-#line 3780 "effective_tld_names.gperf"
+#line 5158 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2148, 0},
-#line 3697 "effective_tld_names.gperf"
+#line 2111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2149, 0},
-#line 3696 "effective_tld_names.gperf"
+#line 398 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2150, 0},
-#line 4183 "effective_tld_names.gperf"
+#line 2539 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2151, 0},
-#line 3685 "effective_tld_names.gperf"
+#line 6365 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2152, 0},
-#line 1911 "effective_tld_names.gperf"
+#line 5193 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2153, 0},
-#line 1831 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2154, 4},
-#line 3701 "effective_tld_names.gperf"
+#line 3904 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2154, 0},
+#line 4777 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2155, 0},
-#line 3688 "effective_tld_names.gperf"
+#line 5194 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2156, 0},
-#line 3692 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2157, 0},
-#line 2943 "effective_tld_names.gperf"
+#line 1694 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2157, 4},
+#line 5239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2158, 0},
-#line 224 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2159, 4},
-#line 3687 "effective_tld_names.gperf"
+#line 393 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2159, 0},
+#line 4693 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2160, 0},
-#line 3669 "effective_tld_names.gperf"
+#line 1518 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2161, 0},
-#line 4234 "effective_tld_names.gperf"
+#line 3705 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2162, 0},
-#line 3809 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2163, 2},
-#line 3765 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2164, 0},
-#line 1843 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2165, 4},
-#line 3693 "effective_tld_names.gperf"
+#line 4987 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2163, 0},
+#line 2212 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2164, 4},
+#line 5280 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2165, 0},
+#line 1553 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2166, 0},
-#line 3775 "effective_tld_names.gperf"
+#line 3588 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2167, 0},
-#line 3771 "effective_tld_names.gperf"
+#line 2868 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2168, 0},
-#line 5335 "effective_tld_names.gperf"
+#line 1743 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2169, 0},
-#line 2705 "effective_tld_names.gperf"
+#line 1647 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2170, 0},
-#line 3879 "effective_tld_names.gperf"
+#line 4823 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2171, 0},
-#line 3157 "effective_tld_names.gperf"
+#line 1989 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2172, 0},
-#line 3699 "effective_tld_names.gperf"
+#line 3652 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2173, 0},
-#line 2735 "effective_tld_names.gperf"
+#line 2176 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2174, 0},
-#line 3772 "effective_tld_names.gperf"
+#line 3585 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2175, 0},
-#line 2856 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2176, 4},
-#line 3858 "effective_tld_names.gperf"
+#line 2776 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2176, 0},
+#line 2546 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2177, 0},
-#line 2453 "effective_tld_names.gperf"
+#line 2056 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2178, 0},
-#line 3684 "effective_tld_names.gperf"
+#line 3508 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2179, 0},
-#line 4534 "effective_tld_names.gperf"
+#line 2131 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2180, 0},
-#line 3768 "effective_tld_names.gperf"
+#line 5093 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2181, 0},
-#line 3729 "effective_tld_names.gperf"
+#line 1622 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2182, 0},
-#line 3728 "effective_tld_names.gperf"
+#line 5751 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2183, 0},
-#line 2964 "effective_tld_names.gperf"
+#line 2292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2184, 0},
-#line 4756 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2185, 4},
-#line 5159 "effective_tld_names.gperf"
+#line 141 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2185, 0},
+#line 4698 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2186, 0},
-#line 4898 "effective_tld_names.gperf"
+#line 406 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2187, 0},
-#line 3694 "effective_tld_names.gperf"
+#line 5301 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2188, 0},
-#line 5235 "effective_tld_names.gperf"
+#line 6248 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2189, 0},
-#line 3908 "effective_tld_names.gperf"
+#line 3961 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2190, 0},
-#line 5228 "effective_tld_names.gperf"
+#line 5247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2191, 0},
-#line 3770 "effective_tld_names.gperf"
+#line 2230 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2192, 0},
-#line 5003 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2193, 4},
-#line 4245 "effective_tld_names.gperf"
+#line 5861 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2193, 0},
+#line 4753 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2194, 0},
-#line 4052 "effective_tld_names.gperf"
+#line 6288 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2195, 0},
-#line 3860 "effective_tld_names.gperf"
+#line 5886 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2196, 0},
-#line 4105 "effective_tld_names.gperf"
+#line 2969 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2197, 0},
-#line 2622 "effective_tld_names.gperf"
+#line 3701 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2198, 0},
-#line 3769 "effective_tld_names.gperf"
+#line 384 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2199, 0},
-#line 3934 "effective_tld_names.gperf"
+#line 3377 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2200, 0},
-#line 3691 "effective_tld_names.gperf"
+#line 2029 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2201, 0},
-#line 4884 "effective_tld_names.gperf"
+#line 5938 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2202, 0},
-#line 4908 "effective_tld_names.gperf"
+#line 4724 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2203, 0},
-#line 3704 "effective_tld_names.gperf"
+#line 2863 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2204, 0},
-#line 3532 "effective_tld_names.gperf"
+#line 3480 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2205, 0},
-#line 3783 "effective_tld_names.gperf"
+#line 3962 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2206, 0},
-#line 3702 "effective_tld_names.gperf"
+#line 3869 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2207, 0},
-#line 3700 "effective_tld_names.gperf"
+#line 5191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2208, 0},
-#line 4223 "effective_tld_names.gperf"
+#line 3998 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2209, 0},
-#line 4224 "effective_tld_names.gperf"
+#line 2097 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2210, 0},
-#line 3861 "effective_tld_names.gperf"
+#line 3729 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2211, 0},
-#line 833 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2212, 4},
-#line 3533 "effective_tld_names.gperf"
+#line 4877 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2212, 0},
+#line 5137 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2213, 0},
-#line 3781 "effective_tld_names.gperf"
+#line 3311 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2214, 0},
-#line 774 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2215, 1},
-#line 3776 "effective_tld_names.gperf"
+#line 2720 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2215, 0},
+#line 5898 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2216, 0},
-#line 3698 "effective_tld_names.gperf"
+#line 3868 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2217, 0},
-#line 82 "effective_tld_names.gperf"
+#line 3650 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2218, 0},
-#line 2037 "effective_tld_names.gperf"
+#line 2337 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2219, 0},
-#line 3690 "effective_tld_names.gperf"
+#line 3865 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2220, 0},
-#line 4782 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2221, 4},
-#line 3530 "effective_tld_names.gperf"
+#line 291 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2221, 0},
+#line 3329 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2222, 0},
-#line 797 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2223, 4},
-#line 273 "effective_tld_names.gperf"
+#line 3492 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2223, 0},
+#line 1762 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2224, 0},
-#line 4040 "effective_tld_names.gperf"
+#line 5097 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2225, 0},
-#line 4222 "effective_tld_names.gperf"
+#line 3759 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2226, 0},
-#line 3589 "effective_tld_names.gperf"
+#line 4848 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2227, 0},
-#line 5436 "effective_tld_names.gperf"
+#line 3324 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2228, 0},
-#line 854 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2229, 4},
-#line 3993 "effective_tld_names.gperf"
+#line 5284 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2229, 0},
+#line 1692 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2230, 0},
-#line 3920 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2231, 2},
-#line 3659 "effective_tld_names.gperf"
+#line 2032 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2231, 0},
+#line 2232 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2232, 0},
-#line 3689 "effective_tld_names.gperf"
+#line 3029 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2233, 0},
-#line 5018 "effective_tld_names.gperf"
+#line 1546 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2234, 0},
-#line 1007 "effective_tld_names.gperf"
+#line 2750 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2235, 0},
-#line 3881 "effective_tld_names.gperf"
+#line 1364 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2236, 0},
-#line 3705 "effective_tld_names.gperf"
+#line 5312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2237, 0},
-#line 3774 "effective_tld_names.gperf"
+#line 2976 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2238, 0},
-#line 3595 "effective_tld_names.gperf"
+#line 4883 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2239, 0},
-#line 3591 "effective_tld_names.gperf"
+#line 1697 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2240, 0},
-#line 1558 "effective_tld_names.gperf"
+#line 163 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2241, 0},
-#line 4085 "effective_tld_names.gperf"
+#line 3489 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2242, 0},
-#line 4617 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2243, 4},
-#line 255 "effective_tld_names.gperf"
+#line 5231 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2243, 0},
+#line 4097 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2244, 0},
-#line 5124 "effective_tld_names.gperf"
+#line 117 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2245, 0},
-#line 3779 "effective_tld_names.gperf"
+#line 5216 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2246, 0},
-#line 1064 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2247, 4},
-#line 211 "effective_tld_names.gperf"
+#line 6326 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2247, 0},
+#line 2735 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2248, 0},
-#line 4114 "effective_tld_names.gperf"
+#line 5680 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2249, 0},
-#line 548 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2250, 4},
-#line 34 "effective_tld_names.gperf"
+#line 3040 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2250, 0},
+#line 2703 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2251, 0},
-#line 1607 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2252, 4},
-#line 3703 "effective_tld_names.gperf"
+#line 3273 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2252, 0},
+#line 5195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2253, 0},
-#line 5265 "effective_tld_names.gperf"
+#line 2967 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2254, 0},
-#line 2062 "effective_tld_names.gperf"
+#line 4669 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2255, 0},
-#line 3477 "effective_tld_names.gperf"
+#line 3964 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2256, 0},
-#line 4225 "effective_tld_names.gperf"
+#line 4000 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2257, 0},
-#line 147 "effective_tld_names.gperf"
+#line 2940 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2258, 0},
-#line 4205 "effective_tld_names.gperf"
+#line 3049 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2259, 0},
-#line 2728 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2260, 4},
-#line 5133 "effective_tld_names.gperf"
+#line 5053 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2260, 0},
+#line 2058 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2261, 0},
-#line 1886 "effective_tld_names.gperf"
+#line 2767 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2262, 0},
-#line 1079 "effective_tld_names.gperf"
+#line 3411 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2263, 0},
-#line 1165 "effective_tld_names.gperf"
+#line 119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2264, 0},
-#line 805 "effective_tld_names.gperf"
+#line 5061 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2265, 0},
-#line 5367 "effective_tld_names.gperf"
+#line 2834 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2266, 0},
-#line 1844 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2267, 4},
-#line 3594 "effective_tld_names.gperf"
+#line 1919 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2267, 0},
+#line 1343 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2268, 0},
-#line 1432 "effective_tld_names.gperf"
+#line 1017 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2269, 0},
-#line 3808 "effective_tld_names.gperf"
+#line 5269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2270, 0},
-#line 4882 "effective_tld_names.gperf"
+#line 6273 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2271, 0},
-#line 3711 "effective_tld_names.gperf"
+#line 1881 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2272, 0},
-#line 5138 "effective_tld_names.gperf"
+#line 362 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2273, 0},
-#line 3962 "effective_tld_names.gperf"
+#line 1304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2274, 0},
-#line 3637 "effective_tld_names.gperf"
+#line 290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2275, 0},
-#line 2693 "effective_tld_names.gperf"
+#line 975 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2276, 0},
-#line 5029 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2277, 1},
-#line 3864 "effective_tld_names.gperf"
+#line 2697 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2277, 0},
+#line 1350 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2278, 0},
-#line 1155 "effective_tld_names.gperf"
+#line 1026 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2279, 0},
-#line 3945 "effective_tld_names.gperf"
+#line 4109 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2280, 0},
-#line 5405 "effective_tld_names.gperf"
+#line 5180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2281, 0},
-#line 4989 "effective_tld_names.gperf"
+#line 4110 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2282, 0},
-#line 3710 "effective_tld_names.gperf"
+#line 6280 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2283, 0},
-#line 4511 "effective_tld_names.gperf"
+#line 5236 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2284, 0},
-#line 3601 "effective_tld_names.gperf"
+#line 3008 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2285, 0},
-#line 4277 "effective_tld_names.gperf"
+#line 5254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2286, 0},
-#line 3991 "effective_tld_names.gperf"
+#line 782 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2287, 0},
-#line 2040 "effective_tld_names.gperf"
+#line 1985 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2288, 0},
-#line 97 "effective_tld_names.gperf"
+#line 4728 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2289, 0},
-#line 3792 "effective_tld_names.gperf"
+#line 2046 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2290, 0},
-#line 150 "effective_tld_names.gperf"
+#line 4257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2291, 0},
-#line 3600 "effective_tld_names.gperf"
+#line 4285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2292, 0},
-#line 4551 "effective_tld_names.gperf"
+#line 4341 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2293, 0},
-#line 483 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2294, 4},
-#line 576 "effective_tld_names.gperf"
+#line 2730 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2294, 0},
+#line 4284 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2295, 0},
-#line 1441 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2296, 4},
-#line 5207 "effective_tld_names.gperf"
+#line 5288 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2296, 0},
+#line 4366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2297, 0},
-#line 1920 "effective_tld_names.gperf"
+#line 4355 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2298, 0},
-#line 28 "effective_tld_names.gperf"
+#line 4354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2299, 0},
-#line 3667 "effective_tld_names.gperf"
+#line 2999 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2300, 0},
-#line 2985 "effective_tld_names.gperf"
+#line 1839 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2301, 0},
-#line 41 "effective_tld_names.gperf"
+#line 4666 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2302, 0},
-#line 498 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2303, 4},
-#line 706 "effective_tld_names.gperf"
+#line 4359 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2303, 0},
+#line 4322 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2304, 0},
-#line 499 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2305, 4},
-#line 3753 "effective_tld_names.gperf"
+#line 4321 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2305, 0},
+#line 4358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2306, 0},
-#line 1143 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2307, 4},
-#line 3666 "effective_tld_names.gperf"
+#line 930 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2307, 0},
+#line 3728 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2308, 0},
-#line 5237 "effective_tld_names.gperf"
+#line 2557 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2309, 0},
-#line 4671 "effective_tld_names.gperf"
+#line 4067 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2310, 0},
-#line 2000 "effective_tld_names.gperf"
+#line 4319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2311, 0},
-#line 5631 "effective_tld_names.gperf"
+#line 4318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2312, 0},
-#line 4543 "effective_tld_names.gperf"
+#line 5166 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2313, 0},
-#line 5131 "effective_tld_names.gperf"
+#line 4320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2314, 0},
-#line 2652 "effective_tld_names.gperf"
+#line 4364 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2315, 0},
-#line 5315 "effective_tld_names.gperf"
+#line 146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2316, 0},
-#line 116 "effective_tld_names.gperf"
+#line 5077 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2317, 0},
-#line 1138 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2318, 4},
-#line 110 "effective_tld_names.gperf"
+#line 4361 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2318, 0},
+#line 2331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2319, 0},
-#line 4049 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2320, 1},
-#line 2604 "effective_tld_names.gperf"
+#line 5083 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2320, 0},
+#line 4129 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2321, 0},
-#line 1983 "effective_tld_names.gperf"
+#line 34 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2322, 0},
-#line 553 "effective_tld_names.gperf"
+#line 4340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2323, 0},
-#line 141 "effective_tld_names.gperf"
+#line 2549 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2324, 0},
-#line 3597 "effective_tld_names.gperf"
+#line 6261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2325, 0},
-#line 2986 "effective_tld_names.gperf"
+#line 2934 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2326, 0},
-#line 3866 "effective_tld_names.gperf"
+#line 4167 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2327, 0},
-#line 4704 "effective_tld_names.gperf"
+#line 2888 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2328, 0},
-#line 3754 "effective_tld_names.gperf"
+#line 3070 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2329, 0},
-#line 2649 "effective_tld_names.gperf"
+#line 4290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2330, 0},
-#line 2753 "effective_tld_names.gperf"
+#line 5168 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2331, 0},
-#line 3404 "effective_tld_names.gperf"
+#line 4287 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2332, 0},
-#line 2020 "effective_tld_names.gperf"
+#line 3716 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2333, 0},
-#line 2534 "effective_tld_names.gperf"
+#line 4374 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2334, 0},
-#line 1914 "effective_tld_names.gperf"
+#line 4371 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2335, 0},
-#line 493 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2336, 4},
-#line 4877 "effective_tld_names.gperf"
+#line 4372 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2336, 0},
+#line 4357 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2337, 0},
-#line 5033 "effective_tld_names.gperf"
+#line 4360 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2338, 0},
-#line 2712 "effective_tld_names.gperf"
+#line 2785 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2339, 0},
-#line 5039 "effective_tld_names.gperf"
+#line 276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2340, 0},
-#line 4747 "effective_tld_names.gperf"
+#line 5833 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2341, 0},
-#line 6103 "effective_tld_names.gperf"
+#line 4317 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2342, 0},
-#line 4667 "effective_tld_names.gperf"
+#line 4288 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2343, 0},
-#line 3042 "effective_tld_names.gperf"
+#line 6295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2344, 0},
-#line 2079 "effective_tld_names.gperf"
+#line 4199 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2345, 0},
-#line 815 "effective_tld_names.gperf"
+#line 2561 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2346, 0},
-#line 3355 "effective_tld_names.gperf"
+#line 1893 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2347, 0},
-#line 2626 "effective_tld_names.gperf"
+#line 1315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2348, 0},
-#line 3686 "effective_tld_names.gperf"
+#line 4275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2349, 0},
-#line 3444 "effective_tld_names.gperf"
+#line 4274 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2350, 0},
-#line 2009 "effective_tld_names.gperf"
+#line 4273 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2351, 0},
-#line 143 "effective_tld_names.gperf"
+#line 6348 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2352, 0},
-#line 486 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2353, 4},
-#line 3789 "effective_tld_names.gperf"
+#line 4377 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2353, 0},
+#line 985 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2354, 0},
-#line 4708 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2355, 4},
-#line 1683 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2356, 1},
-#line 2837 "effective_tld_names.gperf"
+#line 4272 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2355, 0},
+#line 4993 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2356, 0},
+#line 289 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2357, 0},
-#line 2674 "effective_tld_names.gperf"
+#line 4221 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2358, 0},
-#line 3790 "effective_tld_names.gperf"
+#line 1813 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2359, 0},
-#line 3926 "effective_tld_names.gperf"
+#line 4269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2360, 0},
-#line 5560 "effective_tld_names.gperf"
+#line 4305 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2361, 0},
-#line 2001 "effective_tld_names.gperf"
+#line 4307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2362, 0},
-#line 4840 "effective_tld_names.gperf"
+#line 4306 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2363, 0},
-#line 4640 "effective_tld_names.gperf"
+#line 4407 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2364, 0},
-#line 135 "effective_tld_names.gperf"
+#line 4303 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2365, 0},
-#line 3891 "effective_tld_names.gperf"
+#line 2308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2366, 0},
-#line 1631 "effective_tld_names.gperf"
+#line 4338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2367, 0},
-#line 4045 "effective_tld_names.gperf"
+#line 4002 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2368, 0},
-#line 2124 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2369, 4},
-#line 2676 "effective_tld_names.gperf"
+#line 1493 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2369, 0},
+#line 6284 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2370, 0},
-#line 1055 "effective_tld_names.gperf"
+#line 2939 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2371, 0},
-#line 3788 "effective_tld_names.gperf"
+#line 4353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2372, 0},
-#line 3229 "effective_tld_names.gperf"
+#line 3272 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2373, 0},
-#line 2535 "effective_tld_names.gperf"
+#line 1658 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2374, 0},
-#line 1494 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2375, 4},
-#line 1497 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2376, 4},
-#line 1479 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2377, 4},
-#line 1508 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2378, 4},
-#line 1486 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2379, 4},
-#line 4723 "effective_tld_names.gperf"
+#line 3607 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2375, 0},
+#line 4065 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2376, 0},
+#line 2217 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2377, 0},
+#line 3073 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2378, 0},
+#line 4268 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2379, 0},
+#line 1905 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2380, 0},
-#line 1839 "effective_tld_names.gperf"
+#line 4309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2381, 0},
-#line 4935 "effective_tld_names.gperf"
+#line 1329 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2382, 0},
-#line 497 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2383, 4},
-#line 3946 "effective_tld_names.gperf"
+#line 1000 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2383, 0},
+#line 758 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2384, 0},
-#line 3818 "effective_tld_names.gperf"
+#line 6299 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2385, 0},
-#line 3651 "effective_tld_names.gperf"
+#line 5285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2386, 0},
-#line 1910 "effective_tld_names.gperf"
+#line 4331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2387, 0},
-#line 1473 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2388, 4},
-#line 3676 "effective_tld_names.gperf"
+#line 3713 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2388, 0},
+#line 3715 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2389, 0},
-#line 3152 "effective_tld_names.gperf"
+#line 3352 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2390, 0},
-#line 488 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2391, 4},
-#line 4287 "effective_tld_names.gperf"
+#line 4825 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2391, 0},
+#line 4376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2392, 0},
-#line 3043 "effective_tld_names.gperf"
+#line 4328 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2393, 0},
-#line 2939 "effective_tld_names.gperf"
+#line 6372 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2394, 0},
-#line 1477 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2395, 4},
-#line 3626 "effective_tld_names.gperf"
+#line 2137 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2395, 0},
+#line 363 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2396, 0},
-#line 1485 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2397, 4},
-#line 5230 "effective_tld_names.gperf"
+#line 333 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2397, 0},
+#line 4308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2398, 0},
-#line 4841 "effective_tld_names.gperf"
+#line 5259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2399, 0},
-#line 2942 "effective_tld_names.gperf"
+#line 3647 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2400, 0},
-#line 2928 "effective_tld_names.gperf"
+#line 4329 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2401, 0},
-#line 1507 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2402, 4},
-#line 471 "effective_tld_names.gperf"
+#line 4326 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2402, 0},
+#line 4440 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2403, 0},
-#line 1472 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2404, 4},
-#line 3778 "effective_tld_names.gperf"
+#line 147 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2404, 0},
+#line 4052 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2405, 0},
-#line 1069 "effective_tld_names.gperf"
+#line 4277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2406, 0},
-#line 3695 "effective_tld_names.gperf"
+#line 120 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2407, 0},
-#line 778 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2408, 1},
-#line 4885 "effective_tld_names.gperf"
+#line 4389 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2408, 0},
+#line 4265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2409, 0},
-#line 4286 "effective_tld_names.gperf"
+#line 4258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2410, 0},
-#line 5267 "effective_tld_names.gperf"
+#line 5201 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2411, 0},
-#line 5639 "effective_tld_names.gperf"
+#line 2676 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2412, 0},
-#line 757 "effective_tld_names.gperf"
+#line 4271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2413, 0},
-#line 1471 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2414, 4},
-#line 3791 "effective_tld_names.gperf"
+#line 4325 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2414, 0},
+#line 4350 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2415, 0},
-#line 1516 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2416, 4},
-#line 3773 "effective_tld_names.gperf"
+#line 4349 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2416, 0},
+#line 4263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2417, 0},
-#line 3084 "effective_tld_names.gperf"
+#line 906 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2418, 0},
-#line 2065 "effective_tld_names.gperf"
+#line 4259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2419, 0},
-#line 2790 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2420, 4},
-#line 2550 "effective_tld_names.gperf"
+#line 1642 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2420, 0},
+#line 4346 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2421, 0},
-#line 119 "effective_tld_names.gperf"
+#line 3681 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2422, 0},
-#line 3405 "effective_tld_names.gperf"
+#line 5033 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2423, 0},
-#line 1515 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2424, 4},
-#line 1514 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2425, 4},
-#line 2133 "effective_tld_names.gperf"
+#line 273 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2424, 0},
+#line 352 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2425, 0},
+#line 4347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2426, 0},
-#line 6094 "effective_tld_names.gperf"
+#line 2510 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2427, 0},
-#line 5357 "effective_tld_names.gperf"
+#line 4381 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2428, 0},
-#line 495 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2429, 4},
-#line 4622 "effective_tld_names.gperf"
+#line 4343 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2429, 0},
+#line 3669 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2430, 0},
-#line 5287 "effective_tld_names.gperf"
+#line 2678 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2431, 0},
-#line 614 "effective_tld_names.gperf"
+#line 6290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2432, 0},
-#line 2951 "effective_tld_names.gperf"
+#line 4335 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2433, 0},
-#line 2608 "effective_tld_names.gperf"
+#line 4382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2434, 0},
-#line 4826 "effective_tld_names.gperf"
+#line 3981 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2435, 0},
-#line 5069 "effective_tld_names.gperf"
+#line 2910 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2436, 0},
-#line 1504 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2437, 4},
-#line 1503 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2438, 4},
-#line 3057 "effective_tld_names.gperf"
+#line 3459 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2437, 0},
+#line 4007 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2438, 0},
+#line 4991 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2439, 0},
-#line 1500 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2440, 4},
-#line 3856 "effective_tld_names.gperf"
+#line 6350 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2440, 0},
+#line 2787 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2441, 0},
-#line 494 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2442, 4},
-#line 4724 "effective_tld_names.gperf"
+#line 2871 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2442, 0},
+#line 4342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2443, 0},
-#line 2073 "effective_tld_names.gperf"
+#line 488 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2444, 0},
-#line 1490 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2445, 4},
-#line 1555 "effective_tld_names.gperf"
+#line 5753 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2445, 0},
+#line 3465 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2446, 0},
-#line 1483 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2447, 4},
-#line 2005 "effective_tld_names.gperf"
+#line 2825 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2447, 0},
+#line 3319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2448, 0},
-#line 1481 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2449, 4},
-#line 1502 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2450, 4},
-#line 1445 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2451, 4},
-#line 3068 "effective_tld_names.gperf"
+#line 2193 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2449, 0},
+#line 5887 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2450, 0},
+#line 2513 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2451, 0},
+#line 4049 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2452, 0},
-#line 4032 "effective_tld_names.gperf"
+#line 5711 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2453, 0},
-#line 4632 "effective_tld_names.gperf"
+#line 3364 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2454, 0},
-#line 269 "effective_tld_names.gperf"
+#line 5023 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2455, 0},
-#line 496 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2456, 4},
-#line 2018 "effective_tld_names.gperf"
+#line 2740 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2456, 0},
+#line 1998 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2457, 0},
-#line 2014 "effective_tld_names.gperf"
+#line 4408 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2458, 0},
-#line 1436 "effective_tld_names.gperf"
+#line 4262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2459, 0},
-#line 2531 "effective_tld_names.gperf"
+#line 4299 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2460, 0},
-#line 749 "effective_tld_names.gperf"
+#line 1872 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2461, 0},
-#line 4894 "effective_tld_names.gperf"
+#line 1296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2462, 0},
-#line 1475 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2463, 4},
-#line 541 "effective_tld_names.gperf"
+#line 4973 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2463, 0},
+#line 967 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2464, 0},
-#line 4670 "effective_tld_names.gperf"
+#line 3993 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2465, 0},
-#line 1420 "effective_tld_names.gperf"
+#line 4840 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2466, 0},
-#line 1491 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2467, 4},
-#line 1484 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2468, 4},
-#line 3677 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2469, 0},
-#line 3804 "effective_tld_names.gperf"
+#line 3425 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2467, 0},
+#line 2504 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2468, 0},
+#line 2456 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2469, 4},
+#line 2256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2470, 0},
-#line 1299 "effective_tld_names.gperf"
+#line 2526 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2471, 0},
-#line 4742 "effective_tld_names.gperf"
+#line 3322 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2472, 0},
-#line 3596 "effective_tld_names.gperf"
+#line 3730 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2473, 0},
-#line 3039 "effective_tld_names.gperf"
+#line 4383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2474, 0},
-#line 3598 "effective_tld_names.gperf"
+#line 3984 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2475, 0},
-#line 1496 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2476, 4},
-#line 2944 "effective_tld_names.gperf"
+#line 2741 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2476, 0},
+#line 3039 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2477, 0},
-#line 1487 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2478, 4},
-#line 258 "effective_tld_names.gperf"
+#line 3777 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2478, 0},
+#line 135 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2479, 0},
-#line 4068 "effective_tld_names.gperf"
+#line 5040 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2480, 0},
-#line 1513 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2481, 4},
-#line 4745 "effective_tld_names.gperf"
+#line 2727 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2481, 0},
+#line 1648 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2482, 0},
-#line 5439 "effective_tld_names.gperf"
+#line 4441 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2483, 0},
-#line 4648 "effective_tld_names.gperf"
+#line 4236 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2484, 0},
-#line 4815 "effective_tld_names.gperf"
+#line 4312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2485, 0},
-#line 3901 "effective_tld_names.gperf"
+#line 6339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2486, 0},
-#line 1158 "effective_tld_names.gperf"
+#line 5837 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2487, 0},
-#line 5113 "effective_tld_names.gperf"
+#line 5062 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2488, 0},
-#line 74 "effective_tld_names.gperf"
+#line 3447 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2489, 0},
-#line 1134 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2490, 4},
-#line 4244 "effective_tld_names.gperf"
+#line 5028 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2490, 0},
+#line 4314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2491, 0},
-#line 321 "effective_tld_names.gperf"
+#line 5026 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2492, 0},
-#line 4272 "effective_tld_names.gperf"
+#line 4260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2493, 0},
-#line 665 "effective_tld_names.gperf"
+#line 5066 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2494, 0},
-#line 1446 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2495, 4},
-#line 648 "effective_tld_names.gperf"
+#line 4416 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2495, 0},
+#line 3507 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2496, 0},
-#line 658 "effective_tld_names.gperf"
+#line 1660 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2497, 0},
-#line 2781 "effective_tld_names.gperf"
+#line 6298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2498, 0},
-#line 3592 "effective_tld_names.gperf"
+#line 3335 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2499, 0},
-#line 1170 "effective_tld_names.gperf"
+#line 2418 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2500, 0},
-#line 651 "effective_tld_names.gperf"
+#line 3866 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2501, 0},
-#line 3168 "effective_tld_names.gperf"
+#line 2921 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2502, 0},
-#line 644 "effective_tld_names.gperf"
+#line 3281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2503, 0},
-#line 3752 "effective_tld_names.gperf"
+#line 4344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2504, 0},
-#line 1506 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2505, 4},
-#line 642 "effective_tld_names.gperf"
+#line 4188 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2505, 0},
+#line 2742 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2506, 0},
-#line 664 "effective_tld_names.gperf"
+#line 2051 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2507, 0},
-#line 685 "effective_tld_names.gperf"
+#line 4451 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2508, 0},
-#line 5076 "effective_tld_names.gperf"
+#line 1807 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2509, 0},
-#line 655 "effective_tld_names.gperf"
+#line 4128 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2510, 0},
-#line 4010 "effective_tld_names.gperf"
+#line 3453 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2511, 0},
-#line 2448 "effective_tld_names.gperf"
+#line 4433 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2512, 0},
-#line 2668 "effective_tld_names.gperf"
+#line 2304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2513, 0},
-#line 1567 "effective_tld_names.gperf"
+#line 6338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2514, 0},
-#line 624 "effective_tld_names.gperf"
+#line 4410 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2515, 0},
-#line 1526 "effective_tld_names.gperf"
+#line 4888 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2516, 0},
-#line 4469 "effective_tld_names.gperf"
+#line 3490 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2517, 0},
-#line 1478 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2518, 4},
-#line 4012 "effective_tld_names.gperf"
+#line 5110 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2518, 0},
+#line 4205 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2519, 0},
-#line 1499 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2520, 4},
-#line 2071 "effective_tld_names.gperf"
+#line 2116 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2520, 0},
+#line 5791 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2521, 0},
-#line 3593 "effective_tld_names.gperf"
+#line 2779 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2522, 0},
-#line 4909 "effective_tld_names.gperf"
+#line 4449 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2523, 0},
-#line 5232 "effective_tld_names.gperf"
+#line 5260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2524, 0},
-#line 5119 "effective_tld_names.gperf"
+#line 4196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2525, 0},
-#line 4831 "effective_tld_names.gperf"
+#line 6335 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2526, 0},
-#line 1512 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2527, 4},
-#line 4084 "effective_tld_names.gperf"
+#line 2301 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2527, 0},
+#line 4311 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2528, 0},
-#line 689 "effective_tld_names.gperf"
+#line 3484 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2529, 0},
-#line 1900 "effective_tld_names.gperf"
+#line 426 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2530, 0},
-#line 2833 "effective_tld_names.gperf"
+#line 2886 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2531, 0},
-#line 4645 "effective_tld_names.gperf"
+#line 5167 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2532, 0},
-#line 688 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2533, 0},
-#line 4232 "effective_tld_names.gperf"
+#line 2445 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2533, 4},
+#line 5056 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2534, 0},
-#line 779 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2535, 1},
-#line 2828 "effective_tld_names.gperf"
+#line 807 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2535, 0},
+#line 2052 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2536, 0},
-#line 686 "effective_tld_names.gperf"
+#line 6332 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2537, 0},
-#line 4075 "effective_tld_names.gperf"
+#line 4168 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2538, 0},
-#line 4036 "effective_tld_names.gperf"
+#line 5700 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2539, 0},
-#line 684 "effective_tld_names.gperf"
+#line 6293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2540, 0},
-#line 2809 "effective_tld_names.gperf"
+#line 767 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2541, 0},
-#line 678 "effective_tld_names.gperf"
+#line 4997 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2542, 0},
-#line 1011 "effective_tld_names.gperf"
+#line 565 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2543, 0},
-#line 2915 "effective_tld_names.gperf"
+#line 2973 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2544, 0},
-#line 1966 "effective_tld_names.gperf"
+#line 5092 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2545, 0},
-#line 3376 "effective_tld_names.gperf"
+#line 4846 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2546, 0},
-#line 1684 "effective_tld_names.gperf"
+#line 5074 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2547, 0},
-#line 1501 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2548, 4},
-#line 645 "effective_tld_names.gperf"
+#line 2024 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2548, 0},
+#line 4062 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2549, 0},
-#line 4930 "effective_tld_names.gperf"
+#line 2756 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2550, 0},
-#line 1951 "effective_tld_names.gperf"
+#line 145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2551, 0},
-#line 339 "effective_tld_names.gperf"
+#line 5890 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2552, 0},
-#line 1933 "effective_tld_names.gperf"
+#line 281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2553, 0},
-#line 3624 "effective_tld_names.gperf"
+#line 1076 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2554, 0},
-#line 2562 "effective_tld_names.gperf"
+#line 294 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2555, 0},
-#line 1498 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2556, 4},
-#line 5123 "effective_tld_names.gperf"
+#line 5038 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2556, 0},
+#line 6355 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2557, 0},
-#line 5353 "effective_tld_names.gperf"
+#line 771 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2558, 0},
-#line 4741 "effective_tld_names.gperf"
+#line 2975 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2559, 0},
-#line 2682 "effective_tld_names.gperf"
+#line 5055 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2560, 0},
-#line 671 "effective_tld_names.gperf"
+#line 2747 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2561, 0},
-#line 657 "effective_tld_names.gperf"
+#line 6333 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2562, 0},
-#line 2061 "effective_tld_names.gperf"
+#line 139 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2563, 0},
-#line 377 "effective_tld_names.gperf"
+#line 5309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2564, 0},
-#line 2851 "effective_tld_names.gperf"
+#line 4978 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2565, 0},
-#line 3403 "effective_tld_names.gperf"
+#line 2952 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2566, 0},
-#line 4147 "effective_tld_names.gperf"
+#line 3726 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2567, 0},
-#line 2651 "effective_tld_names.gperf"
+#line 1654 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2568, 0},
-#line 3169 "effective_tld_names.gperf"
+#line 2958 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2569, 0},
-#line 660 "effective_tld_names.gperf"
+#line 2295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2570, 0},
-#line 229 "effective_tld_names.gperf"
+#line 2278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2571, 0},
-#line 667 "effective_tld_names.gperf"
+#line 2335 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2572, 0},
-#line 4151 "effective_tld_names.gperf"
+#line 5054 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2573, 0},
-#line 3876 "effective_tld_names.gperf"
+#line 5265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2574, 0},
-#line 3914 "effective_tld_names.gperf"
+#line 4164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2575, 0},
-#line 5358 "effective_tld_names.gperf"
+#line 4665 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2576, 0},
-#line 4278 "effective_tld_names.gperf"
+#line 4988 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2577, 0},
-#line 2008 "effective_tld_names.gperf"
+#line 248 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2578, 0},
-#line 1495 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2579, 4},
-#line 3388 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2580, 0},
-#line 1087 "effective_tld_names.gperf"
+#line 6291 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2579, 0},
+#line 2423 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2580, 4},
+#line 2154 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2581, 0},
-#line 640 "effective_tld_names.gperf"
+#line 2351 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2582, 0},
-#line 2533 "effective_tld_names.gperf"
+#line 2122 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2583, 0},
-#line 646 "effective_tld_names.gperf"
+#line 2718 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2584, 0},
-#line 3261 "effective_tld_names.gperf"
+#line 2220 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2585, 0},
-#line 2012 "effective_tld_names.gperf"
+#line 5063 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2586, 0},
-#line 414 "effective_tld_names.gperf"
+#line 4356 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2587, 0},
-#line 5056 "effective_tld_names.gperf"
+#line 296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2588, 0},
-#line 503 "effective_tld_names.gperf"
+#line 2475 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2589, 4},
-#line 358 "effective_tld_names.gperf"
+#line 613 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2590, 0},
-#line 353 "effective_tld_names.gperf"
+#line 2049 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2591, 0},
-#line 2059 "effective_tld_names.gperf"
+#line 132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2592, 0},
-#line 5615 "effective_tld_names.gperf"
+#line 792 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2593, 0},
-#line 5324 "effective_tld_names.gperf"
+#line 2123 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2594, 0},
-#line 1480 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2595, 4},
-#line 2961 "effective_tld_names.gperf"
+#line 3019 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2595, 0},
+#line 6309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2596, 0},
-#line 2732 "effective_tld_names.gperf"
+#line 4385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2597, 0},
-#line 1129 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2598, 4},
-#line 428 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2599, 4},
-#line 3041 "effective_tld_names.gperf"
+#line 1468 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2598, 0},
+#line 3678 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2599, 0},
+#line 4362 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2600, 0},
-#line 319 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2601, 4},
-#line 188 "effective_tld_names.gperf"
+#line 1775 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2601, 0},
+#line 1240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2602, 0},
-#line 662 "effective_tld_names.gperf"
+#line 5217 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2603, 0},
-#line 441 "effective_tld_names.gperf"
+#line 849 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2604, 0},
-#line 4150 "effective_tld_names.gperf"
+#line 885 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2605, 0},
-#line 4148 "effective_tld_names.gperf"
+#line 894 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2606, 0},
-#line 654 "effective_tld_names.gperf"
+#line 890 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2607, 0},
-#line 4639 "effective_tld_names.gperf"
+#line 4413 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2608, 0},
-#line 5130 "effective_tld_names.gperf"
+#line 6292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2609, 0},
-#line 4080 "effective_tld_names.gperf"
+#line 2277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2610, 0},
-#line 4780 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2611, 4},
-#line 424 "effective_tld_names.gperf"
+#line 893 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2611, 0},
+#line 870 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2612, 0},
-#line 2653 "effective_tld_names.gperf"
+#line 620 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2613, 0},
-#line 1488 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2614, 4},
-#line 1510 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2615, 4},
-#line 1144 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2616, 4},
-#line 2466 "effective_tld_names.gperf"
+#line 3362 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2614, 0},
+#line 4048 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2615, 0},
+#line 4094 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2616, 0},
+#line 4378 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2617, 0},
-#line 2916 "effective_tld_names.gperf"
+#line 366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2618, 0},
-#line 5617 "effective_tld_names.gperf"
+#line 4386 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2619, 0},
-#line 669 "effective_tld_names.gperf"
+#line 2307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2620, 0},
-#line 3671 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2621, 0},
-#line 3873 "effective_tld_names.gperf"
+#line 877 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2621, 4},
+#line 3041 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2622, 0},
-#line 3253 "effective_tld_names.gperf"
+#line 272 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2623, 0},
-#line 4038 "effective_tld_names.gperf"
+#line 2273 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2624, 0},
-#line 502 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2625, 4},
-#line 3896 "effective_tld_names.gperf"
+#line 233 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2625, 0},
+#line 5073 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2626, 0},
-#line 3219 "effective_tld_names.gperf"
+#line 5799 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2627, 0},
-#line 3939 "effective_tld_names.gperf"
+#line 1984 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2628, 0},
-#line 171 "effective_tld_names.gperf"
+#line 882 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2629, 0},
-#line 4034 "effective_tld_names.gperf"
+#line 4339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2630, 0},
-#line 2914 "effective_tld_names.gperf"
+#line 155 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2631, 0},
-#line 579 "effective_tld_names.gperf"
+#line 2183 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2632, 0},
-#line 2011 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2633, 0},
-#line 683 "effective_tld_names.gperf"
+#line 876 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2633, 4},
+#line 873 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2634, 0},
-#line 3208 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2635, 1},
-#line 4591 "effective_tld_names.gperf"
+#line 4289 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2635, 0},
+#line 1508 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2636, 0},
-#line 5275 "effective_tld_names.gperf"
+#line 5007 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2637, 0},
-#line 1345 "effective_tld_names.gperf"
+#line 2327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2638, 0},
-#line 3251 "effective_tld_names.gperf"
+#line 154 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2639, 0},
-#line 1426 "effective_tld_names.gperf"
+#line 847 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2640, 0},
-#line 2019 "effective_tld_names.gperf"
+#line 2522 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2641, 0},
-#line 5172 "effective_tld_names.gperf"
+#line 884 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2642, 0},
-#line 3618 "effective_tld_names.gperf"
+#line 889 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2643, 0},
-#line 4293 "effective_tld_names.gperf"
+#line 850 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2644, 0},
-#line 1509 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2645, 4},
-#line 1753 "effective_tld_names.gperf"
+#line 2158 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2645, 0},
+#line 872 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2646, 0},
-#line 3226 "effective_tld_names.gperf"
+#line 338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2647, 0},
-#line 1207 "effective_tld_names.gperf"
+#line 1766 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2648, 0},
-#line 905 "effective_tld_names.gperf"
+#line 597 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2649, 0},
-#line 1932 "effective_tld_names.gperf"
+#line 1242 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2650, 0},
-#line 2091 "effective_tld_names.gperf"
+#line 1093 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2651, 0},
-#line 4772 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2652, 4},
-#line 1493 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2653, 4},
-#line 641 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2654, 0},
-#line 6072 "effective_tld_names.gperf"
+#line 2324 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2652, 0},
+#line 857 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2653, 0},
+#line 1936 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2654, 4},
+#line 417 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2655, 0},
-#line 2624 "effective_tld_names.gperf"
+#line 3801 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2656, 0},
-#line 3228 "effective_tld_names.gperf"
+#line 856 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2657, 0},
-#line 6037 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2658, 2},
-#line 4564 "effective_tld_names.gperf"
+#line 231 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2658, 4},
+#line 1234 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2659, 0},
-#line 4733 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2660, 0},
-#line 2443 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2661, 0},
-#line 3140 "effective_tld_names.gperf"
+#line 2241 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2660, 4},
+#line 1436 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2661, 4},
+#line 328 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2662, 0},
-#line 5231 "effective_tld_names.gperf"
+#line 2957 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2663, 0},
-#line 2286 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2664, 0},
-#line 2155 "effective_tld_names.gperf"
+#line 569 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2664, 4},
+#line 2250 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2665, 0},
-#line 2193 "effective_tld_names.gperf"
+#line 4333 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2666, 0},
-#line 3160 "effective_tld_names.gperf"
+#line 1710 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2667, 0},
-#line 725 "effective_tld_names.gperf"
+#line 2005 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2668, 0},
-#line 1999 "effective_tld_names.gperf"
+#line 2737 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2669, 0},
-#line 5187 "effective_tld_names.gperf"
+#line 2099 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2670, 0},
-#line 839 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2671, 0},
-#line 2289 "effective_tld_names.gperf"
+#line 841 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2671, 4},
+#line 4099 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2672, 0},
-#line 5975 "effective_tld_names.gperf"
+#line 1962 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2673, 0},
-#line 1209 "effective_tld_names.gperf"
+#line 2762 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2674, 0},
-#line 2194 "effective_tld_names.gperf"
+#line 4390 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2675, 0},
-#line 1071 "effective_tld_names.gperf"
+#line 3568 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2676, 0},
-#line 908 "effective_tld_names.gperf"
+#line 3343 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2677, 0},
-#line 2614 "effective_tld_names.gperf"
+#line 610 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2678, 0},
-#line 3629 "effective_tld_names.gperf"
+#line 2182 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2679, 0},
-#line 2398 "effective_tld_names.gperf"
+#line 3634 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2680, 0},
-#line 232 "effective_tld_names.gperf"
+#line 4183 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2681, 0},
-#line 1701 "effective_tld_names.gperf"
+#line 5052 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2682, 0},
-#line 1124 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2683, 4},
-#line 1208 "effective_tld_names.gperf"
+#line 6328 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2683, 0},
+#line 2276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2684, 0},
-#line 335 "effective_tld_names.gperf"
+#line 762 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2685, 0},
-#line 1668 "effective_tld_names.gperf"
+#line 5019 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2686, 0},
-#line 2296 "effective_tld_names.gperf"
+#line 3629 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2687, 0},
-#line 5300 "effective_tld_names.gperf"
+#line 1771 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2688, 0},
-#line 907 "effective_tld_names.gperf"
+#line 868 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2689, 0},
-#line 906 "effective_tld_names.gperf"
+#line 5789 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2690, 0},
-#line 841 "effective_tld_names.gperf"
+#line 4266 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2691, 0},
-#line 2165 "effective_tld_names.gperf"
+#line 2187 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2692, 0},
-#line 775 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2693, 1},
-#line 1511 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2694, 4},
-#line 4046 "effective_tld_names.gperf"
+#line 4972 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2693, 0},
+#line 2238 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2694, 0},
+#line 1415 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2695, 0},
-#line 2160 "effective_tld_names.gperf"
+#line 1774 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2696, 0},
-#line 3134 "effective_tld_names.gperf"
+#line 887 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2697, 0},
-#line 691 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2698, 0},
-#line 129 "effective_tld_names.gperf"
+#line 1706 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2698, 4},
+#line 4327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2699, 0},
-#line 2372 "effective_tld_names.gperf"
+#line 6300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2700, 0},
-#line 421 "effective_tld_names.gperf"
+#line 3563 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2701, 0},
-#line 1467 "effective_tld_names.gperf"
+#line 2079 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2702, 0},
-#line 4804 "effective_tld_names.gperf"
+#line 859 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2703, 0},
-#line 134 "effective_tld_names.gperf"
+#line 888 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2704, 0},
-#line 789 "effective_tld_names.gperf"
+#line 1765 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2705, 0},
-#line 271 "effective_tld_names.gperf"
+#line 3346 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2706, 0},
-#line 250 "effective_tld_names.gperf"
+#line 6315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2707, 0},
-#line 3892 "effective_tld_names.gperf"
+#line 1241 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2708, 0},
-#line 5412 "effective_tld_names.gperf"
+#line 878 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2709, 0},
-#line 2136 "effective_tld_names.gperf"
+#line 855 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2710, 0},
-#line 4236 "effective_tld_names.gperf"
+#line 4843 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2711, 0},
-#line 3103 "effective_tld_names.gperf"
+#line 4835 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2712, 0},
-#line 5613 "effective_tld_names.gperf"
+#line 3347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2713, 0},
-#line 3723 "effective_tld_names.gperf"
+#line 1078 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2714, 0},
-#line 3722 "effective_tld_names.gperf"
+#line 3638 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2715, 0},
-#line 3911 "effective_tld_names.gperf"
+#line 2185 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2716, 0},
-#line 2822 "effective_tld_names.gperf"
+#line 5219 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2717, 0},
-#line 544 "effective_tld_names.gperf"
+#line 247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2718, 0},
-#line 3632 "effective_tld_names.gperf"
+#line 453 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2719, 0},
-#line 3982 "effective_tld_names.gperf"
+#line 2078 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2720, 0},
-#line 3905 "effective_tld_names.gperf"
+#line 5777 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2721, 0},
-#line 2202 "effective_tld_names.gperf"
+#line 4261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2722, 0},
-#line 3727 "effective_tld_names.gperf"
+#line 1480 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2723, 0},
-#line 673 "effective_tld_names.gperf"
+#line 6257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2724, 0},
-#line 228 "effective_tld_names.gperf"
+#line 2098 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2725, 0},
-#line 856 "effective_tld_names.gperf"
+#line 891 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2726, 0},
-#line 453 "effective_tld_names.gperf"
+#line 4977 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2727, 0},
-#line 535 "effective_tld_names.gperf"
+#line 1526 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2728, 0},
-#line 5974 "effective_tld_names.gperf"
+#line 4177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2729, 0},
-#line 3950 "effective_tld_names.gperf"
+#line 1687 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2730, 0},
-#line 1073 "effective_tld_names.gperf"
+#line 2254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2731, 0},
-#line 304 "effective_tld_names.gperf"
+#line 2334 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2732, 0},
-#line 4545 "effective_tld_names.gperf"
+#line 4411 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2733, 0},
-#line 3212 "effective_tld_names.gperf"
+#line 3566 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2734, 0},
-#line 438 "effective_tld_names.gperf"
+#line 630 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2735, 0},
-#line 3656 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2736, 1},
-#line 5429 "effective_tld_names.gperf"
+#line 1081 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2736, 0},
+#line 3388 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2737, 0},
-#line 2189 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2738, 2},
-#line 1400 "effective_tld_names.gperf"
+#line 871 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2738, 0},
+#line 5089 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2739, 0},
-#line 2265 "effective_tld_names.gperf"
+#line 2932 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2740, 0},
-#line 4610 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2741, 4},
-#line 2208 "effective_tld_names.gperf"
+#line 5754 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2741, 0},
+#line 3373 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2742, 0},
-#line 1913 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2743, 0},
-#line 2267 "effective_tld_names.gperf"
+#line 5735 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2743, 4},
+#line 121 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2744, 0},
-#line 1601 "effective_tld_names.gperf"
+#line 2009 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2745, 0},
-#line 3872 "effective_tld_names.gperf"
+#line 875 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2746, 0},
-#line 2266 "effective_tld_names.gperf"
+#line 1411 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2747, 0},
-#line 3895 "effective_tld_names.gperf"
+#line 6281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2748, 0},
-#line 5048 "effective_tld_names.gperf"
+#line 3996 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2749, 0},
-#line 2209 "effective_tld_names.gperf"
+#line 30 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2750, 0},
-#line 4006 "effective_tld_names.gperf"
+#line 5779 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2751, 0},
-#line 3130 "effective_tld_names.gperf"
+#line 1995 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2752, 0},
-#line 5642 "effective_tld_names.gperf"
+#line 2275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2753, 0},
-#line 2162 "effective_tld_names.gperf"
+#line 2326 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2754, 0},
-#line 5612 "effective_tld_names.gperf"
+#line 843 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2755, 0},
-#line 1525 "effective_tld_names.gperf"
+#line 2552 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2756, 0},
-#line 4210 "effective_tld_names.gperf"
+#line 2892 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2757, 0},
-#line 996 "effective_tld_names.gperf"
+#line 3633 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2758, 0},
-#line 1930 "effective_tld_names.gperf"
+#line 2333 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2759, 0},
-#line 4079 "effective_tld_names.gperf"
+#line 2873 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2760, 0},
-#line 3726 "effective_tld_names.gperf"
+#line 5186 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2761, 0},
-#line 3724 "effective_tld_names.gperf"
+#line 2656 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2762, 0},
-#line 2134 "effective_tld_names.gperf"
+#line 5792 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2763, 0},
-#line 3497 "effective_tld_names.gperf"
+#line 2323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2764, 0},
-#line 4270 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2765, 0},
-#line 2190 "effective_tld_names.gperf"
+#line 854 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2765, 4},
+#line 4302 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2766, 0},
-#line 1130 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2767, 4},
-#line 6039 "effective_tld_names.gperf"
+#line 860 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2767, 0},
+#line 3342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2768, 0},
-#line 254 "effective_tld_names.gperf"
+#line 5858 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2769, 0},
-#line 2776 "effective_tld_names.gperf"
+#line 490 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2770, 0},
-#line 6059 "effective_tld_names.gperf"
+#line 5224 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2771, 0},
-#line 4250 "effective_tld_names.gperf"
+#line 1504 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2772, 0},
-#line 3246 "effective_tld_names.gperf"
+#line 2338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2773, 0},
-#line 840 "effective_tld_names.gperf"
+#line 4821 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2774, 0},
-#line 2137 "effective_tld_names.gperf"
+#line 2508 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2775, 0},
-#line 2226 "effective_tld_names.gperf"
+#line 4098 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2776, 0},
-#line 4517 "effective_tld_names.gperf"
+#line 109 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2777, 0},
-#line 2223 "effective_tld_names.gperf"
+#line 615 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2778, 0},
-#line 1678 "effective_tld_names.gperf"
+#line 1996 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2779, 0},
-#line 3940 "effective_tld_names.gperf"
+#line 2008 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2780, 0},
-#line 2269 "effective_tld_names.gperf"
+#line 4891 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2781, 0},
-#line 2814 "effective_tld_names.gperf"
+#line 2681 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2782, 0},
-#line 2279 "effective_tld_names.gperf"
+#line 3643 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2783, 0},
-#line 2268 "effective_tld_names.gperf"
+#line 3259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2784, 0},
-#line 3227 "effective_tld_names.gperf"
+#line 5784 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2785, 0},
-#line 3642 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2786, 0},
-#line 2007 "effective_tld_names.gperf"
+#line 819 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2786, 1},
+#line 1676 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2787, 0},
-#line 2850 "effective_tld_names.gperf"
+#line 1773 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2788, 0},
-#line 6090 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2789, 4},
-#line 4065 "effective_tld_names.gperf"
+#line 852 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2789, 0},
+#line 886 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2790, 0},
-#line 2205 "effective_tld_names.gperf"
+#line 6379 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2791, 0},
-#line 1557 "effective_tld_names.gperf"
+#line 4760 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2792, 0},
-#line 3221 "effective_tld_names.gperf"
+#line 4009 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2793, 0},
-#line 5246 "effective_tld_names.gperf"
+#line 3482 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2794, 0},
-#line 3081 "effective_tld_names.gperf"
+#line 6386 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2795, 0},
-#line 1956 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2796, 0},
-#line 72 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2797, 0},
-#line 2467 "effective_tld_names.gperf"
+#line 6361 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2796, 4},
+#line 5766 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2797, 4},
+#line 3997 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2798, 0},
-#line 5720 "effective_tld_names.gperf"
+#line 2221 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2799, 0},
-#line 1068 "effective_tld_names.gperf"
+#line 4030 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2800, 0},
-#line 5268 "effective_tld_names.gperf"
+#line 2297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2801, 0},
-#line 4673 "effective_tld_names.gperf"
+#line 5768 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2802, 0},
-#line 2199 "effective_tld_names.gperf"
+#line 5289 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2803, 0},
-#line 4690 "effective_tld_names.gperf"
+#line 114 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2804, 0},
-#line 5722 "effective_tld_names.gperf"
+#line 2296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2805, 0},
-#line 261 "effective_tld_names.gperf"
+#line 2724 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2806, 0},
-#line 4609 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2807, 4},
-#line 1024 "effective_tld_names.gperf"
+#line 32 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2807, 0},
+#line 2325 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2808, 0},
-#line 2981 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2809, 4},
-#line 3627 "effective_tld_names.gperf"
+#line 2739 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2809, 0},
+#line 764 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2810, 0},
-#line 260 "effective_tld_names.gperf"
+#line 2949 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2811, 0},
-#line 1133 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2812, 4},
-#line 2033 "effective_tld_names.gperf"
+#line 4828 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2812, 0},
+#line 5736 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2813, 0},
-#line 4061 "effective_tld_names.gperf"
+#line 6240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2814, 0},
-#line 3634 "effective_tld_names.gperf"
+#line 2759 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2815, 0},
-#line 2278 "effective_tld_names.gperf"
+#line 4170 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2816, 0},
-#line 108 "effective_tld_names.gperf"
+#line 4256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2817, 0},
-#line 5622 "effective_tld_names.gperf"
+#line 1475 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2818, 0},
-#line 3548 "effective_tld_names.gperf"
+#line 170 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2819, 0},
-#line 2982 "effective_tld_names.gperf"
+#line 4310 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2820, 0},
-#line 2119 "effective_tld_names.gperf"
+#line 1972 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2821, 0},
-#line 5655 "effective_tld_names.gperf"
+#line 5174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2822, 0},
-#line 4912 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2823, 0},
-#line 2010 "effective_tld_names.gperf"
+#line 4963 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2823, 4},
+#line 278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2824, 0},
-#line 2060 "effective_tld_names.gperf"
+#line 1524 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2825, 0},
-#line 6040 "effective_tld_names.gperf"
+#line 2768 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2826, 0},
-#line 896 "effective_tld_names.gperf"
+#line 6329 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2827, 0},
-#line 3292 "effective_tld_names.gperf"
+#line 4184 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2828, 0},
-#line 4991 "effective_tld_names.gperf"
+#line 5966 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2829, 0},
-#line 1021 "effective_tld_names.gperf"
+#line 3620 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2830, 0},
-#line 4627 "effective_tld_names.gperf"
+#line 851 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2831, 0},
-#line 4812 "effective_tld_names.gperf"
+#line 629 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2832, 0},
-#line 1550 "effective_tld_names.gperf"
+#line 5687 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2833, 0},
-#line 351 "effective_tld_names.gperf"
+#line 4644 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2834, 0},
-#line 405 "effective_tld_names.gperf"
+#line 4668 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2835, 0},
-#line 270 "effective_tld_names.gperf"
+#line 137 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2836, 0},
-#line 3430 "effective_tld_names.gperf"
+#line 3994 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2837, 0},
-#line 5236 "effective_tld_names.gperf"
+#line 113 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2838, 0},
-#line 491 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2839, 4},
-#line 146 "effective_tld_names.gperf"
+#line 3963 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2839, 0},
+#line 1101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2840, 0},
-#line 3917 "effective_tld_names.gperf"
+#line 5014 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2841, 0},
-#line 568 "effective_tld_names.gperf"
+#line 2962 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2842, 0},
-#line 2729 "effective_tld_names.gperf"
+#line 1625 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2843, 0},
-#line 3941 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2844, 0},
-#line 5068 "effective_tld_names.gperf"
+#line 495 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2844, 1},
+#line 5017 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2845, 0},
-#line 5040 "effective_tld_names.gperf"
+#line 2789 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2846, 0},
-#line 2730 "effective_tld_names.gperf"
+#line 3336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2847, 0},
-#line 3017 "effective_tld_names.gperf"
+#line 5237 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2848, 0},
-#line 2294 "effective_tld_names.gperf"
+#line 3689 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2849, 0},
-#line 1662 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2850, 4},
-#line 2468 "effective_tld_names.gperf"
+#line 2745 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2850, 0},
+#line 5835 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2851, 0},
-#line 5703 "effective_tld_names.gperf"
+#line 2749 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2852, 0},
-#line 5349 "effective_tld_names.gperf"
+#line 1236 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2853, 0},
-#line 4612 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2854, 4},
-#line 1846 "effective_tld_names.gperf"
+#line 671 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2854, 0},
+#line 1845 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2855, 0},
-#line 4846 "effective_tld_names.gperf"
+#line 1266 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2856, 0},
-#line 1142 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2857, 4},
-#line 2045 "effective_tld_names.gperf"
+#line 1843 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2857, 0},
+#line 934 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2858, 0},
-#line 1402 "effective_tld_names.gperf"
+#line 788 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2859, 0},
-#line 2283 "effective_tld_names.gperf"
+#line 39 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2860, 0},
-#line 4893 "effective_tld_names.gperf"
+#line 2836 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2861, 0},
-#line 5721 "effective_tld_names.gperf"
+#line 2965 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2862, 0},
-#line 4869 "effective_tld_names.gperf"
+#line 4204 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2863, 0},
-#line 612 "effective_tld_names.gperf"
+#line 1842 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2864, 0},
-#line 1371 "effective_tld_names.gperf"
+#line 1779 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2865, 0},
-#line 2578 "effective_tld_names.gperf"
+#line 4842 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2866, 0},
-#line 2290 "effective_tld_names.gperf"
+#line 78 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2867, 0},
-#line 5654 "effective_tld_names.gperf"
+#line 5296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2868, 0},
-#line 256 "effective_tld_names.gperf"
+#line 6385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2869, 0},
-#line 1113 "effective_tld_names.gperf"
+#line 1628 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2870, 0},
-#line 5222 "effective_tld_names.gperf"
+#line 2391 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2871, 0},
-#line 489 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2872, 4},
-#line 132 "effective_tld_names.gperf"
+#line 4439 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2872, 0},
+#line 2181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2873, 0},
-#line 3473 "effective_tld_names.gperf"
+#line 5027 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2874, 0},
-#line 777 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2875, 1},
-#line 5659 "effective_tld_names.gperf"
+#line 5960 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2875, 0},
+#line 3387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2876, 0},
-#line 5210 "effective_tld_names.gperf"
+#line 36 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2877, 0},
-#line 4007 "effective_tld_names.gperf"
+#line 1841 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2878, 0},
-#line 3562 "effective_tld_names.gperf"
+#line 5978 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2879, 0},
-#line 4237 "effective_tld_names.gperf"
+#line 5930 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2880, 0},
-#line 5278 "effective_tld_names.gperf"
+#line 3598 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2881, 0},
-#line 3472 "effective_tld_names.gperf"
+#line 149 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2882, 0},
-#line 1288 "effective_tld_names.gperf"
+#line 3494 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2883, 0},
-#line 5625 "effective_tld_names.gperf"
+#line 1627 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2884, 0},
-#line 2228 "effective_tld_names.gperf"
+#line 3992 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2885, 0},
-#line 721 "effective_tld_names.gperf"
+#line 2192 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2886, 0},
-#line 1482 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2887, 4},
-#line 4056 "effective_tld_names.gperf"
+#line 5957 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2887, 0},
+#line 1238 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2888, 0},
-#line 492 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2889, 4},
-#line 4688 "effective_tld_names.gperf"
+#line 5721 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2889, 0},
+#line 6013 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2890, 0},
-#line 3461 "effective_tld_names.gperf"
+#line 3339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2891, 0},
-#line 490 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2892, 4},
-#line 2583 "effective_tld_names.gperf"
+#line 1268 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2892, 0},
+#line 4363 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2893, 0},
-#line 2920 "effective_tld_names.gperf"
+#line 6274 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2894, 0},
-#line 3620 "effective_tld_names.gperf"
+#line 5970 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2895, 0},
-#line 4642 "effective_tld_names.gperf"
+#line 1239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2896, 0},
-#line 2102 "effective_tld_names.gperf"
+#line 1626 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2897, 0},
-#line 4263 "effective_tld_names.gperf"
+#line 936 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2898, 0},
-#line 1996 "effective_tld_names.gperf"
+#line 1645 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2899, 0},
-#line 1939 "effective_tld_names.gperf"
+#line 2299 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2900, 0},
-#line 3938 "effective_tld_names.gperf"
+#line 2537 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2901, 0},
-#line 1385 "effective_tld_names.gperf"
+#line 1264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2902, 0},
-#line 259 "effective_tld_names.gperf"
+#line 932 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2903, 0},
-#line 4983 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2904, 1},
-#line 323 "effective_tld_names.gperf"
+#line 70 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2904, 0},
+#line 825 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2905, 0},
-#line 3777 "effective_tld_names.gperf"
+#line 4986 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2906, 0},
-#line 2287 "effective_tld_names.gperf"
+#line 3274 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2907, 0},
-#line 5686 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2908, 0},
-#line 2003 "effective_tld_names.gperf"
+#line 5691 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2908, 4},
+#line 3372 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2909, 0},
-#line 4761 "effective_tld_names.gperf"
+#line 2639 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2910, 0},
-#line 1650 "effective_tld_names.gperf"
+#line 5971 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2911, 0},
-#line 2112 "effective_tld_names.gperf"
+#line 3758 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2912, 0},
-#line 5325 "effective_tld_names.gperf"
+#line 5883 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2913, 0},
-#line 4033 "effective_tld_names.gperf"
+#line 4169 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2914, 0},
-#line 1834 "effective_tld_names.gperf"
+#line 2390 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2915, 0},
-#line 2017 "effective_tld_names.gperf"
+#line 5156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2916, 0},
-#line 3820 "effective_tld_names.gperf"
+#line 4270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2917, 0},
-#line 437 "effective_tld_names.gperf"
+#line 5880 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2918, 0},
-#line 290 "effective_tld_names.gperf"
+#line 3331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2919, 0},
-#line 3793 "effective_tld_names.gperf"
+#line 5952 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2920, 0},
-#line 1982 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2921, 4},
-#line 5097 "effective_tld_names.gperf"
+#line 2751 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2921, 0},
+#line 4434 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2922, 0},
-#line 2864 "effective_tld_names.gperf"
+#line 6057 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2923, 0},
-#line 1006 "effective_tld_names.gperf"
+#line 2553 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2924, 0},
-#line 2566 "effective_tld_names.gperf"
+#line 6180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2925, 0},
-#line 2288 "effective_tld_names.gperf"
+#line 2979 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2926, 0},
-#line 1141 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2927, 4},
-#line 5175 "effective_tld_names.gperf"
+#line 5954 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2927, 0},
+#line 6282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2928, 0},
-#line 4481 "effective_tld_names.gperf"
+#line 6237 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2929, 0},
-#line 262 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2930, 0},
-#line 2962 "effective_tld_names.gperf"
+#line 503 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2930, 4},
+#line 2288 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2931, 0},
-#line 2196 "effective_tld_names.gperf"
+#line 6145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2932, 0},
-#line 1532 "effective_tld_names.gperf"
+#line 6279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2933, 0},
-#line 4811 "effective_tld_names.gperf"
+#line 1728 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2934, 0},
-#line 4495 "effective_tld_names.gperf"
+#line 4836 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2935, 0},
-#line 2158 "effective_tld_names.gperf"
+#line 739 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2936, 0},
-#line 5377 "effective_tld_names.gperf"
+#line 2960 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2937, 0},
-#line 3633 "effective_tld_names.gperf"
+#line 3558 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2938, 0},
-#line 5643 "effective_tld_names.gperf"
+#line 945 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2939, 0},
-#line 2206 "effective_tld_names.gperf"
+#line 96 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2940, 0},
-#line 378 "effective_tld_names.gperf"
+#line 6058 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2941, 0},
-#line 5596 "effective_tld_names.gperf"
+#line 3714 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2942, 0},
-#line 1997 "effective_tld_names.gperf"
+#line 445 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2943, 0},
-#line 5692 "effective_tld_names.gperf"
+#line 2861 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2944, 0},
-#line 2135 "effective_tld_names.gperf"
+#line 2998 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2945, 0},
-#line 1604 "effective_tld_names.gperf"
+#line 69 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2946, 0},
-#line 3910 "effective_tld_names.gperf"
+#line 295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2947, 0},
-#line 4774 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2948, 4},
-#line 1347 "effective_tld_names.gperf"
+#line 3830 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2948, 0},
+#line 6319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2949, 0},
-#line 4073 "effective_tld_names.gperf"
+#line 2118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2950, 0},
-#line 3541 "effective_tld_names.gperf"
+#line 6349 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2951, 0},
-#line 2600 "effective_tld_names.gperf"
+#line 4388 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2952, 0},
-#line 1423 "effective_tld_names.gperf"
+#line 4222 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2953, 0},
-#line 3459 "effective_tld_names.gperf"
+#line 316 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2954, 0},
-#line 4259 "effective_tld_names.gperf"
+#line 1454 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2955, 0},
-#line 1422 "effective_tld_names.gperf"
+#line 4838 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2956, 0},
-#line 3467 "effective_tld_names.gperf"
+#line 4223 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2957, 0},
-#line 5031 "effective_tld_names.gperf"
+#line 1768 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2958, 0},
-#line 5153 "effective_tld_names.gperf"
+#line 6182 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2959, 0},
-#line 3457 "effective_tld_names.gperf"
+#line 4873 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2960, 0},
-#line 4624 "effective_tld_names.gperf"
+#line 861 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2961, 0},
-#line 5705 "effective_tld_names.gperf"
+#line 4721 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2962, 0},
-#line 4018 "effective_tld_names.gperf"
+#line 3071 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2963, 0},
-#line 1135 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2964, 4},
-#line 316 "effective_tld_names.gperf"
+#line 2274 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2964, 0},
+#line 4206 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2965, 0},
-#line 1560 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2966, 0},
-#line 5408 "effective_tld_names.gperf"
+#line 504 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2966, 4},
+#line 864 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2967, 0},
-#line 1636 "effective_tld_names.gperf"
+#line 6172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2968, 0},
-#line 2280 "effective_tld_names.gperf"
+#line 874 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2969, 0},
-#line 3823 "effective_tld_names.gperf"
+#line 4345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2970, 0},
-#line 4886 "effective_tld_names.gperf"
+#line 3784 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2971, 0},
-#line 3464 "effective_tld_names.gperf"
+#line 5962 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2972, 0},
-#line 3678 "effective_tld_names.gperf"
+#line 803 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2973, 0},
-#line 379 "effective_tld_names.gperf"
+#line 6069 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2974, 0},
-#line 3558 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2975, 0},
-#line 2631 "effective_tld_names.gperf"
+#line 2983 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2975, 4},
+#line 2361 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2976, 0},
-#line 4613 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2977, 4},
-#line 125 "effective_tld_names.gperf"
+#line 883 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2977, 0},
+#line 5728 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2978, 0},
-#line 1691 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str2979, 0},
-#line 1290 "effective_tld_names.gperf"
+#line 6316 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str2979, 2},
+#line 4837 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2980, 0},
-#line 152 "effective_tld_names.gperf"
+#line 3428 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2981, 0},
-#line 2903 "effective_tld_names.gperf"
+#line 6272 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2982, 0},
-#line 4879 "effective_tld_names.gperf"
+#line 5813 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2983, 0},
-#line 4878 "effective_tld_names.gperf"
+#line 2222 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2984, 0},
-#line 2639 "effective_tld_names.gperf"
+#line 4213 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2985, 0},
-#line 2710 "effective_tld_names.gperf"
+#line 863 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2986, 0},
-#line 4053 "effective_tld_names.gperf"
+#line 2936 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2987, 0},
-#line 2053 "effective_tld_names.gperf"
+#line 3426 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2988, 0},
-#line 3398 "effective_tld_names.gperf"
+#line 6177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2989, 0},
-#line 4575 "effective_tld_names.gperf"
+#line 6320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2990, 0},
-#line 5554 "effective_tld_names.gperf"
+#line 1769 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2991, 0},
-#line 2863 "effective_tld_names.gperf"
+#line 865 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2992, 0},
-#line 3145 "effective_tld_names.gperf"
+#line 2696 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2993, 0},
-#line 1742 "effective_tld_names.gperf"
+#line 1108 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2994, 0},
-#line 1741 "effective_tld_names.gperf"
+#line 1951 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2995, 0},
-#line 4999 "effective_tld_names.gperf"
+#line 6060 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2996, 0},
-#line 1194 "effective_tld_names.gperf"
+#line 1055 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2997, 0},
-#line 1193 "effective_tld_names.gperf"
+#line 6277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2998, 0},
-#line 890 "effective_tld_names.gperf"
+#line 2495 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str2999, 0},
-#line 889 "effective_tld_names.gperf"
+#line 6376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3000, 0},
-#line 888 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3001, 4},
-#line 1743 "effective_tld_names.gperf"
+#line 6321 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3001, 0},
+#line 1937 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3002, 0},
-#line 1195 "effective_tld_names.gperf"
+#line 1090 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3003, 0},
-#line 3550 "effective_tld_names.gperf"
+#line 5087 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3004, 0},
-#line 661 "effective_tld_names.gperf"
+#line 1080 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3005, 0},
-#line 891 "effective_tld_names.gperf"
+#line 213 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3006, 0},
-#line 1663 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3007, 0},
-#line 817 "effective_tld_names.gperf"
+#line 87 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3007, 4},
+#line 827 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3008, 0},
-#line 5467 "effective_tld_names.gperf"
+#line 5081 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3009, 0},
-#line 1128 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3010, 4},
-#line 5129 "effective_tld_names.gperf"
+#line 575 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3010, 0},
+#line 232 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3011, 0},
-#line 2507 "effective_tld_names.gperf"
+#line 549 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3012, 0},
-#line 1922 "effective_tld_names.gperf"
+#line 6230 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3013, 0},
-#line 5644 "effective_tld_names.gperf"
+#line 3064 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3014, 0},
-#line 2835 "effective_tld_names.gperf"
+#line 623 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3015, 0},
-#line 3894 "effective_tld_names.gperf"
+#line 6150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3016, 0},
-#line 5555 "effective_tld_names.gperf"
+#line 153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3017, 0},
-#line 5521 "effective_tld_names.gperf"
+#line 594 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3018, 0},
-#line 3959 "effective_tld_names.gperf"
+#line 570 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3019, 0},
-#line 2750 "effective_tld_names.gperf"
+#line 1552 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3020, 0},
-#line 2051 "effective_tld_names.gperf"
+#line 6137 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3021, 0},
-#line 248 "effective_tld_names.gperf"
+#line 494 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3022, 0},
-#line 4606 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3023, 4},
-#line 3014 "effective_tld_names.gperf"
+#line 1386 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3023, 0},
+#line 2547 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3024, 0},
-#line 249 "effective_tld_names.gperf"
+#line 842 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3025, 0},
-#line 5725 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3026, 0},
-#line 2645 "effective_tld_names.gperf"
+#line 506 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3026, 4},
+#line 17 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3027, 0},
-#line 4854 "effective_tld_names.gperf"
+#line 3623 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3028, 0},
-#line 5718 "effective_tld_names.gperf"
+#line 1715 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3029, 0},
-#line 690 "effective_tld_names.gperf"
+#line 191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3030, 0},
-#line 2888 "effective_tld_names.gperf"
+#line 2527 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3031, 0},
-#line 5459 "effective_tld_names.gperf"
+#line 730 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3032, 0},
-#line 4512 "effective_tld_names.gperf"
+#line 4717 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3033, 0},
-#line 5541 "effective_tld_names.gperf"
+#line 6159 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3034, 0},
-#line 2231 "effective_tld_names.gperf"
+#line 547 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3035, 0},
-#line 687 "effective_tld_names.gperf"
+#line 1092 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3036, 0},
-#line 1447 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3037, 0},
-#line 4488 "effective_tld_names.gperf"
+#line 2470 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3037, 4},
+#line 227 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3038, 0},
-#line 3927 "effective_tld_names.gperf"
+#line 5780 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3039, 0},
-#line 5186 "effective_tld_names.gperf"
+#line 327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3040, 0},
-#line 1974 "effective_tld_names.gperf"
+#line 6097 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3041, 0},
-#line 2655 "effective_tld_names.gperf"
+#line 1465 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3042, 0},
-#line 4678 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3043, 0},
-#line 539 "effective_tld_names.gperf"
+#line 2426 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3043, 4},
+#line 596 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3044, 0},
-#line 1553 "effective_tld_names.gperf"
+#line 3690 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3045, 0},
-#line 2192 "effective_tld_names.gperf"
+#line 669 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3046, 0},
-#line 267 "effective_tld_names.gperf"
+#line 4191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3047, 0},
-#line 5618 "effective_tld_names.gperf"
+#line 2997 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3048, 0},
-#line 243 "effective_tld_names.gperf"
+#line 2985 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3049, 0},
-#line 2006 "effective_tld_names.gperf"
+#line 6322 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3050, 0},
-#line 581 "effective_tld_names.gperf"
+#line 862 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3051, 0},
-#line 5026 "effective_tld_names.gperf"
+#line 4757 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3052, 0},
-#line 530 "effective_tld_names.gperf"
+#line 4879 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3053, 0},
-#line 2331 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3054, 4},
-#line 4605 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3055, 4},
-#line 4946 "effective_tld_names.gperf"
+#line 4207 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3054, 0},
+#line 6188 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3055, 0},
+#line 806 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3056, 0},
-#line 272 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3057, 0},
-#line 4988 "effective_tld_names.gperf"
+#line 5737 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3057, 4},
+#line 2897 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3058, 0},
-#line 5379 "effective_tld_names.gperf"
+#line 1173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3059, 0},
-#line 5460 "effective_tld_names.gperf"
+#line 3738 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3060, 0},
-#line 2076 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3061, 4},
-#line 4217 "effective_tld_names.gperf"
+#line 1224 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3061, 0},
+#line 3567 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3062, 0},
-#line 5693 "effective_tld_names.gperf"
+#line 6255 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3063, 0},
-#line 4121 "effective_tld_names.gperf"
+#line 3632 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3064, 0},
-#line 2391 "effective_tld_names.gperf"
+#line 5912 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3065, 0},
-#line 1945 "effective_tld_names.gperf"
+#line 1340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3066, 0},
-#line 5523 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3067, 0},
-#line 1318 "effective_tld_names.gperf"
+#line 2487 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3067, 4},
+#line 1013 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3068, 0},
-#line 200 "effective_tld_names.gperf"
+#line 450 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3069, 0},
-#line 1674 "effective_tld_names.gperf"
+#line 6204 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3070, 0},
-#line 5458 "effective_tld_names.gperf"
+#line 1481 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3071, 0},
-#line 1592 "effective_tld_names.gperf"
+#line 2152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3072, 0},
-#line 6057 "effective_tld_names.gperf"
+#line 4454 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3073, 0},
-#line 5575 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3074, 0},
-#line 4848 "effective_tld_names.gperf"
+#line 2472 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3074, 4},
+#line 1060 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3075, 0},
-#line 5200 "effective_tld_names.gperf"
+#line 3808 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3076, 0},
-#line 5316 "effective_tld_names.gperf"
+#line 5982 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3077, 0},
-#line 3635 "effective_tld_names.gperf"
+#line 260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3078, 0},
-#line 6022 "effective_tld_names.gperf"
+#line 1469 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3079, 0},
-#line 1403 "effective_tld_names.gperf"
+#line 2955 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3080, 0},
-#line 1980 "effective_tld_names.gperf"
+#line 4401 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3081, 0},
-#line 4563 "effective_tld_names.gperf"
+#line 1111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3082, 0},
-#line 1132 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3083, 4},
-#line 3556 "effective_tld_names.gperf"
+#line 1957 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3083, 0},
+#line 1065 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3084, 0},
-#line 5482 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3085, 2},
-#line 3576 "effective_tld_names.gperf"
+#line 6162 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3085, 0},
+#line 1112 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3086, 0},
-#line 3173 "effective_tld_names.gperf"
+#line 5675 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3087, 0},
-#line 4127 "effective_tld_names.gperf"
+#line 3562 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3088, 0},
-#line 4766 "effective_tld_names.gperf"
+#line 1166 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3089, 0},
-#line 1909 "effective_tld_names.gperf"
+#line 5694 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3090, 0},
-#line 2063 "effective_tld_names.gperf"
+#line 4200 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3091, 0},
-#line 951 "effective_tld_names.gperf"
+#line 1402 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3092, 0},
-#line 950 "effective_tld_names.gperf"
+#line 6374 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3093, 0},
-#line 1666 "effective_tld_names.gperf"
+#line 164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3094, 0},
-#line 824 "effective_tld_names.gperf"
+#line 1132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3095, 0},
-#line 4778 "effective_tld_names.gperf"
+#line 2311 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3096, 0},
-#line 820 "effective_tld_names.gperf"
+#line 2674 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3097, 0},
-#line 5452 "effective_tld_names.gperf"
+#line 5271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3098, 0},
-#line 1661 "effective_tld_names.gperf"
+#line 3345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3099, 0},
-#line 1167 "effective_tld_names.gperf"
+#line 853 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3100, 0},
-#line 1802 "effective_tld_names.gperf"
+#line 251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3101, 0},
-#line 813 "effective_tld_names.gperf"
+#line 2705 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3102, 0},
-#line 1253 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3103, 0},
-#line 4856 "effective_tld_names.gperf"
+#line 833 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3103, 4},
+#line 3637 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3104, 0},
-#line 1097 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3105, 4},
-#line 2328 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3106, 4},
-#line 3552 "effective_tld_names.gperf"
+#line 2367 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3105, 0},
+#line 1923 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3106, 0},
+#line 3676 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3107, 0},
-#line 6046 "effective_tld_names.gperf"
+#line 339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3108, 0},
-#line 3575 "effective_tld_names.gperf"
+#line 1020 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3109, 0},
-#line 3560 "effective_tld_names.gperf"
+#line 1061 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3110, 0},
-#line 203 "effective_tld_names.gperf"
+#line 6098 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3111, 0},
-#line 1032 "effective_tld_names.gperf"
+#line 1525 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3112, 0},
-#line 6036 "effective_tld_names.gperf"
+#line 6190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3113, 0},
-#line 1333 "effective_tld_names.gperf"
+#line 1066 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3114, 0},
-#line 609 "effective_tld_names.gperf"
+#line 2229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3115, 0},
-#line 344 "effective_tld_names.gperf"
+#line 6055 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3116, 0},
-#line 3109 "effective_tld_names.gperf"
+#line 6178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3117, 0},
-#line 1566 "effective_tld_names.gperf"
+#line 3337 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3118, 0},
-#line 3286 "effective_tld_names.gperf"
+#line 2369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3119, 0},
-#line 4644 "effective_tld_names.gperf"
+#line 1940 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3120, 0},
-#line 4503 "effective_tld_names.gperf"
+#line 1674 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3121, 0},
-#line 3555 "effective_tld_names.gperf"
+#line 628 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3122, 0},
-#line 1803 "effective_tld_names.gperf"
+#line 1144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3123, 0},
-#line 84 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3124, 4},
-#line 1380 "effective_tld_names.gperf"
+#line 3386 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3124, 0},
+#line 1861 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3125, 0},
-#line 1254 "effective_tld_names.gperf"
+#line 1286 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3126, 0},
-#line 952 "effective_tld_names.gperf"
+#line 2219 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3127, 0},
-#line 1370 "effective_tld_names.gperf"
+#line 5048 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3128, 0},
-#line 196 "effective_tld_names.gperf"
+#line 1432 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3129, 0},
-#line 4852 "effective_tld_names.gperf"
+#line 552 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3130, 0},
-#line 3458 "effective_tld_names.gperf"
+#line 253 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3131, 0},
-#line 5260 "effective_tld_names.gperf"
+#line 6183 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3132, 0},
-#line 3577 "effective_tld_names.gperf"
+#line 373 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3133, 0},
-#line 1960 "effective_tld_names.gperf"
+#line 6202 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3134, 0},
-#line 5500 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3135, 0},
-#line 3579 "effective_tld_names.gperf"
+#line 6363 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3135, 4},
+#line 4730 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3136, 0},
-#line 3554 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3137, 0},
-#line 3827 "effective_tld_names.gperf"
+#line 815 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3137, 1},
+#line 3609 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3138, 0},
-#line 6012 "effective_tld_names.gperf"
+#line 5220 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3139, 0},
-#line 4546 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3140, 0},
-#line 2681 "effective_tld_names.gperf"
+#line 2455 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3140, 4},
+#line 432 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3141, 0},
-#line 5061 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3142, 0},
-#line 5549 "effective_tld_names.gperf"
+#line 2519 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3142, 4},
+#line 6285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3143, 0},
-#line 780 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3144, 1},
-#line 4607 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3145, 4},
-#line 5337 "effective_tld_names.gperf"
+#line 2286 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3144, 0},
+#line 224 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3145, 0},
+#line 1401 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3146, 0},
-#line 1784 "effective_tld_names.gperf"
+#line 6157 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3147, 0},
-#line 1779 "effective_tld_names.gperf"
+#line 268 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3148, 0},
-#line 3481 "effective_tld_names.gperf"
+#line 2914 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3149, 0},
-#line 1234 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3150, 0},
-#line 1229 "effective_tld_names.gperf"
+#line 2469 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3150, 4},
+#line 350 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3151, 0},
-#line 1781 "effective_tld_names.gperf"
+#line 1158 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3152, 0},
-#line 1231 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3153, 0},
-#line 929 "effective_tld_names.gperf"
+#line 1572 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3153, 4},
+#line 6118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3154, 0},
-#line 3249 "effective_tld_names.gperf"
+#line 3618 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3155, 0},
-#line 927 "effective_tld_names.gperf"
+#line 6089 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3156, 0},
-#line 1780 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3157, 0},
-#line 1230 "effective_tld_names.gperf"
+#line 1585 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3157, 4},
+#line 6231 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3158, 0},
-#line 4483 "effective_tld_names.gperf"
+#line 5972 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3159, 0},
-#line 926 "effective_tld_names.gperf"
+#line 1161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3160, 0},
-#line 818 "effective_tld_names.gperf"
+#line 2200 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3161, 0},
-#line 1778 "effective_tld_names.gperf"
+#line 1887 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3162, 0},
-#line 2788 "effective_tld_names.gperf"
+#line 2166 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3163, 0},
-#line 5307 "effective_tld_names.gperf"
+#line 1309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3164, 0},
-#line 5723 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3165, 1},
-#line 3672 "effective_tld_names.gperf"
+#line 2368 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3165, 0},
+#line 6256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3166, 0},
-#line 5690 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3167, 0},
-#line 4611 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3168, 4},
-#line 4292 "effective_tld_names.gperf"
+#line 1586 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3167, 4},
+#line 1719 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3168, 0},
+#line 1064 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3169, 0},
-#line 3456 "effective_tld_names.gperf"
+#line 2344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3170, 0},
-#line 5517 "effective_tld_names.gperf"
+#line 5232 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3171, 0},
-#line 2505 "effective_tld_names.gperf"
+#line 6158 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3172, 0},
-#line 3385 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3173, 0},
-#line 4513 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3174, 0},
-#line 2847 "effective_tld_names.gperf"
+#line 1571 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3173, 4},
+#line 1591 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3174, 4},
+#line 4749 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3175, 0},
-#line 3443 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3176, 0},
-#line 4764 "effective_tld_names.gperf"
+#line 1607 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3176, 4},
+#line 438 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3177, 0},
-#line 5518 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3178, 0},
-#line 4239 "effective_tld_names.gperf"
+#line 1589 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3178, 4},
+#line 4201 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3179, 0},
-#line 650 "effective_tld_names.gperf"
+#line 435 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3180, 0},
-#line 2689 "effective_tld_names.gperf"
+#line 2042 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3181, 0},
-#line 2848 "effective_tld_names.gperf"
+#line 4755 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3182, 0},
-#line 2104 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3183, 0},
-#line 1786 "effective_tld_names.gperf"
+#line 1605 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3183, 4},
+#line 5268 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3184, 0},
-#line 4554 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3185, 0},
-#line 4960 "effective_tld_names.gperf"
+#line 1604 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3185, 4},
+#line 5299 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3186, 0},
-#line 3012 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3187, 0},
-#line 930 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3188, 0},
-#line 4618 "effective_tld_names.gperf"
+#line 1570 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3187, 4},
+#line 1584 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3188, 4},
+#line 5928 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3189, 0},
-#line 3832 "effective_tld_names.gperf"
+#line 1489 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3190, 0},
-#line 2504 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3191, 0},
-#line 5461 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3192, 1},
-#line 4273 "effective_tld_names.gperf"
+#line 1603 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3191, 4},
+#line 1250 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3192, 0},
+#line 2343 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3193, 0},
-#line 5032 "effective_tld_names.gperf"
+#line 640 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3194, 0},
-#line 2602 "effective_tld_names.gperf"
+#line 916 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3195, 0},
-#line 4691 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3196, 2},
-#line 5262 "effective_tld_names.gperf"
+#line 2540 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3196, 0},
+#line 4180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3197, 0},
-#line 3374 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3198, 4},
-#line 1757 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3199, 0},
-#line 1211 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3200, 0},
-#line 1919 "effective_tld_names.gperf"
+#line 2548 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3198, 0},
+#line 3381 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3199, 4},
+#line 1606 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3200, 4},
+#line 185 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3201, 0},
-#line 1785 "effective_tld_names.gperf"
+#line 3982 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3202, 0},
-#line 1783 "effective_tld_names.gperf"
+#line 4178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3203, 0},
-#line 910 "effective_tld_names.gperf"
+#line 6201 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3204, 0},
-#line 1233 "effective_tld_names.gperf"
+#line 742 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3205, 0},
-#line 3237 "effective_tld_names.gperf"
+#line 3053 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3206, 0},
-#line 3011 "effective_tld_names.gperf"
+#line 1035 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3207, 0},
-#line 843 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3208, 0},
-#line 1390 "effective_tld_names.gperf"
+#line 1568 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3208, 4},
+#line 1901 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3209, 0},
-#line 1639 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3210, 0},
-#line 5497 "effective_tld_names.gperf"
+#line 1590 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3210, 4},
+#line 1325 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3211, 0},
-#line 233 "effective_tld_names.gperf"
+#line 1399 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3212, 0},
-#line 2874 "effective_tld_names.gperf"
+#line 4202 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3213, 0},
-#line 6077 "effective_tld_names.gperf"
+#line 107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3214, 0},
-#line 368 "effective_tld_names.gperf"
+#line 451 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3215, 0},
-#line 6050 "effective_tld_names.gperf"
+#line 1930 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3216, 0},
-#line 3631 "effective_tld_names.gperf"
+#line 1353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3217, 0},
-#line 3171 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3218, 0},
-#line 4619 "effective_tld_names.gperf"
+#line 2214 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3218, 4},
+#line 1031 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3219, 0},
-#line 680 "effective_tld_names.gperf"
+#line 3732 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3220, 0},
-#line 5281 "effective_tld_names.gperf"
+#line 6059 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3221, 0},
-#line 1782 "effective_tld_names.gperf"
+#line 4444 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3222, 0},
-#line 1232 "effective_tld_names.gperf"
+#line 1498 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3223, 0},
-#line 289 "effective_tld_names.gperf"
+#line 94 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3224, 0},
-#line 1428 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3225, 0},
-#line 928 "effective_tld_names.gperf"
+#line 1569 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3225, 4},
+#line 1846 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3226, 0},
-#line 5167 "effective_tld_names.gperf"
+#line 1267 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3227, 0},
-#line 3138 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3228, 0},
-#line 5241 "effective_tld_names.gperf"
+#line 2462 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3228, 4},
+#line 1085 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3229, 0},
-#line 5552 "effective_tld_names.gperf"
+#line 935 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3230, 0},
-#line 5224 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3231, 1},
-#line 1906 "effective_tld_names.gperf"
+#line 4776 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3231, 0},
+#line 2927 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3232, 0},
-#line 3784 "effective_tld_names.gperf"
+#line 3018 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3233, 0},
-#line 2413 "effective_tld_names.gperf"
+#line 1530 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3234, 0},
-#line 722 "effective_tld_names.gperf"
+#line 6153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3235, 0},
-#line 2004 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3236, 0},
-#line 5504 "effective_tld_names.gperf"
+#line 1567 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3236, 4},
+#line 2685 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3237, 0},
-#line 3172 "effective_tld_names.gperf"
+#line 3622 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3238, 0},
-#line 6106 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3239, 0},
-#line 5122 "effective_tld_names.gperf"
+#line 2436 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3239, 4},
+#line 3932 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3240, 0},
-#line 6060 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3241, 0},
-#line 5360 "effective_tld_names.gperf"
+#line 1615 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3241, 4},
+#line 5997 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3242, 0},
-#line 5338 "effective_tld_names.gperf"
+#line 1063 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3243, 0},
-#line 3660 "effective_tld_names.gperf"
+#line 551 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3244, 0},
-#line 2211 "effective_tld_names.gperf"
+#line 1653 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3245, 0},
-#line 2584 "effective_tld_names.gperf"
+#line 3894 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3246, 0},
-#line 2724 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3247, 0},
-#line 2230 "effective_tld_names.gperf"
+#line 2215 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3247, 4},
+#line 2402 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3248, 0},
-#line 231 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3249, 0},
-#line 4850 "effective_tld_names.gperf"
+#line 1616 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3249, 4},
+#line 3941 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3250, 0},
-#line 5041 "effective_tld_names.gperf"
+#line 4657 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3251, 0},
-#line 3238 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3252, 0},
-#line 5578 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3253, 0},
-#line 1150 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3254, 0},
-#line 2445 "effective_tld_names.gperf"
+#line 1618 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3252, 4},
+#line 1581 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3253, 4},
+#line 1579 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3254, 4},
+#line 5274 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3255, 0},
-#line 2486 "effective_tld_names.gperf"
+#line 2353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3256, 0},
-#line 451 "effective_tld_names.gperf"
+#line 2840 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3257, 0},
-#line 3706 "effective_tld_names.gperf"
+#line 3727 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3258, 0},
-#line 5166 "effective_tld_names.gperf"
+#line 4731 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3259, 0},
-#line 3523 "effective_tld_names.gperf"
+#line 1164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3260, 0},
-#line 4231 "effective_tld_names.gperf"
+#line 6151 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3261, 0},
-#line 2709 "effective_tld_names.gperf"
+#line 4435 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3262, 0},
-#line 2898 "effective_tld_names.gperf"
+#line 5022 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3263, 0},
-#line 6111 "effective_tld_names.gperf"
+#line 6050 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3264, 0},
-#line 2897 "effective_tld_names.gperf"
+#line 1056 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3265, 0},
-#line 5121 "effective_tld_names.gperf"
+#line 4396 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3266, 0},
-#line 4832 "effective_tld_names.gperf"
+#line 2781 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3267, 0},
-#line 3661 "effective_tld_names.gperf"
+#line 2536 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3268, 0},
-#line 2382 "effective_tld_names.gperf"
+#line 1784 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3269, 0},
-#line 2270 "effective_tld_names.gperf"
+#line 1284 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3270, 0},
-#line 2839 "effective_tld_names.gperf"
+#line 2385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3271, 0},
-#line 6051 "effective_tld_names.gperf"
+#line 955 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3272, 0},
-#line 712 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3273, 0},
-#line 3311 "effective_tld_names.gperf"
+#line 1726 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3273, 4},
+#line 1122 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3274, 0},
-#line 5484 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3275, 4},
-#line 4998 "effective_tld_names.gperf"
+#line 2693 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3275, 0},
+#line 1180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3276, 0},
-#line 1455 "effective_tld_names.gperf"
+#line 4228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3277, 0},
-#line 1563 "effective_tld_names.gperf"
+#line 6171 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3278, 0},
-#line 5647 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3279, 0},
-#line 4822 "effective_tld_names.gperf"
+#line 1167 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3279, 4},
+#line 1955 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3280, 0},
-#line 3561 "effective_tld_names.gperf"
+#line 2530 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3281, 0},
-#line 3989 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3282, 0},
-#line 2764 "effective_tld_names.gperf"
+#line 1582 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3282, 4},
+#line 425 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3283, 0},
-#line 3139 "effective_tld_names.gperf"
+#line 4976 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3284, 0},
-#line 3089 "effective_tld_names.gperf"
+#line 6123 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3285, 0},
-#line 4680 "effective_tld_names.gperf"
+#line 5967 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3286, 0},
-#line 3483 "effective_tld_names.gperf"
+#line 412 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3287, 0},
-#line 89 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3288, 0},
-#line 1419 "effective_tld_names.gperf"
+#line 1168 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3288, 4},
+#line 6082 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3289, 0},
-#line 2225 "effective_tld_names.gperf"
+#line 4658 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3290, 0},
-#line 2538 "effective_tld_names.gperf"
+#line 6323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3291, 0},
-#line 5402 "effective_tld_names.gperf"
+#line 265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3292, 0},
-#line 78 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3293, 0},
-#line 2396 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3294, 4},
-#line 3407 "effective_tld_names.gperf"
+#line 2322 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3293, 4},
+#line 6334 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3294, 0},
+#line 2167 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3295, 0},
-#line 3957 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3296, 0},
-#line 4888 "effective_tld_names.gperf"
+#line 1617 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3296, 4},
+#line 4671 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3297, 0},
-#line 3961 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3298, 0},
-#line 2662 "effective_tld_names.gperf"
+#line 1576 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3298, 4},
+#line 6138 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3299, 0},
-#line 3302 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3300, 0},
-#line 2680 "effective_tld_names.gperf"
+#line 1592 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3300, 4},
+#line 3987 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3301, 0},
-#line 3176 "effective_tld_names.gperf"
+#line 1058 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3302, 0},
-#line 3875 "effective_tld_names.gperf"
+#line 6127 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3303, 0},
-#line 735 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3304, 0},
-#line 3437 "effective_tld_names.gperf"
+#line 2434 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3304, 4},
+#line 1159 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3305, 0},
-#line 3046 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3306, 0},
-#line 752 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3307, 0},
-#line 560 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3308, 0},
-#line 5476 "effective_tld_names.gperf"
+#line 5920 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3306, 4},
+#line 1583 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3307, 4},
+#line 1200 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3308, 4},
+#line 1870 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3309, 0},
-#line 3822 "effective_tld_names.gperf"
+#line 1294 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3310, 0},
-#line 2108 "effective_tld_names.gperf"
+#line 3905 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3311, 0},
-#line 2293 "effective_tld_names.gperf"
+#line 5862 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3312, 0},
-#line 2472 "effective_tld_names.gperf"
+#line 2030 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3313, 0},
-#line 580 "effective_tld_names.gperf"
+#line 4854 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3314, 0},
-#line 284 "effective_tld_names.gperf"
+#line 6212 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3315, 0},
-#line 3113 "effective_tld_names.gperf"
+#line 3034 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3316, 0},
-#line 5005 "effective_tld_names.gperf"
+#line 6093 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3317, 0},
-#line 283 "effective_tld_names.gperf"
+#line 6115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3318, 0},
-#line 2625 "effective_tld_names.gperf"
+#line 1378 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3319, 0},
-#line 5177 "effective_tld_names.gperf"
+#line 2162 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3320, 0},
-#line 2041 "effective_tld_names.gperf"
+#line 3437 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3321, 0},
-#line 349 "effective_tld_names.gperf"
+#line 177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3322, 0},
-#line 3553 "effective_tld_names.gperf"
+#line 4336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3323, 0},
-#line 4665 "effective_tld_names.gperf"
+#line 1620 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3324, 0},
-#line 3821 "effective_tld_names.gperf"
+#line 5181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3325, 0},
-#line 4268 "effective_tld_names.gperf"
+#line 4887 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3326, 0},
-#line 3446 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3327, 0},
-#line 795 "effective_tld_names.gperf"
+#line 1201 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3327, 4},
+#line 319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3328, 0},
-#line 341 "effective_tld_names.gperf"
+#line 2199 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3329, 0},
-#line 214 "effective_tld_names.gperf"
+#line 4428 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3330, 0},
-#line 736 "effective_tld_names.gperf"
+#line 429 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3331, 0},
-#line 616 "effective_tld_names.gperf"
+#line 75 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3332, 0},
-#line 317 "effective_tld_names.gperf"
+#line 866 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3333, 0},
-#line 2262 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3334, 0},
-#line 578 "effective_tld_names.gperf"
+#line 2461 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3334, 4},
+#line 487 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3335, 0},
-#line 4035 "effective_tld_names.gperf"
+#line 6312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3336, 0},
-#line 558 "effective_tld_names.gperf"
+#line 3757 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3337, 0},
-#line 3958 "effective_tld_names.gperf"
+#line 6297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3338, 0},
-#line 2648 "effective_tld_names.gperf"
+#line 379 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3339, 0},
-#line 3295 "effective_tld_names.gperf"
+#line 3919 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3340, 0},
-#line 555 "effective_tld_names.gperf"
+#line 6085 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3341, 0},
-#line 3542 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3342, 0},
-#line 3814 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3343, 1},
-#line 4584 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3344, 0},
-#line 3578 "effective_tld_names.gperf"
+#line 2255 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3342, 4},
+#line 3771 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3343, 0},
+#line 1221 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3344, 4},
+#line 3360 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3345, 0},
-#line 5314 "effective_tld_names.gperf"
+#line 6045 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3346, 0},
-#line 3810 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3347, 1},
-#line 2522 "effective_tld_names.gperf"
+#line 3266 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3347, 0},
+#line 3731 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3348, 0},
-#line 2519 "effective_tld_names.gperf"
+#line 1195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3349, 0},
-#line 2518 "effective_tld_names.gperf"
+#line 390 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3350, 0},
-#line 1043 "effective_tld_names.gperf"
+#line 3383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3351, 0},
-#line 3125 "effective_tld_names.gperf"
+#line 1999 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3352, 0},
-#line 2520 "effective_tld_names.gperf"
+#line 6139 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3353, 0},
-#line 2121 "effective_tld_names.gperf"
+#line 588 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3354, 0},
-#line 337 "effective_tld_names.gperf"
+#line 6164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3355, 0},
-#line 3543 "effective_tld_names.gperf"
+#line 1664 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3356, 0},
-#line 4055 "effective_tld_names.gperf"
+#line 1564 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3357, 0},
-#line 122 "effective_tld_names.gperf"
+#line 1718 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3358, 0},
-#line 2824 "effective_tld_names.gperf"
+#line 3556 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3359, 0},
-#line 3549 "effective_tld_names.gperf"
+#line 4403 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3360, 0},
-#line 2517 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3361, 0},
-#line 2873 "effective_tld_names.gperf"
+#line 2092 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3361, 4},
+#line 953 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3362, 0},
-#line 2523 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3363, 0},
-#line 2002 "effective_tld_names.gperf"
+#line 1575 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3363, 4},
+#line 3271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3364, 0},
-#line 6017 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3365, 0},
-#line 3030 "effective_tld_names.gperf"
+#line 2302 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3365, 4},
+#line 6099 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3366, 0},
-#line 3027 "effective_tld_names.gperf"
+#line 5977 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3367, 0},
-#line 3026 "effective_tld_names.gperf"
+#line 263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3368, 0},
-#line 2800 "effective_tld_names.gperf"
+#line 2780 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3369, 0},
-#line 3028 "effective_tld_names.gperf"
+#line 1554 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3370, 0},
-#line 2941 "effective_tld_names.gperf"
+#line 1806 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3371, 0},
-#line 3431 "effective_tld_names.gperf"
+#line 6096 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3372, 0},
-#line 5195 "effective_tld_names.gperf"
+#line 2405 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3373, 0},
-#line 745 "effective_tld_names.gperf"
+#line 5881 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3374, 0},
-#line 257 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3375, 0},
-#line 623 "effective_tld_names.gperf"
+#line 1602 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3375, 4},
+#line 6262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3376, 0},
-#line 1098 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3377, 4},
-#line 1449 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3378, 0},
-#line 5334 "effective_tld_names.gperf"
+#line 1088 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3377, 0},
+#line 2420 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3378, 4},
+#line 5107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3379, 0},
-#line 3025 "effective_tld_names.gperf"
+#line 1137 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3380, 0},
-#line 5255 "effective_tld_names.gperf"
+#line 2168 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3381, 0},
-#line 1080 "effective_tld_names.gperf"
+#line 2626 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3382, 0},
-#line 3031 "effective_tld_names.gperf"
+#line 1152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3383, 0},
-#line 5989 "effective_tld_names.gperf"
+#line 6236 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3384, 0},
-#line 3357 "effective_tld_names.gperf"
+#line 5874 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3385, 0},
-#line 6038 "effective_tld_names.gperf"
+#line 4720 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3386, 0},
-#line 3813 "effective_tld_names.gperf"
+#line 5240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3387, 0},
-#line 861 "effective_tld_names.gperf"
+#line 4297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3388, 0},
-#line 2727 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3389, 4},
-#line 1628 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3390, 4},
-#line 5279 "effective_tld_names.gperf"
+#line 1231 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3389, 0},
+#line 5059 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3390, 0},
+#line 3395 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3391, 0},
-#line 5542 "effective_tld_names.gperf"
+#line 4116 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3392, 0},
-#line 5234 "effective_tld_names.gperf"
+#line 320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3393, 0},
-#line 2186 "effective_tld_names.gperf"
+#line 4664 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3394, 0},
-#line 6107 "effective_tld_names.gperf"
+#line 5244 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3395, 0},
-#line 365 "effective_tld_names.gperf"
+#line 1770 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3396, 0},
-#line 1546 "effective_tld_names.gperf"
+#line 2984 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3397, 0},
-#line 1297 "effective_tld_names.gperf"
+#line 1243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3398, 0},
-#line 2524 "effective_tld_names.gperf"
+#line 867 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3399, 0},
-#line 166 "effective_tld_names.gperf"
+#line 5164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3400, 0},
-#line 3402 "effective_tld_names.gperf"
+#line 4296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3401, 0},
-#line 5664 "effective_tld_names.gperf"
+#line 1501 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3402, 0},
-#line 4842 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3403, 0},
-#line 3462 "effective_tld_names.gperf"
+#line 832 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3403, 4},
+#line 4291 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3404, 0},
-#line 776 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3405, 1},
-#line 5600 "effective_tld_names.gperf"
+#line 5067 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3405, 0},
+#line 5245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3406, 0},
-#line 1962 "effective_tld_names.gperf"
+#line 1938 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3407, 0},
-#line 1148 "effective_tld_names.gperf"
+#line 5827 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3408, 0},
-#line 2521 "effective_tld_names.gperf"
+#line 6330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3409, 0},
-#line 3968 "effective_tld_names.gperf"
+#line 199 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3410, 0},
-#line 3874 "effective_tld_names.gperf"
+#line 80 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3411, 0},
-#line 771 "effective_tld_names.gperf"
+#line 1075 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3412, 0},
-#line 3032 "effective_tld_names.gperf"
+#line 1388 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3413, 0},
-#line 1378 "effective_tld_names.gperf"
+#line 6346 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3414, 0},
-#line 6005 "effective_tld_names.gperf"
+#line 3990 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3415, 0},
-#line 1474 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3416, 4},
-#line 2794 "effective_tld_names.gperf"
+#line 2022 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3416, 0},
+#line 3653 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3417, 0},
-#line 554 "effective_tld_names.gperf"
+#line 743 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3418, 0},
-#line 5675 "effective_tld_names.gperf"
+#line 6216 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3419, 0},
-#line 2791 "effective_tld_names.gperf"
+#line 5189 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3420, 0},
-#line 4099 "effective_tld_names.gperf"
+#line 4438 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3421, 0},
-#line 1905 "effective_tld_names.gperf"
+#line 1735 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3422, 0},
-#line 4060 "effective_tld_names.gperf"
+#line 6235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3423, 0},
-#line 3029 "effective_tld_names.gperf"
+#line 3435 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3424, 0},
-#line 4535 "effective_tld_names.gperf"
+#line 561 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3425, 0},
-#line 412 "effective_tld_names.gperf"
+#line 97 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3426, 0},
-#line 4683 "effective_tld_names.gperf"
+#line 5838 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3427, 0},
-#line 2412 "effective_tld_names.gperf"
+#line 2625 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3428, 0},
-#line 2016 "effective_tld_names.gperf"
+#line 6208 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3429, 0},
-#line 4849 "effective_tld_names.gperf"
+#line 1192 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3430, 0},
-#line 5468 "effective_tld_names.gperf"
+#line 3886 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3431, 0},
-#line 213 "effective_tld_names.gperf"
+#line 5785 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3432, 0},
-#line 4783 "effective_tld_names.gperf"
+#line 5931 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3433, 0},
-#line 5035 "effective_tld_names.gperf"
+#line 3277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3434, 0},
-#line 1042 "effective_tld_names.gperf"
+#line 5985 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3435, 0},
-#line 5688 "effective_tld_names.gperf"
+#line 189 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3436, 0},
-#line 5440 "effective_tld_names.gperf"
+#line 6125 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3437, 0},
-#line 1100 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3438, 4},
-#line 5488 "effective_tld_names.gperf"
+#line 6064 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3438, 0},
+#line 6106 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3439, 0},
-#line 3150 "effective_tld_names.gperf"
+#line 4455 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3440, 0},
-#line 3606 "effective_tld_names.gperf"
+#line 6143 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3441, 0},
-#line 4487 "effective_tld_names.gperf"
+#line 3415 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3442, 0},
-#line 4569 "effective_tld_names.gperf"
+#line 1520 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3443, 0},
-#line 743 "effective_tld_names.gperf"
+#line 471 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3444, 0},
-#line 5474 "effective_tld_names.gperf"
+#line 357 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3445, 0},
-#line 408 "effective_tld_names.gperf"
+#line 1760 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3446, 0},
-#line 1430 "effective_tld_names.gperf"
+#line 5250 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3447, 0},
-#line 401 "effective_tld_names.gperf"
+#line 3616 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3448, 0},
-#line 5528 "effective_tld_names.gperf"
+#line 2941 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3449, 0},
-#line 5339 "effective_tld_names.gperf"
+#line 5175 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3450, 0},
-#line 5052 "effective_tld_names.gperf"
+#line 4387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3451, 0},
-#line 3585 "effective_tld_names.gperf"
+#line 643 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3452, 0},
-#line 5144 "effective_tld_names.gperf"
+#line 3674 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3453, 0},
-#line 4652 "effective_tld_names.gperf"
+#line 3979 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3454, 0},
-#line 113 "effective_tld_names.gperf"
+#line 4294 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3455, 0},
-#line 1427 "effective_tld_names.gperf"
+#line 5774 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3456, 0},
-#line 1869 "effective_tld_names.gperf"
+#line 2048 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3457, 0},
-#line 5146 "effective_tld_names.gperf"
+#line 2383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3458, 0},
-#line 4523 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3459, 0},
-#line 829 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3460, 0},
-#line 633 "effective_tld_names.gperf"
+#line 2188 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3459, 4},
+#line 2216 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3460, 4},
+#line 6117 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3461, 0},
-#line 1050 "effective_tld_names.gperf"
+#line 2041 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3462, 0},
-#line 974 "effective_tld_names.gperf"
+#line 5773 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3463, 0},
-#line 972 "effective_tld_names.gperf"
+#line 4827 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3464, 0},
-#line 6053 "effective_tld_names.gperf"
+#line 3719 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3465, 0},
-#line 1822 "effective_tld_names.gperf"
+#line 4967 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3466, 0},
-#line 1270 "effective_tld_names.gperf"
+#line 1764 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3467, 0},
-#line 2714 "effective_tld_names.gperf"
+#line 343 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3468, 0},
-#line 971 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3469, 0},
-#line 1572 "effective_tld_names.gperf"
+#line 1220 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3469, 4},
+#line 5855 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3470, 0},
-#line 1521 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3471, 4},
-#line 3969 "effective_tld_names.gperf"
+#line 5149 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3471, 0},
+#line 1230 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3472, 0},
-#line 2620 "effective_tld_names.gperf"
+#line 577 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3473, 0},
-#line 2302 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3474, 4},
-#line 411 "effective_tld_names.gperf"
+#line 439 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3474, 0},
+#line 389 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3475, 0},
-#line 5397 "effective_tld_names.gperf"
+#line 5079 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3476, 0},
-#line 2176 "effective_tld_names.gperf"
+#line 3584 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3477, 0},
-#line 791 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3478, 4},
-#line 2640 "effective_tld_names.gperf"
+#line 642 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3478, 0},
+#line 4656 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3479, 0},
-#line 3966 "effective_tld_names.gperf"
+#line 745 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3480, 0},
-#line 1645 "effective_tld_names.gperf"
+#line 562 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3481, 0},
-#line 3433 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3482, 1},
-#line 2427 "effective_tld_names.gperf"
+#line 171 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3482, 0},
+#line 6215 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3483, 0},
-#line 2741 "effective_tld_names.gperf"
+#line 4845 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3484, 0},
-#line 156 "effective_tld_names.gperf"
+#line 2885 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3485, 0},
-#line 2015 "effective_tld_names.gperf"
+#line 5039 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3486, 0},
-#line 4593 "effective_tld_names.gperf"
+#line 3072 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3487, 0},
-#line 2896 "effective_tld_names.gperf"
+#line 778 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3488, 0},
-#line 205 "effective_tld_names.gperf"
+#line 1072 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3489, 0},
-#line 6026 "effective_tld_names.gperf"
+#line 3718 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3490, 0},
-#line 5206 "effective_tld_names.gperf"
+#line 656 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3491, 0},
-#line 4548 "effective_tld_names.gperf"
+#line 5088 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3492, 0},
-#line 2032 "effective_tld_names.gperf"
+#line 1559 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3493, 0},
-#line 4561 "effective_tld_names.gperf"
+#line 277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3494, 0},
-#line 6014 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3495, 0},
-#line 4743 "effective_tld_names.gperf"
+#line 1169 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3495, 4},
+#line 5136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3496, 0},
-#line 2367 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3497, 4},
-#line 354 "effective_tld_names.gperf"
+#line 413 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3497, 0},
+#line 1146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3498, 0},
-#line 2077 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3499, 4},
-#line 1329 "effective_tld_names.gperf"
+#line 829 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3499, 0},
+#line 1691 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3500, 0},
-#line 4281 "effective_tld_names.gperf"
+#line 3720 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3501, 0},
-#line 2844 "effective_tld_names.gperf"
+#line 2086 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3502, 0},
-#line 1519 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3503, 4},
-#line 2191 "effective_tld_names.gperf"
+#line 1679 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3503, 0},
+#line 5018 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3504, 0},
-#line 1358 "effective_tld_names.gperf"
+#line 2631 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3505, 0},
-#line 2881 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3506, 0},
-#line 4262 "effective_tld_names.gperf"
+#line 1198 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3506, 4},
+#line 6206 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3507, 0},
-#line 3508 "effective_tld_names.gperf"
+#line 2177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3508, 0},
-#line 1322 "effective_tld_names.gperf"
+#line 1702 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3509, 0},
-#line 3988 "effective_tld_names.gperf"
+#line 5144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3510, 0},
-#line 5169 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3511, 0},
-#line 1854 "effective_tld_names.gperf"
+#line 2483 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3511, 4},
+#line 6146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3512, 0},
-#line 2821 "effective_tld_names.gperf"
+#line 376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3513, 0},
-#line 4600 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3514, 4},
-#line 4373 "effective_tld_names.gperf"
+#line 5091 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3514, 0},
+#line 6122 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3515, 0},
-#line 4697 "effective_tld_names.gperf"
+#line 4849 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3516, 0},
-#line 2408 "effective_tld_names.gperf"
+#line 1135 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3517, 0},
-#line 4744 "effective_tld_names.gperf"
+#line 3390 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3518, 0},
-#line 4003 "effective_tld_names.gperf"
+#line 3573 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3519, 0},
-#line 2773 "effective_tld_names.gperf"
+#line 2407 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3520, 0},
-#line 2431 "effective_tld_names.gperf"
+#line 4895 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3521, 0},
-#line 1377 "effective_tld_names.gperf"
+#line 1156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3522, 0},
-#line 2775 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3523, 0},
-#line 2846 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3524, 0},
-#line 5396 "effective_tld_names.gperf"
+#line 2441 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3523, 4},
+#line 1202 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3524, 4},
+#line 4237 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3525, 0},
-#line 4406 "effective_tld_names.gperf"
+#line 1069 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3526, 0},
-#line 4430 "effective_tld_names.gperf"
+#line 4960 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3527, 0},
-#line 2422 "effective_tld_names.gperf"
+#line 5974 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3528, 0},
-#line 4377 "effective_tld_names.gperf"
+#line 4953 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3529, 0},
-#line 4460 "effective_tld_names.gperf"
+#line 3288 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3530, 0},
-#line 4454 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3531, 0},
-#line 4324 "effective_tld_names.gperf"
+#line 731 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3531, 4},
+#line 2071 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3532, 0},
-#line 3142 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3533, 0},
-#line 2455 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3534, 1},
-#line 3511 "effective_tld_names.gperf"
+#line 1577 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3533, 4},
+#line 1593 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3534, 4},
+#line 2315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3535, 0},
-#line 4466 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3536, 0},
-#line 4887 "effective_tld_names.gperf"
+#line 1573 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3536, 4},
+#line 2516 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3537, 0},
-#line 5084 "effective_tld_names.gperf"
+#line 156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3538, 0},
-#line 2105 "effective_tld_names.gperf"
+#line 4185 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3539, 0},
-#line 2987 "effective_tld_names.gperf"
+#line 606 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3540, 0},
-#line 1813 "effective_tld_names.gperf"
+#line 663 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3541, 0},
-#line 5599 "effective_tld_names.gperf"
+#line 5046 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3542, 0},
-#line 1308 "effective_tld_names.gperf"
+#line 3739 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3543, 0},
-#line 4451 "effective_tld_names.gperf"
+#line 2713 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3544, 0},
-#line 4431 "effective_tld_names.gperf"
+#line 1036 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3545, 0},
-#line 618 "effective_tld_names.gperf"
+#line 1097 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3546, 0},
-#line 4407 "effective_tld_names.gperf"
+#line 5749 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3547, 0},
-#line 552 "effective_tld_names.gperf"
+#line 323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3548, 0},
-#line 4447 "effective_tld_names.gperf"
+#line 809 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3549, 0},
-#line 5715 "effective_tld_names.gperf"
+#line 2556 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3550, 0},
-#line 5355 "effective_tld_names.gperf"
+#line 1460 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3551, 0},
-#line 5527 "effective_tld_names.gperf"
+#line 258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3552, 0},
-#line 4325 "effective_tld_names.gperf"
+#line 6325 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3553, 0},
-#line 4736 "effective_tld_names.gperf"
+#line 6070 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3554, 0},
-#line 2132 "effective_tld_names.gperf"
+#line 3724 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3555, 0},
-#line 5155 "effective_tld_names.gperf"
+#line 5120 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3556, 0},
-#line 4452 "effective_tld_names.gperf"
+#line 3767 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3557, 0},
-#line 3512 "effective_tld_names.gperf"
+#line 207 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3558, 0},
-#line 3802 "effective_tld_names.gperf"
+#line 3312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3559, 0},
-#line 4327 "effective_tld_names.gperf"
+#line 31 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3560, 0},
-#line 3990 "effective_tld_names.gperf"
+#line 5794 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3561, 0},
-#line 2589 "effective_tld_names.gperf"
+#line 4875 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3562, 0},
-#line 4408 "effective_tld_names.gperf"
+#line 4398 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3563, 0},
-#line 4489 "effective_tld_names.gperf"
+#line 6065 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3564, 0},
-#line 4326 "effective_tld_names.gperf"
+#line 4186 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3565, 0},
-#line 4296 "effective_tld_names.gperf"
+#line 4166 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3566, 0},
-#line 1740 "effective_tld_names.gperf"
+#line 6067 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3567, 0},
-#line 4957 "effective_tld_names.gperf"
+#line 2031 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3568, 0},
-#line 635 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3569, 0},
-#line 1864 "effective_tld_names.gperf"
+#line 1727 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3569, 4},
+#line 1850 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3570, 0},
-#line 3803 "effective_tld_names.gperf"
+#line 1271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3571, 0},
-#line 1450 "effective_tld_names.gperf"
+#line 4619 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3572, 0},
-#line 6061 "effective_tld_names.gperf"
+#line 940 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3573, 0},
-#line 4735 "effective_tld_names.gperf"
+#line 4575 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3574, 0},
-#line 4332 "effective_tld_names.gperf"
+#line 776 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3575, 0},
-#line 4438 "effective_tld_names.gperf"
+#line 6294 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3576, 0},
-#line 5042 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3577, 0},
-#line 6034 "effective_tld_names.gperf"
+#line 2457 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3577, 4},
+#line 5961 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3578, 0},
-#line 5399 "effective_tld_names.gperf"
+#line 3407 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3579, 0},
-#line 5143 "effective_tld_names.gperf"
+#line 4532 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3580, 0},
-#line 4374 "effective_tld_names.gperf"
+#line 608 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3581, 0},
-#line 1593 "effective_tld_names.gperf"
+#line 3056 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3582, 0},
-#line 2416 "effective_tld_names.gperf"
+#line 6217 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3583, 0},
-#line 5165 "effective_tld_names.gperf"
+#line 5993 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3584, 0},
-#line 6115 "effective_tld_names.gperf"
+#line 3574 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3585, 0},
-#line 4037 "effective_tld_names.gperf"
+#line 4565 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3586, 0},
-#line 1524 "effective_tld_names.gperf"
+#line 3031 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3587, 0},
-#line 4432 "effective_tld_names.gperf"
+#line 256 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3588, 0},
-#line 4353 "effective_tld_names.gperf"
+#line 2797 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3589, 0},
-#line 1651 "effective_tld_names.gperf"
+#line 4627 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3590, 0},
-#line 6085 "effective_tld_names.gperf"
+#line 2040 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3591, 0},
-#line 5532 "effective_tld_names.gperf"
+#line 4600 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3592, 0},
-#line 4375 "effective_tld_names.gperf"
+#line 279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3593, 0},
-#line 2871 "effective_tld_names.gperf"
+#line 1027 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3594, 0},
-#line 5201 "effective_tld_names.gperf"
+#line 2164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3595, 0},
-#line 3509 "effective_tld_names.gperf"
+#line 3334 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3596, 0},
-#line 2432 "effective_tld_names.gperf"
+#line 4219 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3597, 0},
-#line 4396 "effective_tld_names.gperf"
+#line 4607 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3598, 0},
-#line 4364 "effective_tld_names.gperf"
+#line 4456 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3599, 0},
-#line 123 "effective_tld_names.gperf"
+#line 4543 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3600, 0},
-#line 3255 "effective_tld_names.gperf"
+#line 4457 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3601, 0},
-#line 4695 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3602, 0},
-#line 5244 "effective_tld_names.gperf"
+#line 1949 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3602, 4},
+#line 5935 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3603, 0},
-#line 5118 "effective_tld_names.gperf"
+#line 4488 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3604, 0},
-#line 3471 "effective_tld_names.gperf"
+#line 3814 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3605, 0},
-#line 1950 "effective_tld_names.gperf"
+#line 5926 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3606, 0},
-#line 4297 "effective_tld_names.gperf"
+#line 125 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3607, 0},
-#line 2406 "effective_tld_names.gperf"
+#line 2300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3608, 0},
-#line 1874 "effective_tld_names.gperf"
+#line 196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3609, 0},
-#line 3670 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3610, 4},
-#line 3997 "effective_tld_names.gperf"
+#line 1160 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3610, 0},
+#line 249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3611, 0},
-#line 2907 "effective_tld_names.gperf"
+#line 1197 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3612, 0},
-#line 984 "effective_tld_names.gperf"
+#line 4623 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3613, 0},
-#line 3893 "effective_tld_names.gperf"
+#line 101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3614, 0},
-#line 4365 "effective_tld_names.gperf"
+#line 6259 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3615, 0},
-#line 4021 "effective_tld_names.gperf"
+#line 2227 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3616, 0},
-#line 4299 "effective_tld_names.gperf"
+#line 184 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3617, 0},
-#line 1556 "effective_tld_names.gperf"
+#line 6278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3618, 0},
-#line 1938 "effective_tld_names.gperf"
+#line 4018 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3619, 0},
-#line 2991 "effective_tld_names.gperf"
+#line 1033 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3620, 0},
-#line 5010 "effective_tld_names.gperf"
+#line 1840 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3621, 0},
-#line 4295 "effective_tld_names.gperf"
+#line 1263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3622, 0},
-#line 3949 "effective_tld_names.gperf"
+#line 1034 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3623, 0},
-#line 5075 "effective_tld_names.gperf"
+#line 931 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3624, 0},
-#line 338 "effective_tld_names.gperf"
+#line 6234 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3625, 0},
-#line 1091 "effective_tld_names.gperf"
+#line 4603 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3626, 0},
-#line 5667 "effective_tld_names.gperf"
+#line 6105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3627, 0},
-#line 2980 "effective_tld_names.gperf"
+#line 193 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3628, 0},
-#line 5668 "effective_tld_names.gperf"
+#line 4628 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3629, 0},
-#line 1315 "effective_tld_names.gperf"
+#line 3819 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3630, 0},
-#line 3174 "effective_tld_names.gperf"
+#line 6225 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3631, 0},
-#line 1985 "effective_tld_names.gperf"
+#line 3522 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3632, 0},
-#line 4300 "effective_tld_names.gperf"
+#line 3821 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3633, 0},
-#line 2400 "effective_tld_names.gperf"
+#line 5698 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3634, 0},
-#line 1596 "effective_tld_names.gperf"
+#line 4024 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3635, 4},
-#line 4455 "effective_tld_names.gperf"
+#line 5714 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3636, 0},
-#line 4284 "effective_tld_names.gperf"
+#line 2205 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3637, 0},
-#line 4616 "effective_tld_names.gperf"
+#line 1663 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3638, 0},
-#line 4344 "effective_tld_names.gperf"
+#line 4602 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3639, 0},
-#line 4732 "effective_tld_names.gperf"
+#line 2664 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3640, 0},
-#line 1554 "effective_tld_names.gperf"
+#line 563 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3641, 0},
-#line 3500 "effective_tld_names.gperf"
+#line 6296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3642, 0},
-#line 4363 "effective_tld_names.gperf"
+#line 1121 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3643, 0},
-#line 5990 "effective_tld_names.gperf"
+#line 5130 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3644, 0},
-#line 158 "effective_tld_names.gperf"
+#line 4637 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3645, 0},
-#line 4427 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3646, 0},
-#line 5329 "effective_tld_names.gperf"
+#line 1536 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3646, 4},
+#line 4088 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3647, 0},
-#line 5419 "effective_tld_names.gperf"
+#line 4089 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3648, 0},
-#line 4806 "effective_tld_names.gperf"
+#line 4493 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3649, 0},
-#line 4779 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3650, 4},
-#line 4027 "effective_tld_names.gperf"
+#line 4085 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3650, 0},
+#line 3292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3651, 0},
-#line 5342 "effective_tld_names.gperf"
+#line 4606 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3652, 0},
-#line 6010 "effective_tld_names.gperf"
+#line 5738 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3653, 0},
-#line 4433 "effective_tld_names.gperf"
+#line 2287 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3654, 0},
-#line 4404 "effective_tld_names.gperf"
+#line 4592 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3655, 0},
-#line 4449 "effective_tld_names.gperf"
+#line 6044 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3656, 0},
-#line 4425 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3657, 4},
-#line 772 "effective_tld_names.gperf"
+#line 4761 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3657, 0},
+#line 6207 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3658, 0},
-#line 2093 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3659, 4},
-#line 4700 "effective_tld_names.gperf"
+#line 3326 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3659, 0},
+#line 779 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3660, 0},
-#line 1569 "effective_tld_names.gperf"
+#line 4542 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3661, 0},
-#line 2327 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3662, 4},
-#line 3840 "effective_tld_names.gperf"
+#line 3046 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3662, 0},
+#line 644 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3663, 0},
-#line 2618 "effective_tld_names.gperf"
+#line 4614 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3664, 0},
-#line 816 "effective_tld_names.gperf"
+#line 2637 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3665, 0},
-#line 2435 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3666, 0},
-#line 3986 "effective_tld_names.gperf"
+#line 1950 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3666, 4},
+#line 659 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3667, 0},
-#line 4825 "effective_tld_names.gperf"
+#line 175 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3668, 0},
-#line 2173 "effective_tld_names.gperf"
+#line 5202 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3669, 0},
-#line 1654 "effective_tld_names.gperf"
+#line 6224 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3670, 0},
-#line 221 "effective_tld_names.gperf"
+#line 5125 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3671, 0},
-#line 3980 "effective_tld_names.gperf"
+#line 6203 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3672, 0},
-#line 6086 "effective_tld_names.gperf"
+#line 1139 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3673, 0},
-#line 5063 "effective_tld_names.gperf"
+#line 4102 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3674, 0},
-#line 1350 "effective_tld_names.gperf"
+#line 2055 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3675, 0},
-#line 2383 "effective_tld_names.gperf"
+#line 5988 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3676, 0},
-#line 1976 "effective_tld_names.gperf"
+#line 4589 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3677, 0},
-#line 4436 "effective_tld_names.gperf"
+#line 5725 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3678, 0},
-#line 6009 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3679, 0},
-#line 3254 "effective_tld_names.gperf"
+#line 816 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3679, 1},
+#line 4220 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3680, 0},
-#line 2742 "effective_tld_names.gperf"
+#line 4892 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3681, 0},
-#line 6011 "effective_tld_names.gperf"
+#line 2145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3682, 0},
-#line 237 "effective_tld_names.gperf"
+#line 5013 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3683, 0},
-#line 4423 "effective_tld_names.gperf"
+#line 4458 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3684, 0},
-#line 4333 "effective_tld_names.gperf"
+#line 4014 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3685, 0},
-#line 2067 "effective_tld_names.gperf"
+#line 6016 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3686, 0},
-#line 860 "effective_tld_names.gperf"
+#line 4732 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3687, 0},
-#line 2543 "effective_tld_names.gperf"
+#line 1829 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3688, 0},
-#line 3836 "effective_tld_names.gperf"
+#line 1253 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3689, 0},
-#line 5539 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3690, 0},
-#line 2861 "effective_tld_names.gperf"
+#line 2851 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3690, 4},
+#line 920 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3691, 0},
-#line 5511 "effective_tld_names.gperf"
+#line 4021 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3692, 0},
-#line 5261 "effective_tld_names.gperf"
+#line 4480 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3693, 0},
-#line 5663 "effective_tld_names.gperf"
+#line 579 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3694, 0},
-#line 322 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3695, 4},
-#line 5535 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3696, 0},
-#line 4076 "effective_tld_names.gperf"
+#line 6068 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3695, 0},
+#line 225 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3696, 4},
+#line 2645 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3697, 0},
-#line 1522 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3698, 4},
-#line 1686 "effective_tld_names.gperf"
+#line 5078 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3698, 0},
+#line 6226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3699, 0},
-#line 2436 "effective_tld_names.gperf"
+#line 566 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3700, 0},
-#line 719 "effective_tld_names.gperf"
+#line 3817 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3701, 0},
-#line 4636 "effective_tld_names.gperf"
+#line 5724 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3702, 0},
-#line 3051 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3703, 0},
-#line 2667 "effective_tld_names.gperf"
+#line 1756 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3703, 4},
+#line 2093 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3704, 0},
-#line 5082 "effective_tld_names.gperf"
+#line 3736 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3705, 0},
-#line 5508 "effective_tld_names.gperf"
+#line 5681 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3706, 0},
-#line 2446 "effective_tld_names.gperf"
+#line 4525 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3707, 0},
-#line 1998 "effective_tld_names.gperf"
+#line 1196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3708, 0},
-#line 4001 "effective_tld_names.gperf"
+#line 5939 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3709, 0},
-#line 3868 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3710, 4},
-#line 1029 "effective_tld_names.gperf"
+#line 2388 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3710, 0},
+#line 2729 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3711, 0},
-#line 5671 "effective_tld_names.gperf"
+#line 264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3712, 0},
-#line 4359 "effective_tld_names.gperf"
+#line 4608 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3713, 0},
-#line 1159 "effective_tld_names.gperf"
+#line 3766 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3714, 0},
-#line 238 "effective_tld_names.gperf"
+#line 4591 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3715, 0},
-#line 4969 "effective_tld_names.gperf"
+#line 6265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3716, 0},
-#line 5514 "effective_tld_names.gperf"
+#line 3989 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3717, 0},
-#line 4463 "effective_tld_names.gperf"
+#line 4540 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3718, 0},
-#line 2919 "effective_tld_names.gperf"
+#line 2109 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3719, 0},
-#line 1543 "effective_tld_names.gperf"
+#line 4522 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3720, 0},
-#line 487 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3721, 4},
-#line 2542 "effective_tld_names.gperf"
+#line 2028 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3721, 0},
+#line 3775 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3722, 0},
-#line 1840 "effective_tld_names.gperf"
+#line 3764 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3723, 0},
-#line 3974 "effective_tld_names.gperf"
+#line 5475 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3724, 0},
-#line 5538 "effective_tld_names.gperf"
+#line 5417 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3725, 0},
-#line 611 "effective_tld_names.gperf"
+#line 4561 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3726, 0},
-#line 5606 "effective_tld_names.gperf"
+#line 5666 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3727, 0},
-#line 3257 "effective_tld_names.gperf"
+#line 2856 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3728, 0},
-#line 1139 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3729, 4},
-#line 3965 "effective_tld_names.gperf"
+#line 1812 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3729, 0},
+#line 4729 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3730, 0},
-#line 6013 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3731, 0},
-#line 2046 "effective_tld_names.gperf"
+#line 5570 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3731, 2},
+#line 4100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3732, 0},
-#line 3050 "effective_tld_names.gperf"
+#line 5460 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3733, 0},
-#line 4261 "effective_tld_names.gperf"
+#line 4733 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3734, 0},
-#line 4562 "effective_tld_names.gperf"
+#line 1071 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3735, 0},
-#line 1291 "effective_tld_names.gperf"
+#line 4020 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3736, 0},
-#line 5501 "effective_tld_names.gperf"
+#line 6270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3737, 0},
-#line 3846 "effective_tld_names.gperf"
+#line 1723 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3738, 0},
-#line 1520 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3739, 4},
-#line 2707 "effective_tld_names.gperf"
+#line 5530 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3739, 0},
+#line 3262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3740, 0},
-#line 2117 "effective_tld_names.gperf"
+#line 3323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3741, 0},
-#line 130 "effective_tld_names.gperf"
+#line 4080 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3742, 0},
-#line 6004 "effective_tld_names.gperf"
+#line 5313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3743, 0},
-#line 3610 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3744, 0},
-#line 4638 "effective_tld_names.gperf"
+#line 502 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3744, 4},
+#line 5472 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3745, 0},
-#line 2569 "effective_tld_names.gperf"
+#line 4620 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3746, 0},
-#line 4974 "effective_tld_names.gperf"
+#line 5314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3747, 0},
-#line 2923 "effective_tld_names.gperf"
+#line 4138 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3748, 0},
-#line 1160 "effective_tld_names.gperf"
+#line 4507 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3749, 0},
-#line 4393 "effective_tld_names.gperf"
+#line 4521 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3750, 0},
-#line 6016 "effective_tld_names.gperf"
+#line 5011 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3751, 0},
-#line 859 "effective_tld_names.gperf"
+#line 142 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3752, 0},
-#line 5489 "effective_tld_names.gperf"
+#line 4017 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3753, 0},
-#line 5633 "effective_tld_names.gperf"
+#line 4870 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3754, 0},
-#line 6092 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3755, 4},
-#line 1942 "effective_tld_names.gperf"
+#line 6384 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3755, 0},
+#line 4593 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3756, 0},
-#line 2819 "effective_tld_names.gperf"
+#line 4092 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3757, 0},
-#line 2164 "effective_tld_names.gperf"
+#line 4621 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3758, 0},
-#line 3525 "effective_tld_names.gperf"
+#line 2945 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3759, 0},
-#line 4464 "effective_tld_names.gperf"
+#line 4494 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3760, 0},
-#line 4357 "effective_tld_names.gperf"
+#line 4955 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3761, 0},
-#line 5678 "effective_tld_names.gperf"
+#line 5636 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3762, 0},
-#line 4748 "effective_tld_names.gperf"
+#line 6194 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3763, 0},
-#line 1437 "effective_tld_names.gperf"
+#line 151 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3764, 0},
-#line 2644 "effective_tld_names.gperf"
+#line 4515 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3765, 0},
-#line 373 "effective_tld_names.gperf"
+#line 4518 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3766, 0},
-#line 4847 "effective_tld_names.gperf"
+#line 4951 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3767, 0},
-#line 3932 "effective_tld_names.gperf"
+#line 3287 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3768, 0},
-#line 4662 "effective_tld_names.gperf"
+#line 4429 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3769, 0},
-#line 1643 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3770, 4},
-#line 4442 "effective_tld_names.gperf"
+#line 5975 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3770, 0},
+#line 2404 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3771, 0},
-#line 3069 "effective_tld_names.gperf"
+#line 5601 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3772, 0},
-#line 1904 "effective_tld_names.gperf"
+#line 3013 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3773, 0},
-#line 2882 "effective_tld_names.gperf"
+#line 5872 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3774, 0},
-#line 327 "effective_tld_names.gperf"
+#line 4479 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3775, 0},
-#line 5676 "effective_tld_names.gperf"
+#line 5870 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3776, 0},
-#line 3510 "effective_tld_names.gperf"
+#line 4292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3777, 0},
-#line 2080 "effective_tld_names.gperf"
+#line 4086 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3778, 0},
-#line 2170 "effective_tld_names.gperf"
+#line 3965 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3779, 0},
-#line 5346 "effective_tld_names.gperf"
+#line 1776 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3780, 0},
-#line 3602 "effective_tld_names.gperf"
+#line 5025 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3781, 0},
-#line 1544 "effective_tld_names.gperf"
+#line 4574 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3782, 0},
-#line 738 "effective_tld_names.gperf"
+#line 6219 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3783, 0},
-#line 6052 "effective_tld_names.gperf"
+#line 892 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3784, 0},
-#line 4439 "effective_tld_names.gperf"
+#line 848 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3785, 0},
-#line 4641 "effective_tld_names.gperf"
+#line 5454 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3786, 0},
-#line 4763 "effective_tld_names.gperf"
+#line 6289 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3787, 0},
-#line 2989 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3788, 4},
-#line 4094 "effective_tld_names.gperf"
+#line 2157 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3788, 0},
+#line 2257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3789, 0},
-#line 4392 "effective_tld_names.gperf"
+#line 786 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3790, 0},
-#line 2368 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3791, 4},
-#line 5707 "effective_tld_names.gperf"
+#line 2870 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3791, 0},
+#line 3768 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3792, 0},
-#line 2765 "effective_tld_names.gperf"
+#line 3811 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3793, 0},
-#line 3236 "effective_tld_names.gperf"
+#line 5640 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3794, 0},
-#line 4252 "effective_tld_names.gperf"
+#line 6155 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3795, 0},
-#line 1300 "effective_tld_names.gperf"
+#line 2878 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3796, 0},
-#line 2220 "effective_tld_names.gperf"
+#line 3464 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3797, 0},
-#line 4653 "effective_tld_names.gperf"
+#line 553 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3798, 0},
-#line 285 "effective_tld_names.gperf"
+#line 858 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3799, 0},
-#line 5147 "effective_tld_names.gperf"
+#line 636 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3800, 0},
-#line 1923 "effective_tld_names.gperf"
+#line 5798 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3801, 0},
-#line 3960 "effective_tld_names.gperf"
+#line 4531 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3802, 0},
-#line 1957 "effective_tld_names.gperf"
+#line 1873 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3803, 0},
-#line 204 "effective_tld_names.gperf"
+#line 1297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3804, 0},
-#line 5140 "effective_tld_names.gperf"
+#line 968 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3805, 0},
-#line 2554 "effective_tld_names.gperf"
+#line 4868 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3806, 0},
-#line 5099 "effective_tld_names.gperf"
+#line 5873 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3807, 0},
-#line 4077 "effective_tld_names.gperf"
+#line 6107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3808, 0},
-#line 4238 "effective_tld_names.gperf"
+#line 5600 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3809, 0},
-#line 5309 "effective_tld_names.gperf"
+#line 4001 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3810, 0},
-#line 2953 "effective_tld_names.gperf"
+#line 5455 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3811, 0},
-#line 6045 "effective_tld_names.gperf"
+#line 2944 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3812, 0},
-#line 3425 "effective_tld_names.gperf"
+#line 475 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3813, 0},
-#line 6008 "effective_tld_names.gperf"
+#line 5461 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3814, 0},
-#line 3265 "effective_tld_names.gperf"
+#line 5591 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3815, 0},
-#line 4693 "effective_tld_names.gperf"
+#line 903 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3816, 0},
-#line 4401 "effective_tld_names.gperf"
+#line 5793 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3817, 0},
-#line 565 "effective_tld_names.gperf"
+#line 5433 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3818, 0},
-#line 4604 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3819, 4},
-#line 3919 "effective_tld_names.gperf"
+#line 348 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3819, 0},
+#line 5597 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3820, 0},
-#line 3862 "effective_tld_names.gperf"
+#line 5826 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3821, 0},
-#line 5047 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3822, 0},
-#line 2187 "effective_tld_names.gperf"
+#line 2094 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3822, 4},
+#line 5423 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3823, 0},
-#line 1765 "effective_tld_names.gperf"
+#line 1371 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3824, 0},
-#line 1217 "effective_tld_names.gperf"
+#line 6354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3825, 0},
-#line 1764 "effective_tld_names.gperf"
+#line 2846 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3826, 0},
-#line 915 "effective_tld_names.gperf"
+#line 5485 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3827, 0},
-#line 1769 "effective_tld_names.gperf"
+#line 5448 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3828, 0},
-#line 1216 "effective_tld_names.gperf"
+#line 4528 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3829, 0},
-#line 1221 "effective_tld_names.gperf"
+#line 666 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3830, 0},
-#line 1763 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3831, 0},
-#line 914 "effective_tld_names.gperf"
+#line 1374 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3831, 4},
+#line 2317 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3832, 0},
-#line 1215 "effective_tld_names.gperf"
+#line 5411 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3833, 0},
-#line 918 "effective_tld_names.gperf"
+#line 4581 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3834, 0},
-#line 913 "effective_tld_names.gperf"
+#line 364 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3835, 0},
-#line 2197 "effective_tld_names.gperf"
+#line 2698 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3836, 0},
-#line 2862 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3837, 0},
-#line 2300 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3838, 4},
-#line 3588 "effective_tld_names.gperf"
+#line 2095 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3837, 4},
+#line 4844 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3838, 0},
+#line 4467 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3839, 0},
-#line 63 "effective_tld_names.gperf"
+#line 4069 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3840, 0},
-#line 1591 "effective_tld_names.gperf"
+#line 6218 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3841, 0},
-#line 4368 "effective_tld_names.gperf"
+#line 1703 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3842, 0},
-#line 737 "effective_tld_names.gperf"
+#line 5294 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3843, 0},
-#line 4342 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3844, 2},
-#line 1292 "effective_tld_names.gperf"
+#line 1409 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3844, 0},
+#line 2542 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3845, 0},
-#line 5294 "effective_tld_names.gperf"
+#line 5864 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3846, 0},
-#line 481 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3847, 4},
-#line 3994 "effective_tld_names.gperf"
+#line 4230 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3847, 0},
+#line 5639 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3848, 0},
-#line 4024 "effective_tld_names.gperf"
+#line 3812 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3849, 0},
-#line 4664 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3850, 0},
-#line 5044 "effective_tld_names.gperf"
+#line 1578 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3850, 4},
+#line 5646 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3851, 0},
-#line 4681 "effective_tld_names.gperf"
+#line 1847 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3852, 0},
-#line 2739 "effective_tld_names.gperf"
+#line 4036 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3853, 0},
-#line 4343 "effective_tld_names.gperf"
+#line 76 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3854, 0},
-#line 5000 "effective_tld_names.gperf"
+#line 5471 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3855, 0},
-#line 2212 "effective_tld_names.gperf"
+#line 5663 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3856, 0},
-#line 296 "effective_tld_names.gperf"
+#line 3421 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3857, 0},
-#line 5403 "effective_tld_names.gperf"
+#line 470 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3858, 0},
-#line 4428 "effective_tld_names.gperf"
+#line 5068 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3859, 0},
-#line 3455 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3860, 0},
-#line 4429 "effective_tld_names.gperf"
+#line 2452 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3860, 4},
+#line 4734 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3861, 0},
-#line 1766 "effective_tld_names.gperf"
+#line 1490 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3862, 0},
-#line 1218 "effective_tld_names.gperf"
+#line 6244 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3863, 0},
-#line 569 "effective_tld_names.gperf"
+#line 5772 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3864, 0},
-#line 2107 "effective_tld_names.gperf"
+#line 4780 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3865, 0},
-#line 2771 "effective_tld_names.gperf"
+#line 4503 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3866, 0},
-#line 1117 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3867, 0},
-#line 4331 "effective_tld_names.gperf"
+#line 1222 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3867, 4},
+#line 5568 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3868, 0},
-#line 5371 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3869, 4},
-#line 3811 "effective_tld_names.gperf"
+#line 3857 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3869, 0},
+#line 4161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3870, 0},
-#line 3849 "effective_tld_names.gperf"
+#line 5574 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3871, 0},
-#line 1324 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3872, 0},
-#line 4303 "effective_tld_names.gperf"
+#line 3500 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3872, 4},
+#line 4680 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3873, 0},
-#line 4620 "effective_tld_names.gperf"
+#line 5899 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3874, 0},
-#line 3375 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3875, 0},
-#line 4446 "effective_tld_names.gperf"
+#line 4742 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3875, 4},
+#line 4469 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3876, 0},
-#line 3112 "effective_tld_names.gperf"
+#line 4563 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3877, 0},
-#line 1542 "effective_tld_names.gperf"
+#line 2763 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3878, 0},
-#line 626 "effective_tld_names.gperf"
+#line 5876 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3879, 0},
-#line 1925 "effective_tld_names.gperf"
+#line 5445 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3880, 0},
-#line 5713 "effective_tld_names.gperf"
+#line 5542 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3881, 0},
-#line 3331 "effective_tld_names.gperf"
+#line 5800 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3882, 0},
-#line 5537 "effective_tld_names.gperf"
+#line 3646 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3883, 0},
-#line 4740 "effective_tld_names.gperf"
+#line 5903 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3884, 0},
-#line 2428 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3885, 0},
-#line 2094 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3886, 4},
-#line 3170 "effective_tld_names.gperf"
+#line 4767 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3885, 4},
+#line 789 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3886, 0},
+#line 5263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3887, 0},
-#line 3992 "effective_tld_names.gperf"
+#line 4858 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3888, 0},
-#line 2770 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3889, 0},
-#line 4980 "effective_tld_names.gperf"
+#line 329 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3889, 4},
+#line 4715 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3890, 0},
-#line 3972 "effective_tld_names.gperf"
+#line 4814 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3891, 0},
-#line 446 "effective_tld_names.gperf"
+#line 5594 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3892, 0},
-#line 4643 "effective_tld_names.gperf"
+#line 4231 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3893, 0},
-#line 268 "effective_tld_names.gperf"
+#line 3366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3894, 0},
-#line 2295 "effective_tld_names.gperf"
+#line 4541 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3895, 0},
-#line 1462 "effective_tld_names.gperf"
+#line 3296 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3896, 0},
-#line 3343 "effective_tld_names.gperf"
+#line 2050 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3897, 0},
-#line 3335 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3898, 0},
-#line 3267 "effective_tld_names.gperf"
+#line 1612 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3898, 4},
+#line 2829 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3899, 0},
-#line 4235 "effective_tld_names.gperf"
+#line 2847 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3900, 0},
-#line 3118 "effective_tld_names.gperf"
+#line 6116 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3901, 0},
-#line 5151 "effective_tld_names.gperf"
+#line 4954 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3902, 0},
-#line 5976 "effective_tld_names.gperf"
+#line 5884 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3903, 0},
-#line 1924 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3904, 4},
-#line 4305 "effective_tld_names.gperf"
+#line 2346 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3904, 0},
+#line 3859 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3905, 0},
-#line 61 "effective_tld_names.gperf"
+#line 3533 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3906, 0},
-#line 5660 "effective_tld_names.gperf"
+#line 204 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3907, 0},
-#line 3844 "effective_tld_names.gperf"
+#line 6066 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3908, 0},
-#line 1861 "effective_tld_names.gperf"
+#line 6271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3909, 0},
-#line 3812 "effective_tld_names.gperf"
+#line 5459 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3910, 0},
-#line 62 "effective_tld_names.gperf"
+#line 5024 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3911, 0},
-#line 4367 "effective_tld_names.gperf"
+#line 763 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3912, 0},
-#line 2752 "effective_tld_names.gperf"
+#line 3855 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3913, 0},
-#line 4456 "effective_tld_names.gperf"
+#line 4677 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3914, 0},
-#line 2031 "effective_tld_names.gperf"
+#line 4147 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3915, 0},
-#line 4630 "effective_tld_names.gperf"
+#line 6387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3916, 0},
-#line 3148 "effective_tld_names.gperf"
+#line 5943 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3917, 0},
-#line 1789 "effective_tld_names.gperf"
+#line 1494 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3918, 0},
-#line 4587 "effective_tld_names.gperf"
+#line 5909 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3919, 0},
-#line 4426 "effective_tld_names.gperf"
+#line 5786 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3920, 0},
-#line 1238 "effective_tld_names.gperf"
+#line 2708 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3921, 0},
-#line 3639 "effective_tld_names.gperf"
+#line 5783 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3922, 0},
-#line 1518 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3923, 4},
-#line 934 "effective_tld_names.gperf"
+#line 6052 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3923, 0},
+#line 4893 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3924, 0},
-#line 3263 "effective_tld_names.gperf"
+#line 5434 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3925, 0},
-#line 33 "effective_tld_names.gperf"
+#line 4555 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3926, 0},
-#line 4482 "effective_tld_names.gperf"
+#line 3640 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3927, 0},
-#line 2576 "effective_tld_names.gperf"
+#line 5662 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3928, 0},
-#line 3933 "effective_tld_names.gperf"
+#line 6344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3929, 0},
-#line 206 "effective_tld_names.gperf"
+#line 5778 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3930, 0},
-#line 6024 "effective_tld_names.gperf"
+#line 3443 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3931, 0},
-#line 4306 "effective_tld_names.gperf"
+#line 4630 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3932, 0},
-#line 5213 "effective_tld_names.gperf"
+#line 3959 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3933, 0},
-#line 2702 "effective_tld_names.gperf"
+#line 4536 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3934, 0},
-#line 995 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3935, 0},
-#line 3450 "effective_tld_names.gperf"
+#line 2211 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3935, 4},
+#line 4038 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3936, 0},
-#line 3396 "effective_tld_names.gperf"
+#line 5573 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3937, 0},
-#line 6006 "effective_tld_names.gperf"
+#line 5811 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3938, 0},
-#line 5229 "effective_tld_names.gperf"
+#line 5529 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3939, 0},
-#line 3242 "effective_tld_names.gperf"
+#line 6222 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3940, 0},
-#line 461 "effective_tld_names.gperf"
+#line 4636 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3941, 0},
-#line 6049 "effective_tld_names.gperf"
+#line 6266 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3942, 0},
-#line 2141 "effective_tld_names.gperf"
+#line 1126 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3943, 0},
-#line 3841 "effective_tld_names.gperf"
+#line 5546 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3944, 0},
-#line 4264 "effective_tld_names.gperf"
+#line 2262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3945, 0},
-#line 6043 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3946, 0},
-#line 4022 "effective_tld_names.gperf"
+#line 2210 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3946, 4},
+#line 4481 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3947, 0},
-#line 98 "effective_tld_names.gperf"
+#line 2070 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3948, 0},
-#line 1060 "effective_tld_names.gperf"
+#line 1157 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3949, 0},
-#line 5320 "effective_tld_names.gperf"
+#line 1233 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3950, 0},
-#line 4981 "effective_tld_names.gperf"
+#line 4464 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3951, 0},
-#line 4388 "effective_tld_names.gperf"
+#line 1140 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3952, 0},
-#line 5021 "effective_tld_names.gperf"
+#line 4584 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3953, 0},
-#line 3655 "effective_tld_names.gperf"
+#line 2867 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3954, 0},
-#line 154 "effective_tld_names.gperf"
+#line 4860 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3955, 0},
-#line 4260 "effective_tld_names.gperf"
+#line 4822 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3956, 0},
-#line 2908 "effective_tld_names.gperf"
+#line 6084 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3957, 0},
-#line 1872 "effective_tld_names.gperf"
+#line 6366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3958, 0},
-#line 2050 "effective_tld_names.gperf"
+#line 5452 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3959, 0},
-#line 1393 "effective_tld_names.gperf"
+#line 2876 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3960, 0},
-#line 266 "effective_tld_names.gperf"
+#line 4562 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3961, 0},
-#line 4603 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3962, 4},
-#line 127 "effective_tld_names.gperf"
+#line 3765 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3962, 0},
+#line 5532 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3963, 0},
-#line 4547 "effective_tld_names.gperf"
+#line 4495 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3964, 0},
-#line 1625 "effective_tld_names.gperf"
+#line 5819 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3965, 0},
-#line 4994 "effective_tld_names.gperf"
+#line 4629 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3966, 0},
-#line 3298 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3967, 0},
-#line 3163 "effective_tld_names.gperf"
+#line 2496 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3967, 4},
+#line 6061 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3968, 0},
-#line 2646 "effective_tld_names.gperf"
+#line 6001 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3969, 0},
-#line 1857 "effective_tld_names.gperf"
+#line 4831 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3970, 0},
-#line 3300 "effective_tld_names.gperf"
+#line 1406 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3971, 0},
-#line 4970 "effective_tld_names.gperf"
+#line 143 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3972, 0},
-#line 3297 "effective_tld_names.gperf"
+#line 757 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3973, 0},
-#line 1773 "effective_tld_names.gperf"
+#line 5283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3974, 0},
-#line 1225 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3975, 0},
-#line 3334 "effective_tld_names.gperf"
+#line 2497 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3975, 4},
+#line 4025 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3976, 0},
-#line 4821 "effective_tld_names.gperf"
+#line 2114 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3977, 0},
-#line 922 "effective_tld_names.gperf"
+#line 2348 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3978, 0},
-#line 3837 "effective_tld_names.gperf"
+#line 4253 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3979, 0},
-#line 4062 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3980, 4},
-#line 478 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3981, 1},
-#line 1517 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str3982, 4},
-#line 1770 "effective_tld_names.gperf"
+#line 4431 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3980, 0},
+#line 4524 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3981, 0},
+#line 4625 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str3982, 0},
+#line 4553 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3983, 0},
-#line 1222 "effective_tld_names.gperf"
+#line 4093 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3984, 0},
-#line 919 "effective_tld_names.gperf"
+#line 6251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3985, 0},
-#line 812 "effective_tld_names.gperf"
+#line 1153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3986, 0},
-#line 6065 "effective_tld_names.gperf"
+#line 550 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3987, 0},
-#line 415 "effective_tld_names.gperf"
+#line 5221 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3988, 0},
-#line 1772 "effective_tld_names.gperf"
+#line 4189 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3989, 0},
-#line 1224 "effective_tld_names.gperf"
+#line 2349 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3990, 0},
-#line 1551 "effective_tld_names.gperf"
+#line 4564 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3991, 0},
-#line 921 "effective_tld_names.gperf"
+#line 4765 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3992, 0},
-#line 3438 "effective_tld_names.gperf"
+#line 112 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3993, 0},
-#line 4355 "effective_tld_names.gperf"
+#line 4293 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3994, 0},
-#line 4400 "effective_tld_names.gperf"
+#line 1450 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3995, 0},
-#line 1771 "effective_tld_names.gperf"
+#line 5082 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3996, 0},
-#line 1223 "effective_tld_names.gperf"
+#line 4772 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3997, 0},
-#line 4227 "effective_tld_names.gperf"
+#line 4952 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3998, 0},
-#line 2635 "effective_tld_names.gperf"
+#line 4583 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str3999, 0},
-#line 920 "effective_tld_names.gperf"
+#line 4415 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4000, 0},
-#line 172 "effective_tld_names.gperf"
+#line 2263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4001, 0},
-#line 6075 "effective_tld_names.gperf"
+#line 3481 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4002, 0},
-#line 4405 "effective_tld_names.gperf"
+#line 5703 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4003, 0},
-#line 6056 "effective_tld_names.gperf"
+#line 6173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4004, 0},
-#line 1559 "effective_tld_names.gperf"
+#line 2528 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4005, 0},
-#line 3339 "effective_tld_names.gperf"
+#line 4087 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4006, 0},
-#line 1775 "effective_tld_names.gperf"
+#line 5973 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4007, 0},
-#line 3073 "effective_tld_names.gperf"
+#line 4812 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4008, 0},
-#line 1452 "effective_tld_names.gperf"
+#line 5161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4009, 0},
-#line 3299 "effective_tld_names.gperf"
+#line 5436 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4010, 0},
-#line 2637 "effective_tld_names.gperf"
+#line 2039 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4011, 0},
-#line 1871 "effective_tld_names.gperf"
+#line 4582 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4012, 0},
-#line 5046 "effective_tld_names.gperf"
+#line 5963 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4013, 0},
-#line 1774 "effective_tld_names.gperf"
+#line 4613 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4014, 0},
-#line 1226 "effective_tld_names.gperf"
+#line 5511 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4015, 0},
-#line 3494 "effective_tld_names.gperf"
+#line 5398 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4016, 0},
-#line 2426 "effective_tld_names.gperf"
+#line 5593 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4017, 0},
-#line 923 "effective_tld_names.gperf"
+#line 2265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4018, 0},
-#line 3534 "effective_tld_names.gperf"
+#line 4943 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4019, 0},
-#line 834 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4020, 4},
-#line 4843 "effective_tld_names.gperf"
+#line 4218 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4020, 0},
+#line 434 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4021, 0},
-#line 5152 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4022, 0},
-#line 1112 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4023, 4},
-#line 3099 "effective_tld_names.gperf"
+#line 2894 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4022, 2},
+#line 4818 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4023, 0},
+#line 759 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4024, 0},
-#line 4057 "effective_tld_names.gperf"
+#line 4527 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4025, 0},
-#line 234 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4026, 0},
-#line 2514 "effective_tld_names.gperf"
+#line 2033 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4026, 4},
+#line 5304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4027, 0},
-#line 693 "effective_tld_names.gperf"
+#line 284 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4028, 0},
-#line 5491 "effective_tld_names.gperf"
+#line 4471 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4029, 0},
-#line 1323 "effective_tld_names.gperf"
+#line 3009 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4030, 0},
-#line 5478 "effective_tld_names.gperf"
+#line 2270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4031, 0},
-#line 832 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4032, 4},
-#line 3266 "effective_tld_names.gperf"
+#line 5656 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4032, 0},
+#line 6264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4033, 0},
-#line 3833 "effective_tld_names.gperf"
+#line 2924 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4034, 0},
-#line 2024 "effective_tld_names.gperf"
+#line 5830 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4035, 0},
-#line 4966 "effective_tld_names.gperf"
+#line 5846 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4036, 0},
-#line 1934 "effective_tld_names.gperf"
+#line 4966 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4037, 0},
-#line 1926 "effective_tld_names.gperf"
+#line 2014 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4038, 0},
-#line 5293 "effective_tld_names.gperf"
+#line 5128 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4039, 0},
-#line 3022 "effective_tld_names.gperf"
+#line 3686 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4040, 0},
-#line 29 "effective_tld_names.gperf"
+#line 4463 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4041, 0},
-#line 4009 "effective_tld_names.gperf"
+#line 5804 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4042, 0},
-#line 985 "effective_tld_names.gperf"
+#line 5545 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4043, 0},
-#line 287 "effective_tld_names.gperf"
+#line 4152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4044, 0},
-#line 663 "effective_tld_names.gperf"
+#line 5845 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4045, 0},
-#line 5183 "effective_tld_names.gperf"
+#line 6073 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4046, 0},
-#line 5604 "effective_tld_names.gperf"
+#line 3936 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4047, 0},
-#line 1627 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4048, 4},
-#line 6069 "effective_tld_names.gperf"
+#line 5213 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4048, 0},
+#line 6092 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4049, 0},
-#line 5507 "effective_tld_names.gperf"
+#line 2054 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4050, 0},
-#line 1767 "effective_tld_names.gperf"
+#line 6233 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4051, 0},
-#line 1219 "effective_tld_names.gperf"
+#line 4942 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4052, 0},
-#line 1903 "effective_tld_names.gperf"
+#line 5537 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4053, 0},
-#line 643 "effective_tld_names.gperf"
+#line 3066 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4054, 0},
-#line 916 "effective_tld_names.gperf"
+#line 5541 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4055, 0},
-#line 3955 "effective_tld_names.gperf"
+#line 5998 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4056, 0},
-#line 3451 "effective_tld_names.gperf"
+#line 4638 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4057, 0},
-#line 5266 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4058, 0},
-#line 3907 "effective_tld_names.gperf"
+#line 4945 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4058, 4},
+#line 3877 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4059, 0},
-#line 4470 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4060, 4},
-#line 3389 "effective_tld_names.gperf"
+#line 1062 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4060, 0},
+#line 6243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4061, 0},
-#line 3129 "effective_tld_names.gperf"
+#line 5147 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4062, 0},
-#line 4962 "effective_tld_names.gperf"
+#line 4612 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4063, 0},
-#line 4711 "effective_tld_names.gperf"
+#line 1114 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4064, 0},
-#line 2430 "effective_tld_names.gperf"
+#line 4956 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4065, 0},
-#line 32 "effective_tld_names.gperf"
+#line 6149 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4066, 0},
-#line 5012 "effective_tld_names.gperf"
+#line 5844 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4067, 0},
-#line 5629 "effective_tld_names.gperf"
+#line 3760 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4068, 0},
-#line 726 "effective_tld_names.gperf"
+#line 3368 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4069, 0},
-#line 1102 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4070, 4},
-#line 4143 "effective_tld_names.gperf"
+#line 5609 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4070, 0},
+#line 4826 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4071, 0},
-#line 2817 "effective_tld_names.gperf"
+#line 5586 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4072, 0},
-#line 4100 "effective_tld_names.gperf"
+#line 3750 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4073, 0},
-#line 2911 "effective_tld_names.gperf"
+#line 5801 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4074, 0},
-#line 982 "effective_tld_names.gperf"
+#line 99 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4075, 0},
-#line 3304 "effective_tld_names.gperf"
+#line 6227 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4076, 0},
-#line 3447 "effective_tld_names.gperf"
+#line 447 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4077, 0},
-#line 2890 "effective_tld_names.gperf"
+#line 5621 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4078, 0},
-#line 1850 "effective_tld_names.gperf"
+#line 1474 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4079, 0},
-#line 3264 "effective_tld_names.gperf"
+#line 2838 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4080, 0},
-#line 288 "effective_tld_names.gperf"
+#line 4635 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4081, 0},
-#line 5036 "effective_tld_names.gperf"
+#line 3842 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4082, 0},
-#line 4661 "effective_tld_names.gperf"
+#line 4805 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4083, 0},
-#line 1984 "effective_tld_names.gperf"
+#line 3791 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4084, 0},
-#line 3845 "effective_tld_names.gperf"
+#line 4682 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4085, 0},
-#line 2390 "effective_tld_names.gperf"
+#line 5543 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4086, 0},
-#line 5023 "effective_tld_names.gperf"
+#line 5021 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4087, 0},
-#line 4602 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4088, 4},
-#line 2952 "effective_tld_names.gperf"
+#line 3069 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4088, 0},
+#line 5184 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4089, 0},
-#line 5137 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4090, 0},
-#line 6042 "effective_tld_names.gperf"
+#line 2442 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4090, 4},
+#line 5807 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4091, 0},
-#line 69 "effective_tld_names.gperf"
+#line 3915 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4092, 0},
-#line 4350 "effective_tld_names.gperf"
+#line 6168 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4093, 0},
-#line 4258 "effective_tld_names.gperf"
+#line 2624 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4094, 0},
-#line 740 "effective_tld_names.gperf"
+#line 6079 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4095, 0},
-#line 2366 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4096, 4},
-#line 5473 "effective_tld_names.gperf"
+#line 5484 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4096, 0},
+#line 3946 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4097, 0},
-#line 4146 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4098, 0},
-#line 145 "effective_tld_names.gperf"
+#line 4806 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4098, 4},
+#line 2774 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4099, 0},
-#line 589 "effective_tld_names.gperf"
+#line 3858 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4100, 0},
-#line 2759 "effective_tld_names.gperf"
+#line 4807 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4101, 0},
-#line 4660 "effective_tld_names.gperf"
+#line 6074 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4102, 0},
-#line 2978 "effective_tld_names.gperf"
+#line 6214 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4103, 0},
-#line 482 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4104, 4},
-#line 4145 "effective_tld_names.gperf"
+#line 4904 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4104, 0},
+#line 5394 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4105, 0},
-#line 3231 "effective_tld_names.gperf"
+#line 4547 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4106, 0},
-#line 4993 "effective_tld_names.gperf"
+#line 4235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4107, 0},
-#line 1955 "effective_tld_names.gperf"
+#line 1857 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4108, 0},
-#line 4144 "effective_tld_names.gperf"
+#line 1279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4109, 0},
-#line 394 "effective_tld_names.gperf"
+#line 6133 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4110, 0},
-#line 4029 "effective_tld_names.gperf"
+#line 949 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4111, 0},
-#line 5148 "effective_tld_names.gperf"
+#line 422 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4112, 0},
-#line 4549 "effective_tld_names.gperf"
+#line 5535 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4113, 0},
-#line 4810 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4114, 4},
-#line 4399 "effective_tld_names.gperf"
+#line 2734 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4114, 0},
+#line 6189 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4115, 0},
-#line 4801 "effective_tld_names.gperf"
+#line 5009 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4116, 0},
-#line 5188 "effective_tld_names.gperf"
+#line 3024 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4117, 0},
-#line 4087 "effective_tld_names.gperf"
+#line 4743 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4118, 0},
-#line 980 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4119, 0},
-#line 2166 "effective_tld_names.gperf"
+#line 2498 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4119, 4},
+#line 3751 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4120, 0},
-#line 1051 "effective_tld_names.gperf"
+#line 5847 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4121, 0},
-#line 3453 "effective_tld_names.gperf"
+#line 3873 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4122, 0},
-#line 5291 "effective_tld_names.gperf"
+#line 4391 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4123, 0},
-#line 1981 "effective_tld_names.gperf"
+#line 3604 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4124, 0},
-#line 2656 "effective_tld_names.gperf"
+#line 4141 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4125, 0},
-#line 4710 "effective_tld_names.gperf"
+#line 5143 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4126, 0},
-#line 5289 "effective_tld_names.gperf"
+#line 2128 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4127, 0},
-#line 1836 "effective_tld_names.gperf"
+#line 4847 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4128, 0},
-#line 2462 "effective_tld_names.gperf"
+#line 5671 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4129, 0},
-#line 2182 "effective_tld_names.gperf"
+#line 4736 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4130, 0},
-#line 1994 "effective_tld_names.gperf"
+#line 6276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4131, 0},
-#line 981 "effective_tld_names.gperf"
+#line 282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4132, 0},
-#line 4028 "effective_tld_names.gperf"
+#line 5514 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4133, 0},
-#line 6044 "effective_tld_names.gperf"
+#line 4676 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4134, 0},
-#line 1082 "effective_tld_names.gperf"
+#line 3967 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4135, 0},
-#line 1162 "effective_tld_names.gperf"
+#line 2502 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4136, 0},
-#line 5469 "effective_tld_names.gperf"
+#line 5401 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4137, 0},
-#line 352 "effective_tld_names.gperf"
+#line 4496 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4138, 0},
-#line 4348 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4139, 0},
-#line 5347 "effective_tld_names.gperf"
+#line 5731 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4139, 4},
+#line 6037 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4140, 0},
-#line 174 "effective_tld_names.gperf"
+#line 4165 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4141, 0},
-#line 5209 "effective_tld_names.gperf"
+#line 4999 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4142, 0},
-#line 5327 "effective_tld_names.gperf"
+#line 2764 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4143, 0},
-#line 2055 "effective_tld_names.gperf"
+#line 4470 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4144, 0},
-#line 2341 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4145, 4},
-#line 2585 "effective_tld_names.gperf"
+#line 4714 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4145, 0},
+#line 4395 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4146, 0},
-#line 989 "effective_tld_names.gperf"
+#line 5424 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4147, 1},
-#line 2236 "effective_tld_names.gperf"
+#line 768 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4148, 0},
-#line 4921 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4149, 4},
-#line 1859 "effective_tld_names.gperf"
+#line 5538 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4149, 0},
+#line 3885 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4150, 0},
-#line 5520 "effective_tld_names.gperf"
+#line 5524 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4151, 0},
-#line 5368 "effective_tld_names.gperf"
+#line 4535 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4152, 0},
-#line 4496 "effective_tld_names.gperf"
+#line 5489 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4153, 0},
-#line 2054 "effective_tld_names.gperf"
+#line 3520 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4154, 0},
-#line 4522 "effective_tld_names.gperf"
+#line 5002 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4155, 0},
-#line 2516 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4156, 0},
-#line 1935 "effective_tld_names.gperf"
+#line 1609 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4156, 4},
+#line 4617 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4157, 0},
-#line 2247 "effective_tld_names.gperf"
+#line 5431 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4158, 0},
-#line 45 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4159, 0},
-#line 4844 "effective_tld_names.gperf"
+#line 1587 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4159, 4},
+#line 4905 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4160, 0},
-#line 1242 "effective_tld_names.gperf"
+#line 133 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4161, 0},
-#line 1794 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4162, 0},
-#line 3024 "effective_tld_names.gperf"
+#line 4103 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4162, 4},
+#line 4101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4163, 0},
-#line 1245 "effective_tld_names.gperf"
+#line 4758 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4164, 0},
-#line 940 "effective_tld_names.gperf"
+#line 5086 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4165, 0},
-#line 2237 "effective_tld_names.gperf"
+#line 1172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4166, 4},
-#line 943 "effective_tld_names.gperf"
+#line 4735 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4167, 0},
-#line 1747 "effective_tld_names.gperf"
+#line 6163 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4168, 0},
-#line 1200 "effective_tld_names.gperf"
+#line 5320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4169, 0},
-#line 595 "effective_tld_names.gperf"
+#line 77 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4170, 0},
-#line 2213 "effective_tld_names.gperf"
+#line 6223 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4171, 0},
-#line 1750 "effective_tld_names.gperf"
+#line 6345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4172, 0},
-#line 4015 "effective_tld_names.gperf"
+#line 5995 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4173, 0},
-#line 897 "effective_tld_names.gperf"
+#line 6088 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4174, 0},
-#line 1202 "effective_tld_names.gperf"
+#line 4744 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4175, 0},
-#line 814 "effective_tld_names.gperf"
+#line 5513 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4176, 0},
-#line 1748 "effective_tld_names.gperf"
+#line 5492 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4177, 0},
-#line 2129 "effective_tld_names.gperf"
+#line 4915 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4178, 0},
-#line 899 "effective_tld_names.gperf"
+#line 5491 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4179, 0},
-#line 3584 "effective_tld_names.gperf"
+#line 4654 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4180, 0},
-#line 1241 "effective_tld_names.gperf"
+#line 4759 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4181, 0},
-#line 5972 "effective_tld_names.gperf"
+#line 5426 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4182, 0},
-#line 696 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4183, 4},
-#line 939 "effective_tld_names.gperf"
+#line 4920 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4183, 2},
+#line 4740 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4184, 0},
-#line 1798 "effective_tld_names.gperf"
+#line 4058 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4185, 0},
-#line 1249 "effective_tld_names.gperf"
+#line 558 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4186, 0},
-#line 946 "effective_tld_names.gperf"
+#line 3871 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4187, 0},
-#line 3344 "effective_tld_names.gperf"
+#line 2531 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4188, 0},
-#line 2142 "effective_tld_names.gperf"
+#line 5987 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4189, 0},
-#line 1671 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4190, 0},
-#line 5093 "effective_tld_names.gperf"
+#line 2463 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4190, 4},
+#line 2314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4191, 0},
-#line 4629 "effective_tld_names.gperf"
+#line 6040 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4192, 0},
-#line 847 "effective_tld_names.gperf"
+#line 4739 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4193, 0},
-#line 3581 "effective_tld_names.gperf"
+#line 4919 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4194, 0},
-#line 747 "effective_tld_names.gperf"
+#line 5099 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4195, 0},
-#line 3794 "effective_tld_names.gperf"
+#line 3741 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4196, 0},
-#line 3463 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4197, 0},
-#line 1698 "effective_tld_names.gperf"
+#line 1580 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4197, 4},
+#line 1125 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4198, 0},
-#line 2106 "effective_tld_names.gperf"
+#line 5526 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4199, 0},
-#line 2092 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4200, 4},
-#line 5197 "effective_tld_names.gperf"
+#line 4913 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4200, 0},
+#line 3582 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4201, 0},
-#line 2303 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4202, 4},
-#line 4251 "effective_tld_names.gperf"
+#line 5581 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4202, 0},
+#line 4706 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4203, 0},
-#line 3478 "effective_tld_names.gperf"
+#line 6342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4204, 0},
-#line 2233 "effective_tld_names.gperf"
+#line 4918 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4205, 0},
-#line 1995 "effective_tld_names.gperf"
+#line 5326 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4206, 0},
-#line 4486 "effective_tld_names.gperf"
+#line 2195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4207, 0},
-#line 295 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4208, 0},
-#line 1693 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4209, 4},
-#line 2256 "effective_tld_names.gperf"
+#line 2917 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4208, 4},
+#line 5391 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4209, 0},
+#line 2783 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4210, 0},
-#line 1271 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4211, 0},
-#line 2257 "effective_tld_names.gperf"
+#line 2443 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4211, 4},
+#line 5578 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4212, 0},
-#line 973 "effective_tld_names.gperf"
+#line 4914 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4213, 0},
-#line 1096 "effective_tld_names.gperf"
+#line 2206 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4214, 4},
-#line 3502 "effective_tld_names.gperf"
+#line 5388 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4215, 0},
-#line 1907 "effective_tld_names.gperf"
+#line 5645 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4216, 0},
-#line 3432 "effective_tld_names.gperf"
+#line 3816 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4217, 0},
-#line 1799 "effective_tld_names.gperf"
+#line 898 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4218, 0},
-#line 5701 "effective_tld_names.gperf"
+#line 4912 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4219, 0},
-#line 1250 "effective_tld_names.gperf"
+#line 4516 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4220, 0},
-#line 947 "effective_tld_names.gperf"
+#line 4667 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4221, 0},
-#line 5727 "effective_tld_names.gperf"
+#line 556 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4222, 0},
-#line 2309 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4223, 4},
-#line 2195 "effective_tld_names.gperf"
+#line 5117 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4223, 0},
+#line 2690 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4224, 0},
-#line 1206 "effective_tld_names.gperf"
+#line 5994 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4225, 0},
-#line 2322 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4226, 4},
-#line 2250 "effective_tld_names.gperf"
+#line 6310 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4226, 0},
+#line 5536 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4227, 0},
-#line 903 "effective_tld_names.gperf"
+#line 4958 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4228, 0},
-#line 5264 "effective_tld_names.gperf"
+#line 5654 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4229, 0},
-#line 2240 "effective_tld_names.gperf"
+#line 3781 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4230, 0},
-#line 1797 "effective_tld_names.gperf"
+#line 5979 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4231, 0},
-#line 1796 "effective_tld_names.gperf"
+#line 5438 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4232, 0},
-#line 1804 "effective_tld_names.gperf"
+#line 2134 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4233, 0},
-#line 1248 "effective_tld_names.gperf"
+#line 3282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4234, 0},
-#line 2234 "effective_tld_names.gperf"
+#line 6211 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4235, 0},
-#line 1247 "effective_tld_names.gperf"
+#line 5860 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4236, 0},
-#line 1255 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4237, 0},
-#line 628 "effective_tld_names.gperf"
+#line 1219 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4237, 4},
+#line 5404 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4238, 0},
-#line 945 "effective_tld_names.gperf"
+#line 4162 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4239, 0},
-#line 4889 "effective_tld_names.gperf"
+#line 5521 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4240, 0},
-#line 953 "effective_tld_names.gperf"
+#line 5508 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4241, 0},
-#line 1752 "effective_tld_names.gperf"
+#line 161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4242, 0},
-#line 1751 "effective_tld_names.gperf"
+#line 1383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4243, 0},
-#line 1205 "effective_tld_names.gperf"
+#line 6038 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4244, 0},
-#line 1203 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4245, 0},
-#line 36 "effective_tld_names.gperf"
+#line 501 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4245, 4},
+#line 4911 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4246, 0},
-#line 902 "effective_tld_names.gperf"
+#line 4655 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4247, 0},
-#line 900 "effective_tld_names.gperf"
+#line 798 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4248, 0},
-#line 1137 "effective_tld_names.gperf"
+#line 2421 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4249, 4},
-#line 4279 "effective_tld_names.gperf"
+#line 5243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4250, 0},
-#line 1690 "effective_tld_names.gperf"
+#line 4029 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4251, 0},
-#line 1038 "effective_tld_names.gperf"
+#line 4124 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4252, 0},
-#line 2424 "effective_tld_names.gperf"
+#line 5100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4253, 0},
-#line 3098 "effective_tld_names.gperf"
+#line 6313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4254, 0},
-#line 4090 "effective_tld_names.gperf"
+#line 4925 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4255, 0},
-#line 343 "effective_tld_names.gperf"
+#line 6254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4256, 0},
-#line 1795 "effective_tld_names.gperf"
+#line 4707 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4257, 0},
-#line 3719 "effective_tld_names.gperf"
+#line 3332 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4258, 0},
-#line 275 "effective_tld_names.gperf"
+#line 1473 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4259, 0},
-#line 1246 "effective_tld_names.gperf"
+#line 6258 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4260, 0},
-#line 131 "effective_tld_names.gperf"
+#line 6308 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4261, 0},
-#line 2238 "effective_tld_names.gperf"
+#line 5638 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4262, 0},
-#line 3448 "effective_tld_names.gperf"
+#line 4834 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4263, 0},
-#line 944 "effective_tld_names.gperf"
+#line 1384 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4264, 0},
-#line 4340 "effective_tld_names.gperf"
+#line 5894 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4265, 0},
-#line 3214 "effective_tld_names.gperf"
+#line 4856 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4266, 0},
-#line 4655 "effective_tld_names.gperf"
+#line 2127 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4267, 0},
-#line 4086 "effective_tld_names.gperf"
+#line 5540 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4268, 0},
-#line 732 "effective_tld_names.gperf"
+#line 586 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4269, 0},
-#line 2347 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4270, 4},
-#line 656 "effective_tld_names.gperf"
+#line 4149 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4270, 0},
+#line 6165 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4271, 0},
-#line 3574 "effective_tld_names.gperf"
+#line 6324 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4272, 0},
-#line 2319 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4273, 4},
-#line 3083 "effective_tld_names.gperf"
+#line 4726 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4273, 0},
+#line 6035 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4274, 0},
-#line 768 "effective_tld_names.gperf"
+#line 5635 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4275, 0},
-#line 4574 "effective_tld_names.gperf"
+#line 5155 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4276, 0},
-#line 2255 "effective_tld_names.gperf"
+#line 5323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4277, 0},
-#line 2111 "effective_tld_names.gperf"
+#line 5210 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4278, 0},
-#line 2034 "effective_tld_names.gperf"
+#line 5208 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4279, 0},
-#line 324 "effective_tld_names.gperf"
+#line 4618 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4280, 0},
-#line 442 "effective_tld_names.gperf"
+#line 2084 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4281, 0},
-#line 4947 "effective_tld_names.gperf"
+#line 1543 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4282, 0},
-#line 2183 "effective_tld_names.gperf"
+#line 2224 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4283, 0},
-#line 1875 "effective_tld_names.gperf"
+#line 2174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4284, 0},
-#line 4995 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4285, 0},
-#line 1342 "effective_tld_names.gperf"
+#line 5576 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4285, 4},
+#line 4450 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4286, 0},
-#line 3248 "effective_tld_names.gperf"
+#line 5051 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4287, 0},
-#line 252 "effective_tld_names.gperf"
+#line 4369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4288, 0},
-#line 1681 "effective_tld_names.gperf"
+#line 6126 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4289, 0},
-#line 4805 "effective_tld_names.gperf"
+#line 3688 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4290, 0},
-#line 1682 "effective_tld_names.gperf"
+#line 5655 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4291, 0},
-#line 2349 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4292, 4},
-#line 3269 "effective_tld_names.gperf"
+#line 3021 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4292, 0},
+#line 340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4293, 0},
-#line 2248 "effective_tld_names.gperf"
+#line 4324 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4294, 0},
-#line 5726 "effective_tld_names.gperf"
+#line 5185 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4295, 0},
-#line 3252 "effective_tld_names.gperf"
+#line 1462 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4296, 0},
-#line 128 "effective_tld_names.gperf"
+#line 4672 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4297, 0},
-#line 4316 "effective_tld_names.gperf"
+#line 4379 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4298, 0},
-#line 2249 "effective_tld_names.gperf"
+#line 2339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4299, 0},
-#line 4608 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4300, 4},
-#line 1680 "effective_tld_names.gperf"
+#line 5481 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4300, 0},
+#line 1566 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4301, 0},
-#line 3721 "effective_tld_names.gperf"
+#line 5582 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4302, 0},
-#line 3333 "effective_tld_names.gperf"
+#line 1150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4303, 0},
-#line 692 "effective_tld_names.gperf"
+#line 2700 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4304, 0},
-#line 35 "effective_tld_names.gperf"
+#line 3776 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4305, 0},
-#line 3998 "effective_tld_names.gperf"
+#line 5103 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4306, 0},
-#line 3342 "effective_tld_names.gperf"
+#line 5065 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4307, 0},
-#line 1788 "effective_tld_names.gperf"
+#line 3398 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4308, 0},
-#line 4362 "effective_tld_names.gperf"
+#line 1120 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4309, 0},
-#line 2246 "effective_tld_names.gperf"
+#line 5408 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4310, 0},
-#line 1236 "effective_tld_names.gperf"
+#line 6327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4311, 0},
-#line 1694 "effective_tld_names.gperf"
+#line 3824 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4312, 0},
-#line 2171 "effective_tld_names.gperf"
+#line 2172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4313, 0},
-#line 932 "effective_tld_names.gperf"
+#line 5674 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4314, 0},
-#line 3720 "effective_tld_names.gperf"
+#line 2722 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4315, 0},
-#line 2242 "effective_tld_names.gperf"
+#line 136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4316, 0},
-#line 804 "effective_tld_names.gperf"
+#line 3004 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4317, 0},
-#line 1131 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4318, 4},
-#line 114 "effective_tld_names.gperf"
+#line 4708 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4318, 0},
+#line 1725 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4319, 0},
-#line 6084 "effective_tld_names.gperf"
+#line 3717 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4320, 0},
-#line 3215 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4321, 0},
-#line 1687 "effective_tld_names.gperf"
+#line 4961 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4321, 4},
+#line 4193 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4322, 0},
-#line 1927 "effective_tld_names.gperf"
+#line 3691 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4323, 0},
-#line 4717 "effective_tld_names.gperf"
+#line 3687 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4324, 0},
-#line 50 "effective_tld_names.gperf"
+#line 1978 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4325, 0},
-#line 1879 "effective_tld_names.gperf"
+#line 1971 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4326, 0},
-#line 48 "effective_tld_names.gperf"
+#line 1967 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4327, 0},
-#line 2845 "effective_tld_names.gperf"
+#line 5414 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4328, 0},
-#line 2210 "effective_tld_names.gperf"
+#line 3980 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4329, 0},
-#line 43 "effective_tld_names.gperf"
+#line 5275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4330, 0},
-#line 2421 "effective_tld_names.gperf"
+#line 1968 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4331, 0},
-#line 4758 "effective_tld_names.gperf"
+#line 1973 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4332, 0},
-#line 1928 "effective_tld_names.gperf"
+#line 3769 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4333, 0},
-#line 3909 "effective_tld_names.gperf"
+#line 5632 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4334, 0},
-#line 674 "effective_tld_names.gperf"
+#line 2589 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4335, 0},
-#line 4927 "effective_tld_names.gperf"
+#line 2591 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4336, 0},
-#line 1463 "effective_tld_names.gperf"
+#line 4337 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4337, 0},
-#line 4398 "effective_tld_names.gperf"
+#line 4820 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4338, 0},
-#line 782 "effective_tld_names.gperf"
+#line 4810 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4339, 0},
-#line 2831 "effective_tld_names.gperf"
+#line 1975 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4340, 0},
-#line 1365 "effective_tld_names.gperf"
+#line 1917 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4341, 0},
-#line 1677 "effective_tld_names.gperf"
+#line 3862 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4342, 0},
-#line 4880 "effective_tld_names.gperf"
+#line 1341 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4343, 0},
-#line 465 "effective_tld_names.gperf"
+#line 1820 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4344, 0},
-#line 1303 "effective_tld_names.gperf"
+#line 1015 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4345, 0},
-#line 3336 "effective_tld_names.gperf"
+#line 1819 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4346, 0},
-#line 397 "effective_tld_names.gperf"
+#line 5834 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4347, 0},
-#line 2983 "effective_tld_names.gperf"
+#line 1879 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4348, 0},
-#line 3066 "effective_tld_names.gperf"
+#line 6103 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4349, 0},
-#line 4064 "effective_tld_names.gperf"
+#line 5197 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4350, 0},
-#line 185 "effective_tld_names.gperf"
+#line 1969 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4351, 0},
-#line 2038 "effective_tld_names.gperf"
+#line 6269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4352, 0},
-#line 4510 "effective_tld_names.gperf"
+#line 3942 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4353, 0},
-#line 1612 "effective_tld_names.gperf"
+#line 1815 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4354, 0},
-#line 3345 "effective_tld_names.gperf"
+#line 2564 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4355, 0},
-#line 742 "effective_tld_names.gperf"
+#line 619 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4356, 0},
-#line 6076 "effective_tld_names.gperf"
+#line 4938 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4357, 0},
-#line 4876 "effective_tld_names.gperf"
+#line 5222 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4358, 0},
-#line 3240 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4359, 4},
-#line 2178 "effective_tld_names.gperf"
+#line 2267 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4359, 0},
+#line 6101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4360, 0},
-#line 5653 "effective_tld_names.gperf"
+#line 4808 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4361, 0},
-#line 222 "effective_tld_names.gperf"
+#line 5292 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4362, 0},
-#line 5973 "effective_tld_names.gperf"
+#line 2570 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4363, 0},
-#line 5247 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4364, 4},
-#line 1046 "effective_tld_names.gperf"
+#line 5141 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4364, 0},
+#line 1124 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4365, 0},
-#line 3306 "effective_tld_names.gperf"
+#line 4703 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4366, 0},
-#line 3289 "effective_tld_names.gperf"
+#line 5494 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4367, 0},
-#line 4518 "effective_tld_names.gperf"
+#line 2716 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4368, 0},
-#line 2180 "effective_tld_names.gperf"
+#line 5169 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4369, 0},
-#line 103 "effective_tld_names.gperf"
+#line 1925 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4370, 0},
-#line 5305 "effective_tld_names.gperf"
+#line 2377 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4371, 0},
-#line 4069 "effective_tld_names.gperf"
+#line 1347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4372, 0},
-#line 2100 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4373, 4},
-#line 4349 "effective_tld_names.gperf"
+#line 4352 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4373, 0},
+#line 216 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4374, 0},
-#line 57 "effective_tld_names.gperf"
+#line 1022 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4375, 0},
-#line 5519 "effective_tld_names.gperf"
+#line 2535 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4376, 0},
-#line 1618 "effective_tld_names.gperf"
+#line 5969 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4377, 0},
-#line 3551 "effective_tld_names.gperf"
+#line 1821 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4378, 0},
-#line 4285 "effective_tld_names.gperf"
+#line 4502 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4379, 0},
-#line 5043 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4380, 0},
-#line 714 "effective_tld_names.gperf"
+#line 2189 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4380, 4},
+#line 5407 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4381, 0},
-#line 1094 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4382, 4},
-#line 3590 "effective_tld_names.gperf"
+#line 1838 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4382, 0},
+#line 2598 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4383, 0},
-#line 1704 "effective_tld_names.gperf"
+#line 5425 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4384, 0},
-#line 3824 "effective_tld_names.gperf"
+#line 1262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4385, 0},
-#line 1460 "effective_tld_names.gperf"
+#line 5266 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4386, 0},
-#line 3851 "effective_tld_names.gperf"
+#line 929 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4387, 0},
-#line 46 "effective_tld_names.gperf"
+#line 5010 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4388, 0},
-#line 5728 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4389, 0},
-#line 467 "effective_tld_names.gperf"
+#line 2578 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4389, 1},
+#line 3854 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4390, 0},
-#line 5605 "effective_tld_names.gperf"
+#line 5457 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4391, 0},
-#line 5022 "effective_tld_names.gperf"
+#line 4924 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4392, 0},
-#line 5512 "effective_tld_names.gperf"
+#line 1865 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4393, 0},
-#line 2830 "effective_tld_names.gperf"
+#line 2279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4394, 0},
-#line 1947 "effective_tld_names.gperf"
+#line 1289 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4395, 0},
-#line 3979 "effective_tld_names.gperf"
+#line 1977 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4396, 0},
-#line 3195 "effective_tld_names.gperf"
+#line 2401 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4397, 0},
-#line 3321 "effective_tld_names.gperf"
+#line 2110 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4398, 0},
-#line 1949 "effective_tld_names.gperf"
+#line 4529 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4399, 0},
-#line 4853 "effective_tld_names.gperf"
+#line 2406 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4400, 0},
-#line 754 "effective_tld_names.gperf"
+#line 4011 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4401, 0},
-#line 4799 "effective_tld_names.gperf"
+#line 2375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4402, 0},
-#line 466 "effective_tld_names.gperf"
+#line 5695 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4403, 0},
-#line 3291 "effective_tld_names.gperf"
+#line 5043 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4404, 0},
-#line 2399 "effective_tld_names.gperf"
+#line 5592 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4405, 0},
-#line 4985 "effective_tld_names.gperf"
+#line 367 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4406, 0},
-#line 1440 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4407, 4},
-#line 3628 "effective_tld_names.gperf"
+#line 2615 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4407, 0},
+#line 1959 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4408, 0},
-#line 3312 "effective_tld_names.gperf"
+#line 4871 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4409, 0},
-#line 2351 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4410, 4},
-#line 1692 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4411, 4},
-#line 4457 "effective_tld_names.gperf"
+#line 6104 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4410, 0},
+#line 2588 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4411, 2},
+#line 4517 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4412, 0},
-#line 2101 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4413, 4},
-#line 1243 "effective_tld_names.gperf"
+#line 1311 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4413, 0},
+#line 980 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4414, 0},
-#line 4020 "effective_tld_names.gperf"
+#line 6102 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4415, 0},
-#line 2694 "effective_tld_names.gperf"
+#line 1963 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4416, 0},
-#line 941 "effective_tld_names.gperf"
+#line 5246 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4417, 0},
-#line 3144 "effective_tld_names.gperf"
+#line 765 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4418, 0},
-#line 2536 "effective_tld_names.gperf"
+#line 2173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4419, 0},
-#line 5414 "effective_tld_names.gperf"
+#line 1359 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4420, 0},
-#line 3308 "effective_tld_names.gperf"
+#line 5382 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4421, 0},
-#line 2241 "effective_tld_names.gperf"
+#line 4691 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4422, 0},
-#line 1095 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4423, 4},
-#line 2508 "effective_tld_names.gperf"
+#line 1814 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4423, 0},
+#line 5178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4424, 0},
-#line 3599 "effective_tld_names.gperf"
+#line 1961 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4425, 0},
-#line 6063 "effective_tld_names.gperf"
+#line 1964 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4426, 0},
-#line 3817 "effective_tld_names.gperf"
+#line 3524 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4427, 0},
-#line 5103 "effective_tld_names.gperf"
+#line 4511 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4428, 0},
-#line 5182 "effective_tld_names.gperf"
+#line 3845 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4429, 0},
-#line 3882 "effective_tld_names.gperf"
+#line 2106 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4430, 0},
-#line 5295 "effective_tld_names.gperf"
+#line 38 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4431, 0},
-#line 2579 "effective_tld_names.gperf"
+#line 6286 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4432, 0},
-#line 3044 "effective_tld_names.gperf"
+#line 5449 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4433, 0},
-#line 620 "effective_tld_names.gperf"
+#line 5486 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4434, 0},
-#line 3015 "effective_tld_names.gperf"
+#line 2606 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4435, 0},
-#line 4004 "effective_tld_names.gperf"
+#line 3972 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4436, 0},
-#line 5108 "effective_tld_names.gperf"
+#line 4689 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4437, 0},
-#line 4313 "effective_tld_names.gperf"
+#line 1696 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4438, 0},
-#line 413 "effective_tld_names.gperf"
+#line 1904 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4439, 0},
-#line 2253 "effective_tld_names.gperf"
+#line 1328 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4440, 0},
-#line 4050 "effective_tld_names.gperf"
+#line 999 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4441, 0},
-#line 463 "effective_tld_names.gperf"
+#line 5758 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4442, 0},
-#line 475 "effective_tld_names.gperf"
+#line 1818 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4443, 0},
-#line 387 "effective_tld_names.gperf"
+#line 4104 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4444, 0},
-#line 2509 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4445, 0},
-#line 5503 "effective_tld_names.gperf"
+#line 4969 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4445, 4},
+#line 837 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4446, 0},
-#line 1204 "effective_tld_names.gperf"
+#line 4209 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4447, 0},
-#line 2853 "effective_tld_names.gperf"
+#line 4315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4448, 0},
-#line 263 "effective_tld_names.gperf"
+#line 1747 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4449, 0},
-#line 901 "effective_tld_names.gperf"
+#line 6311 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4450, 0},
-#line 4070 "effective_tld_names.gperf"
+#line 2614 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4451, 0},
-#line 2254 "effective_tld_names.gperf"
+#line 6353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4452, 0},
-#line 2252 "effective_tld_names.gperf"
+#line 2397 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4453, 0},
-#line 1298 "effective_tld_names.gperf"
+#line 4690 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4454, 0},
-#line 3652 "effective_tld_names.gperf"
+#line 1960 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4455, 0},
-#line 382 "effective_tld_names.gperf"
+#line 6307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4456, 0},
-#line 3682 "effective_tld_names.gperf"
+#line 3619 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4457, 0},
-#line 455 "effective_tld_names.gperf"
+#line 2597 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4458, 0},
-#line 2537 "effective_tld_names.gperf"
+#line 1816 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4459, 0},
-#line 2140 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4460, 0},
-#line 3351 "effective_tld_names.gperf"
+#line 4505 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4460, 2},
+#line 4917 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4461, 0},
-#line 2251 "effective_tld_names.gperf"
+#line 5122 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4462, 0},
-#line 3016 "effective_tld_names.gperf"
+#line 1510 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4463, 0},
-#line 2243 "effective_tld_names.gperf"
+#line 486 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4464, 0},
-#line 276 "effective_tld_names.gperf"
+#line 5096 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4465, 0},
-#line 4058 "effective_tld_names.gperf"
+#line 6249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4466, 0},
-#line 1793 "effective_tld_names.gperf"
+#line 377 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4467, 0},
-#line 3349 "effective_tld_names.gperf"
+#line 1749 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4468, 0},
-#line 1244 "effective_tld_names.gperf"
+#line 5679 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4469, 0},
-#line 1665 "effective_tld_names.gperf"
+#line 2025 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4470, 0},
-#line 1936 "effective_tld_names.gperf"
+#line 5608 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4471, 0},
-#line 1168 "effective_tld_names.gperf"
+#line 1285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4472, 0},
-#line 942 "effective_tld_names.gperf"
+#line 957 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4473, 0},
-#line 823 "effective_tld_names.gperf"
+#line 5413 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4474, 0},
-#line 1749 "effective_tld_names.gperf"
+#line 5333 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4475, 0},
-#line 1201 "effective_tld_names.gperf"
+#line 1948 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4476, 0},
-#line 77 "effective_tld_names.gperf"
+#line 4832 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4477, 0},
-#line 2793 "effective_tld_names.gperf"
+#line 4679 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4478, 0},
-#line 202 "effective_tld_names.gperf"
+#line 1965 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4479, 0},
-#line 1078 "effective_tld_names.gperf"
+#line 1699 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4480, 0},
-#line 3045 "effective_tld_names.gperf"
+#line 5098 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4481, 0},
-#line 898 "effective_tld_names.gperf"
+#line 3458 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4482, 0},
-#line 2598 "effective_tld_names.gperf"
+#line 257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4483, 0},
-#line 5225 "effective_tld_names.gperf"
+#line 5745 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4484, 0},
-#line 1110 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4485, 4},
-#line 6058 "effective_tld_names.gperf"
+#line 4886 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4485, 0},
+#line 5182 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4486, 0},
-#line 1624 "effective_tld_names.gperf"
+#line 5670 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4487, 0},
-#line 1833 "effective_tld_names.gperf"
+#line 2067 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4488, 0},
-#line 4002 "effective_tld_names.gperf"
+#line 5520 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4489, 0},
-#line 2013 "effective_tld_names.gperf"
+#line 5534 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4490, 0},
-#line 2318 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4491, 4},
-#line 2179 "effective_tld_names.gperf"
+#line 4590 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4491, 0},
+#line 3820 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4492, 0},
-#line 1301 "effective_tld_names.gperf"
+#line 5839 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4493, 0},
-#line 4129 "effective_tld_names.gperf"
+#line 3649 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4494, 0},
-#line 4128 "effective_tld_names.gperf"
+#line 2107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4495, 0},
-#line 170 "effective_tld_names.gperf"
+#line 4989 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4496, 0},
-#line 1077 "effective_tld_names.gperf"
+#line 2350 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4497, 0},
-#line 4130 "effective_tld_names.gperf"
+#line 4421 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4498, 0},
-#line 2834 "effective_tld_names.gperf"
+#line 5525 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4499, 0},
-#line 2708 "effective_tld_names.gperf"
+#line 3774 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4500, 0},
-#line 2145 "effective_tld_names.gperf"
+#line 3703 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4501, 0},
-#line 2365 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4502, 4},
-#line 5114 "effective_tld_names.gperf"
+#line 3887 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4502, 0},
+#line 5302 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4503, 0},
-#line 4043 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4504, 0},
-#line 2245 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4505, 0},
-#line 5059 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4506, 4},
-#line 4378 "effective_tld_names.gperf"
+#line 4881 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4504, 2},
+#line 474 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4505, 4},
+#line 5016 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4506, 0},
+#line 5307 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4507, 0},
-#line 1849 "effective_tld_names.gperf"
+#line 5316 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4508, 0},
-#line 4656 "effective_tld_names.gperf"
+#line 4405 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4509, 0},
-#line 4958 "effective_tld_names.gperf"
+#line 1358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4510, 0},
-#line 2954 "effective_tld_names.gperf"
+#line 5392 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4511, 0},
-#line 5126 "effective_tld_names.gperf"
+#line 5402 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4512, 0},
-#line 1076 "effective_tld_names.gperf"
+#line 4127 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4513, 0},
-#line 781 "effective_tld_names.gperf"
+#line 5145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4514, 0},
-#line 2354 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4515, 4},
-#line 5486 "effective_tld_names.gperf"
+#line 2935 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4515, 0},
+#line 3793 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4516, 0},
-#line 1953 "effective_tld_names.gperf"
+#line 2064 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4517, 0},
-#line 1309 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4518, 4},
-#line 2490 "effective_tld_names.gperf"
+#line 660 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4518, 0},
+#line 5277 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4519, 0},
-#line 3395 "effective_tld_names.gperf"
+#line 2604 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4520, 0},
-#line 3216 "effective_tld_names.gperf"
+#line 5622 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4521, 0},
-#line 6104 "effective_tld_names.gperf"
+#line 4851 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4522, 0},
-#line 2405 "effective_tld_names.gperf"
+#line 5708 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4523, 0},
-#line 3091 "effective_tld_names.gperf"
+#line 2577 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4524, 0},
-#line 2244 "effective_tld_names.gperf"
+#line 4935 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4525, 0},
-#line 2688 "effective_tld_names.gperf"
+#line 4927 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4526, 0},
-#line 538 "effective_tld_names.gperf"
+#line 607 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4527, 0},
-#line 3350 "effective_tld_names.gperf"
+#line 6014 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4528, 0},
-#line 2332 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4529, 4},
-#line 2617 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4530, 0},
-#line 2356 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4531, 4},
-#line 5806 "effective_tld_names.gperf"
+#line 5381 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4529, 0},
+#line 4939 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4530, 4},
+#line 5610 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4531, 0},
+#line 5050 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4532, 0},
-#line 2596 "effective_tld_names.gperf"
+#line 3310 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4533, 0},
-#line 5962 "effective_tld_names.gperf"
+#line 3351 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4534, 0},
-#line 3346 "effective_tld_names.gperf"
+#line 1355 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4535, 0},
-#line 1952 "effective_tld_names.gperf"
+#line 4634 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4536, 0},
-#line 4017 "effective_tld_names.gperf"
+#line 2261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4537, 0},
-#line 1580 "effective_tld_names.gperf"
+#line 5443 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4538, 0},
-#line 5422 "effective_tld_names.gperf"
+#line 2100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4539, 0},
-#line 2641 "effective_tld_names.gperf"
+#line 5384 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4540, 0},
-#line 6067 "effective_tld_names.gperf"
+#line 3280 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4541, 0},
-#line 3854 "effective_tld_names.gperf"
+#line 3721 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4542, 0},
-#line 416 "effective_tld_names.gperf"
+#line 386 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4543, 0},
-#line 3194 "effective_tld_names.gperf"
+#line 5761 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4544, 0},
-#line 138 "effective_tld_names.gperf"
+#line 2596 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4545, 0},
-#line 1307 "effective_tld_names.gperf"
+#line 5377 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4546, 0},
-#line 3850 "effective_tld_names.gperf"
+#line 5602 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4547, 0},
-#line 5873 "effective_tld_names.gperf"
+#line 5892 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4548, 0},
-#line 5738 "effective_tld_names.gperf"
+#line 6036 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4549, 0},
-#line 2559 "effective_tld_names.gperf"
+#line 5226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4550, 0},
-#line 5407 "effective_tld_names.gperf"
+#line 796 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4551, 0},
-#line 3795 "effective_tld_names.gperf"
+#line 2580 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4552, 0},
-#line 3151 "effective_tld_names.gperf"
+#line 4250 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4553, 0},
-#line 1972 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4554, 0},
-#line 5150 "effective_tld_names.gperf"
+#line 5112 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4554, 4},
+#line 6318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4555, 0},
-#line 5006 "effective_tld_names.gperf"
+#line 4252 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4556, 0},
-#line 144 "effective_tld_names.gperf"
+#line 3986 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4557, 0},
-#line 1539 "effective_tld_names.gperf"
+#line 3597 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4558, 0},
-#line 6064 "effective_tld_names.gperf"
+#line 4452 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4559, 0},
-#line 5915 "effective_tld_names.gperf"
+#line 2603 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4560, 0},
-#line 3580 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4561, 0},
-#line 1855 "effective_tld_names.gperf"
+#line 1539 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4561, 4},
+#line 4192 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4562, 0},
-#line 3378 "effective_tld_names.gperf"
+#line 3267 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4563, 0},
-#line 4366 "effective_tld_names.gperf"
+#line 4512 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4564, 0},
-#line 2339 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4565, 4},
-#line 2159 "effective_tld_names.gperf"
+#line 5400 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4565, 0},
+#line 4246 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4566, 0},
-#line 2766 "effective_tld_names.gperf"
+#line 6039 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4567, 0},
-#line 3557 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4568, 2},
-#line 4867 "effective_tld_names.gperf"
+#line 4869 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4568, 0},
+#line 5104 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4569, 0},
-#line 3362 "effective_tld_names.gperf"
+#line 4500 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4570, 0},
-#line 2643 "effective_tld_names.gperf"
+#line 4113 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4571, 0},
-#line 2360 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4572, 4},
-#line 4450 "effective_tld_names.gperf"
+#line 1403 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4572, 0},
+#line 4238 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4573, 0},
-#line 2338 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4574, 4},
-#line 3977 "effective_tld_names.gperf"
+#line 571 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4574, 0},
+#line 4241 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4575, 0},
-#line 3239 "effective_tld_names.gperf"
+#line 3036 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4576, 0},
-#line 675 "effective_tld_names.gperf"
+#line 4125 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4577, 0},
-#line 197 "effective_tld_names.gperf"
+#line 5162 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4578, 0},
-#line 4289 "effective_tld_names.gperf"
+#line 5279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4579, 0},
-#line 2661 "effective_tld_names.gperf"
+#line 5085 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4580, 0},
-#line 3641 "effective_tld_names.gperf"
+#line 6263 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4581, 0},
-#line 5940 "effective_tld_names.gperf"
+#line 4215 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4582, 0},
-#line 3366 "effective_tld_names.gperf"
+#line 648 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4583, 0},
-#line 2414 "effective_tld_names.gperf"
+#line 766 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4584, 0},
-#line 4320 "effective_tld_names.gperf"
+#line 4424 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4585, 0},
-#line 733 "effective_tld_names.gperf"
+#line 1651 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4586, 0},
-#line 4196 "effective_tld_names.gperf"
+#line 2731 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4587, 0},
-#line 3449 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4588, 0},
-#line 1126 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4589, 4},
-#line 5433 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4590, 0},
-#line 5091 "effective_tld_names.gperf"
+#line 2440 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4588, 4},
+#line 5049 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4589, 0},
+#line 1540 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4590, 4},
+#line 4245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4591, 0},
-#line 4315 "effective_tld_names.gperf"
+#line 4211 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4592, 0},
-#line 3124 "effective_tld_names.gperf"
+#line 4226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4593, 0},
-#line 3307 "effective_tld_names.gperf"
+#line 4240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4594, 0},
-#line 4304 "effective_tld_names.gperf"
+#line 1515 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4595, 0},
-#line 4091 "effective_tld_names.gperf"
+#line 5567 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4596, 0},
-#line 3290 "effective_tld_names.gperf"
+#line 5114 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4597, 0},
-#line 5415 "effective_tld_names.gperf"
+#line 5360 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4598, 0},
-#line 2098 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4599, 4},
-#line 4197 "effective_tld_names.gperf"
+#line 4418 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4599, 0},
+#line 3659 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4600, 0},
-#line 2555 "effective_tld_names.gperf"
+#line 5633 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4601, 0},
-#line 5757 "effective_tld_names.gperf"
+#line 4123 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4602, 0},
-#line 385 "effective_tld_names.gperf"
+#line 653 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4603, 0},
-#line 746 "effective_tld_names.gperf"
+#line 2376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4604, 0},
-#line 105 "effective_tld_names.gperf"
+#line 2782 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4605, 0},
-#line 1768 "effective_tld_names.gperf"
+#line 4453 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4606, 0},
-#line 5120 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4607, 0},
-#line 1220 "effective_tld_names.gperf"
+#line 2458 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4607, 4},
+#line 5620 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4608, 0},
-#line 410 "effective_tld_names.gperf"
+#line 1954 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4609, 0},
-#line 917 "effective_tld_names.gperf"
+#line 91 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4610, 0},
-#line 2768 "effective_tld_names.gperf"
+#line 6156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4611, 0},
-#line 5924 "effective_tld_names.gperf"
+#line 4247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4612, 0},
-#line 2184 "effective_tld_names.gperf"
+#line 1516 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4613, 0},
-#line 2052 "effective_tld_names.gperf"
+#line 5910 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4614, 0},
-#line 5736 "effective_tld_names.gperf"
+#line 2572 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4615, 0},
-#line 4282 "effective_tld_names.gperf"
+#line 4817 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4616, 0},
-#line 1013 "effective_tld_names.gperf"
+#line 4442 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4617, 0},
-#line 4198 "effective_tld_names.gperf"
+#line 3641 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4618, 0},
-#line 4771 "effective_tld_names.gperf"
+#line 3576 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4619, 0},
-#line 5918 "effective_tld_names.gperf"
+#line 839 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4620, 0},
-#line 3987 "effective_tld_names.gperf"
+#line 4778 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4621, 0},
-#line 2594 "effective_tld_names.gperf"
+#line 3773 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4622, 0},
-#line 2685 "effective_tld_names.gperf"
+#line 1113 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4623, 0},
-#line 3964 "effective_tld_names.gperf"
+#line 5264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4624, 0},
-#line 4019 "effective_tld_names.gperf"
+#line 2309 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4625, 0},
-#line 670 "effective_tld_names.gperf"
+#line 4217 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4626, 0},
-#line 2895 "effective_tld_names.gperf"
+#line 2575 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4627, 0},
-#line 713 "effective_tld_names.gperf"
+#line 4171 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4628, 0},
-#line 1127 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4629, 4},
-#line 3971 "effective_tld_names.gperf"
+#line 2568 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4629, 0},
+#line 1646 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4630, 0},
-#line 4672 "effective_tld_names.gperf"
+#line 5395 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4631, 0},
-#line 4819 "effective_tld_names.gperf"
+#line 108 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4632, 0},
-#line 681 "effective_tld_names.gperf"
+#line 5368 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4633, 0},
-#line 6066 "effective_tld_names.gperf"
+#line 4427 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4634, 0},
-#line 3708 "effective_tld_names.gperf"
+#line 4155 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4635, 0},
-#line 3707 "effective_tld_names.gperf"
+#line 4239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4636, 0},
-#line 758 "effective_tld_names.gperf"
+#line 4249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4637, 0},
-#line 1067 "effective_tld_names.gperf"
+#line 2234 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4638, 0},
-#line 759 "effective_tld_names.gperf"
+#line 1189 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4639, 0},
-#line 3709 "effective_tld_names.gperf"
+#line 1753 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4640, 0},
-#line 4175 "effective_tld_names.gperf"
+#line 4027 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4641, 0},
-#line 4170 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4642, 0},
-#line 4172 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4643, 0},
-#line 2381 "effective_tld_names.gperf"
+#line 5948 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4642, 4},
+#line 4678 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4643, 4},
+#line 1802 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4644, 0},
-#line 3348 "effective_tld_names.gperf"
+#line 2142 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4645, 0},
-#line 4171 "effective_tld_names.gperf"
+#line 2733 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4646, 0},
-#line 94 "effective_tld_names.gperf"
+#line 2266 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4647, 0},
-#line 5922 "effective_tld_names.gperf"
+#line 3782 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4648, 0},
-#line 3380 "effective_tld_names.gperf"
+#line 5495 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4649, 0},
-#line 6079 "effective_tld_names.gperf"
+#line 4181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4650, 0},
-#line 2565 "effective_tld_names.gperf"
+#line 2595 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4651, 0},
-#line 4169 "effective_tld_names.gperf"
+#line 5349 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4652, 0},
-#line 53 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4653, 0},
-#line 5522 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4654, 4},
-#line 2139 "effective_tld_names.gperf"
+#line 2424 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4653, 4},
+#line 4931 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4654, 0},
+#line 2074 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4655, 0},
-#line 5749 "effective_tld_names.gperf"
+#line 1483 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4656, 0},
-#line 5933 "effective_tld_names.gperf"
+#line 2898 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4657, 0},
-#line 1561 "effective_tld_names.gperf"
+#line 2937 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4658, 0},
-#line 3330 "effective_tld_names.gperf"
+#line 1537 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4659, 0},
-#line 4685 "effective_tld_names.gperf"
+#line 4172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4660, 0},
-#line 3586 "effective_tld_names.gperf"
+#line 4863 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4661, 0},
-#line 4072 "effective_tld_names.gperf"
+#line 3971 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4662, 0},
-#line 5743 "effective_tld_names.gperf"
+#line 4422 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4663, 0},
-#line 5481 "effective_tld_names.gperf"
+#line 5298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4664, 0},
-#line 5925 "effective_tld_names.gperf"
+#line 1105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4665, 0},
-#line 5920 "effective_tld_names.gperf"
+#line 2691 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4666, 0},
-#line 3379 "effective_tld_names.gperf"
+#line 5707 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4667, 0},
-#line 5450 "effective_tld_names.gperf"
+#line 5523 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4668, 0},
-#line 2634 "effective_tld_names.gperf"
+#line 454 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4669, 0},
-#line 4176 "effective_tld_names.gperf"
+#line 4445 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4670, 0},
-#line 5350 "effective_tld_names.gperf"
+#line 1106 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4671, 0},
-#line 4679 "effective_tld_names.gperf"
+#line 176 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4672, 0},
-#line 3347 "effective_tld_names.gperf"
+#line 5004 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4673, 0},
-#line 2049 "effective_tld_names.gperf"
+#line 5290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4674, 0},
-#line 3912 "effective_tld_names.gperf"
+#line 2666 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4675, 0},
-#line 2417 "effective_tld_names.gperf"
+#line 5233 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4676, 0},
-#line 6082 "effective_tld_names.gperf"
+#line 1181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4677, 0},
-#line 5351 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4678, 0},
-#line 2783 "effective_tld_names.gperf"
+#line 4971 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4678, 4},
+#line 2712 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4679, 0},
-#line 2216 "effective_tld_names.gperf"
+#line 5353 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4680, 0},
-#line 2433 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4681, 0},
-#line 4149 "effective_tld_names.gperf"
+#line 5000 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4681, 4},
+#line 324 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4682, 0},
-#line 3816 "effective_tld_names.gperf"
+#line 5356 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4683, 0},
-#line 551 "effective_tld_names.gperf"
+#line 4117 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4684, 0},
-#line 5911 "effective_tld_names.gperf"
+#line 1223 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4685, 0},
-#line 4174 "effective_tld_names.gperf"
+#line 2141 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4686, 0},
-#line 3434 "effective_tld_names.gperf"
+#line 4663 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4687, 0},
-#line 4291 "effective_tld_names.gperf"
+#line 4936 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4688, 0},
-#line 4601 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4689, 4},
-#line 3570 "effective_tld_names.gperf"
+#line 4839 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4689, 0},
+#line 3592 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4690, 0},
-#line 1992 "effective_tld_names.gperf"
+#line 5628 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4691, 0},
-#line 4047 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4692, 1},
-#line 1577 "effective_tld_names.gperf"
+#line 5945 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4692, 0},
+#line 131 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4693, 0},
-#line 2808 "effective_tld_names.gperf"
+#line 4281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4694, 0},
-#line 4173 "effective_tld_names.gperf"
+#line 1357 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4695, 0},
-#line 790 "effective_tld_names.gperf"
+#line 5376 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4696, 0},
-#line 6105 "effective_tld_names.gperf"
+#line 408 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4697, 0},
-#line 5717 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4698, 4},
-#line 3679 "effective_tld_names.gperf"
+#line 4746 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4698, 0},
+#line 5716 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4699, 0},
-#line 5221 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4700, 4},
-#line 5413 "effective_tld_names.gperf"
+#line 5512 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4700, 0},
+#line 4934 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4701, 0},
-#line 1341 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4702, 4},
-#line 2308 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4703, 4},
-#line 1884 "effective_tld_names.gperf"
+#line 5615 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4702, 0},
+#line 6267 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4703, 0},
+#line 4745 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4704, 0},
-#line 2722 "effective_tld_names.gperf"
+#line 5393 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4705, 0},
-#line 5964 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4706, 0},
-#line 5425 "effective_tld_names.gperf"
+#line 5198 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4706, 4},
+#line 3227 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4707, 0},
-#line 592 "effective_tld_names.gperf"
+#line 3226 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4708, 0},
-#line 2613 "effective_tld_names.gperf"
+#line 1789 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4709, 0},
-#line 4485 "effective_tld_names.gperf"
+#line 1342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4710, 0},
-#line 5398 "effective_tld_names.gperf"
+#line 5956 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4711, 0},
-#line 2346 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4712, 4},
-#line 1421 "effective_tld_names.gperf"
+#line 1016 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4712, 0},
+#line 3991 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4713, 0},
-#line 5949 "effective_tld_names.gperf"
+#line 5084 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4714, 0},
-#line 1039 "effective_tld_names.gperf"
+#line 5519 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4715, 0},
-#line 3889 "effective_tld_names.gperf"
+#line 1880 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4716, 0},
-#line 3888 "effective_tld_names.gperf"
+#line 5179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4717, 0},
-#line 3834 "effective_tld_names.gperf"
+#line 1303 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4718, 0},
-#line 4857 "effective_tld_names.gperf"
+#line 974 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4719, 0},
-#line 5024 "effective_tld_names.gperf"
+#line 3234 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4720, 0},
-#line 4322 "effective_tld_names.gperf"
+#line 2648 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4721, 0},
-#line 4914 "effective_tld_names.gperf"
+#line 3075 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4722, 0},
-#line 6098 "effective_tld_names.gperf"
+#line 3076 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4723, 0},
-#line 4873 "effective_tld_names.gperf"
+#line 3215 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4724, 0},
-#line 2056 "effective_tld_names.gperf"
+#line 300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4725, 0},
-#line 2301 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4726, 4},
-#line 5483 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4727, 4},
-#line 6097 "effective_tld_names.gperf"
+#line 2600 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4726, 0},
+#line 5709 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4727, 0},
+#line 3228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4728, 0},
-#line 5916 "effective_tld_names.gperf"
+#line 3300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4729, 0},
-#line 1310 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4730, 4},
-#line 2036 "effective_tld_names.gperf"
+#line 5350 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4730, 0},
+#line 4283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4731, 0},
-#line 1870 "effective_tld_names.gperf"
+#line 1356 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4732, 0},
-#line 3665 "effective_tld_names.gperf"
+#line 2524 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4733, 0},
-#line 2972 "effective_tld_names.gperf"
+#line 3104 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4734, 0},
-#line 4787 "effective_tld_names.gperf"
+#line 5389 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4735, 0},
-#line 5942 "effective_tld_names.gperf"
+#line 394 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4736, 0},
-#line 1635 "effective_tld_names.gperf"
+#line 6100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4737, 0},
-#line 3915 "effective_tld_names.gperf"
+#line 4279 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4738, 0},
-#line 2777 "effective_tld_names.gperf"
+#line 3132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4739, 0},
-#line 4739 "effective_tld_names.gperf"
+#line 4425 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4740, 0},
-#line 4731 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4741, 2},
-#line 5173 "effective_tld_names.gperf"
+#line 5029 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4741, 0},
+#line 3197 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4742, 0},
-#line 1777 "effective_tld_names.gperf"
+#line 2670 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4743, 0},
-#line 1228 "effective_tld_names.gperf"
+#line 5437 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4744, 0},
-#line 925 "effective_tld_names.gperf"
+#line 3867 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4745, 0},
-#line 282 "effective_tld_names.gperf"
+#line 5983 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4746, 0},
-#line 4013 "effective_tld_names.gperf"
+#line 4950 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4747, 0},
-#line 4765 "effective_tld_names.gperf"
+#line 2379 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4748, 0},
-#line 4025 "effective_tld_names.gperf"
+#line 3253 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4749, 0},
-#line 2392 "effective_tld_names.gperf"
+#line 4878 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4750, 0},
-#line 1901 "effective_tld_names.gperf"
+#line 3244 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4751, 0},
-#line 2684 "effective_tld_names.gperf"
+#line 5338 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4752, 0},
-#line 3930 "effective_tld_names.gperf"
+#line 4393 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4753, 0},
-#line 4982 "effective_tld_names.gperf"
+#line 5421 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4754, 0},
-#line 5941 "effective_tld_names.gperf"
+#line 2601 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4755, 0},
-#line 3976 "effective_tld_names.gperf"
+#line 3242 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4756, 0},
-#line 4646 "effective_tld_names.gperf"
+#line 3027 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4757, 0},
-#line 4689 "effective_tld_names.gperf"
+#line 4190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4758, 0},
-#line 5145 "effective_tld_names.gperf"
+#line 2047 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4759, 0},
-#line 1787 "effective_tld_names.gperf"
+#line 802 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4760, 0},
-#line 1235 "effective_tld_names.gperf"
+#line 3233 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4761, 0},
-#line 582 "effective_tld_names.gperf"
+#line 1891 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4762, 0},
-#line 5345 "effective_tld_names.gperf"
+#line 1312 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4763, 0},
-#line 931 "effective_tld_names.gperf"
+#line 4930 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4764, 0},
-#line 3609 "effective_tld_names.gperf"
+#line 982 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4765, 0},
-#line 1990 "effective_tld_names.gperf"
+#line 410 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4766, 0},
-#line 5948 "effective_tld_names.gperf"
+#line 5297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4767, 0},
-#line 567 "effective_tld_names.gperf"
+#line 1447 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4768, 0},
-#line 4913 "effective_tld_names.gperf"
+#line 5364 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4769, 0},
-#line 3884 "effective_tld_names.gperf"
+#line 3144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4770, 0},
-#line 1118 "effective_tld_names.gperf"
+#line 6017 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4771, 0},
-#line 2167 "effective_tld_names.gperf"
+#line 3803 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4772, 0},
-#line 2476 "effective_tld_names.gperf"
+#line 3111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4773, 0},
-#line 5505 "effective_tld_names.gperf"
+#line 1461 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4774, 0},
-#line 2597 "effective_tld_names.gperf"
+#line 5037 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4775, 0},
-#line 3630 "effective_tld_names.gperf"
+#line 5479 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4776, 0},
-#line 3798 "effective_tld_names.gperf"
+#line 604 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4777, 0},
-#line 5410 "effective_tld_names.gperf"
+#line 3077 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4778, 0},
-#line 2163 "effective_tld_names.gperf"
+#line 5257 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4779, 0},
-#line 251 "effective_tld_names.gperf"
+#line 2395 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4780, 0},
-#line 4592 "effective_tld_names.gperf"
+#line 3115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4781, 0},
-#line 4448 "effective_tld_names.gperf"
+#line 4242 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4782, 0},
-#line 4267 "effective_tld_names.gperf"
+#line 2571 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4783, 0},
-#line 3766 "effective_tld_names.gperf"
+#line 830 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4784, 0},
-#line 2219 "effective_tld_names.gperf"
+#line 5686 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4785, 0},
-#line 3498 "effective_tld_names.gperf"
+#line 4975 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4786, 0},
-#line 2425 "effective_tld_names.gperf"
+#line 794 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4787, 0},
-#line 3853 "effective_tld_names.gperf"
+#line 3089 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4788, 0},
-#line 4657 "effective_tld_names.gperf"
+#line 3190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4789, 0},
-#line 6074 "effective_tld_names.gperf"
+#line 5365 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4790, 0},
-#line 2334 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4791, 4},
-#line 1865 "effective_tld_names.gperf"
+#line 3250 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4791, 0},
+#line 5403 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4792, 0},
-#line 5058 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4793, 4},
-#line 1993 "effective_tld_names.gperf"
+#line 3201 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4793, 0},
+#line 275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4794, 0},
-#line 2966 "effective_tld_names.gperf"
+#line 194 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4795, 0},
-#line 2515 "effective_tld_names.gperf"
+#line 2574 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4796, 0},
-#line 4290 "effective_tld_names.gperf"
+#line 4005 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4797, 0},
-#line 5308 "effective_tld_names.gperf"
+#line 3770 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4798, 0},
-#line 1895 "effective_tld_names.gperf"
+#line 5342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4799, 0},
-#line 2840 "effective_tld_names.gperf"
+#line 3602 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4800, 0},
-#line 2222 "effective_tld_names.gperf"
+#line 3123 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4801, 0},
-#line 3213 "effective_tld_names.gperf"
+#line 4243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4802, 0},
-#line 5540 "effective_tld_names.gperf"
+#line 5366 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4803, 0},
-#line 3746 "effective_tld_names.gperf"
+#line 1713 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4804, 0},
-#line 3743 "effective_tld_names.gperf"
+#line 5505 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4805, 0},
-#line 3744 "effective_tld_names.gperf"
+#line 3125 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4806, 0},
-#line 3023 "effective_tld_names.gperf"
+#line 5123 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4807, 0},
-#line 5745 "effective_tld_names.gperf"
+#line 3196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4808, 0},
-#line 2343 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4809, 4},
-#line 5038 "effective_tld_names.gperf"
+#line 4414 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4809, 0},
+#line 2995 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4810, 0},
-#line 5926 "effective_tld_names.gperf"
+#line 5080 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4811, 0},
-#line 355 "effective_tld_names.gperf"
+#line 5989 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4812, 0},
-#line 556 "effective_tld_names.gperf"
+#line 3472 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4813, 0},
-#line 192 "effective_tld_names.gperf"
+#line 3094 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4814, 0},
-#line 2313 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4815, 4},
-#line 2999 "effective_tld_names.gperf"
+#line 6351 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4815, 0},
+#line 3199 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4816, 0},
-#line 3742 "effective_tld_names.gperf"
+#line 3444 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4817, 0},
-#line 121 "effective_tld_names.gperf"
+#line 337 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4818, 0},
-#line 5971 "effective_tld_names.gperf"
+#line 2855 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4819, 0},
-#line 2229 "effective_tld_names.gperf"
+#line 3328 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4820, 0},
-#line 5958 "effective_tld_names.gperf"
+#line 5383 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4821, 0},
-#line 5807 "effective_tld_names.gperf"
+#line 3174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4822, 0},
-#line 1314 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4823, 0},
-#line 1062 "effective_tld_names.gperf"
+#line 1185 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4823, 4},
+#line 3239 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4824, 0},
-#line 3411 "effective_tld_names.gperf"
+#line 3142 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4825, 0},
-#line 6025 "effective_tld_names.gperf"
+#line 2378 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4826, 0},
-#line 1594 "effective_tld_names.gperf"
+#line 2860 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4827, 0},
-#line 5304 "effective_tld_names.gperf"
+#line 3173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4828, 0},
-#line 6020 "effective_tld_names.gperf"
+#line 479 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4829, 0},
-#line 2564 "effective_tld_names.gperf"
+#line 3178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4830, 0},
-#line 3340 "effective_tld_names.gperf"
+#line 2903 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4831, 0},
-#line 5732 "effective_tld_names.gperf"
+#line 2384 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4832, 0},
-#line 5071 "effective_tld_names.gperf"
+#line 3143 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4833, 0},
-#line 3747 "effective_tld_names.gperf"
+#line 5617 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4834, 0},
-#line 2317 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4835, 4},
-#line 4465 "effective_tld_names.gperf"
+#line 4750 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4835, 0},
+#line 3207 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4836, 0},
-#line 5319 "effective_tld_names.gperf"
+#line 6336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4837, 0},
-#line 1827 "effective_tld_names.gperf"
+#line 3168 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4838, 0},
-#line 2720 "effective_tld_names.gperf"
+#line 3169 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4839, 0},
-#line 2719 "effective_tld_names.gperf"
+#line 804 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4840, 0},
-#line 3725 "effective_tld_names.gperf"
+#line 3164 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4841, 0},
-#line 1862 "effective_tld_names.gperf"
+#line 5057 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4842, 0},
-#line 4573 "effective_tld_names.gperf"
+#line 4712 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4843, 0},
-#line 3390 "effective_tld_names.gperf"
+#line 4399 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4844, 0},
-#line 584 "effective_tld_names.gperf"
+#line 5358 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4845, 0},
-#line 1049 "effective_tld_names.gperf"
+#line 2562 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4846, 0},
-#line 5982 "effective_tld_names.gperf"
+#line 3166 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4847, 0},
-#line 3859 "effective_tld_names.gperf"
+#line 2831 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4848, 0},
-#line 139 "effective_tld_names.gperf"
+#line 3179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4849, 0},
-#line 4936 "effective_tld_names.gperf"
+#line 5034 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4850, 0},
-#line 2320 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4851, 4},
-#line 3745 "effective_tld_names.gperf"
+#line 4365 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4851, 0},
+#line 4126 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4852, 0},
-#line 3126 "effective_tld_names.gperf"
+#line 3155 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4853, 0},
-#line 729 "effective_tld_names.gperf"
+#line 431 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4854, 0},
-#line 4370 "effective_tld_names.gperf"
+#line 1659 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4855, 0},
-#line 59 "effective_tld_names.gperf"
+#line 591 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4856, 0},
-#line 5907 "effective_tld_names.gperf"
+#line 3110 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4857, 0},
-#line 5531 "effective_tld_names.gperf"
+#line 3096 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4858, 0},
-#line 5553 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4859, 4},
-#line 5921 "effective_tld_names.gperf"
+#line 3575 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4859, 0},
+#line 5422 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4860, 0},
-#line 3924 "effective_tld_names.gperf"
+#line 2931 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4861, 0},
-#line 1655 "effective_tld_names.gperf"
+#line 437 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4862, 0},
-#line 4504 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4863, 4},
-#line 2207 "effective_tld_names.gperf"
+#line 5367 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4863, 0},
+#line 4133 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4864, 0},
-#line 2723 "effective_tld_names.gperf"
+#line 5895 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4865, 0},
-#line 1111 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4866, 4},
-#line 235 "effective_tld_names.gperf"
+#line 3165 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4866, 0},
+#line 2925 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4867, 0},
-#line 3365 "effective_tld_names.gperf"
+#line 5234 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4868, 0},
-#line 2153 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4869, 0},
-#line 3539 "effective_tld_names.gperf"
+#line 554 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4869, 4},
+#line 781 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4870, 0},
-#line 4769 "effective_tld_names.gperf"
+#line 3446 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4871, 0},
-#line 2440 "effective_tld_names.gperf"
+#line 1740 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4872, 0},
-#line 393 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4873, 4},
-#line 3916 "effective_tld_names.gperf"
+#line 3151 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4873, 0},
+#line 6081 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4874, 0},
-#line 2664 "effective_tld_names.gperf"
+#line 4373 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4875, 0},
-#line 2761 "effective_tld_names.gperf"
+#line 4578 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4876, 0},
-#line 615 "effective_tld_names.gperf"
+#line 2948 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4877, 0},
-#line 5487 "effective_tld_names.gperf"
+#line 3177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4878, 0},
-#line 384 "effective_tld_names.gperf"
+#line 2770 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4879, 0},
-#line 2217 "effective_tld_names.gperf"
+#line 5109 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4880, 0},
-#line 462 "effective_tld_names.gperf"
+#line 4406 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4881, 0},
-#line 2442 "effective_tld_names.gperf"
+#line 3025 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4882, 0},
-#line 5361 "effective_tld_names.gperf"
+#line 3302 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4883, 0},
-#line 5753 "effective_tld_names.gperf"
+#line 3162 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4884, 0},
-#line 3942 "effective_tld_names.gperf"
+#line 3161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4885, 0},
-#line 3454 "effective_tld_names.gperf"
+#line 3149 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4886, 0},
-#line 4241 "effective_tld_names.gperf"
+#line 3150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4887, 0},
-#line 5741 "effective_tld_names.gperf"
+#line 3290 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4888, 0},
-#line 2110 "effective_tld_names.gperf"
+#line 4304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4889, 0},
-#line 91 "effective_tld_names.gperf"
+#line 2754 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4890, 0},
-#line 3587 "effective_tld_names.gperf"
+#line 297 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4891, 0},
-#line 3303 "effective_tld_names.gperf"
+#line 6033 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4892, 0},
-#line 731 "effective_tld_names.gperf"
+#line 4448 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4893, 0},
-#line 418 "effective_tld_names.gperf"
+#line 5347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4894, 0},
-#line 6015 "effective_tld_names.gperf"
+#line 3203 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4895, 0},
-#line 4931 "effective_tld_names.gperf"
+#line 2970 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4896, 0},
-#line 2762 "effective_tld_names.gperf"
+#line 4174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4897, 0},
-#line 4309 "effective_tld_names.gperf"
+#line 3158 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4898, 0},
-#line 1439 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4899, 4},
-#line 3847 "effective_tld_names.gperf"
+#line 5629 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4899, 0},
+#line 5856 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4900, 0},
-#line 5937 "effective_tld_names.gperf"
+#line 3137 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4901, 0},
-#line 5205 "effective_tld_names.gperf"
+#line 3136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4902, 0},
-#line 4221 "effective_tld_names.gperf"
+#line 6331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4903, 0},
-#line 5298 "effective_tld_names.gperf"
+#line 3134 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4904, 0},
-#line 3956 "effective_tld_names.gperf"
+#line 3254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4905, 0},
-#line 4219 "effective_tld_names.gperf"
+#line 3156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4906, 0},
-#line 4026 "effective_tld_names.gperf"
+#line 3361 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4907, 0},
-#line 1101 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4908, 4},
-#line 3852 "effective_tld_names.gperf"
+#line 1688 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4908, 0},
+#line 3157 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4909, 0},
-#line 2298 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4910, 4},
-#line 4218 "effective_tld_names.gperf"
+#line 3176 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4910, 0},
+#line 3135 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4911, 0},
-#line 3363 "effective_tld_names.gperf"
+#line 4227 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4912, 0},
-#line 5641 "effective_tld_names.gperf"
+#line 4330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4913, 0},
-#line 4459 "effective_tld_names.gperf"
+#line 2140 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4914, 0},
-#line 2553 "effective_tld_names.gperf"
+#line 3065 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4915, 0},
-#line 3524 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4916, 0},
-#line 3648 "effective_tld_names.gperf"
+#line 2819 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4916, 2},
+#line 4774 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4917, 0},
-#line 366 "effective_tld_names.gperf"
+#line 3493 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4918, 0},
-#line 5526 "effective_tld_names.gperf"
+#line 4264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4919, 0},
-#line 2397 "effective_tld_names.gperf"
+#line 5748 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4920, 0},
-#line 5424 "effective_tld_names.gperf"
+#line 3195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4921, 0},
-#line 3141 "effective_tld_names.gperf"
+#line 5319 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4922, 0},
-#line 5733 "effective_tld_names.gperf"
+#line 3723 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4923, 0},
-#line 5758 "effective_tld_names.gperf"
+#line 2911 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4924, 0},
-#line 1414 "effective_tld_names.gperf"
+#line 2534 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4925, 0},
-#line 2321 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4926, 4},
-#line 5932 "effective_tld_names.gperf"
+#line 2881 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4926, 0},
+#line 3175 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4927, 0},
-#line 659 "effective_tld_names.gperf"
+#line 342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4928, 0},
-#line 5328 "effective_tld_names.gperf"
+#line 3159 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4929, 0},
-#line 3984 "effective_tld_names.gperf"
+#line 4146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4930, 0},
-#line 1540 "effective_tld_names.gperf"
+#line 4348 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4931, 0},
-#line 652 "effective_tld_names.gperf"
+#line 3183 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4932, 0},
-#line 5577 "effective_tld_names.gperf"
+#line 5344 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4933, 0},
-#line 3338 "effective_tld_names.gperf"
+#line 3692 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4934, 0},
-#line 3268 "effective_tld_names.gperf"
+#line 4384 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4935, 0},
-#line 396 "effective_tld_names.gperf"
+#line 2147 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4936, 0},
-#line 4845 "effective_tld_names.gperf"
+#line 3087 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4937, 0},
-#line 625 "effective_tld_names.gperf"
+#line 72 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4938, 0},
-#line 3636 "effective_tld_names.gperf"
+#line 5341 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4939, 0},
-#line 5910 "effective_tld_names.gperf"
+#line 4282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4940, 0},
-#line 5696 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4941, 4},
-#line 480 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4942, 4},
-#line 5970 "effective_tld_names.gperf"
+#line 6054 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4941, 0},
+#line 2004 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4942, 0},
+#line 4498 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4943, 0},
-#line 1800 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4944, 0},
-#line 1251 "effective_tld_names.gperf"
+#line 4898 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4944, 4},
+#line 3116 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4945, 0},
-#line 3978 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4946, 4},
-#line 392 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4947, 4},
-#line 948 "effective_tld_names.gperf"
+#line 5504 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4946, 0},
+#line 166 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4947, 0},
+#line 6253 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4948, 0},
-#line 3826 "effective_tld_names.gperf"
+#line 3184 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4949, 0},
-#line 2395 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4950, 4},
-#line 904 "effective_tld_names.gperf"
+#line 3722 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4950, 0},
+#line 4586 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4951, 0},
-#line 126 "effective_tld_names.gperf"
+#line 5300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4952, 0},
-#line 4813 "effective_tld_names.gperf"
+#line 869 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4953, 0},
-#line 5751 "effective_tld_names.gperf"
+#line 4830 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4954, 0},
-#line 5515 "effective_tld_names.gperf"
+#line 3246 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4955, 0},
-#line 5953 "effective_tld_names.gperf"
+#line 63 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4956, 0},
-#line 2324 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4957, 4},
-#line 4288 "effective_tld_names.gperf"
+#line 66 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4957, 0},
+#line 4300 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4958, 0},
-#line 2410 "effective_tld_names.gperf"
+#line 5305 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4959, 0},
-#line 2889 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4960, 0},
-#line 1858 "effective_tld_names.gperf"
+#line 4789 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4960, 4},
+#line 5345 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4961, 0},
-#line 2558 "effective_tld_names.gperf"
+#line 3153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4962, 0},
-#line 2198 "effective_tld_names.gperf"
+#line 2218 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4963, 0},
-#line 2595 "effective_tld_names.gperf"
+#line 1118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4964, 0},
-#line 2774 "effective_tld_names.gperf"
+#line 59 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4965, 0},
-#line 4044 "effective_tld_names.gperf"
+#line 2956 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4966, 0},
-#line 6112 "effective_tld_names.gperf"
+#line 55 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4967, 0},
-#line 1366 "effective_tld_names.gperf"
+#line 4107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4968, 0},
-#line 3983 "effective_tld_names.gperf"
+#line 4078 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4969, 0},
-#line 5714 "effective_tld_names.gperf"
+#line 60 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4970, 0},
-#line 2116 "effective_tld_names.gperf"
+#line 62 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4971, 0},
-#line 5699 "effective_tld_names.gperf"
+#line 6245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4972, 0},
-#line 5928 "effective_tld_names.gperf"
+#line 40 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4973, 0},
-#line 668 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str4974, 0},
-#line 4341 "effective_tld_names.gperf"
+#line 4643 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str4974, 4},
+#line 5030 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4975, 0},
-#line 2737 "effective_tld_names.gperf"
+#line 3129 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4976, 0},
-#line 2115 "effective_tld_names.gperf"
+#line 3148 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4977, 0},
-#line 536 "effective_tld_names.gperf"
+#line 41 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4978, 0},
-#line 5418 "effective_tld_names.gperf"
+#line 54 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4979, 0},
-#line 1030 "effective_tld_names.gperf"
+#line 46 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4980, 0},
-#line 1325 "effective_tld_names.gperf"
+#line 4560 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4981, 0},
-#line 3614 "effective_tld_names.gperf"
+#line 45 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4982, 0},
-#line 5939 "effective_tld_names.gperf"
+#line 3082 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4983, 0},
-#line 2763 "effective_tld_names.gperf"
+#line 2804 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4984, 0},
-#line 1867 "effective_tld_names.gperf"
+#line 5630 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4985, 0},
-#line 3843 "effective_tld_names.gperf"
+#line 4313 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4986, 0},
-#line 4860 "effective_tld_names.gperf"
+#line 6260 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4987, 0},
-#line 2434 "effective_tld_names.gperf"
+#line 3931 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4988, 0},
-#line 2114 "effective_tld_names.gperf"
+#line 44 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4989, 0},
-#line 5746 "effective_tld_names.gperf"
+#line 4476 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4990, 0},
-#line 4276 "effective_tld_names.gperf"
+#line 2799 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4991, 0},
-#line 5909 "effective_tld_names.gperf"
+#line 2543 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4992, 0},
-#line 5804 "effective_tld_names.gperf"
+#line 6378 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4993, 0},
-#line 474 "effective_tld_names.gperf"
+#line 3590 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4994, 0},
-#line 5551 "effective_tld_names.gperf"
+#line 3761 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4995, 0},
-#line 5954 "effective_tld_names.gperf"
+#line 3091 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4996, 0},
-#line 2573 "effective_tld_names.gperf"
+#line 5270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4997, 0},
-#line 6068 "effective_tld_names.gperf"
+#line 3995 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4998, 0},
-#line 2743 "effective_tld_names.gperf"
+#line 261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str4999, 0},
-#line 4242 "effective_tld_names.gperf"
+#line 3363 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5000, 0},
-#line 619 "effective_tld_names.gperf"
+#line 52 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5001, 0},
-#line 5080 "effective_tld_names.gperf"
+#line 5012 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5002, 0},
-#line 3545 "effective_tld_names.gperf"
+#line 4497 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5003, 0},
-#line 3332 "effective_tld_names.gperf"
+#line 65 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5004, 0},
-#line 1845 "effective_tld_names.gperf"
+#line 5435 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5005, 0},
-#line 5128 "effective_tld_names.gperf"
+#line 5451 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5006, 0},
-#line 4628 "effective_tld_names.gperf"
+#line 5324 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5007, 0},
-#line 3904 "effective_tld_names.gperf"
+#line 2579 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5008, 0},
-#line 2970 "effective_tld_names.gperf"
+#line 3938 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5009, 0},
-#line 6035 "effective_tld_names.gperf"
+#line 4465 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5010, 0},
-#line 3617 "effective_tld_names.gperf"
+#line 43 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5011, 0},
-#line 4005 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5012, 0},
-#line 2214 "effective_tld_names.gperf"
+#line 3090 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5012, 4},
+#line 5483 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5013, 0},
-#line 677 "effective_tld_names.gperf"
+#line 5405 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5014, 0},
-#line 2879 "effective_tld_names.gperf"
+#line 1817 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5015, 0},
-#line 2686 "effective_tld_names.gperf"
+#line 3853 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5016, 0},
-#line 5759 "effective_tld_names.gperf"
+#line 6046 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5017, 0},
-#line 2285 "effective_tld_names.gperf"
+#line 4119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5018, 0},
-#line 1119 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5019, 4},
-#line 5556 "effective_tld_names.gperf"
+#line 1193 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5019, 0},
+#line 3834 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5020, 0},
-#line 3262 "effective_tld_names.gperf"
+#line 3733 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5021, 0},
-#line 6021 "effective_tld_names.gperf"
+#line 6250 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5022, 0},
-#line 5963 "effective_tld_names.gperf"
+#line 2298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5023, 0},
-#line 2403 "effective_tld_names.gperf"
+#line 701 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5024, 0},
-#line 2078 "effective_tld_names.gperf"
+#line 53 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5025, 0},
-#line 3391 "effective_tld_names.gperf"
+#line 3191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5026, 0},
-#line 2185 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5027, 4},
-#line 4938 "effective_tld_names.gperf"
+#line 4437 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5027, 0},
+#line 4142 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5028, 0},
-#line 5280 "effective_tld_names.gperf"
+#line 3001 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5029, 0},
-#line 4249 "effective_tld_names.gperf"
+#line 3603 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5030, 0},
-#line 2333 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5031, 4},
-#line 6047 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5032, 2},
-#line 3787 "effective_tld_names.gperf"
+#line 4530 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5031, 0},
+#line 192 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5032, 0},
+#line 4130 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5033, 0},
-#line 5665 "effective_tld_names.gperf"
+#line 2586 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5034, 0},
-#line 3785 "effective_tld_names.gperf"
+#line 2613 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5035, 0},
-#line 5744 "effective_tld_names.gperf"
+#line 6034 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5036, 0},
-#line 4874 "effective_tld_names.gperf"
+#line 4244 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5037, 0},
-#line 1576 "effective_tld_names.gperf"
+#line 4229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5038, 0},
-#line 5008 "effective_tld_names.gperf"
+#line 1708 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5039, 0},
-#line 2905 "effective_tld_names.gperf"
+#line 4642 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5040, 0},
-#line 3309 "effective_tld_names.gperf"
+#line 3900 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5041, 0},
-#line 679 "effective_tld_names.gperf"
+#line 2877 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5042, 0},
-#line 4311 "effective_tld_names.gperf"
+#line 5374 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5043, 0},
-#line 2628 "effective_tld_names.gperf"
+#line 4254 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5044, 0},
-#line 3870 "effective_tld_names.gperf"
+#line 415 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5045, 0},
-#line 3537 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5046, 1},
-#line 4797 "effective_tld_names.gperf"
+#line 42 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5046, 0},
+#line 3078 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5047, 0},
-#line 4937 "effective_tld_names.gperf"
+#line 4423 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5048, 0},
-#line 2784 "effective_tld_names.gperf"
+#line 402 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5049, 0},
-#line 326 "effective_tld_names.gperf"
+#line 1188 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5050, 0},
-#line 120 "effective_tld_names.gperf"
+#line 4118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5051, 0},
-#line 2215 "effective_tld_names.gperf"
+#line 5673 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5052, 0},
-#line 3925 "effective_tld_names.gperf"
+#line 3918 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5053, 0},
-#line 5805 "effective_tld_names.gperf"
+#line 3119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5054, 0},
-#line 3863 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5055, 1},
-#line 3392 "effective_tld_names.gperf"
+#line 64 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5055, 0},
+#line 1419 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5056, 0},
-#line 3673 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5057, 1},
-#line 1552 "effective_tld_names.gperf"
+#line 3544 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5057, 0},
+#line 4404 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5058, 0},
-#line 4668 "effective_tld_names.gperf"
+#line 3642 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5059, 0},
-#line 707 "effective_tld_names.gperf"
+#line 1670 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5060, 0},
-#line 5585 "effective_tld_names.gperf"
+#line 1700 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5061, 0},
-#line 5451 "effective_tld_names.gperf"
+#line 2655 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5062, 0},
-#line 210 "effective_tld_names.gperf"
+#line 2922 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5063, 0},
-#line 5927 "effective_tld_names.gperf"
+#line 401 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5064, 0},
-#line 239 "effective_tld_names.gperf"
+#line 1783 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5065, 0},
-#line 2616 "effective_tld_names.gperf"
+#line 1282 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5066, 0},
-#line 2599 "effective_tld_names.gperf"
+#line 5371 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5067, 0},
-#line 5142 "effective_tld_names.gperf"
+#line 952 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5068, 0},
-#line 639 "effective_tld_names.gperf"
+#line 1235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5069, 0},
-#line 299 "effective_tld_names.gperf"
+#line 3788 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5070, 0},
-#line 2370 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5071, 4},
-#line 3928 "effective_tld_names.gperf"
+#line 2816 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5071, 0},
+#line 5518 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5072, 0},
-#line 4965 "effective_tld_names.gperf"
+#line 4420 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5073, 0},
-#line 1533 "effective_tld_names.gperf"
+#line 5330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5074, 0},
-#line 2769 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5075, 2},
-#line 672 "effective_tld_names.gperf"
+#line 4234 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5075, 0},
+#line 2235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5076, 0},
-#line 4071 "effective_tld_names.gperf"
+#line 3809 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5077, 0},
-#line 3619 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5078, 0},
-#line 4654 "effective_tld_names.gperf"
+#line 2486 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5078, 4},
+#line 3000 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5079, 0},
-#line 2627 "effective_tld_names.gperf"
+#line 4400 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5080, 0},
-#line 5754 "effective_tld_names.gperf"
+#line 3874 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5081, 0},
-#line 3975 "effective_tld_names.gperf"
+#line 3754 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5082, 0},
-#line 3394 "effective_tld_names.gperf"
+#line 5660 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5083, 0},
-#line 3408 "effective_tld_names.gperf"
+#line 5397 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5084, 0},
-#line 3681 "effective_tld_names.gperf"
+#line 5094 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5085, 0},
-#line 3680 "effective_tld_names.gperf"
+#line 2283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5086, 0},
-#line 2335 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5087, 4},
-#line 2336 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5088, 4},
-#line 5443 "effective_tld_names.gperf"
+#line 772 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5087, 0},
+#line 5458 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5088, 0},
+#line 4198 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5089, 0},
-#line 4424 "effective_tld_names.gperf"
+#line 3186 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5090, 0},
-#line 2658 "effective_tld_names.gperf"
+#line 3127 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5091, 0},
-#line 5536 "effective_tld_names.gperf"
+#line 4819 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5092, 0},
-#line 2838 "effective_tld_names.gperf"
+#line 2342 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5093, 0},
-#line 2657 "effective_tld_names.gperf"
+#line 4499 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5094, 0},
-#line 1090 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5095, 0},
-#line 3621 "effective_tld_names.gperf"
+#line 879 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5095, 4},
+#line 5579 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5096, 0},
-#line 4942 "effective_tld_names.gperf"
+#line 4841 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5097, 0},
-#line 2181 "effective_tld_names.gperf"
+#line 3725 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5098, 0},
-#line 5984 "effective_tld_names.gperf"
+#line 3734 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5099, 0},
-#line 2439 "effective_tld_names.gperf"
+#line 5064 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5100, 0},
-#line 2379 "effective_tld_names.gperf"
+#line 2723 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5101, 0},
-#line 3897 "effective_tld_names.gperf"
+#line 880 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5102, 0},
-#line 5250 "effective_tld_names.gperf"
+#line 4140 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5103, 0},
-#line 4254 "effective_tld_names.gperf"
+#line 3187 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5104, 0},
-#line 5747 "effective_tld_names.gperf"
+#line 4151 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5105, 0},
-#line 5563 "effective_tld_names.gperf"
+#line 1134 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5106, 0},
-#line 3943 "effective_tld_names.gperf"
+#line 1561 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5107, 0},
-#line 2582 "effective_tld_names.gperf"
+#line 5641 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5108, 0},
-#line 5716 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5109, 4},
-#line 2977 "effective_tld_names.gperf"
+#line 5976 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5109, 0},
+#line 5965 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5110, 0},
-#line 5466 "effective_tld_names.gperf"
+#line 6169 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5111, 0},
-#line 1092 "effective_tld_names.gperf"
+#line 3100 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5112, 0},
-#line 2557 "effective_tld_names.gperf"
+#line 5332 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5113, 0},
-#line 2795 "effective_tld_names.gperf"
+#line 4397 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5114, 0},
-#line 5090 "effective_tld_names.gperf"
+#line 5843 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5115, 0},
-#line 2829 "effective_tld_names.gperf"
+#line 5510 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5116, 0},
-#line 2169 "effective_tld_names.gperf"
+#line 2715 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5117, 0},
-#line 2292 "effective_tld_names.gperf"
+#line 5743 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5118, 0},
-#line 5285 "effective_tld_names.gperf"
+#line 4704 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5119, 0},
-#line 1466 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5120, 0},
-#line 2590 "effective_tld_names.gperf"
+#line 1133 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5120, 4},
+#line 6205 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5121, 0},
-#line 2361 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5122, 4},
-#line 2454 "effective_tld_names.gperf"
+#line 3102 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5122, 0},
+#line 5522 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5123, 0},
-#line 5312 "effective_tld_names.gperf"
+#line 2809 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5124, 0},
-#line 4669 "effective_tld_names.gperf"
+#line 2544 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5125, 0},
-#line 3835 "effective_tld_names.gperf"
+#line 3787 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5126, 0},
-#line 587 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5127, 4},
-#line 5363 "effective_tld_names.gperf"
+#line 5379 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5127, 0},
+#line 4738 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5128, 0},
-#line 5420 "effective_tld_names.gperf"
+#line 6148 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5129, 0},
-#line 2444 "effective_tld_names.gperf"
+#line 1976 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5130, 0},
-#line 3337 "effective_tld_names.gperf"
+#line 4153 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5131, 0},
-#line 1959 "effective_tld_names.gperf"
+#line 3534 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5132, 0},
-#line 3900 "effective_tld_names.gperf"
+#line 5369 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5133, 0},
-#line 3513 "effective_tld_names.gperf"
+#line 572 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5134, 0},
-#line 5763 "effective_tld_names.gperf"
+#line 4121 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5135, 0},
-#line 4531 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5136, 4},
-#line 5952 "effective_tld_names.gperf"
+#line 4232 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5136, 0},
+#line 6091 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5137, 0},
-#line 784 "effective_tld_names.gperf"
+#line 6152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5138, 0},
-#line 4727 "effective_tld_names.gperf"
+#line 5060 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5139, 0},
-#line 3536 "effective_tld_names.gperf"
+#line 2291 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5140, 0},
-#line 5111 "effective_tld_names.gperf"
+#line 5361 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5141, 0},
-#line 2679 "effective_tld_names.gperf"
+#line 1191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5142, 0},
-#line 6081 "effective_tld_names.gperf"
+#line 4409 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5143, 0},
-#line 2157 "effective_tld_names.gperf"
+#line 4286 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5144, 0},
-#line 1889 "effective_tld_names.gperf"
+#line 1162 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5145, 0},
-#line 4749 "effective_tld_names.gperf"
+#line 3434 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5146, 0},
-#line 3527 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5147, 4},
-#line 6080 "effective_tld_names.gperf"
+#line 3551 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5147, 0},
+#line 4370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5148, 0},
-#line 4156 "effective_tld_names.gperf"
+#line 2996 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5149, 0},
-#line 3164 "effective_tld_names.gperf"
+#line 4380 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5150, 0},
-#line 4155 "effective_tld_names.gperf"
+#line 6131 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5151, 0},
-#line 4160 "effective_tld_names.gperf"
+#line 4114 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5152, 0},
-#line 4154 "effective_tld_names.gperf"
+#line 2743 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5153, 0},
-#line 3674 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5154, 0},
-#line 3563 "effective_tld_names.gperf"
+#line 2489 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5154, 4},
+#line 4214 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5155, 0},
-#line 5154 "effective_tld_names.gperf"
+#line 47 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5156, 0},
-#line 5509 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5157, 0},
-#line 2760 "effective_tld_names.gperf"
+#line 1422 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5157, 4},
+#line 5517 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5158, 0},
-#line 5934 "effective_tld_names.gperf"
+#line 3536 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5159, 0},
-#line 4859 "effective_tld_names.gperf"
+#line 5642 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5160, 0},
-#line 5739 "effective_tld_names.gperf"
+#line 4661 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5161, 0},
-#line 1136 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5162, 4},
-#line 4294 "effective_tld_names.gperf"
+#line 50 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5162, 0},
+#line 4278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5163, 0},
-#line 4858 "effective_tld_names.gperf"
+#line 6144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5164, 0},
-#line 3535 "effective_tld_names.gperf"
+#line 56 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5165, 0},
-#line 4321 "effective_tld_names.gperf"
+#line 6025 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5166, 0},
-#line 5423 "effective_tld_names.gperf"
+#line 61 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5167, 0},
-#line 5955 "effective_tld_names.gperf"
+#line 4176 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5168, 0},
-#line 3544 "effective_tld_names.gperf"
+#line 4436 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5169, 0},
-#line 4096 "effective_tld_names.gperf"
+#line 5659 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5170, 0},
-#line 4157 "effective_tld_names.gperf"
+#line 3999 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5171, 0},
-#line 5426 "effective_tld_names.gperf"
+#line 49 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5172, 0},
-#line 5951 "effective_tld_names.gperf"
+#line 5643 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5173, 0},
-#line 5465 "effective_tld_names.gperf"
+#line 2850 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5174, 0},
-#line 629 "effective_tld_names.gperf"
+#line 6023 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5175, 0},
-#line 2083 "effective_tld_names.gperf"
+#line 4224 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5176, 0},
-#line 750 "effective_tld_names.gperf"
+#line 1464 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5177, 0},
-#line 2022 "effective_tld_names.gperf"
+#line 5035 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5178, 0},
-#line 2778 "effective_tld_names.gperf"
+#line 6042 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5179, 0},
-#line 6041 "effective_tld_names.gperf"
+#line 4483 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5180, 0},
-#line 3918 "effective_tld_names.gperf"
+#line 6024 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5181, 0},
-#line 2438 "effective_tld_names.gperf"
+#line 4884 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5182, 0},
-#line 5697 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5183, 4},
-#line 753 "effective_tld_names.gperf"
+#line 3299 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5183, 0},
+#line 5702 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5184, 0},
-#line 2409 "effective_tld_names.gperf"
+#line 4539 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5185, 0},
-#line 2437 "effective_tld_names.gperf"
+#line 6022 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5186, 0},
-#line 2276 "effective_tld_names.gperf"
+#line 1190 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5187, 0},
-#line 5687 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5188, 0},
-#line 1108 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5189, 4},
-#line 2647 "effective_tld_names.gperf"
+#line 3193 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5188, 4},
+#line 2695 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5189, 0},
+#line 4267 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5190, 0},
-#line 3644 "effective_tld_names.gperf"
+#line 4150 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5191, 0},
-#line 3583 "effective_tld_names.gperf"
+#line 3975 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5192, 0},
-#line 5548 "effective_tld_names.gperf"
+#line 2907 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5193, 0},
-#line 3377 "effective_tld_names.gperf"
+#line 4673 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5194, 0},
-#line 3149 "effective_tld_names.gperf"
+#line 5499 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5195, 0},
-#line 4719 "effective_tld_names.gperf"
+#line 3340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5196, 0},
-#line 66 "effective_tld_names.gperf"
+#line 48 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5197, 0},
-#line 4266 "effective_tld_names.gperf"
+#line 1844 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5198, 0},
-#line 4248 "effective_tld_names.gperf"
+#line 1265 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5199, 0},
-#line 3582 "effective_tld_names.gperf"
+#line 933 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5200, 0},
-#line 649 "effective_tld_names.gperf"
+#line 2947 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5201, 0},
-#line 4180 "effective_tld_names.gperf"
+#line 728 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5202, 0},
-#line 2852 "effective_tld_names.gperf"
+#line 354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5203, 0},
-#line 5677 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5204, 0},
-#line 3647 "effective_tld_names.gperf"
+#line 405 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5204, 4},
+#line 2835 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5205, 0},
-#line 4760 "effective_tld_names.gperf"
+#line 2808 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5206, 0},
-#line 3963 "effective_tld_names.gperf"
+#line 3172 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5207, 0},
-#line 4039 "effective_tld_names.gperf"
+#line 4083 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5208, 0},
-#line 1988 "effective_tld_names.gperf"
+#line 2807 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5209, 0},
-#line 3675 "effective_tld_names.gperf"
+#line 3212 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5210, 0},
-#line 3931 "effective_tld_names.gperf"
+#line 4157 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5211, 0},
-#line 3615 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5212, 0},
-#line 5603 "effective_tld_names.gperf"
+#line 1420 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5212, 4},
+#line 4136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5213, 0},
-#line 5960 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5214, 0},
-#line 2311 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5215, 4},
-#line 4851 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5216, 0},
-#line 3883 "effective_tld_names.gperf"
+#line 4233 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5214, 4},
+#line 2083 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5215, 0},
+#line 1421 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5216, 4},
+#line 5585 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5217, 0},
-#line 3645 "effective_tld_names.gperf"
+#line 5095 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5218, 0},
-#line 1335 "effective_tld_names.gperf"
+#line 3167 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5219, 0},
-#line 55 "effective_tld_names.gperf"
+#line 4251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5220, 0},
-#line 5499 "effective_tld_names.gperf"
+#line 5432 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5221, 0},
-#line 3995 "effective_tld_names.gperf"
+#line 3221 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5222, 0},
-#line 1916 "effective_tld_names.gperf"
+#line 5325 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5223, 0},
-#line 4164 "effective_tld_names.gperf"
+#line 4694 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5224, 0},
-#line 550 "effective_tld_names.gperf"
+#line 3949 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5225, 0},
-#line 4161 "effective_tld_names.gperf"
+#line 6030 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5226, 0},
-#line 3657 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5227, 1},
-#line 3899 "effective_tld_names.gperf"
+#line 1142 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5227, 0},
+#line 2814 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5228, 0},
-#line 5587 "effective_tld_names.gperf"
+#line 3755 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5229, 0},
-#line 4166 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5230, 0},
-#line 2575 "effective_tld_names.gperf"
+#line 4713 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5230, 4},
+#line 4075 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5231, 0},
-#line 4163 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5232, 0},
-#line 4162 "effective_tld_names.gperf"
+#line 1624 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5232, 4},
+#line 6005 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5233, 0},
-#line 3731 "effective_tld_names.gperf"
+#line 4897 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5234, 0},
-#line 3734 "effective_tld_names.gperf"
+#line 4003 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5235, 0},
-#line 3730 "effective_tld_names.gperf"
+#line 6129 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5236, 0},
-#line 5875 "effective_tld_names.gperf"
+#line 4159 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5237, 0},
-#line 4866 "effective_tld_names.gperf"
+#line 2821 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5238, 0},
-#line 5645 "effective_tld_names.gperf"
+#line 3247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5239, 0},
-#line 2429 "effective_tld_names.gperf"
+#line 5488 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5240, 0},
-#line 5135 "effective_tld_names.gperf"
+#line 4122 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5241, 0},
-#line 2420 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5242, 0},
-#line 4820 "effective_tld_names.gperf"
+#line 1423 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5242, 4},
+#line 5580 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5243, 0},
-#line 734 "effective_tld_names.gperf"
+#line 2673 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5244, 0},
-#line 4165 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5245, 0},
-#line 4722 "effective_tld_names.gperf"
+#line 1532 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5245, 4},
+#line 4316 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5246, 0},
-#line 140 "effective_tld_names.gperf"
+#line 2977 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5247, 0},
-#line 5943 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5248, 0},
-#line 5657 "effective_tld_names.gperf"
+#line 1199 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5248, 4},
+#line 4426 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5249, 0},
-#line 5087 "effective_tld_names.gperf"
+#line 3545 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5250, 0},
-#line 4934 "effective_tld_names.gperf"
+#line 5281 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5251, 0},
-#line 5750 "effective_tld_names.gperf"
+#line 3807 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5252, 0},
-#line 2099 "effective_tld_names.gperf"
+#line 2471 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5253, 4},
-#line 3732 "effective_tld_names.gperf"
+#line 6314 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5254, 0},
-#line 1965 "effective_tld_names.gperf"
+#line 4670 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5255, 0},
-#line 1093 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5256, 4},
-#line 5669 "effective_tld_names.gperf"
+#line 6198 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5256, 0},
+#line 6192 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5257, 0},
-#line 6007 "effective_tld_names.gperf"
+#line 6000 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5258, 0},
-#line 4158 "effective_tld_names.gperf"
+#line 5981 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5259, 0},
-#line 2096 "effective_tld_names.gperf"
+#line 2448 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5260, 4},
-#line 2345 "effective_tld_names.gperf"
+#line 2446 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5261, 4},
-#line 3538 "effective_tld_names.gperf"
+#line 3359 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5262, 0},
-#line 31 "effective_tld_names.gperf"
+#line 5506 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5263, 0},
-#line 2357 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5264, 4},
-#line 2678 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5265, 0},
-#line 2872 "effective_tld_names.gperf"
+#line 5036 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5264, 0},
+#line 4216 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5265, 4},
+#line 4210 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5266, 0},
-#line 400 "effective_tld_names.gperf"
+#line 306 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5267, 0},
-#line 4048 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5268, 1},
-#line 5730 "effective_tld_names.gperf"
+#line 5406 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5268, 0},
+#line 3213 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5269, 0},
-#line 3643 "effective_tld_names.gperf"
+#line 5616 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5270, 0},
-#line 2342 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5271, 4},
-#line 1009 "effective_tld_names.gperf"
+#line 317 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5271, 0},
+#line 3546 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5272, 0},
-#line 2297 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5273, 4},
-#line 4379 "effective_tld_names.gperf"
+#line 6184 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5273, 0},
+#line 6132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5274, 0},
-#line 5908 "effective_tld_names.gperf"
+#line 1772 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5275, 0},
-#line 2352 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5276, 4},
-#line 5959 "effective_tld_names.gperf"
+#line 1244 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5276, 0},
+#line 881 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5277, 0},
-#line 2811 "effective_tld_names.gperf"
+#line 6026 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5278, 0},
-#line 5566 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5279, 0},
-#line 853 "effective_tld_names.gperf"
+#line 1218 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5279, 4},
+#line 3427 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5280, 0},
-#line 4066 "effective_tld_names.gperf"
+#line 4060 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5281, 0},
-#line 2143 "effective_tld_names.gperf"
+#line 6063 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5282, 0},
-#line 3842 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5283, 0},
-#line 4275 "effective_tld_names.gperf"
+#line 612 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5283, 4},
+#line 4225 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5284, 0},
-#line 2877 "effective_tld_names.gperf"
+#line 2812 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5285, 0},
-#line 4089 "effective_tld_names.gperf"
+#line 5626 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5286, 0},
-#line 2329 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5287, 4},
-#line 3751 "effective_tld_names.gperf"
+#line 6062 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5287, 0},
+#line 3577 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5288, 0},
-#line 2042 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5289, 0},
-#line 3573 "effective_tld_names.gperf"
+#line 4979 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5289, 4},
+#line 6193 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5290, 0},
-#line 1776 "effective_tld_names.gperf"
+#line 2573 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5291, 0},
-#line 6071 "effective_tld_names.gperf"
+#line 3893 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5292, 0},
-#line 1227 "effective_tld_names.gperf"
+#line 1047 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5293, 0},
-#line 2348 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5294, 4},
-#line 924 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5295, 0},
-#line 1568 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5296, 0},
-#line 2687 "effective_tld_names.gperf"
+#line 5329 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5294, 0},
+#line 2468 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5295, 4},
+#line 2459 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5296, 4},
+#line 4255 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5297, 0},
-#line 380 "effective_tld_names.gperf"
+#line 3093 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5298, 0},
-#line 5480 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5299, 0},
-#line 2358 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5300, 4},
-#line 3658 "effective_tld_names.gperf"
+#line 1608 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5299, 4},
+#line 4158 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5300, 0},
+#line 4813 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5301, 0},
-#line 3839 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5302, 0},
-#line 2323 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5303, 4},
-#line 5139 "effective_tld_names.gperf"
+#line 4980 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5302, 4},
+#line 2125 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5303, 0},
+#line 5782 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5304, 0},
-#line 3738 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5305, 0},
-#line 3735 "effective_tld_names.gperf"
+#line 2449 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5305, 4},
+#line 5242 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5306, 0},
-#line 2353 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5307, 4},
-#line 4082 "effective_tld_names.gperf"
+#line 6187 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5307, 0},
+#line 1073 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5308, 0},
-#line 4474 "effective_tld_names.gperf"
+#line 5788 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5309, 0},
-#line 49 "effective_tld_names.gperf"
+#line 6161 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5310, 0},
-#line 4890 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5311, 0},
-#line 3737 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5312, 0},
-#line 5427 "effective_tld_names.gperf"
+#line 2488 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5311, 4},
+#line 1574 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5312, 4},
+#line 6213 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5313, 0},
-#line 1031 "effective_tld_names.gperf"
+#line 5343 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5314, 0},
-#line 5708 "effective_tld_names.gperf"
+#line 4473 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5315, 0},
-#line 4649 "effective_tld_names.gperf"
+#line 2824 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5316, 0},
-#line 1109 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5317, 4},
-#line 3736 "effective_tld_names.gperf"
+#line 3122 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5317, 0},
+#line 5340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5318, 0},
-#line 5961 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5319, 0},
-#line 6029 "effective_tld_names.gperf"
+#line 443 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5319, 4},
+#line 4145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5320, 0},
-#line 2404 "effective_tld_names.gperf"
+#line 4187 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5321, 0},
-#line 5702 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5322, 0},
-#line 293 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5323, 0},
-#line 5524 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5324, 4},
-#line 4185 "effective_tld_names.gperf"
+#line 1534 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5322, 4},
+#line 1799 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5323, 4},
+#line 5355 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5324, 0},
+#line 3291 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5325, 0},
-#line 4269 "effective_tld_names.gperf"
+#line 3902 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5326, 0},
-#line 4188 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5327, 0},
-#line 3739 "effective_tld_names.gperf"
+#line 1171 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5327, 4},
+#line 5076 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5328, 0},
-#line 5470 "effective_tld_names.gperf"
+#line 4022 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5329, 0},
-#line 4135 "effective_tld_names.gperf"
+#line 2823 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5330, 0},
-#line 4138 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5331, 0},
-#line 3848 "effective_tld_names.gperf"
+#line 1213 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5331, 4},
+#line 6186 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5332, 0},
-#line 4136 "effective_tld_names.gperf"
+#line 5363 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5333, 0},
-#line 4184 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5334, 0},
-#line 4192 "effective_tld_names.gperf"
+#line 1170 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5334, 4},
+#line 6087 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5335, 0},
-#line 3611 "effective_tld_names.gperf"
+#line 4577 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5336, 0},
-#line 173 "effective_tld_names.gperf"
+#line 104 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5337, 0},
-#line 5628 "effective_tld_names.gperf"
+#line 6015 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5338, 0},
-#line 3165 "effective_tld_names.gperf"
+#line 2075 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5339, 0},
-#line 5627 "effective_tld_names.gperf"
+#line 6019 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5340, 0},
-#line 436 "effective_tld_names.gperf"
+#line 4622 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5341, 0},
-#line 4220 "effective_tld_names.gperf"
+#line 5688 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5342, 0},
-#line 3996 "effective_tld_names.gperf"
+#line 71 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5343, 0},
-#line 5547 "effective_tld_names.gperf"
+#line 3756 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5344, 0},
-#line 4193 "effective_tld_names.gperf"
+#line 5625 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5345, 0},
-#line 68 "effective_tld_names.gperf"
+#line 2611 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5346, 0},
-#line 4142 "effective_tld_names.gperf"
+#line 3204 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5347, 0},
-#line 4191 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5348, 0},
-#line 4190 "effective_tld_names.gperf"
+#line 1212 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5348, 4},
+#line 2904 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5349, 0},
-#line 1977 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5350, 0},
-#line 4434 "effective_tld_names.gperf"
+#line 1601 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5350, 4},
+#line 5287 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5351, 0},
-#line 4141 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5352, 0},
-#line 4139 "effective_tld_names.gperf"
+#line 4788 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5352, 4},
+#line 4484 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5353, 0},
-#line 4444 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5354, 1},
-#line 3546 "effective_tld_names.gperf"
+#line 5337 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5354, 0},
+#line 6075 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5355, 0},
-#line 2325 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5356, 4},
-#line 4800 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5357, 0},
-#line 4189 "effective_tld_names.gperf"
+#line 51 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5356, 0},
+#line 1208 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5357, 4},
+#line 5354 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5358, 0},
-#line 92 "effective_tld_names.gperf"
+#line 472 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5359, 0},
-#line 2156 "effective_tld_names.gperf"
+#line 5359 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5360, 0},
-#line 1294 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5361, 4},
-#line 741 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5362, 0},
-#line 2378 "effective_tld_names.gperf"
+#line 4394 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5361, 0},
+#line 2490 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5362, 4},
+#line 5228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5363, 0},
-#line 3301 "effective_tld_names.gperf"
+#line 1637 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5364, 0},
-#line 5472 "effective_tld_names.gperf"
+#line 3392 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5365, 0},
-#line 3605 "effective_tld_names.gperf"
+#line 6181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5366, 0},
-#line 1868 "effective_tld_names.gperf"
+#line 5509 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5367, 0},
-#line 1125 "effective_tld_names.gperf"
+#line 1389 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5368, 4},
-#line 5752 "effective_tld_names.gperf"
+#line 411 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5369, 0},
-#line 443 "effective_tld_names.gperf"
+#line 5118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5370, 0},
-#line 5919 "effective_tld_names.gperf"
+#line 1096 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5371, 0},
-#line 1340 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5372, 4},
-#line 1991 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5373, 0},
-#line 2880 "effective_tld_names.gperf"
+#line 2403 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5372, 0},
+#line 2518 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5373, 4},
+#line 1038 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5374, 0},
-#line 4178 "effective_tld_names.gperf"
+#line 4885 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5375, 0},
-#line 4383 "effective_tld_names.gperf"
+#line 1932 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5376, 0},
-#line 367 "effective_tld_names.gperf"
+#line 3211 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5377, 0},
-#line 2315 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5378, 4},
-#line 3796 "effective_tld_names.gperf"
+#line 6086 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5378, 0},
+#line 2020 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5379, 0},
-#line 5748 "effective_tld_names.gperf"
+#line 4632 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5380, 0},
-#line 2654 "effective_tld_names.gperf"
+#line 4491 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5381, 0},
-#line 2097 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5382, 4},
-#line 5724 "effective_tld_names.gperf"
+#line 5996 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5382, 0},
+#line 3181 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5383, 0},
-#line 676 "effective_tld_names.gperf"
+#line 286 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5384, 0},
-#line 2126 "effective_tld_names.gperf"
+#line 4461 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5385, 0},
-#line 2393 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5386, 0},
-#line 2260 "effective_tld_names.gperf"
+#line 1600 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5386, 4},
+#line 4533 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5387, 0},
-#line 2259 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5388, 0},
-#line 3886 "effective_tld_names.gperf"
+#line 500 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5388, 4},
+#line 4570 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5389, 0},
-#line 4419 "effective_tld_names.gperf"
+#line 4182 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5390, 0},
-#line 4351 "effective_tld_names.gperf"
+#line 3666 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5391, 0},
-#line 1647 "effective_tld_names.gperf"
+#line 5829 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5392, 0},
-#line 3885 "effective_tld_names.gperf"
+#line 5229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5393, 0},
-#line 2340 "effective_tld_names.gperf"
+#line 1598 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5394, 4},
-#line 3902 "effective_tld_names.gperf"
+#line 378 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5395, 0},
-#line 4390 "effective_tld_names.gperf"
+#line 4985 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5396, 0},
-#line 3898 "effective_tld_names.gperf"
+#line 5822 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5397, 0},
-#line 3819 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5398, 0},
-#line 2677 "effective_tld_names.gperf"
+#line 499 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5398, 4},
+#line 3320 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5399, 0},
-#line 5569 "effective_tld_names.gperf"
+#line 1119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5400, 0},
-#line 4421 "effective_tld_names.gperf"
+#line 1944 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5401, 0},
-#line 3625 "effective_tld_names.gperf"
+#line 2765 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5402, 0},
-#line 5134 "effective_tld_names.gperf"
+#line 5502 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5403, 0},
-#line 990 "effective_tld_names.gperf"
+#line 1178 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5404, 0},
-#line 1606 "effective_tld_names.gperf"
+#line 5385 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5405, 0},
-#line 3756 "effective_tld_names.gperf"
+#line 4571 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5406, 0},
-#line 3668 "effective_tld_names.gperf"
+#line 4572 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5407, 0},
-#line 3758 "effective_tld_names.gperf"
+#line 4992 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5408, 0},
-#line 2572 "effective_tld_names.gperf"
+#line 4948 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5409, 0},
-#line 3712 "effective_tld_names.gperf"
+#line 3083 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5410, 0},
-#line 4283 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5411, 0},
-#line 3713 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5412, 0},
-#line 3755 "effective_tld_names.gperf"
+#line 2474 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5411, 4},
+#line 2478 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5412, 4},
+#line 4148 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5413, 0},
-#line 3762 "effective_tld_names.gperf"
+#line 5852 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5414, 0},
-#line 5498 "effective_tld_names.gperf"
+#line 6352 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5415, 0},
-#line 2168 "effective_tld_names.gperf"
+#line 4402 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5416, 0},
-#line 137 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5417, 0},
-#line 3887 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5418, 0},
-#line 4186 "effective_tld_names.gperf"
+#line 1210 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5417, 4},
+#line 1599 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5418, 4},
+#line 5572 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5419, 0},
-#line 4410 "effective_tld_names.gperf"
+#line 4489 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5420, 0},
-#line 3786 "effective_tld_names.gperf"
+#line 4872 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5421, 0},
-#line 3763 "effective_tld_names.gperf"
+#line 5474 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5422, 0},
-#line 4356 "effective_tld_names.gperf"
+#line 3275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5423, 0},
-#line 3717 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5424, 0},
-#line 4734 "effective_tld_names.gperf"
+#line 4981 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5424, 4},
+#line 2796 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5425, 0},
-#line 4422 "effective_tld_names.gperf"
+#line 5729 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5426, 0},
-#line 3761 "effective_tld_names.gperf"
+#line 3232 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5427, 0},
-#line 3760 "effective_tld_names.gperf"
+#line 4137 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5428, 0},
-#line 3767 "effective_tld_names.gperf"
+#line 4688 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5429, 0},
-#line 3716 "effective_tld_names.gperf"
+#line 5500 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5430, 0},
-#line 3714 "effective_tld_names.gperf"
+#line 4194 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5431, 0},
-#line 4098 "effective_tld_names.gperf"
+#line 2908 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5432, 0},
-#line 637 "effective_tld_names.gperf"
+#line 5999 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5433, 0},
-#line 4385 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5434, 0},
-#line 3838 "effective_tld_names.gperf"
+#line 1596 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5434, 4},
+#line 4573 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5435, 0},
-#line 4403 "effective_tld_names.gperf"
+#line 6121 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5436, 0},
-#line 4256 "effective_tld_names.gperf"
+#line 3790 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5437, 0},
-#line 3759 "effective_tld_names.gperf"
+#line 6108 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5438, 0},
-#line 4140 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5439, 0},
-#line 4360 "effective_tld_names.gperf"
+#line 2435 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5439, 4},
+#line 6111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5440, 0},
-#line 5929 "effective_tld_names.gperf"
+#line 4443 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5441, 0},
-#line 5568 "effective_tld_names.gperf"
+#line 5467 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5442, 0},
-#line 2660 "effective_tld_names.gperf"
+#line 5469 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5443, 0},
-#line 4187 "effective_tld_names.gperf"
+#line 574 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5444, 0},
-#line 2337 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5445, 4},
-#line 5656 "effective_tld_names.gperf"
+#line 5493 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5445, 0},
+#line 5470 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5446, 0},
-#line 4137 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5447, 0},
-#line 4443 "effective_tld_names.gperf"
+#line 1209 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5447, 4},
+#line 1512 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5448, 0},
-#line 3153 "effective_tld_names.gperf"
+#line 1945 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5449, 0},
-#line 3805 "effective_tld_names.gperf"
+#line 6174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5450, 0},
-#line 5993 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5451, 0},
-#line 5666 "effective_tld_names.gperf"
+#line 1597 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5451, 4},
+#line 5462 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5452, 0},
-#line 2326 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5453, 4},
-#line 2394 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5454, 4},
-#line 2330 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5455, 4},
-#line 4246 "effective_tld_names.gperf"
+#line 641 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5453, 0},
+#line 5652 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5454, 0},
+#line 5653 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5455, 0},
+#line 3813 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5456, 0},
-#line 4314 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5457, 1},
-#line 3078 "effective_tld_names.gperf"
+#line 2422 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5457, 4},
+#line 6090 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5458, 0},
-#line 3749 "effective_tld_names.gperf"
+#line 5069 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5459, 0},
-#line 647 "effective_tld_names.gperf"
+#line 6283 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5460, 0},
-#line 3607 "effective_tld_names.gperf"
+#line 5456 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5461, 0},
-#line 2284 "effective_tld_names.gperf"
+#line 3146 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5462, 0},
-#line 1619 "effective_tld_names.gperf"
+#line 5419 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5463, 0},
-#line 5756 "effective_tld_names.gperf"
+#line 6136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5464, 0},
-#line 653 "effective_tld_names.gperf"
+#line 5528 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5465, 0},
-#line 3616 "effective_tld_names.gperf"
+#line 4295 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5466, 0},
-#line 3514 "effective_tld_names.gperf"
+#line 6113 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5467, 0},
-#line 5874 "effective_tld_names.gperf"
+#line 6232 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5468, 0},
-#line 2344 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5469, 4},
-#line 4750 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5470, 4},
-#line 3571 "effective_tld_names.gperf"
+#line 5430 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5469, 0},
+#line 6175 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5470, 0},
+#line 4084 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5471, 0},
-#line 4967 "effective_tld_names.gperf"
+#line 5372 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5472, 0},
-#line 6019 "effective_tld_names.gperf"
+#line 4173 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5473, 0},
-#line 3608 "effective_tld_names.gperf"
+#line 93 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5474, 0},
-#line 1940 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5475, 0},
-#line 5217 "effective_tld_names.gperf"
+#line 2464 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5475, 4},
+#line 4447 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5476, 0},
-#line 3495 "effective_tld_names.gperf"
+#line 3549 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5477, 0},
-#line 5988 "effective_tld_names.gperf"
+#line 5223 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5478, 0},
-#line 75 "effective_tld_names.gperf"
+#line 3539 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5479, 0},
-#line 991 "effective_tld_names.gperf"
+#line 5214 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5480, 0},
-#line 445 "effective_tld_names.gperf"
+#line 4197 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5481, 0},
-#line 5872 "effective_tld_names.gperf"
+#line 6268 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5482, 0},
-#line 5923 "effective_tld_names.gperf"
+#line 3205 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5483, 0},
-#line 2312 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5484, 4},
-#line 2380 "effective_tld_names.gperf"
+#line 3542 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5484, 0},
+#line 2593 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5485, 0},
-#line 5950 "effective_tld_names.gperf"
+#line 3529 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5486, 0},
-#line 2201 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5487, 0},
-#line 3829 "effective_tld_names.gperf"
+#line 2437 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5487, 4},
+#line 92 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5488, 0},
-#line 2316 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5489, 4},
-#line 5567 "effective_tld_names.gperf"
+#line 1123 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5489, 0},
+#line 5230 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5490, 0},
-#line 3797 "effective_tld_names.gperf"
+#line 3976 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5491, 0},
-#line 638 "effective_tld_names.gperf"
+#line 564 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5492, 0},
-#line 4030 "effective_tld_names.gperf"
+#line 4916 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5493, 0},
-#line 5917 "effective_tld_names.gperf"
+#line 6080 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5494, 0},
-#line 1529 "effective_tld_names.gperf"
+#line 1143 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5495, 0},
-#line 2152 "effective_tld_names.gperf"
+#line 5463 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5496, 0},
-#line 2767 "effective_tld_names.gperf"
+#line 6176 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5497, 0},
-#line 5761 "effective_tld_names.gperf"
+#line 2565 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5498, 0},
-#line 5808 "effective_tld_names.gperf"
+#line 4492 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5499, 0},
-#line 4728 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5500, 0},
-#line 2612 "effective_tld_names.gperf"
+#line 2476 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5500, 4},
+#line 4504 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5501, 0},
-#line 4233 "effective_tld_names.gperf"
+#line 5464 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5502, 0},
-#line 5471 "effective_tld_names.gperf"
+#line 1754 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5503, 0},
-#line 2355 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5504, 4},
-#line 5987 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5505, 0},
-#line 3715 "effective_tld_names.gperf"
+#line 5041 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5504, 0},
+#line 1204 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5505, 4},
+#line 5647 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5506, 0},
-#line 3664 "effective_tld_names.gperf"
+#line 5651 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5507, 0},
-#line 1327 "effective_tld_names.gperf"
+#line 5744 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5508, 0},
-#line 2172 "effective_tld_names.gperf"
+#line 5415 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5509, 0},
-#line 3985 "effective_tld_names.gperf"
+#line 5648 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5510, 0},
-#line 4413 "effective_tld_names.gperf"
+#line 5986 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5511, 0},
-#line 4159 "effective_tld_names.gperf"
+#line 128 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5512, 0},
-#line 5067 "effective_tld_names.gperf"
+#line 6306 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5513, 0},
-#line 3547 "effective_tld_names.gperf"
+#line 6210 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5514, 0},
-#line 2350 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5515, 4},
-#line 2487 "effective_tld_names.gperf"
+#line 5335 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5515, 0},
+#line 103 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5516, 0},
-#line 3757 "effective_tld_names.gperf"
+#line 2096 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5517, 0},
-#line 5421 "effective_tld_names.gperf"
+#line 3220 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5518, 0},
-#line 2371 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5519, 4},
-#line 4737 "effective_tld_names.gperf"
+#line 201 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5519, 0},
+#line 5490 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5520, 0},
-#line 4054 "effective_tld_names.gperf"
+#line 637 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5521, 0},
-#line 3654 "effective_tld_names.gperf"
+#line 4580 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5522, 0},
-#line 4420 "effective_tld_names.gperf"
+#line 2243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5523, 0},
-#line 4307 "effective_tld_names.gperf"
+#line 5003 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5524, 0},
-#line 1931 "effective_tld_names.gperf"
+#line 387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5525, 0},
-#line 5755 "effective_tld_names.gperf"
+#line 6275 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5526, 0},
-#line 5936 "effective_tld_names.gperf"
+#line 2822 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5527, 0},
-#line 2748 "effective_tld_names.gperf"
+#line 5927 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5528, 0},
-#line 4382 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5529, 0},
-#line 4354 "effective_tld_names.gperf"
+#line 4982 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5529, 4},
+#line 6119 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5530, 0},
-#line 5616 "effective_tld_names.gperf"
+#line 5199 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5531, 0},
-#line 3951 "effective_tld_names.gperf"
+#line 6029 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5532, 0},
-#line 5878 "effective_tld_names.gperf"
+#line 5795 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5533, 0},
-#line 2282 "effective_tld_names.gperf"
+#line 6347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5534, 0},
-#line 2203 "effective_tld_names.gperf"
+#line 5501 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5535, 0},
-#line 3469 "effective_tld_names.gperf"
+#line 5322 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5536, 0},
-#line 3572 "effective_tld_names.gperf"
+#line 4546 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5537, 0},
-#line 5181 "effective_tld_names.gperf"
+#line 4487 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5538, 0},
-#line 2043 "effective_tld_names.gperf"
+#line 4639 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5539, 0},
-#line 2304 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5540, 4},
-#line 5735 "effective_tld_names.gperf"
+#line 5032 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5540, 0},
+#line 1179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5541, 0},
-#line 2698 "effective_tld_names.gperf"
+#line 4576 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5542, 0},
-#line 1374 "effective_tld_names.gperf"
+#line 4853 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5543, 0},
-#line 5533 "effective_tld_names.gperf"
+#line 67 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5544, 0},
-#line 5930 "effective_tld_names.gperf"
+#line 5196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5545, 0},
-#line 3187 "effective_tld_names.gperf"
+#line 5896 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5546, 0},
-#line 2227 "effective_tld_names.gperf"
+#line 4626 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5547, 0},
-#line 5679 "effective_tld_names.gperf"
+#line 2920 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5548, 0},
-#line 3903 "effective_tld_names.gperf"
+#line 2906 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5549, 0},
-#line 2151 "effective_tld_names.gperf"
+#line 4544 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5550, 0},
-#line 2359 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5551, 4},
-#line 5202 "effective_tld_names.gperf"
+#line 1131 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5551, 0},
+#line 4490 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5552, 0},
-#line 5658 "effective_tld_names.gperf"
+#line 1966 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5553, 0},
-#line 534 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5554, 4},
-#line 5694 "effective_tld_names.gperf"
+#line 4624 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5554, 0},
+#line 1174 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5555, 4},
-#line 5914 "effective_tld_names.gperf"
+#line 5328 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5556, 0},
-#line 4445 "effective_tld_names.gperf"
+#line 2820 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5557, 0},
-#line 5313 "effective_tld_names.gperf"
+#line 5133 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5558, 0},
-#line 3807 "effective_tld_names.gperf"
+#line 4850 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5559, 0},
-#line 1943 "effective_tld_names.gperf"
+#line 4519 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5560, 0},
-#line 4328 "effective_tld_names.gperf"
+#line 5261 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5561, 0},
-#line 4243 "effective_tld_names.gperf"
+#line 3870 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5562, 0},
-#line 4891 "effective_tld_names.gperf"
+#line 5331 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5563, 0},
-#line 4041 "effective_tld_names.gperf"
+#line 3365 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5564, 0},
-#line 5712 "effective_tld_names.gperf"
+#line 5072 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5565, 0},
-#line 5475 "effective_tld_names.gperf"
+#line 2076 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5566, 0},
-#line 2369 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5567, 4},
-#line 5991 "effective_tld_names.gperf"
+#line 4859 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5567, 0},
+#line 5160 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5568, 0},
-#line 3393 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5569, 0},
-#line 5809 "effective_tld_names.gperf"
+#line 2431 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5569, 4},
+#line 5442 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5570, 0},
-#line 2314 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5571, 4},
-#line 5495 "effective_tld_names.gperf"
+#line 793 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5571, 0},
+#line 3108 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5572, 0},
-#line 4453 "effective_tld_names.gperf"
+#line 3960 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5573, 0},
-#line 2272 "effective_tld_names.gperf"
+#line 3101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5574, 0},
-#line 5544 "effective_tld_names.gperf"
+#line 5908 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5575, 0},
-#line 1531 "effective_tld_names.gperf"
+#line 4763 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5576, 0},
-#line 4168 "effective_tld_names.gperf"
+#line 6221 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5577, 0},
-#line 1237 "effective_tld_names.gperf"
+#line 4460 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5578, 0},
-#line 5913 "effective_tld_names.gperf"
+#line 4538 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5579, 0},
-#line 2271 "effective_tld_names.gperf"
+#line 2801 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5580, 0},
-#line 933 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5581, 0},
-#line 2188 "effective_tld_names.gperf"
+#line 2517 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5581, 4},
+#line 4212 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5582, 0},
-#line 6033 "effective_tld_names.gperf"
+#line 4633 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5583, 0},
-#line 3181 "effective_tld_names.gperf"
+#line 5362 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5584, 0},
-#line 4412 "effective_tld_names.gperf"
+#line 4548 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5585, 0},
-#line 5301 "effective_tld_names.gperf"
+#line 4501 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5586, 0},
-#line 4177 "effective_tld_names.gperf"
+#line 3535 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5587, 0},
-#line 6003 "effective_tld_names.gperf"
+#line 3810 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5588, 0},
-#line 3733 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5589, 0},
-#line 727 "effective_tld_names.gperf"
+#line 2447 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5589, 4},
+#line 129 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5590, 0},
-#line 3947 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5591, 4},
-#line 4265 "effective_tld_names.gperf"
+#line 123 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5591, 0},
+#line 5476 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5592, 0},
-#line 4409 "effective_tld_names.gperf"
+#line 5606 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5593, 0},
-#line 2299 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5594, 4},
-#line 2955 "effective_tld_names.gperf"
+#line 5444 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5594, 0},
+#line 5571 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5595, 0},
-#line 4892 "effective_tld_names.gperf"
+#line 1138 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5596, 0},
-#line 5670 "effective_tld_names.gperf"
+#line 6229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5597, 0},
-#line 3830 "effective_tld_names.gperf"
+#line 5339 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5598, 0},
-#line 2154 "effective_tld_names.gperf"
+#line 6179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5599, 0},
-#line 1304 "effective_tld_names.gperf"
+#line 5657 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5600, 0},
-#line 155 "effective_tld_names.gperf"
+#line 649 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5601, 0},
-#line 3435 "effective_tld_names.gperf"
+#line 5278 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5602, 0},
-#line 5912 "effective_tld_names.gperf"
+#line 5473 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5603, 0},
-#line 992 "effective_tld_names.gperf"
+#line 5357 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5604, 0},
-#line 3831 "effective_tld_names.gperf"
+#line 5418 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5605, 0},
-#line 3828 "effective_tld_names.gperf"
+#line 5047 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5606, 0},
-#line 5704 "effective_tld_names.gperf"
+#line 3147 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5607, 0},
-#line 3815 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5608, 1},
-#line 6083 "effective_tld_names.gperf"
+#line 555 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5608, 0},
+#line 2818 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5609, 0},
-#line 2810 "effective_tld_names.gperf"
+#line 4610 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5610, 0},
-#line 2384 "effective_tld_names.gperf"
+#line 5346 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5611, 0},
-#line 1679 "effective_tld_names.gperf"
+#line 2810 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5612, 0},
-#line 730 "effective_tld_names.gperf"
+#line 2815 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5613, 0},
-#line 5981 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5614, 0},
-#line 2307 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5615, 4},
-#line 5681 "effective_tld_names.gperf"
+#line 1215 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5614, 4},
+#line 4154 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5615, 0},
+#line 2777 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5616, 0},
-#line 3381 "effective_tld_names.gperf"
+#line 5031 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5617, 0},
-#line 5742 "effective_tld_names.gperf"
+#line 5001 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5618, 0},
-#line 3177 "effective_tld_names.gperf"
+#line 74 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5619, 0},
-#line 2580 "effective_tld_names.gperf"
+#line 6043 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5620, 0},
-#line 4696 "effective_tld_names.gperf"
+#line 5637 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5621, 0},
-#line 2669 "effective_tld_names.gperf"
+#line 5375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5622, 0},
-#line 4976 "effective_tld_names.gperf"
+#line 4367 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5623, 0},
-#line 3906 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5624, 0},
-#line 5662 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5625, 0},
-#line 2816 "effective_tld_names.gperf"
+#line 4983 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5624, 4},
+#line 2439 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5625, 4},
+#line 4557 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5626, 0},
-#line 5393 "effective_tld_names.gperf"
+#line 6228 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5627, 0},
-#line 5978 "effective_tld_names.gperf"
+#line 3548 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5628, 0},
-#line 4386 "effective_tld_names.gperf"
+#line 5015 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5629, 0},
-#line 4997 "effective_tld_names.gperf"
+#line 4432 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5630, 0},
-#line 3192 "effective_tld_names.gperf"
+#line 6337 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5631, 0},
-#line 2239 "effective_tld_names.gperf"
+#line 5315 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5632, 0},
-#line 5938 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5633, 0},
-#line 5689 "effective_tld_names.gperf"
+#line 2438 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5633, 4},
+#line 3955 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5634, 0},
-#line 5931 "effective_tld_names.gperf"
+#line 4375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5635, 0},
-#line 4666 "effective_tld_names.gperf"
+#line 73 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5636, 0},
-#line 3806 "effective_tld_names.gperf"
+#line 5569 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5637, 0},
-#line 4318 "effective_tld_names.gperf"
+#line 6304 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5638, 0},
-#line 2174 "effective_tld_names.gperf"
+#line 5450 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5639, 0},
-#line 3256 "effective_tld_names.gperf"
+#line 262 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5640, 0},
-#line 1383 "effective_tld_names.gperf"
+#line 5650 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5641, 0},
-#line 334 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5642, 0},
-#line 4768 "effective_tld_names.gperf"
+#line 2454 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5642, 4},
+#line 4276 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5643, 0},
-#line 3741 "effective_tld_names.gperf"
+#line 1149 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5644, 0},
-#line 2460 "effective_tld_names.gperf"
+#line 4179 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5645, 0},
-#line 2258 "effective_tld_names.gperf"
+#line 3306 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5646, 0},
-#line 157 "effective_tld_names.gperf"
+#line 3587 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5647, 0},
-#line 2388 "effective_tld_names.gperf"
+#line 5453 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5648, 0},
-#line 6100 "effective_tld_names.gperf"
+#line 6191 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5649, 0},
-#line 3748 "effective_tld_names.gperf"
+#line 4569 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5650, 0},
-#line 783 "effective_tld_names.gperf"
+#line 2791 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5651, 0},
-#line 6073 "effective_tld_names.gperf"
+#line 2802 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5652, 0},
-#line 4352 "effective_tld_names.gperf"
+#line 6340 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5653, 0},
-#line 3104 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5654, 0},
-#line 1373 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5655, 0},
-#line 4194 "effective_tld_names.gperf"
+#line 1205 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5654, 4},
+#line 6357 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5655, 4},
+#line 2269 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5656, 0},
-#line 5502 "effective_tld_names.gperf"
+#line 5929 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5657, 0},
-#line 1848 "effective_tld_names.gperf"
+#line 4332 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5658, 0},
-#line 6093 "effective_tld_names.gperf"
+#line 6051 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5659, 0},
-#line 3384 "effective_tld_names.gperf"
+#line 4466 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5660, 0},
-#line 5879 "effective_tld_names.gperf"
+#line 3953 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5661, 0},
-#line 3178 "effective_tld_names.gperf"
+#line 5649 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5662, 0},
-#line 5683 "effective_tld_names.gperf"
+#line 5387 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5663, 0},
-#line 70 "effective_tld_names.gperf"
+#line 2347 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5664, 0},
-#line 5968 "effective_tld_names.gperf"
+#line 6130 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5665, 0},
-#line 5672 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5666, 0},
-#line 5698 "effective_tld_names.gperf"
+#line 1216 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5666, 4},
+#line 3057 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5667, 0},
-#line 2224 "effective_tld_names.gperf"
+#line 1141 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5668, 0},
-#line 2275 "effective_tld_names.gperf"
+#line 5665 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5669, 0},
-#line 5966 "effective_tld_names.gperf"
+#line 4908 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5670, 0},
-#line 2144 "effective_tld_names.gperf"
+#line 4351 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5671, 0},
-#line 5957 "effective_tld_names.gperf"
+#line 4910 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5672, 0},
-#line 3604 "effective_tld_names.gperf"
+#line 3856 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5673, 0},
-#line 4317 "effective_tld_names.gperf"
+#line 4520 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5674, 0},
-#line 1311 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5675, 4},
-#line 2277 "effective_tld_names.gperf"
+#line 3068 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5675, 0},
+#line 3550 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5676, 0},
-#line 5737 "effective_tld_names.gperf"
+#line 4559 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5677, 0},
-#line 5969 "effective_tld_names.gperf"
+#line 6302 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5678, 0},
-#line 3825 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5679, 0},
-#line 728 "effective_tld_names.gperf"
+#line 1203 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5679, 4},
+#line 5070 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5680, 0},
-#line 5695 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5681, 4},
-#line 3612 "effective_tld_names.gperf"
+#line 1237 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5681, 0},
+#line 4301 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5682, 0},
-#line 5967 "effective_tld_names.gperf"
+#line 4906 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5683, 0},
-#line 5070 "effective_tld_names.gperf"
+#line 5869 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5684, 0},
-#line 5885 "effective_tld_names.gperf"
+#line 4111 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5685, 0},
-#line 4416 "effective_tld_names.gperf"
+#line 6154 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5686, 0},
-#line 1626 "effective_tld_names.gperf"
+#line 1117 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5687, 0},
-#line 5506 "effective_tld_names.gperf"
+#line 4907 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5688, 0},
-#line 4417 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5689, 0},
-#line 5192 "effective_tld_names.gperf"
+#line 2491 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5689, 4},
+#line 5658 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5690, 0},
-#line 2274 "effective_tld_names.gperf"
+#line 5477 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5691, 0},
-#line 6048 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5692, 0},
-#line 4338 "effective_tld_names.gperf"
+#line 1217 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5692, 4},
+#line 5992 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5693, 0},
-#line 3386 "effective_tld_names.gperf"
+#line 5722 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5694, 0},
-#line 3653 "effective_tld_names.gperf"
+#line 4510 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5695, 0},
-#line 3559 "effective_tld_names.gperf"
+#line 5990 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5696, 0},
-#line 5740 "effective_tld_names.gperf"
+#line 4996 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5697, 0},
-#line 5880 "effective_tld_names.gperf"
+#line 3202 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5698, 0},
-#line 2671 "effective_tld_names.gperf"
+#line 5390 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5699, 0},
-#line 4274 "effective_tld_names.gperf"
+#line 5183 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5700, 0},
-#line 2457 "effective_tld_names.gperf"
+#line 3222 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5701, 0},
-#line 3922 "effective_tld_names.gperf"
+#line 3485 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5702, 0},
-#line 5156 "effective_tld_names.gperf"
+#line 5126 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5703, 0},
-#line 3190 "effective_tld_names.gperf"
+#line 5599 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5704, 0},
-#line 4570 "effective_tld_names.gperf"
+#line 6301 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5705, 0},
-#line 2263 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5706, 0},
-#line 4310 "effective_tld_names.gperf"
+#line 5447 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5706, 4},
+#line 3114 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5707, 0},
-#line 5691 "effective_tld_names.gperf"
+#line 4074 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5708, 0},
-#line 5493 "effective_tld_names.gperf"
+#line 5742 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5709, 0},
-#line 3603 "effective_tld_names.gperf"
+#line 3818 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5710, 0},
-#line 2376 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5711, 4},
-#line 5768 "effective_tld_names.gperf"
+#line 4674 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5711, 0},
+#line 592 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5712, 0},
-#line 3162 "effective_tld_names.gperf"
+#line 3540 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5713, 0},
-#line 2363 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5714, 4},
-#line 1361 "effective_tld_names.gperf"
+#line 3113 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5714, 0},
+#line 3243 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5715, 0},
-#line 4302 "effective_tld_names.gperf"
+#line 4144 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5716, 0},
-#line 3764 "effective_tld_names.gperf"
+#line 5327 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5717, 0},
-#line 3718 "effective_tld_names.gperf"
+#line 5348 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5718, 0},
-#line 2820 "effective_tld_names.gperf"
+#line 5020 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5719, 0},
-#line 6095 "effective_tld_names.gperf"
+#line 6083 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5720, 0},
-#line 5332 "effective_tld_names.gperf"
+#line 5321 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5721, 0},
-#line 2374 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5722, 4},
-#line 3182 "effective_tld_names.gperf"
+#line 4514 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5722, 0},
+#line 1136 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5723, 0},
-#line 1289 "effective_tld_names.gperf"
+#line 2171 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5724, 0},
-#line 4074 "effective_tld_names.gperf"
+#line 2817 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5725, 0},
-#line 1541 "effective_tld_names.gperf"
+#line 5527 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5726, 0},
-#line 3137 "effective_tld_names.gperf"
+#line 5429 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5727, 0},
-#line 2377 "effective_tld_names.gperf"
+#line 6003 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5728, 0},
-#line 2375 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5729, 4},
-#line 279 "effective_tld_names.gperf"
+#line 5129 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5729, 0},
+#line 3237 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5730, 0},
-#line 5798 "effective_tld_names.gperf"
+#line 2268 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5731, 0},
-#line 3913 "effective_tld_names.gperf"
+#line 1444 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5732, 0},
-#line 2659 "effective_tld_names.gperf"
+#line 3537 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5733, 0},
-#line 1530 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5734, 0},
-#line 3516 "effective_tld_names.gperf"
+#line 4475 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5734, 1},
+#line 3800 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5735, 0},
-#line 3185 "effective_tld_names.gperf"
+#line 5006 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5736, 0},
-#line 3622 "effective_tld_names.gperf"
+#line 5008 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5737, 0},
-#line 5494 "effective_tld_names.gperf"
+#line 4616 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5738, 0},
-#line 3567 "effective_tld_names.gperf"
+#line 5516 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5739, 0},
-#line 2826 "effective_tld_names.gperf"
+#line 5604 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5740, 0},
-#line 2910 "effective_tld_names.gperf"
+#line 4551 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5741, 0},
-#line 2411 "effective_tld_names.gperf"
+#line 895 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5742, 0},
-#line 4414 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5743, 0},
-#line 2386 "effective_tld_names.gperf"
+#line 1184 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5743, 4},
+#line 5446 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5744, 0},
-#line 5980 "effective_tld_names.gperf"
+#line 2806 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5745, 0},
-#line 5318 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5746, 0},
-#line 3566 "effective_tld_names.gperf"
+#line 1183 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5746, 4},
+#line 3789 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5747, 0},
-#line 5700 "effective_tld_names.gperf"
+#line 2811 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5748, 0},
-#line 1706 "effective_tld_names.gperf"
+#line 896 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5749, 0},
-#line 5546 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5750, 0},
-#line 5661 "effective_tld_names.gperf"
+#line 2242 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5750, 4},
+#line 2609 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5751, 0},
-#line 3801 "effective_tld_names.gperf"
+#line 6041 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5752, 0},
-#line 5997 "effective_tld_names.gperf"
+#line 2587 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5753, 0},
-#line 4339 "effective_tld_names.gperf"
+#line 6375 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5754, 0},
-#line 5877 "effective_tld_names.gperf"
+#line 4509 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5755, 0},
-#line 3188 "effective_tld_names.gperf"
+#line 4601 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5756, 0},
-#line 4441 "effective_tld_names.gperf"
+#line 6170 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5757, 0},
-#line 2261 "effective_tld_names.gperf"
+#line 3973 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5758, 0},
-#line 4384 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5759, 0},
-#line 5734 "effective_tld_names.gperf"
+#line 1707 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5759, 4},
+#line 5584 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5760, 0},
-#line 3565 "effective_tld_names.gperf"
+#line 6199 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5761, 0},
-#line 5550 "effective_tld_names.gperf"
+#line 4567 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5762, 0},
-#line 5462 "effective_tld_names.gperf"
+#line 4417 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5763, 0},
-#line 5685 "effective_tld_names.gperf"
+#line 5428 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5764, 0},
-#line 5711 "effective_tld_names.gperf"
+#line 4833 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5765, 0},
-#line 6027 "effective_tld_names.gperf"
+#line 5583 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5766, 0},
-#line 5956 "effective_tld_names.gperf"
+#line 5980 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5767, 0},
-#line 3387 "effective_tld_names.gperf"
+#line 4957 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5768, 0},
-#line 3857 "effective_tld_names.gperf"
+#line 3983 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5769, 0},
-#line 4347 "effective_tld_names.gperf"
+#line 2285 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5770, 0},
-#line 5684 "effective_tld_names.gperf"
+#line 5310 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5771, 0},
-#line 6099 "effective_tld_names.gperf"
+#line 250 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5772, 0},
-#line 5965 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5773, 0},
-#line 278 "effective_tld_names.gperf"
+#line 1390 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5773, 4},
+#line 6109 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5774, 0},
-#line 6023 "effective_tld_names.gperf"
+#line 3543 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5775, 0},
-#line 5799 "effective_tld_names.gperf"
+#line 6209 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5776, 0},
-#line 5773 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5777, 0},
-#line 6054 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5778, 0},
-#line 3649 "effective_tld_names.gperf"
+#line 2444 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5777, 4},
+#line 2473 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5778, 4},
+#line 5045 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5779, 0},
-#line 4402 "effective_tld_names.gperf"
+#line 4900 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5780, 0},
-#line 2204 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5781, 4},
-#line 5770 "effective_tld_names.gperf"
+#line 4477 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5781, 0},
+#line 5478 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5782, 0},
-#line 4944 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5783, 0},
-#line 5800 "effective_tld_names.gperf"
+#line 6362 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5783, 4},
+#line 5619 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5784, 0},
-#line 4387 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5785, 0},
-#line 5112 "effective_tld_names.gperf"
+#line 1595 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5785, 4},
+#line 5531 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5786, 0},
-#line 5673 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5787, 0},
-#line 2235 "effective_tld_names.gperf"
+#line 2430 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5787, 4},
+#line 4430 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5788, 0},
-#line 3184 "effective_tld_names.gperf"
+#line 5577 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5789, 0},
-#line 2057 "effective_tld_names.gperf"
+#line 3236 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5790, 0},
-#line 6062 "effective_tld_names.gperf"
+#line 6147 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5791, 0},
-#line 3341 "effective_tld_names.gperf"
+#line 1151 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5792, 0},
-#line 5485 "effective_tld_names.gperf"
+#line 4368 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5793, 0},
-#line 3111 "effective_tld_names.gperf"
+#line 2857 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5794, 0},
-#line 5994 "effective_tld_names.gperf"
+#line 4323 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5795, 0},
-#line 3186 "effective_tld_names.gperf"
+#line 4901 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5796, 0},
-#line 4411 "effective_tld_names.gperf"
+#line 2271 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5797, 0},
-#line 5771 "effective_tld_names.gperf"
+#line 5380 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5798, 0},
-#line 3452 "effective_tld_names.gperf"
+#line 4156 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5799, 0},
-#line 5793 "effective_tld_names.gperf"
+#line 4112 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5800, 0},
-#line 4896 "effective_tld_names.gperf"
+#line 5409 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5801, 0},
-#line 4361 "effective_tld_names.gperf"
+#line 5317 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5802, 0},
-#line 4702 "effective_tld_names.gperf"
+#line 4334 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5803, 0},
-#line 3189 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5804, 0},
-#line 5983 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5805, 0},
-#line 5477 "effective_tld_names.gperf"
+#line 1187 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5804, 4},
+#line 5692 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5805, 4},
+#line 6142 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5806, 0},
-#line 6028 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5807, 0},
-#line 2401 "effective_tld_names.gperf"
+#line 2427 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5807, 4},
+#line 1974 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5808, 0},
-#line 5729 "effective_tld_names.gperf"
+#line 1970 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5809, 0},
-#line 4599 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5810, 4},
-#line 2389 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5811, 0},
-#line 2175 "effective_tld_names.gperf"
+#line 6049 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5810, 0},
+#line 221 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5811, 4},
+#line 4203 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5812, 0},
-#line 2177 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5813, 0},
-#line 2264 "effective_tld_names.gperf"
+#line 5253 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5813, 4},
+#line 4031 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5814, 0},
-#line 6078 "effective_tld_names.gperf"
+#line 4556 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5815, 0},
-#line 3191 "effective_tld_names.gperf"
+#line 6110 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5816, 0},
-#line 2402 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5817, 0},
-#line 2670 "effective_tld_names.gperf"
+#line 3519 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5817, 4},
+#line 6071 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5818, 0},
-#line 6002 "effective_tld_names.gperf"
+#line 5466 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5819, 0},
-#line 5574 "effective_tld_names.gperf"
+#line 4921 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5820, 0},
-#line 5977 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5821, 0},
-#line 3613 "effective_tld_names.gperf"
+#line 326 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5821, 4},
+#line 3171 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5822, 0},
-#line 5788 "effective_tld_names.gperf"
+#line 5991 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5823, 0},
-#line 2273 "effective_tld_names.gperf"
+#line 6072 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5824, 0},
-#line 6030 "effective_tld_names.gperf"
+#line 4894 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5825, 0},
-#line 5719 "effective_tld_names.gperf"
+#line 270 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5826, 0},
-#line 5774 "effective_tld_names.gperf"
+#line 85 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5827, 0},
-#line 5709 "effective_tld_names.gperf"
+#line 5192 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5828, 0},
-#line 5845 "effective_tld_names.gperf"
+#line 2864 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5829, 0},
-#line 5777 "effective_tld_names.gperf"
+#line 2560 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5830, 0},
-#line 4167 "effective_tld_names.gperf"
+#line 5441 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5831, 0},
-#line 6000 "effective_tld_names.gperf"
+#line 1437 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5832, 0},
-#line 3640 "effective_tld_names.gperf"
+#line 6252 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5833, 0},
-#line 4330 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5834, 0},
-#line 739 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5835, 0},
-#line 5881 "effective_tld_names.gperf"
+#line 4968 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5834, 4},
+#line 4984 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5835, 4},
+#line 6195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5836, 0},
-#line 4614 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5837, 4},
-#line 5772 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5838, 0},
-#line 2749 "effective_tld_names.gperf"
+#line 2585 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5837, 0},
+#line 2608 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5838, 4},
+#line 5515 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5839, 0},
-#line 4308 "effective_tld_names.gperf"
+#line 1398 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5840, 0},
-#line 5211 "effective_tld_names.gperf"
+#line 1492 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5841, 0},
-#line 3568 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5842, 0},
-#line 5534 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5843, 0},
-#line 5680 "effective_tld_names.gperf"
+#line 4802 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5842, 4},
+#line 3680 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5843, 4},
+#line 4874 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5844, 0},
-#line 5792 "effective_tld_names.gperf"
+#line 5618 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5845, 0},
-#line 682 "effective_tld_names.gperf"
+#line 3670 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5846, 0},
-#line 5998 "effective_tld_names.gperf"
+#line 6047 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5847, 0},
-#line 5674 "effective_tld_names.gperf"
+#line 3248 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5848, 0},
-#line 3638 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5849, 1},
-#line 4376 "effective_tld_names.gperf"
+#line 1611 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5849, 4},
+#line 4506 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5850, 0},
-#line 5463 "effective_tld_names.gperf"
+#line 4922 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5851, 0},
-#line 3800 "effective_tld_names.gperf"
+#line 6141 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5852, 0},
-#line 4271 "effective_tld_names.gperf"
+#line 4195 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5853, 0},
-#line 4394 "effective_tld_names.gperf"
+#line 3154 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5854, 0},
-#line 5898 "effective_tld_names.gperf"
+#line 5634 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5855, 0},
-#line 4023 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5856, 0},
-#line 5778 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5857, 0},
-#line 4298 "effective_tld_names.gperf"
+#line 1610 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5856, 4},
+#line 1435 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5857, 4},
+#line 3735 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5858, 0},
-#line 5843 "effective_tld_names.gperf"
+#line 6220 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5859, 0},
-#line 4345 "effective_tld_names.gperf"
+#line 5336 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5860, 0},
-#line 5769 "effective_tld_names.gperf"
+#line 5627 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5861, 0},
-#line 5889 "effective_tld_names.gperf"
+#line 6160 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5862, 0},
-#line 5492 "effective_tld_names.gperf"
+#line 6095 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5863, 0},
-#line 5996 "effective_tld_names.gperf"
+#line 1147 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5864, 0},
-#line 3740 "effective_tld_names.gperf"
+#line 4923 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5865, 0},
-#line 5890 "effective_tld_names.gperf"
+#line 3245 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5866, 0},
-#line 5897 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5867, 0},
-#line 6055 "effective_tld_names.gperf"
+#line 5734 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5867, 4},
+#line 1115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5868, 0},
-#line 2849 "effective_tld_names.gperf"
+#line 777 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5869, 0},
-#line 2362 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5870, 4},
-#line 2385 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5871, 0},
-#line 5212 "effective_tld_names.gperf"
+#line 3126 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5870, 0},
+#line 5733 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5871, 4},
+#line 1041 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5872, 0},
-#line 2305 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5873, 4},
-#line 5797 "effective_tld_names.gperf"
+#line 2805 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5873, 0},
+#line 4932 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5874, 0},
-#line 4897 "effective_tld_names.gperf"
+#line 3208 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5875, 0},
-#line 5992 "effective_tld_names.gperf"
+#line 4933 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5876, 0},
-#line 4461 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5877, 0},
-#line 5935 "effective_tld_names.gperf"
+#line 223 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5877, 4},
+#line 4132 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5878, 0},
-#line 1582 "effective_tld_names.gperf"
+#line 2602 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5879, 0},
-#line 5861 "effective_tld_names.gperf"
+#line 2599 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5880, 0},
-#line 5844 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5881, 0},
-#line 71 "effective_tld_names.gperf"
+#line 222 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5881, 4},
+#line 2612 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5882, 0},
-#line 2733 "effective_tld_names.gperf"
+#line 1992 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5883, 0},
-#line 2407 "effective_tld_names.gperf"
+#line 3079 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5884, 0},
-#line 5896 "effective_tld_names.gperf"
+#line 5311 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5885, 0},
-#line 4437 "effective_tld_names.gperf"
+#line 2905 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5886, 0},
-#line 2161 "effective_tld_names.gperf"
+#line 4929 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5887, 0},
-#line 4440 "effective_tld_names.gperf"
+#line 2616 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5888, 0},
-#line 4372 "effective_tld_names.gperf"
+#line 1182 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5889, 0},
-#line 6001 "effective_tld_names.gperf"
+#line 1128 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5890, 0},
-#line 3166 "effective_tld_names.gperf"
+#line 3230 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5891, 0},
-#line 3623 "effective_tld_names.gperf"
+#line 6247 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5892, 0},
-#line 5893 "effective_tld_names.gperf"
+#line 3188 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5893, 0},
-#line 5490 "effective_tld_names.gperf"
+#line 2087 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5894, 0},
-#line 4329 "effective_tld_names.gperf"
+#line 717 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5895, 0},
-#line 2232 "effective_tld_names.gperf"
+#line 676 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5896, 0},
-#line 5851 "effective_tld_names.gperf"
+#line 2627 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5897, 0},
-#line 5525 "effective_tld_names.gperf"
+#line 675 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5898, 0},
-#line 5870 "effective_tld_names.gperf"
+#line 674 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5899, 0},
-#line 3517 "effective_tld_names.gperf"
+#line 4298 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5900, 0},
-#line 4389 "effective_tld_names.gperf"
+#line 712 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5901, 0},
-#line 5860 "effective_tld_names.gperf"
+#line 698 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5902, 0},
-#line 3646 "effective_tld_names.gperf"
+#line 694 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5903, 0},
-#line 5766 "effective_tld_names.gperf"
+#line 673 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5904, 0},
-#line 2423 "effective_tld_names.gperf"
+#line 699 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5905, 0},
-#line 5803 "effective_tld_names.gperf"
+#line 4615 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5906, 0},
-#line 5765 "effective_tld_names.gperf"
+#line 4857 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5907, 0},
-#line 5136 "effective_tld_names.gperf"
+#line 703 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5908, 0},
-#line 3179 "effective_tld_names.gperf"
+#line 4175 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5909, 0},
-#line 3871 "effective_tld_names.gperf"
+#line 3958 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5910, 0},
-#line 5995 "effective_tld_names.gperf"
+#line 718 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5911, 0},
-#line 2672 "effective_tld_names.gperf"
+#line 5539 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5912, 0},
-#line 5986 "effective_tld_names.gperf"
+#line 3086 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5913, 0},
-#line 4346 "effective_tld_names.gperf"
+#line 5071 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5914, 0},
-#line 2306 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5915, 4},
-#line 4369 "effective_tld_names.gperf"
+#line 2610 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5915, 0},
+#line 684 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5916, 0},
-#line 5868 "effective_tld_names.gperf"
+#line 697 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5917, 0},
-#line 4462 "effective_tld_names.gperf"
+#line 678 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5918, 0},
-#line 5802 "effective_tld_names.gperf"
+#line 681 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5919, 0},
-#line 4751 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5920, 4},
-#line 5944 "effective_tld_names.gperf"
+#line 720 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5920, 0},
+#line 695 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5921, 0},
-#line 5902 "effective_tld_names.gperf"
+#line 2264 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5922, 0},
-#line 5513 "effective_tld_names.gperf"
+#line 1129 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5923, 0},
-#line 2663 "effective_tld_names.gperf"
+#line 704 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5924, 0},
-#line 5895 "effective_tld_names.gperf"
+#line 700 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5925, 0},
-#line 5945 "effective_tld_names.gperf"
+#line 5503 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5926, 0},
-#line 5862 "effective_tld_names.gperf"
+#line 682 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5927, 0},
-#line 5849 "effective_tld_names.gperf"
+#line 6196 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5928, 0},
-#line 2571 "effective_tld_names.gperf"
+#line 5701 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5929, 0},
-#line 5847 "effective_tld_names.gperf"
+#line 330 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5930, 0},
-#line 2291 "effective_tld_names.gperf"
+#line 3251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5931, 0},
-#line 5903 "effective_tld_names.gperf"
+#line 4446 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5932, 0},
-#line 5682 "effective_tld_names.gperf"
+#line 696 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5933, 0},
-#line 5891 "effective_tld_names.gperf"
+#line 715 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5934, 0},
-#line 5850 "effective_tld_names.gperf"
+#line 679 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5935, 0},
-#line 5848 "effective_tld_names.gperf"
+#line 3105 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5936, 0},
-#line 4253 "effective_tld_names.gperf"
+#line 1148 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5937, 0},
-#line 5901 "effective_tld_names.gperf"
+#line 690 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5938, 0},
-#line 5790 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5939, 0},
-#line 748 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5940, 0},
-#line 4179 "effective_tld_names.gperf"
+#line 2466 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5939, 4},
+#line 5955 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5940, 1},
+#line 4131 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5941, 0},
-#line 5510 "effective_tld_names.gperf"
+#line 1042 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5942, 0},
-#line 5846 "effective_tld_names.gperf"
+#line 709 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5943, 0},
-#line 5867 "effective_tld_names.gperf"
+#line 3240 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5944, 0},
-#line 5999 "effective_tld_names.gperf"
+#line 706 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5945, 0},
-#line 5529 "effective_tld_names.gperf"
+#line 707 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5946, 0},
-#line 5479 "effective_tld_names.gperf"
+#line 2576 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5947, 0},
-#line 5852 "effective_tld_names.gperf"
+#line 5318 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5948, 0},
-#line 4395 "effective_tld_names.gperf"
+#line 692 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5949, 0},
-#line 2218 "effective_tld_names.gperf"
+#line 3216 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5950, 0},
-#line 4000 "effective_tld_names.gperf"
+#line 693 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5951, 0},
-#line 3135 "effective_tld_names.gperf"
+#line 1067 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5952, 0},
-#line 2373 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5953, 4},
-#line 5876 "effective_tld_names.gperf"
+#line 4926 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5953, 0},
+#line 683 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5954, 0},
-#line 5767 "effective_tld_names.gperf"
+#line 4909 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5955, 0},
-#line 3948 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5956, 0},
-#line 2146 "effective_tld_names.gperf"
+#line 404 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5956, 4},
+#line 4861 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5957, 0},
-#line 5899 "effective_tld_names.gperf"
+#line 208 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5958, 0},
-#line 3183 "effective_tld_names.gperf"
+#line 691 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5959, 0},
-#line 4435 "effective_tld_names.gperf"
+#line 708 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5960, 0},
-#line 2138 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5961, 4},
-#line 3750 "effective_tld_names.gperf"
+#line 677 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5961, 0},
+#line 2520 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5962, 0},
-#line 5814 "effective_tld_names.gperf"
+#line 4508 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5963, 0},
-#line 5815 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5964, 0},
-#line 3540 "effective_tld_names.gperf"
+#line 1767 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5964, 4},
+#line 710 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5965, 0},
-#line 4596 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5966, 4},
-#line 4458 "effective_tld_names.gperf"
+#line 685 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5966, 0},
+#line 705 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5967, 0},
-#line 5530 "effective_tld_names.gperf"
+#line 5005 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5968, 0},
-#line 4337 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5969, 0},
-#line 5947 "effective_tld_names.gperf"
+#line 2479 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5969, 4},
+#line 1650 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5970, 0},
-#line 5764 "effective_tld_names.gperf"
+#line 5370 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5971, 0},
-#line 4895 "effective_tld_names.gperf"
+#line 2408 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5972, 0},
-#line 4597 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5973, 4},
-#line 4415 "effective_tld_names.gperf"
+#line 672 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5973, 0},
+#line 711 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5974, 0},
-#line 4418 "effective_tld_names.gperf"
+#line 1145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5975, 0},
-#line 5706 "effective_tld_names.gperf"
+#line 1177 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5976, 0},
-#line 5794 "effective_tld_names.gperf"
+#line 5882 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5977, 0},
-#line 5819 "effective_tld_names.gperf"
+#line 5204 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5978, 0},
-#line 5801 "effective_tld_names.gperf"
+#line 2538 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5979, 0},
-#line 5842 "effective_tld_names.gperf"
+#line 5334 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5980, 0},
-#line 5863 "effective_tld_names.gperf"
+#line 3209 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5981, 0},
-#line 4397 "effective_tld_names.gperf"
+#line 3140 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5982, 0},
-#line 4336 "effective_tld_names.gperf"
+#line 4160 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5983, 0},
-#line 2419 "effective_tld_names.gperf"
+#line 5251 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5984, 0},
-#line 4358 "effective_tld_names.gperf"
+#line 4609 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5985, 0},
-#line 3569 "effective_tld_names.gperf"
+#line 3235 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5986, 0},
-#line 5886 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5987, 0},
-#line 5812 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5988, 0},
-#line 5791 "effective_tld_names.gperf"
+#line 4791 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5987, 4},
+#line 4792 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5988, 4},
+#line 274 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5989, 0},
-#line 5710 "effective_tld_names.gperf"
+#line 3107 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5990, 0},
-#line 5835 "effective_tld_names.gperf"
+#line 5351 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5991, 0},
-#line 3564 "effective_tld_names.gperf"
+#line 3229 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5992, 0},
-#line 4598 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5993, 4},
-#line 5831 "effective_tld_names.gperf"
+#line 3139 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5993, 0},
+#line 2541 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5994, 0},
-#line 4335 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str5995, 0},
-#line 5811 "effective_tld_names.gperf"
+#line 4787 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str5995, 4},
+#line 4280 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5996, 0},
-#line 5775 "effective_tld_names.gperf"
+#line 3231 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5997, 0},
-#line 4334 "effective_tld_names.gperf"
+#line 3133 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5998, 0},
-#line 5818 "effective_tld_names.gperf"
+#line 35 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str5999, 0},
-#line 5760 "effective_tld_names.gperf"
+#line 3217 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6000, 0},
-#line 5883 "effective_tld_names.gperf"
+#line 4947 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6001, 0},
-#line 5887 "effective_tld_names.gperf"
+#line 2594 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6002, 0},
-#line 2387 "effective_tld_names.gperf"
+#line 2902 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6003, 0},
-#line 5795 "effective_tld_names.gperf"
+#line 3241 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6004, 0},
-#line 5543 "effective_tld_names.gperf"
+#line 4599 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6005, 0},
-#line 5839 "effective_tld_names.gperf"
+#line 5763 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6006, 0},
-#line 5838 "effective_tld_names.gperf"
+#line 5613 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6007, 0},
-#line 5731 "effective_tld_names.gperf"
+#line 5218 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6008, 0},
-#line 4323 "effective_tld_names.gperf"
+#line 3189 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6009, 0},
-#line 218 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6010, 4},
-#line 2415 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6011, 0},
-#line 6032 "effective_tld_names.gperf"
+#line 3668 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6010, 0},
+#line 1613 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6011, 4},
+#line 3145 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6012, 0},
-#line 6070 "effective_tld_names.gperf"
+#line 4604 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6013, 0},
-#line 5841 "effective_tld_names.gperf"
+#line 687 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6014, 0},
-#line 2310 "effective_tld_names.gperf"
+#line 3112 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6015, 4},
-#line 5810 "effective_tld_names.gperf"
+#line 688 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6016, 0},
-#line 5785 "effective_tld_names.gperf"
+#line 5480 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6017, 0},
-#line 2149 "effective_tld_names.gperf"
+#line 5075 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6018, 0},
-#line 5825 "effective_tld_names.gperf"
+#line 4248 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6019, 0},
-#line 5816 "effective_tld_names.gperf"
+#line 689 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6020, 0},
-#line 5813 "effective_tld_names.gperf"
+#line 725 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6021, 0},
-#line 5884 "effective_tld_names.gperf"
+#line 5588 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6022, 0},
-#line 5853 "effective_tld_names.gperf"
+#line 241 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6023, 0},
-#line 5946 "effective_tld_names.gperf"
+#line 5598 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6024, 0},
-#line 5827 "effective_tld_names.gperf"
+#line 3050 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6025, 0},
-#line 1961 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6026, 0},
-#line 2673 "effective_tld_names.gperf"
+#line 5420 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6026, 4},
+#line 727 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6027, 0},
-#line 2150 "effective_tld_names.gperf"
+#line 1043 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6028, 0},
-#line 5789 "effective_tld_names.gperf"
+#line 3255 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6029, 0},
-#line 5787 "effective_tld_names.gperf"
+#line 4552 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6030, 0},
-#line 3855 "effective_tld_names.gperf"
+#line 4412 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6031, 0},
-#line 5892 "effective_tld_names.gperf"
+#line 2566 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6032, 0},
-#line 5834 "effective_tld_names.gperf"
+#line 1116 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6033, 0},
-#line 3650 "effective_tld_names.gperf"
+#line 5661 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6034, 0},
-#line 5783 "effective_tld_names.gperf"
+#line 724 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6035, 0},
-#line 5784 "effective_tld_names.gperf"
+#line 5589 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6036, 0},
-#line 6018 "effective_tld_names.gperf"
+#line 5410 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6037, 0},
-#line 5830 "effective_tld_names.gperf"
+#line 2590 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6038, 0},
-#line 5820 "effective_tld_names.gperf"
+#line 5590 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6039, 0},
-#line 5776 "effective_tld_names.gperf"
+#line 5439 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6040, 0},
-#line 5904 "effective_tld_names.gperf"
+#line 3206 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6041, 0},
-#line 5782 "effective_tld_names.gperf"
+#line 726 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6042, 0},
-#line 5854 "effective_tld_names.gperf"
+#line 6166 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6043, 0},
-#line 5828 "effective_tld_names.gperf"
+#line 686 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6044, 0},
-#line 5856 "effective_tld_names.gperf"
+#line 3200 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6045, 0},
-#line 2949 "effective_tld_names.gperf"
+#line 4597 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6046, 0},
-#line 5864 "effective_tld_names.gperf"
+#line 5101 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6047, 0},
-#line 5865 "effective_tld_names.gperf"
+#line 3180 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6048, 0},
-#line 4312 "effective_tld_names.gperf"
+#line 5595 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6049, 0},
-#line 4380 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6050, 4},
-#line 5979 "effective_tld_names.gperf"
+#line 4585 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6050, 0},
+#line 4588 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6051, 0},
-#line 5829 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6052, 0},
-#line 5858 "effective_tld_names.gperf"
+#line 4940 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6052, 4},
+#line 3118 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6053, 0},
-#line 5836 "effective_tld_names.gperf"
+#line 5664 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6054, 0},
-#line 6031 "effective_tld_names.gperf"
+#line 3152 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6055, 0},
-#line 2418 "effective_tld_names.gperf"
+#line 2060 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6056, 0},
-#line 5900 "effective_tld_names.gperf"
+#line 3160 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6057, 0},
-#line 5894 "effective_tld_names.gperf"
+#line 3095 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6058, 0},
-#line 5786 "effective_tld_names.gperf"
+#line 5396 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6059, 0},
-#line 5781 "effective_tld_names.gperf"
+#line 5623 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6060, 0},
-#line 4371 "effective_tld_names.gperf"
+#line 3084 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6061, 0},
-#line 2221 "effective_tld_names.gperf"
+#line 590 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6062, 0},
-#line 2148 "effective_tld_names.gperf"
+#line 3218 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6063, 0},
-#line 5779 "effective_tld_names.gperf"
+#line 5984 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6064, 0},
-#line 5869 "effective_tld_names.gperf"
+#line 6167 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6065, 0},
-#line 4319 "effective_tld_names.gperf"
+#line 4115 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6066, 0},
-#line 5516 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6067, 0},
-#line 5855 "effective_tld_names.gperf"
+#line 3120 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6067, 4},
+#line 3198 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6068, 0},
-#line 5866 "effective_tld_names.gperf"
+#line 4523 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6069, 0},
-#line 4381 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6070, 4},
-#line 5762 "effective_tld_names.gperf"
+#line 4478 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6070, 0},
+#line 3097 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6071, 0},
-#line 5882 "effective_tld_names.gperf"
+#line 719 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6072, 0},
-#line 5837 "effective_tld_names.gperf"
+#line 4587 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6073, 0},
-#line 3180 "effective_tld_names.gperf"
+#line 1130 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6074, 0},
-#line 5832 "effective_tld_names.gperf"
+#line 3249 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6075, 0},
-#line 4301 "effective_tld_names.gperf"
+#line 4631 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6076, 0},
-#line 5833 "effective_tld_names.gperf"
+#line 58 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6077, 0},
-#line 5821 "effective_tld_names.gperf"
+#line 5547 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6078, 0},
-#line 5780 "effective_tld_names.gperf"
+#line 4120 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6079, 0},
-#line 5905 "effective_tld_names.gperf"
+#line 3080 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6080, 0},
-#line 2281 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6081, 0},
-#line 5796 "effective_tld_names.gperf"
+#line 6356 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6081, 4},
+#line 3601 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6082, 0},
-#line 5822 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6083, 0},
-#line 5906 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6084, 0},
-#line 5840 "effective_tld_names.gperf"
+#line 1533 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6083, 4},
+#line 5252 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6084, 4},
+#line 5607 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6085, 0},
-#line 3799 "effective_tld_names.gperf"
+#line 5596 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6086, 0},
-#line 4391 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6087, 0},
-#line 2364 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6088, 4},
-#line 5826 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6089, 0},
-#line 2147 "effective_tld_names.gperf"
+#line 1535 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6087, 4},
+#line 5964 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6088, 0},
+#line 4595 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6089, 4},
+#line 5533 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6090, 0},
-#line 5859 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6091, 0},
-#line 5824 "effective_tld_names.gperf"
+#line 1614 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6091, 4},
+#line 5644 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6092, 0},
-#line 5817 "effective_tld_names.gperf"
+#line 57 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6093, 0},
-#line 5985 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6094, 0},
-#line 2200 "effective_tld_names.gperf"
+#line 4946 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6094, 4},
+#line 4534 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6095, 0},
-#line 5857 "effective_tld_names.gperf"
+#line 3541 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6096, 0},
-#line 5888 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6097, 0},
-#line 5871 "effective_tld_names.gperf"
+#line 2208 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6097, 4},
+#line 4208 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6098, 0},
-#line 5496 "effective_tld_names.gperf"
+#line 6021 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6099, 0},
-#line 5823 "effective_tld_names.gperf"
+#line 3667 "effective_tld_names.gperf"
{(int)(long)&((struct stringpool_t *)0)->stringpool_str6100, 0},
-#line 5545 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6101, 0},
-#line 5464 "effective_tld_names.gperf"
- {(int)(long)&((struct stringpool_t *)0)->stringpool_str6102, 0}
+#line 4784 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6101, 4},
+#line 4468 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6102, 0},
+#line 5603 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6103, 0},
+#line 5487 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6104, 0},
+#line 6078 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6105, 0},
+#line 4134 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6106, 4},
+#line 3088 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6107, 0},
+#line 4139 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6108, 0},
+#line 5624 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6109, 0},
+#line 4579 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6110, 0},
+#line 5775 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6111, 0},
+#line 4605 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6112, 0},
+#line 4786 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6113, 4},
+#line 4785 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6114, 4},
+#line 5482 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6115, 0},
+#line 5378 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6116, 0},
+#line 4143 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6117, 0},
+#line 2813 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6118, 0},
+#line 6020 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6119, 0},
+#line 5544 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6120, 0},
+#line 1155 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6121, 0},
+#line 4790 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6122, 4},
+#line 3121 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6123, 0},
+#line 3957 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6124, 0},
+#line 5605 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6125, 0},
+#line 3085 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6126, 0},
+#line 2499 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6127, 4},
+#line 5631 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6128, 0},
+#line 4902 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6129, 0},
+#line 4554 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6130, 0},
+#line 4550 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6131, 4},
+#line 3131 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6132, 0},
+#line 3138 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6133, 0},
+#line 4804 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6134, 4},
+#line 6002 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6135, 0},
+#line 3956 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6136, 0},
+#line 5685 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6137, 0},
+#line 3192 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6138, 4},
+#line 4474 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6139, 0},
+#line 5373 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6140, 0},
+#line 3194 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6141, 0},
+#line 428 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6142, 0},
+#line 4079 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6143, 0},
+#line 5386 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6144, 0},
+#line 5440 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6145, 0},
+#line 2460 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6146, 4},
+#line 3538 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6147, 0},
+#line 5412 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6148, 0},
+#line 1541 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6149, 0},
+#line 4513 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6150, 0},
+#line 4798 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6151, 4},
+#line 5399 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6152, 0},
+#line 4797 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6153, 4},
+#line 6004 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6154, 0},
+#line 5171 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6155, 0},
+#line 1695 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6156, 4},
+#line 1176 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6157, 4},
+#line 6076 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6158, 0},
+#line 5548 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6159, 0},
+#line 4472 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6160, 0},
+#line 1979 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6161, 0},
+#line 5507 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6162, 0},
+#line 3951 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6163, 0},
+#line 1519 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6164, 0},
+#line 5612 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6165, 0},
+#line 1594 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6166, 4},
+#line 5498 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6167, 0},
+#line 3547 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6168, 0},
+#line 6140 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6169, 0},
+#line 6112 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6170, 0},
+#line 2169 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6171, 0},
+#line 4392 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6172, 0},
+#line 5154 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6173, 0},
+#line 5551 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6174, 0},
+#line 5207 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6175, 0},
+#line 1214 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6176, 4},
+#line 2429 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6177, 4},
+#line 5465 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6178, 0},
+#line 6009 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6179, 0},
+#line 3795 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6180, 0},
+#line 6010 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6181, 0},
+#line 460 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6182, 0},
+#line 2428 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6183, 4},
+#line 6114 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6184, 0},
+#line 4526 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6185, 0},
+#line 1373 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6186, 4},
+#line 4795 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6187, 4},
+#line 6007 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6188, 0},
+#line 4163 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6189, 0},
+#line 5552 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6190, 0},
+#line 5352 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6191, 0},
+#line 4794 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6192, 4},
+#line 4809 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6193, 0},
+#line 6011 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6194, 0},
+#line 4793 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6195, 4},
+#line 5560 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6196, 0},
+#line 5558 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6197, 0},
+#line 1186 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6198, 4},
+#line 5553 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6199, 0},
+#line 5614 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6200, 0},
+#line 4801 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6201, 4},
+#line 5058 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6202, 0},
+#line 6120 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6203, 0},
+#line 5496 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6204, 0},
+#line 5562 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6205, 0},
+#line 4800 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6206, 4},
+#line 2493 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6207, 4},
+#line 6053 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6208, 0},
+#line 2800 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6209, 0},
+#line 5559 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6210, 0},
+#line 4008 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6211, 0},
+#line 5497 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6212, 0},
+#line 4485 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6213, 0},
+#line 6135 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6214, 0},
+#line 4862 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6215, 0},
+#line 2592 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6216, 0},
+#line 6077 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6217, 0},
+#line 4762 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6218, 0},
+#line 5468 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6219, 0},
+#line 6018 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6220, 0},
+#line 4004 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6221, 0},
+#line 2943 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6222, 0},
+#line 6128 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6223, 0},
+#line 4596 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6224, 0},
+#line 5286 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6225, 0},
+#line 5550 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6226, 0},
+#line 5557 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6227, 0},
+#line 5556 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6228, 0},
+#line 1363 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6229, 0},
+#line 6317 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6230, 0},
+#line 5564 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6231, 0},
+#line 3130 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6232, 0},
+#line 4537 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6233, 0},
+#line 5042 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6234, 0},
+#line 4594 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6235, 0},
+#line 2951 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6236, 0},
+#line 5566 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6237, 0},
+#line 3952 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6238, 0},
+#line 4611 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6239, 0},
+#line 5611 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6240, 0},
+#line 3124 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6241, 0},
+#line 5159 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6242, 0},
+#line 2433 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6243, 4},
+#line 1194 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6244, 4},
+#line 6032 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6245, 0},
+#line 3098 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6246, 0},
+#line 3182 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6247, 0},
+#line 3103 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6248, 0},
+#line 1163 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6249, 0},
+#line 3210 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6250, 0},
+#line 4013 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6251, 0},
+#line 3163 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6252, 0},
+#line 5672 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6253, 0},
+#line 4558 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6254, 0},
+#line 3185 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6255, 0},
+#line 3223 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6256, 0},
+#line 5549 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6257, 0},
+#line 1165 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6258, 0},
+#line 5427 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6259, 0},
+#line 5865 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6260, 0},
+#line 68 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6261, 0},
+#line 6185 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6262, 0},
+#line 6287 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6263, 0},
+#line 5416 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6264, 0},
+#line 5587 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6265, 0},
+#line 6028 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6266, 0},
+#line 2803 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6267, 0},
+#line 5127 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6268, 0},
+#line 5575 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6269, 0},
+#line 6200 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6270, 0},
+#line 4829 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6271, 0},
+#line 3219 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6272, 0},
+#line 5203 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6273, 0},
+#line 3081 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6274, 0},
+#line 1206 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6275, 4},
+#line 2453 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6276, 4},
+#line 4889 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6277, 0},
+#line 6303 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6278, 0},
+#line 2605 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6279, 0},
+#line 3252 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6280, 0},
+#line 1207 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6281, 4},
+#line 6012 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6282, 0},
+#line 4419 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6283, 0},
+#line 1211 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6284, 4},
+#line 4770 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6285, 0},
+#line 6094 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6286, 0},
+#line 2582 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6287, 0},
+#line 6246 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6288, 0},
+#line 3170 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6289, 0},
+#line 2583 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6290, 0},
+#line 3092 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6291, 0},
+#line 2567 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6292, 0},
+#line 2207 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6293, 4},
+#line 1154 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6294, 0},
+#line 3225 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6295, 0},
+#line 3804 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6296, 0},
+#line 2465 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6297, 4},
+#line 4799 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6298, 4},
+#line 2485 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6299, 4},
+#line 716 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6300, 0},
+#line 4928 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6301, 0},
+#line 680 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6302, 0},
+#line 702 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6303, 0},
+#line 2480 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6304, 4},
+#line 2481 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6305, 4},
+#line 4549 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6306, 4},
+#line 4135 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6307, 0},
+#line 1175 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6308, 4},
+#line 2467 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6309, 4},
+#line 3794 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6310, 0},
+#line 5561 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6311, 0},
+#line 714 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6312, 0},
+#line 3106 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6313, 0},
+#line 3792 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6314, 1},
+#line 713 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6315, 0},
+#line 2494 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6316, 4},
+#line 1127 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6317, 0},
+#line 4598 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6318, 0},
+#line 1057 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6319, 0},
+#line 6056 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6320, 0},
+#line 4545 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6321, 0},
+#line 4459 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6322, 0},
+#line 1040 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6323, 4},
+#line 1039 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6324, 4},
+#line 1448 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6325, 0},
+#line 3109 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6326, 0},
+#line 5968 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6327, 0},
+#line 2492 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6328, 4},
+#line 6027 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6329, 0},
+#line 2584 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6330, 0},
+#line 3117 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6331, 0},
+#line 3238 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6332, 0},
+#line 2607 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6333, 4},
+#line 6124 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6334, 0},
+#line 1980 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6335, 0},
+#line 3099 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6336, 0},
+#line 2482 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6337, 4},
+#line 4709 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6338, 0},
+#line 4486 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6339, 0},
+#line 4937 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6340, 0},
+#line 4796 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6341, 4},
+#line 6048 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6342, 0},
+#line 3954 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6343, 0},
+#line 5227 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6344, 0},
+#line 5554 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6345, 0},
+#line 2581 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6346, 0},
+#line 723 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6347, 0},
+#line 722 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6348, 0},
+#line 5563 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6349, 0},
+#line 721 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6350, 0},
+#line 2236 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6351, 0},
+#line 1070 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6352, 0},
+#line 5555 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6353, 0},
+#line 3141 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6354, 0},
+#line 124 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6355, 0},
+#line 5732 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6356, 4},
+#line 2569 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6357, 0},
+#line 4566 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6358, 0},
+#line 4568 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6359, 0},
+#line 4482 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6360, 0},
+#line 3214 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6361, 0},
+#line 3128 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6362, 0},
+#line 6197 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6363, 0},
+#line 5565 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6364, 0},
+#line 4462 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6365, 0},
+#line 6134 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6366, 0},
+#line 5044 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6367, 0},
+#line 1724 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6368, 0},
+#line 1391 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6369, 4},
+#line 5134 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6370, 0},
+#line 6008 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6371, 0},
+#line 3224 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6372, 0},
+#line 6006 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6373, 0},
+#line 6031 "effective_tld_names.gperf"
+ {(int)(long)&((struct stringpool_t *)0)->stringpool_str6374, 0}
};
static const short lookup[] =
{
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 0,
- 1, 2, -1, -1, -1, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, -1, 19, 20,
- 21, 22, -1, 23, -1, 24, 25, 26,
- 27, -1, -1, -1, 28, 29, 30, 31,
- 32, -1, -1, -1, 33, 34, 35, -1,
- 36, 37, 38, 39, -1, -1, -1, -1,
- -1, -1, 40, 41, -1, 42, 43, -1,
- -1, 44, 45, 46, -1, 47, -1, -1,
- -1, -1, 48, 49, 50, -1, 51, 52,
- 53, 54, -1, 55, 56, -1, -1, -1,
- 57, 58, -1, -1, -1, -1, 59, 60,
- -1, 61, 62, 63, 64, 65, 66, -1,
- 67, 68, 69, 70, -1, -1, -1, -1,
- 71, 72, 73, -1, -1, -1, 74, -1,
- 75, -1, -1, -1, -1, 76, 77, 78,
- 79, 80, -1, -1, 81, -1, 82, -1,
- 83, -1, 84, -1, 85, -1, -1, 86,
- 87, -1, -1, 88, 89, -1, 90, -1,
- -1, -1, -1, 91, 92, -1, -1, 93,
- 94, -1, 95, -1, 96, 97, -1, -1,
- -1, -1, -1, 98, 99, -1, 100, 101,
- -1, 102, 103, -1, 104, 105, 106, -1,
- 107, -1, 108, -1, -1, 109, -1, 110,
- 111, -1, 112, 113, -1, -1, 114, 115,
- 116, -1, -1, -1, -1, -1, 117, -1,
- -1, 118, -1, -1, -1, 119, 120, 121,
- 122, -1, -1, 123, -1, -1, 124, -1,
- -1, 125, -1, 126, -1, -1, -1, -1,
- 127, 128, -1, -1, -1, 129, 130, -1,
- -1, 131, -1, -1, 132, -1, -1, -1,
- 133, -1, -1, -1, 134, -1, -1, -1,
- -1, -1, 135, -1, -1, -1, 136, 137,
- 138, 139, -1, 140, 141, -1, -1, -1,
- -1, 142, -1, 143, -1, -1, -1, -1,
- 144, 145, 146, -1, 147, -1, -1, -1,
- -1, -1, 148, 149, -1, -1, -1, -1,
- 150, 151, -1, 152, -1, -1, -1, -1,
- 153, -1, -1, -1, 154, -1, 155, 156,
- 157, 158, 159, 160, 161, -1, 162, -1,
- -1, -1, 163, -1, -1, -1, -1, 164,
- -1, -1, -1, 165, 166, -1, 167, 168,
- 169, 170, -1, 171, -1, 172, 173, 174,
- -1, 175, -1, 176, -1, 177, 178, -1,
- 179, 180, -1, 181, 182, 183, -1, -1,
- 184, 185, -1, -1, -1, -1, -1, 186,
- -1, -1, -1, -1, -1, -1, 187, 188,
- -1, -1, 189, -1, -1, -1, 190, -1,
- -1, -1, -1, -1, 191, -1, 192, 193,
- 194, 195, -1, -1, 196, -1, 197, -1,
- 198, -1, 199, -1, -1, 200, -1, -1,
- -1, -1, -1, -1, 201, -1, 202, -1,
- 203, -1, -1, -1, -1, -1, -1, 204,
- 205, 206, 207, -1, -1, 208, -1, 209,
- 210, 211, 212, 213, -1, 214, 215, -1,
- -1, -1, 216, 217, 218, 219, 220, -1,
- -1, 221, -1, 222, 223, -1, -1, -1,
- -1, 224, 225, 226, 227, 228, 229, -1,
- -1, -1, -1, 230, 231, -1, 232, -1,
- -1, 233, -1, -1, -1, 234, -1, 235,
- -1, 236, -1, 237, 238, -1, -1, -1,
- 239, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 240, -1, -1, -1, -1, -1,
- -1, -1, 241, 242, 243, -1, 244, -1,
- 245, 246, -1, 247, -1, -1, -1, 248,
- -1, 249, 250, -1, 251, -1, -1, -1,
- -1, 252, -1, 253, 254, 255, -1, 256,
- -1, -1, -1, 257, 258, -1, 259, 260,
- -1, -1, -1, 261, -1, -1, -1, -1,
- 262, 263, 264, -1, -1, 265, -1, -1,
- 266, 267, -1, -1, 268, 269, 270, 271,
- -1, -1, 272, -1, -1, -1, 273, 274,
- -1, -1, -1, -1, -1, -1, 275, 276,
- -1, 277, 278, 279, -1, -1, 280, -1,
- 281, -1, 282, 283, -1, -1, 284, 285,
- 286, 287, 288, -1, -1, -1, -1, 289,
- 290, -1, 291, -1, -1, -1, 292, -1,
- 293, -1, -1, -1, -1, -1, 294, -1,
- -1, -1, -1, -1, -1, -1, 295, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 296, 297, -1, -1, 298, -1, 299,
- 300, -1, 301, 302, 303, 304, -1, 305,
- -1, 306, -1, -1, 307, 308, -1, -1,
- -1, 309, 310, -1, -1, -1, 311, -1,
- -1, 312, 313, -1, 314, -1, -1, -1,
- -1, 315, -1, 316, 317, -1, -1, 318,
- -1, -1, -1, -1, 319, -1, -1, -1,
- -1, -1, -1, -1, -1, 320, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 321, -1, 322, 323, -1, 324, 325,
- -1, -1, -1, -1, -1, -1, -1, 326,
- -1, 327, 328, -1, -1, 329, -1, 330,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 331, -1, 332, 333, 334, -1, -1,
- 335, 336, -1, -1, -1, 337, 338, -1,
- -1, 339, -1, -1, 340, 341, 342, -1,
- -1, 343, 344, 345, 346, 347, 348, 349,
- 350, 351, 352, 353, 354, 355, 356, 357,
- 358, 359, -1, 360, -1, -1, -1, -1,
- 361, -1, -1, 362, -1, -1, 363, -1,
- 364, -1, -1, -1, -1, 365, -1, -1,
- -1, 366, -1, 367, -1, 368, -1, 369,
- -1, 370, -1, -1, -1, 371, 372, -1,
- 373, -1, -1, 374, -1, -1, -1, -1,
- -1, -1, -1, 375, -1, 376, -1, -1,
- -1, 377, 378, -1, -1, -1, -1, 379,
- -1, 380, -1, 381, -1, -1, 382, -1,
- 383, -1, 384, 385, 386, 387, -1, 388,
- -1, -1, -1, -1, 389, -1, 390, -1,
- -1, -1, 391, 392, 393, 394, 395, -1,
- -1, -1, -1, 396, -1, -1, 397, 398,
- -1, -1, -1, 399, 400, -1, -1, -1,
- 401, -1, 402, -1, -1, 403, 404, 405,
- 406, -1, -1, -1, 407, -1, -1, -1,
- 408, -1, -1, 409, -1, -1, -1, -1,
- 410, 411, -1, -1, -1, -1, -1, 412,
- 413, 414, 415, -1, 416, -1, 417, 418,
- -1, -1, -1, -1, -1, 419, -1, 420,
- -1, -1, 421, 422, 423, 424, -1, 425,
- -1, 426, 427, -1, -1, 428, 429, -1,
- 430, -1, -1, 431, 432, -1, -1, -1,
- 433, -1, 434, -1, -1, -1, -1, -1,
- 435, -1, 436, -1, -1, 437, -1, -1,
- -1, 438, -1, 439, 440, -1, -1, -1,
- -1, -1, 441, 442, -1, -1, -1, -1,
- -1, -1, -1, 443, -1, -1, -1, -1,
- 444, -1, 445, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 446, -1, 447, 448,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 449, -1, -1, -1, -1,
- -1, -1, -1, -1, 450, -1, -1, 451,
- -1, 452, 453, -1, 454, -1, -1, -1,
- 455, -1, -1, 456, -1, 457, -1, -1,
- -1, -1, -1, 458, -1, 459, -1, -1,
- -1, -1, 460, -1, -1, -1, -1, 461,
- -1, 462, 463, -1, -1, -1, 464, -1,
- -1, -1, -1, 465, -1, -1, -1, 466,
- -1, 467, -1, -1, -1, -1, 468, 469,
- -1, -1, 470, 471, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 472, -1, 473,
- -1, -1, -1, 474, -1, -1, -1, -1,
- -1, 475, 476, 477, -1, -1, -1, -1,
- -1, 478, -1, -1, -1, -1, -1, 479,
- -1, -1, -1, -1, -1, 480, -1, -1,
- -1, -1, -1, 481, -1, -1, -1, 482,
- 483, -1, 484, -1, -1, -1, -1, -1,
- 485, -1, -1, -1, -1, -1, 486, 487,
- -1, -1, -1, 488, -1, -1, -1, -1,
- -1, 489, -1, 490, 491, 492, -1, 493,
- 494, -1, 495, -1, -1, -1, 496, -1,
- -1, -1, -1, 497, -1, -1, -1, -1,
- -1, -1, -1, -1, 498, -1, -1, -1,
- -1, -1, -1, -1, 499, 500, 501, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 502, 503, 504, -1, -1, -1, -1,
- -1, -1, -1, 505, -1, 506, -1, -1,
- 507, -1, 508, -1, 509, 510, 511, -1,
- -1, 512, 513, -1, -1, -1, -1, -1,
- -1, 514, -1, -1, 515, -1, 516, -1,
+ 0, -1, 1, 2, 3, -1, -1, -1,
+ -1, -1, 4, 5, -1, 6, -1, 7,
+ -1, 8, -1, -1, -1, 9, 10, 11,
+ -1, -1, 12, -1, -1, 13, 14, -1,
+ 15, 16, 17, 18, -1, -1, 19, -1,
+ -1, 20, 21, 22, 23, 24, 25, -1,
+ -1, -1, 26, -1, -1, -1, 27, -1,
+ 28, -1, 29, -1, 30, -1, 31, -1,
+ -1, -1, 32, -1, -1, -1, 33, -1,
+ -1, 34, 35, -1, -1, -1, -1, -1,
+ 36, -1, -1, 37, -1, 38, -1, -1,
+ 39, 40, 41, 42, -1, 43, -1, -1,
+ -1, -1, 44, 45, 46, 47, -1, 48,
+ 49, -1, 50, -1, -1, 51, 52, -1,
+ -1, 53, -1, -1, -1, -1, 54, 55,
+ 56, 57, 58, -1, 59, 60, 61, 62,
+ -1, -1, 63, 64, 65, 66, 67, -1,
+ -1, -1, -1, -1, -1, -1, 68, 69,
+ 70, 71, -1, -1, 72, -1, -1, -1,
+ 73, 74, 75, -1, 76, -1, -1, -1,
+ -1, 77, -1, -1, -1, 78, -1, -1,
+ 79, -1, 80, 81, 82, 83, 84, 85,
+ 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 104, -1, -1, -1, 105, 106,
+ 107, 108, 109, 110, -1, -1, -1, -1,
+ -1, -1, -1, 111, -1, -1, -1, -1,
+ 112, -1, -1, -1, -1, -1, -1, 113,
+ -1, -1, -1, 114, -1, -1, 115, -1,
+ -1, -1, 116, 117, -1, 118, 119, 120,
+ 121, 122, -1, 123, -1, -1, -1, 124,
+ -1, -1, 125, 126, -1, -1, -1, 127,
+ -1, -1, 128, -1, -1, 129, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 130,
+ -1, 131, 132, 133, -1, -1, -1, -1,
+ 134, -1, -1, 135, 136, 137, 138, 139,
+ 140, -1, 141, 142, -1, -1, 143, -1,
+ 144, -1, -1, -1, 145, 146, -1, -1,
+ -1, 147, -1, 148, 149, 150, 151, -1,
+ -1, 152, -1, 153, -1, -1, 154, -1,
+ -1, 155, -1, -1, -1, 156, -1, 157,
+ -1, -1, 158, 159, 160, 161, 162, -1,
+ -1, 163, 164, -1, 165, -1, 166, -1,
+ -1, 167, -1, -1, -1, -1, -1, -1,
+ 168, -1, 169, 170, -1, -1, 171, -1,
+ -1, -1, -1, -1, -1, -1, 172, 173,
+ -1, -1, -1, 174, -1, -1, 175, 176,
+ -1, -1, 177, -1, -1, -1, -1, 178,
+ 179, -1, 180, -1, -1, -1, -1, -1,
+ -1, -1, -1, 181, -1, 182, -1, 183,
+ -1, -1, 184, -1, -1, 185, 186, 187,
+ -1, 188, -1, -1, 189, 190, 191, 192,
+ 193, -1, -1, -1, 194, -1, -1, 195,
+ 196, 197, 198, 199, -1, 200, -1, -1,
+ 201, -1, -1, -1, 202, -1, -1, -1,
+ -1, -1, -1, -1, -1, 203, -1, -1,
+ -1, -1, 204, -1, -1, 205, 206, -1,
+ 207, 208, 209, -1, 210, 211, 212, -1,
+ -1, -1, -1, 213, 214, 215, 216, -1,
+ -1, -1, -1, 217, -1, -1, 218, -1,
+ 219, 220, 221, 222, 223, -1, -1, 224,
+ -1, -1, 225, -1, 226, -1, 227, -1,
+ -1, -1, 228, 229, -1, -1, 230, 231,
+ -1, 232, -1, -1, -1, -1, -1, 233,
+ -1, -1, 234, 235, -1, -1, -1, -1,
+ -1, 236, 237, 238, -1, 239, 240, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 241, -1, -1, -1, -1, -1, -1, -1,
+ 242, -1, 243, -1, 244, -1, -1, 245,
+ 246, 247, -1, 248, 249, -1, -1, 250,
+ -1, -1, -1, -1, 251, 252, -1, 253,
+ -1, -1, -1, -1, -1, -1, -1, 254,
+ 255, 256, -1, 257, 258, 259, -1, 260,
+ -1, -1, -1, 261, -1, 262, -1, -1,
+ 263, -1, 264, -1, -1, -1, 265, -1,
+ -1, -1, -1, -1, 266, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 267, -1, -1,
+ -1, -1, -1, -1, -1, 268, 269, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 270, -1, 271, -1, -1,
+ 272, 273, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 274, 275, -1, -1, -1, 276, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 277, 278, -1, 279, -1, -1, -1,
+ -1, -1, 280, 281, 282, -1, -1, 283,
+ -1, -1, -1, -1, -1, -1, 284, -1,
+ 285, -1, 286, -1, 287, 288, 289, -1,
+ -1, -1, -1, -1, 290, 291, -1, -1,
+ 292, -1, -1, 293, 294, 295, 296, -1,
+ -1, -1, -1, -1, -1, -1, 297, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 298, -1, -1, -1, -1, 299,
+ -1, 300, -1, -1, -1, -1, 301, -1,
+ 302, -1, 303, 304, -1, 305, -1, 306,
+ 307, -1, -1, -1, -1, -1, -1, -1,
+ 308, 309, 310, -1, 311, 312, 313, -1,
+ -1, 314, -1, 315, 316, 317, -1, 318,
+ -1, -1, -1, -1, -1, 319, -1, -1,
+ 320, -1, -1, -1, -1, -1, -1, -1,
+ -1, 321, -1, -1, -1, -1, 322, -1,
+ -1, -1, 323, -1, -1, -1, -1, -1,
+ 324, -1, 325, -1, -1, 326, -1, -1,
+ 327, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 328, -1, 329, 330,
+ -1, 331, -1, -1, -1, -1, 332, 333,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 334, -1, 335,
+ 336, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 337, -1, -1, 338, 339, 340,
+ -1, 341, -1, 342, -1, -1, -1, -1,
+ -1, -1, 343, -1, 344, 345, -1, -1,
+ 346, 347, -1, 348, -1, 349, -1, -1,
+ -1, 350, 351, 352, -1, 353, 354, -1,
+ 355, -1, -1, -1, -1, -1, 356, -1,
+ -1, -1, 357, -1, -1, -1, -1, -1,
+ -1, -1, 358, -1, -1, -1, -1, -1,
+ -1, -1, -1, 359, 360, -1, -1, 361,
+ 362, -1, -1, -1, -1, -1, -1, 363,
+ 364, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 365, -1, -1, -1,
+ 366, 367, -1, -1, 368, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 369, 370, -1, -1,
+ -1, 371, 372, 373, 374, -1, -1, 375,
+ 376, -1, -1, 377, 378, 379, 380, -1,
+ -1, 381, -1, -1, 382, 383, 384, 385,
+ -1, 386, -1, 387, -1, -1, 388, -1,
+ -1, 389, 390, 391, -1, 392, -1, 393,
+ -1, 394, -1, -1, -1, -1, -1, -1,
+ -1, 395, -1, -1, 396, 397, -1, -1,
+ -1, -1, -1, 398, -1, -1, -1, -1,
+ -1, 399, -1, -1, -1, 400, -1, 401,
+ -1, -1, -1, 402, -1, 403, -1, -1,
+ 404, 405, -1, -1, -1, -1, -1, -1,
+ -1, 406, -1, -1, 407, -1, 408, -1,
+ -1, -1, -1, 409, -1, 410, -1, -1,
+ -1, 411, -1, -1, -1, -1, -1, -1,
+ -1, 412, 413, -1, -1, -1, 414, -1,
+ 415, 416, -1, 417, -1, 418, -1, -1,
+ 419, 420, 421, -1, -1, 422, -1, -1,
+ -1, 423, -1, -1, 424, -1, -1, 425,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 426, 427, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 428, -1, -1, -1, -1, -1, -1,
+ -1, -1, 429, -1, -1, -1, -1, -1,
+ 430, -1, -1, 431, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 432, 433, -1, -1, -1, 434,
+ -1, -1, 435, -1, 436, -1, -1, 437,
+ 438, -1, -1, -1, -1, -1, 439, -1,
+ -1, -1, -1, 440, 441, -1, -1, -1,
+ -1, -1, 442, -1, -1, -1, -1, 443,
+ 444, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 445, 446, -1, -1, -1, 447, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 448,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 449, -1, -1, -1, -1, -1,
+ -1, -1, 450, -1, 451, -1, 452, -1,
+ -1, -1, 453, -1, -1, -1, -1, 454,
+ 455, -1, 456, -1, -1, 457, 458, -1,
+ -1, -1, -1, 459, 460, -1, -1, 461,
+ -1, -1, -1, 462, -1, -1, -1, -1,
+ 463, -1, -1, -1, 464, -1, -1, -1,
+ -1, -1, -1, 465, 466, -1, 467, -1,
+ -1, -1, -1, 468, -1, -1, -1, 469,
+ -1, -1, -1, -1, 470, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 471, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 472, -1, -1, -1,
+ 473, -1, -1, -1, -1, 474, -1, 475,
+ -1, -1, -1, -1, -1, -1, -1, 476,
+ 477, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 478,
+ 479, -1, -1, 480, 481, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 482, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 483, -1, -1, -1, 484, 485, -1,
+ 486, -1, 487, -1, -1, -1, -1, -1,
+ -1, -1, -1, 488, 489, 490, -1, 491,
+ -1, -1, 492, -1, -1, 493, -1, 494,
+ -1, -1, -1, -1, -1, 495, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 496, 497, -1,
+ -1, -1, -1, 498, -1, 499, -1, -1,
+ 500, -1, 501, -1, -1, 502, -1, -1,
+ -1, 503, -1, 504, -1, -1, -1, -1,
+ -1, 505, 506, -1, -1, -1, -1, -1,
+ -1, -1, 507, -1, 508, -1, -1, -1,
+ -1, -1, -1, -1, 509, -1, 510, -1,
+ 511, -1, 512, 513, -1, -1, -1, -1,
+ -1, 514, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 515, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 516, -1, -1, -1, -1, -1,
517, -1, -1, 518, -1, -1, -1, -1,
- 519, -1, -1, -1, 520, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 521, -1,
- -1, -1, -1, 522, 523, 524, -1, -1,
- -1, 525, -1, 526, 527, -1, 528, 529,
- 530, -1, 531, -1, 532, -1, 533, -1,
- -1, -1, -1, 534, 535, -1, -1, -1,
- 536, -1, -1, -1, -1, -1, -1, 537,
- -1, -1, -1, 538, -1, -1, -1, -1,
- -1, -1, -1, -1, 539, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 540, -1, -1, -1, 541, 542,
- -1, 543, -1, -1, -1, -1, -1, -1,
- 544, -1, -1, -1, -1, 545, 546, -1,
+ -1, -1, -1, -1, -1, -1, 519, -1,
+ -1, -1, -1, -1, -1, -1, 520, -1,
+ 521, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 522, -1, -1,
+ -1, -1, -1, -1, -1, -1, 523, 524,
+ 525, -1, -1, -1, -1, 526, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 527, -1, -1,
+ 528, -1, 529, -1, 530, -1, 531, -1,
+ -1, -1, -1, -1, -1, -1, 532, -1,
+ -1, -1, -1, -1, 533, -1, -1, -1,
+ -1, -1, 534, -1, -1, -1, 535, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 536, -1, -1, -1, -1, -1,
+ -1, 537, -1, -1, 538, 539, -1, -1,
+ -1, -1, -1, -1, 540, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 541, -1, 542, -1, -1, -1,
+ -1, -1, -1, -1, 543, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 544, -1, 545, -1, -1, -1, 546,
-1, -1, 547, -1, -1, -1, -1, -1,
- -1, 548, -1, -1, -1, -1, 549, -1,
- -1, -1, -1, 550, -1, -1, -1, -1,
- -1, -1, -1, -1, 551, -1, -1, -1,
- -1, -1, -1, -1, 552, -1, -1, -1,
- -1, 553, -1, -1, -1, -1, -1, 554,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 548, -1, 549,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 550, 551, -1, -1, -1, -1, 552, 553,
+ -1, -1, -1, 554, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 555, -1, -1,
- -1, 556, 557, -1, 558, -1, -1, -1,
- 559, 560, -1, -1, -1, 561, 562, -1,
- -1, -1, 563, -1, -1, 564, -1, -1,
- -1, -1, -1, -1, 565, 566, 567, 568,
- -1, 569, 570, -1, 571, -1, 572, -1,
- 573, -1, -1, -1, 574, 575, -1, -1,
- -1, -1, 576, -1, -1, -1, -1, -1,
- -1, -1, 577, -1, 578, -1, -1, -1,
- -1, 579, -1, -1, -1, 580, -1, -1,
- -1, -1, -1, -1, 581, 582, -1, -1,
- -1, -1, 583, -1, -1, -1, -1, -1,
+ -1, -1, 556, 557, -1, -1, -1, -1,
+ -1, -1, 558, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 559, 560, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 561, 562, 563, -1, -1, -1, -1,
+ -1, -1, -1, -1, 564, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 565, -1, -1, -1, -1, 566, -1, 567,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 568, -1, -1, -1, 569, -1, 570, -1,
+ 571, -1, 572, -1, 573, -1, -1, -1,
+ -1, -1, -1, -1, -1, 574, -1, -1,
+ 575, -1, -1, -1, -1, 576, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 577, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 578,
+ 579, -1, -1, -1, 580, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 581,
+ 582, -1, 583, -1, -1, -1, -1, -1,
-1, -1, -1, 584, -1, -1, -1, -1,
- 585, 586, 587, -1, -1, 588, -1, -1,
- -1, 589, -1, -1, 590, 591, -1, -1,
- -1, -1, -1, -1, -1, 592, -1, -1,
- -1, -1, -1, -1, 593, -1, -1, -1,
- 594, -1, -1, -1, -1, -1, 595, 596,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 597, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 598, -1,
- 599, -1, -1, 600, -1, -1, -1, -1,
- -1, -1, -1, 601, -1, -1, 602, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 603, -1, -1, -1,
- 604, 605, -1, -1, 606, -1, -1, -1,
- -1, -1, -1, -1, -1, 607, -1, -1,
- -1, -1, -1, 608, 609, -1, -1, -1,
- -1, 610, 611, -1, -1, -1, -1, -1,
- -1, 612, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 613, -1, -1, 614, -1,
- -1, 615, -1, -1, 616, 617, -1, 618,
- 619, -1, -1, 620, 621, 622, -1, 623,
- -1, -1, -1, -1, -1, 624, 625, -1,
- -1, -1, -1, 626, -1, -1, 627, 628,
- 629, -1, -1, -1, -1, -1, -1, 630,
- -1, -1, -1, -1, -1, -1, 631, -1,
- -1, -1, 632, -1, -1, -1, 633, -1,
- -1, -1, 634, -1, 635, -1, -1, -1,
- 636, -1, -1, -1, -1, 637, -1, -1,
- -1, -1, 638, -1, -1, -1, -1, 639,
- -1, -1, 640, -1, -1, 641, -1, -1,
- -1, -1, -1, -1, -1, 642, 643, -1,
- 644, -1, -1, -1, -1, -1, -1, 645,
- -1, -1, -1, 646, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 647,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 648, -1, 649, -1, -1, -1, -1,
- -1, -1, 650, -1, -1, 651, -1, 652,
- -1, -1, -1, 653, -1, -1, 654, -1,
- -1, 655, -1, -1, -1, -1, -1, 656,
- -1, -1, -1, -1, -1, 657, -1, 658,
- 659, -1, -1, -1, -1, -1, -1, -1,
- 660, -1, 661, 662, -1, 663, -1, 664,
- 665, -1, -1, -1, -1, -1, 666, -1,
- -1, 667, -1, -1, -1, -1, -1, -1,
- 668, 669, 670, -1, -1, -1, -1, 671,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 672, -1, -1, -1, -1, 673, -1,
- -1, -1, -1, -1, 674, -1, 675, 676,
- -1, 677, 678, -1, -1, -1, -1, 679,
- -1, -1, -1, 680, 681, -1, 682, -1,
+ -1, 585, -1, 586, -1, 587, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 588, -1, -1, -1, 589, 590, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 591, -1, 592, 593, 594, -1, -1,
+ 595, -1, -1, -1, -1, -1, 596, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 597, -1, -1, -1,
+ -1, -1, 598, -1, -1, -1, 599, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 600, -1, -1,
+ -1, 601, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 602, -1,
+ 603, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 604, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 605, -1, -1, -1, 606,
+ -1, 607, 608, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 609,
+ -1, -1, -1, -1, -1, -1, -1, 610,
+ -1, -1, -1, 611, -1, 612, -1, -1,
+ -1, -1, -1, -1, -1, 613, 614, -1,
+ -1, -1, -1, 615, -1, -1, 616, -1,
+ -1, -1, -1, -1, 617, 618, -1, -1,
+ -1, -1, 619, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 620, 621,
+ -1, 622, 623, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 624, -1, -1, 625,
+ 626, 627, -1, -1, -1, 628, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 629, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 630,
+ 631, 632, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 633, -1, 634, -1, -1, -1, -1, -1,
+ -1, -1, 635, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 636, -1,
+ -1, -1, -1, -1, -1, -1, 637, -1,
+ -1, 638, -1, 639, 640, -1, -1, -1,
+ -1, -1, 641, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 642, -1, 643,
+ -1, 644, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 645, -1, -1, -1, -1,
+ -1, -1, 646, -1, -1, -1, -1, -1,
+ -1, 647, -1, -1, -1, -1, -1, -1,
+ -1, 648, -1, -1, -1, 649, -1, -1,
+ -1, -1, 650, -1, 651, -1, -1, -1,
+ -1, -1, 652, -1, -1, -1, -1, -1,
+ -1, -1, -1, 653, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 654, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 655, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 656, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 657, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 658, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 659, 660, -1,
+ -1, -1, -1, -1, 661, 662, 663, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 664, -1, -1, 665, -1, -1, -1, 666,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 667, -1, 668, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 669, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 670, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 671, -1, -1, -1, 672,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 673, -1, -1,
+ -1, -1, -1, -1, -1, -1, 674, -1,
+ -1, -1, -1, -1, -1, -1, 675, -1,
+ 676, -1, -1, -1, -1, -1, -1, -1,
+ -1, 677, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 678, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 679,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 680, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 681, -1, -1, -1, -1, -1, -1, -1,
+ -1, 682, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 683, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 684,
- -1, -1, -1, 685, -1, -1, 686, -1,
- -1, -1, 687, -1, -1, 688, -1, -1,
- 689, -1, -1, -1, -1, -1, -1, 690,
- 691, -1, 692, -1, -1, -1, 693, -1,
- -1, -1, -1, -1, 694, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 695,
- 696, -1, -1, -1, -1, 697, -1, -1,
- 698, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 699, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 700,
- -1, -1, -1, -1, 701, -1, -1, -1,
- -1, -1, -1, -1, -1, 702, 703, -1,
- -1, -1, -1, -1, -1, -1, 704, -1,
- 705, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 706, 707, -1, -1, -1, -1,
- -1, -1, -1, 708, -1, -1, -1, -1,
- 709, -1, -1, 710, -1, -1, -1, 711,
- -1, -1, 712, -1, -1, -1, -1, -1,
- -1, -1, 713, 714, -1, -1, -1, -1,
- -1, -1, 715, -1, -1, -1, -1, -1,
- 716, -1, 717, 718, 719, -1, -1, 720,
- 721, -1, -1, -1, -1, -1, 722, 723,
- -1, -1, 724, -1, -1, -1, -1, -1,
- -1, 725, -1, 726, -1, -1, 727, -1,
- -1, 728, -1, -1, -1, -1, -1, 729,
- -1, 730, -1, -1, -1, -1, 731, -1,
- -1, 732, -1, -1, -1, -1, 733, -1,
- -1, -1, -1, -1, 734, -1, -1, 735,
- -1, -1, 736, -1, -1, -1, -1, -1,
- -1, 737, -1, -1, -1, -1, -1, -1,
- 738, -1, -1, 739, -1, -1, -1, -1,
- -1, 740, -1, -1, -1, -1, 741, -1,
- 742, -1, 743, 744, 745, 746, -1, -1,
- -1, 747, 748, -1, 749, -1, 750, 751,
- 752, -1, -1, 753, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 754, 755, -1,
- 756, -1, -1, 757, 758, -1, -1, -1,
- -1, -1, 759, -1, -1, -1, -1, 760,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 684, -1, -1,
+ -1, -1, -1, 685, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 686, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 687, -1, -1, -1, -1,
+ 688, 689, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 690, -1, -1, -1, -1, 691, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 692, -1, -1,
+ -1, -1, -1, 693, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 694, -1, -1, 695, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 696, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 697, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 698, -1, -1, -1, -1, -1, -1,
+ 699, -1, -1, -1, -1, 700, -1, -1,
+ -1, -1, 701, -1, -1, -1, -1, -1,
+ -1, -1, -1, 702, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 703, 704, -1, -1, -1, 705, -1,
+ -1, -1, -1, 706, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 707, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 708, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 709, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 710, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 711, -1, -1, -1, -1, -1,
+ 712, -1, -1, 713, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 714,
+ -1, -1, -1, -1, -1, -1, 715, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 716, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 717,
+ -1, -1, -1, 718, -1, -1, -1, -1,
+ 719, -1, -1, -1, -1, 720, 721, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 722, -1, -1, -1,
+ -1, -1, -1, -1, 723, -1, -1, -1,
+ -1, -1, -1, -1, -1, 724, -1, -1,
+ 725, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 726, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 727, -1,
+ -1, -1, -1, -1, -1, 728, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 729,
+ -1, -1, -1, -1, -1, -1, 730, -1,
+ -1, -1, -1, -1, 731, 732, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 733, -1, -1, -1,
+ -1, -1, -1, -1, -1, 734, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 735, -1, -1, -1, -1, 736, -1, -1,
+ -1, 737, -1, -1, -1, -1, -1, 738,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 739, -1, -1, -1,
+ -1, -1, 740, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 741, -1,
+ 742, -1, 743, -1, -1, -1, -1, 744,
+ -1, -1, 745, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 746, -1,
+ -1, -1, -1, -1, 747, -1, -1, -1,
+ -1, -1, -1, -1, -1, 748, -1, -1,
+ -1, -1, -1, 749, -1, 750, -1, -1,
+ 751, -1, -1, -1, -1, -1, -1, -1,
+ -1, 752, 753, -1, -1, -1, -1, -1,
+ -1, -1, -1, 754, 755, -1, -1, -1,
+ -1, -1, -1, -1, -1, 756, -1, -1,
+ -1, -1, -1, -1, -1, 757, -1, 758,
+ 759, -1, -1, -1, 760, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 761,
- -1, -1, -1, -1, -1, -1, 762, -1,
- -1, 763, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 762, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 763, -1, -1,
-1, -1, -1, -1, 764, -1, -1, -1,
- -1, -1, 765, -1, 766, -1, 767, -1,
- 768, -1, -1, -1, -1, -1, -1, -1,
- -1, 769, -1, -1, -1, -1, -1, -1,
- 770, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 771, -1, -1, -1, 772, -1, -1, 773,
- -1, 774, -1, -1, -1, -1, -1, -1,
- 775, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 776, -1, -1,
- -1, -1, 777, -1, -1, -1, -1, -1,
- -1, 778, -1, 779, -1, -1, 780, -1,
- -1, -1, 781, -1, -1, -1, -1, -1,
- -1, 782, 783, -1, -1, -1, 784, -1,
- -1, -1, 785, 786, 787, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 788, -1,
- -1, 789, 790, -1, -1, -1, -1, 791,
- -1, -1, -1, -1, -1, 792, 793, -1,
- -1, -1, -1, -1, -1, -1, 794, -1,
- -1, -1, -1, 795, 796, 797, -1, 798,
- -1, -1, -1, 799, -1, -1, -1, 800,
- 801, 802, -1, -1, -1, -1, -1, -1,
- -1, -1, 803, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 804, -1,
- -1, -1, -1, -1, -1, -1, 805, -1,
- -1, -1, -1, -1, -1, -1, -1, 806,
- -1, 807, -1, -1, -1, -1, 808, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 809, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 810, -1, -1, -1,
- -1, 811, -1, -1, -1, -1, -1, -1,
- -1, 812, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 813, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 814, -1, -1, -1, -1,
- -1, 815, -1, -1, -1, -1, 816, 817,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 818, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 819, -1, -1, 820,
- -1, -1, 821, -1, -1, -1, -1, -1,
- -1, -1, 822, -1, 823, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 824, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 825, 826, -1, -1,
- -1, -1, -1, -1, 827, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 828, -1, -1, 829, -1, -1, -1,
- -1, -1, 830, -1, -1, 831, -1, 832,
- -1, -1, -1, -1, -1, -1, -1, 833,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 834, 835, 836, -1, -1, -1, -1,
- -1, -1, -1, -1, 837, -1, 838, -1,
- -1, -1, -1, -1, -1, -1, -1, 839,
- -1, -1, 840, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 841, -1, 842,
- -1, -1, -1, -1, -1, -1, -1, 843,
- -1, -1, -1, -1, 844, -1, -1, -1,
- -1, -1, -1, -1, -1, 845, -1, -1,
- -1, -1, -1, 846, -1, 847, -1, -1,
- -1, -1, 848, -1, -1, -1, -1, -1,
- -1, -1, 849, -1, -1, -1, -1, -1,
- -1, 850, 851, 852, -1, -1, -1, -1,
- -1, -1, -1, 853, -1, -1, -1, 854,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 855,
- -1, 856, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 857, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 858, -1,
- 859, -1, -1, -1, -1, -1, 860, 861,
- -1, -1, 862, -1, -1, -1, -1, 863,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 864, 865, 866, -1, -1,
- -1, -1, 867, -1, 868, -1, -1, -1,
- -1, 869, 870, -1, -1, 871, -1, -1,
- -1, 872, -1, -1, 873, 874, 875, -1,
- -1, -1, 876, -1, -1, -1, -1, -1,
- -1, 877, 878, -1, -1, -1, -1, -1,
- 879, -1, -1, -1, -1, 880, -1, -1,
- -1, -1, -1, 881, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 882, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 883, 884, -1,
- -1, -1, -1, 885, -1, -1, -1, 886,
- -1, -1, -1, -1, 887, -1, -1, -1,
- -1, -1, 888, -1, -1, -1, -1, -1,
- 889, -1, -1, -1, -1, -1, -1, 890,
- -1, -1, -1, -1, 891, -1, -1, -1,
- 892, -1, -1, -1, -1, -1, 893, -1,
- -1, -1, 894, -1, -1, -1, -1, -1,
- -1, -1, -1, 895, 896, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 765, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 766, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 767, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 768,
+ -1, -1, -1, -1, -1, -1, -1, 769,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 770, -1, -1, 771, -1, -1, -1, -1,
+ -1, -1, -1, 772, -1, 773, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 774, -1, -1, -1,
+ -1, 775, 776, -1, -1, -1, -1, -1,
+ -1, -1, 777, 778, 779, -1, -1, -1,
+ -1, 780, -1, -1, -1, -1, 781, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 782,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 783, -1, -1, -1, -1,
+ 784, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 785, -1, -1, -1, -1, -1, 786,
+ 787, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 788,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 789, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 790, 791, -1, -1, 792,
+ -1, 793, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 794, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 795, -1, -1,
+ 796, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 797,
+ 798, -1, -1, -1, -1, -1, -1, -1,
+ 799, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 800, -1, -1, -1, -1, -1, 801,
+ -1, 802, 803, 804, -1, -1, -1, -1,
+ -1, -1, -1, -1, 805, -1, 806, 807,
+ -1, -1, -1, 808, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 809, 810, 811, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 812, -1, -1, -1,
+ 813, -1, -1, -1, -1, 814, -1, -1,
+ -1, -1, -1, -1, -1, 815, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 816, -1, -1,
+ -1, -1, -1, 817, -1, -1, -1, -1,
+ -1, 818, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 819, -1,
+ -1, 820, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 821, -1, -1,
+ 822, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 823, -1, -1, -1, 824, -1,
+ -1, -1, -1, -1, -1, 825, -1, -1,
+ -1, -1, -1, -1, 826, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 827, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 828, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 829, -1, -1, 830,
+ 831, -1, -1, -1, -1, 832, -1, 833,
+ 834, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 835, -1, -1, -1, -1,
+ -1, 836, -1, -1, -1, -1, -1, -1,
+ -1, 837, -1, -1, -1, -1, -1, 838,
+ -1, 839, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 840, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 841, -1, -1, -1, 842, -1,
+ 843, -1, -1, -1, -1, -1, -1, -1,
+ 844, -1, -1, -1, -1, -1, -1, -1,
+ 845, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 846, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 847, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 848, -1, 849, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 850, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 851, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 852, -1, -1, -1, -1, -1,
+ -1, -1, -1, 853, -1, -1, -1, -1,
+ -1, 854, -1, -1, -1, -1, 855, -1,
+ -1, -1, -1, -1, -1, 856, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 857, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 858,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 859, 860, -1, -1, 861, 862,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 863, 864, -1, 865, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 866,
+ 867, -1, -1, -1, -1, -1, -1, -1,
+ -1, 868, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 869, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 870, -1, 871, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 872, -1, 873, -1, -1, -1, -1, -1,
+ 874, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 875, -1, -1, -1, -1, -1,
+ -1, -1, -1, 876, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 877, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 878, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 879, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 880, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 881, -1, -1, -1, 882,
+ -1, -1, 883, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 884, -1, -1, -1, -1, -1, -1, 885,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 886, -1,
+ -1, -1, -1, 887, -1, -1, -1, -1,
+ -1, 888, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 889, -1, -1, -1, -1, -1,
+ 890, -1, 891, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 892, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 893, 894, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 895, -1, -1, 896,
-1, -1, -1, -1, -1, -1, -1, 897,
- -1, -1, -1, -1, -1, -1, 898, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 899, -1,
- -1, 900, -1, -1, -1, -1, 901, -1,
- 902, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 903, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 904, -1, -1, -1, -1, -1, -1, -1,
- 905, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 906, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 907, -1, -1,
- -1, -1, -1, -1, -1, -1, 908, -1,
- -1, -1, -1, -1, 909, 910, 911, -1,
+ -1, -1, -1, -1, -1, 898, -1, -1,
+ 899, -1, -1, -1, 900, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 901, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 902, -1, -1, 903, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 904, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 905, 906, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 907, -1,
+ -1, -1, -1, -1, 908, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 909, -1, -1, 910, -1,
+ -1, -1, -1, -1, -1, 911, -1, -1,
+ 912, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 913, -1, -1, -1, -1, 914,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 915, -1, -1, 916, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 917,
+ -1, -1, 918, -1, 919, 920, -1, 921,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 912, -1, -1, -1, -1, -1, -1, 913,
- 914, -1, 915, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 916, -1, -1, -1,
- 917, -1, -1, -1, -1, -1, -1, -1,
- 918, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 919, -1, -1, -1, -1,
- -1, -1, -1, 920, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 921,
- -1, -1, -1, -1, -1, -1, 922, -1,
- -1, -1, -1, -1, 923, -1, -1, -1,
+ -1, -1, -1, 922, -1, 923, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 924,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 924, -1, -1, -1,
- -1, 925, -1, -1, -1, -1, -1, -1,
- 926, -1, 927, 928, -1, -1, -1, -1,
- -1, -1, -1, 929, 930, -1, -1, -1,
- -1, -1, -1, 931, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 932, -1, -1, -1, -1, -1,
- 933, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 934, 935, -1, -1, -1, -1, 936, -1,
- 937, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 925, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 926,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 938, -1, -1, -1, -1, -1, -1,
+ -1, -1, 927, 928, -1, -1, 929, 930,
+ -1, -1, -1, -1, -1, 931, -1, -1,
+ -1, -1, -1, -1, 932, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 939, -1, -1, 940, -1, -1, -1, 941,
- 942, -1, -1, 943, -1, 944, 945, -1,
+ 933, 934, -1, 935, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 936, -1, -1,
+ -1, 937, -1, -1, -1, 938, 939, -1,
+ -1, 940, -1, -1, -1, -1, -1, -1,
+ -1, -1, 941, -1, -1, -1, 942, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 946, -1, -1, -1, -1, -1,
+ -1, -1, 943, -1, -1, -1, -1, 944,
-1, -1, -1, -1, -1, -1, -1, -1,
- 947, -1, -1, 948, -1, -1, -1, -1,
- 949, -1, -1, -1, -1, -1, 950, -1,
- -1, 951, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 952, -1,
- -1, -1, 953, 954, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 945, -1, -1, -1, -1, 946,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 947, -1, -1, 948, 949, 950, -1,
+ -1, -1, -1, -1, 951, -1, -1, -1,
+ -1, -1, 952, -1, -1, -1, -1, -1,
+ 953, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 954, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 955, -1, -1, -1,
- -1, 956, -1, -1, -1, 957, -1, -1,
- -1, -1, -1, -1, 958, 959, 960, -1,
- -1, 961, -1, 962, -1, -1, -1, 963,
- -1, 964, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 965, -1, -1, 966, 967,
- -1, -1, -1, 968, -1, -1, -1, -1,
+ 956, 957, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 969, -1, 970, -1,
- -1, 971, -1, 972, 973, -1, -1, -1,
- -1, 974, -1, -1, -1, -1, -1, -1,
- -1, 975, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 976, -1,
- 977, -1, -1, -1, -1, -1, -1, -1,
- 978, 979, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 980, -1, -1,
- 981, -1, -1, -1, 982, -1, -1, 983,
- -1, 984, -1, -1, -1, -1, -1, -1,
- -1, 985, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 986, -1,
- 987, -1, -1, 988, -1, -1, -1, -1,
- -1, -1, -1, -1, 989, -1, -1, -1,
+ -1, -1, 958, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 990, -1, 991, -1, -1, 992,
- -1, -1, -1, 993, -1, 994, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 995, -1, -1,
- -1, 996, -1, 997, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 998, 999, -1,
- 1000, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1001,
- 1002, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1003, -1, -1, -1, 1004, -1, -1, -1,
- -1, -1, 1005, -1, -1, -1, -1, -1,
- -1, -1, 1006, 1007, -1, 1008, -1, -1,
- -1, 1009, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1010, -1,
- -1, -1, -1, -1, -1, 1011, -1, -1,
- -1, 1012, -1, -1, -1, -1, 1013, -1,
- -1, -1, -1, -1, -1, -1, 1014, 1015,
- 1016, 1017, -1, -1, -1, 1018, 1019, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 959, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1020, -1,
- -1, 1021, -1, -1, -1, -1, 1022, -1,
- 1023, -1, 1024, -1, -1, -1, -1, -1,
- -1, -1, -1, 1025, 1026, -1, -1, -1,
+ 960, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1027, -1,
- -1, -1, -1, -1, -1, -1, -1, 1028,
- 1029, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1030, -1, -1, -1, -1,
- -1, -1, -1, -1, 1031, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1032,
- 1033, -1, -1, -1, 1034, -1, -1, -1,
+ -1, -1, -1, -1, 961, 962, -1, -1,
+ 963, -1, -1, -1, -1, -1, -1, 964,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1035, -1, -1, -1, -1, -1,
- -1, -1, -1, 1036, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1037, -1, -1, -1,
- -1, -1, -1, -1, 1038, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1039, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 965, -1,
+ -1, -1, -1, 966, -1, 967, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 968, -1, -1, -1, -1, -1, -1,
+ -1, -1, 969, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 970, -1, -1,
+ -1, -1, 971, -1, -1, -1, -1, 972,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1040, -1, -1, -1, -1, -1, 1041,
- 1042, -1, -1, -1, 1043, -1, -1, -1,
- -1, -1, -1, 1044, -1, -1, -1, -1,
- -1, -1, -1, -1, 1045, -1, -1, -1,
- -1, -1, -1, 1046, -1, -1, -1, -1,
+ -1, 973, 974, -1, -1, 975, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1047, 1048, -1,
- -1, -1, -1, -1, -1, 1049, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1050, -1, -1, -1, -1, -1, -1, -1,
- -1, 1051, -1, -1, -1, -1, -1, -1,
- -1, 1052, -1, -1, -1, -1, -1, -1,
- -1, -1, 1053, -1, -1, 1054, -1, -1,
- -1, 1055, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1056, -1, -1,
- 1057, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 976, -1, -1, -1,
+ -1, -1, -1, -1, -1, 977, -1, -1,
+ -1, 978, -1, -1, -1, -1, -1, -1,
+ -1, -1, 979, -1, -1, -1, -1, 980,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 981, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 982, 983, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 984, -1, -1, -1, -1, 985,
+ 986, -1, -1, -1, -1, -1, 987, -1,
+ -1, -1, -1, -1, -1, -1, 988, -1,
+ -1, -1, -1, 989, -1, -1, 990, -1,
+ 991, -1, -1, -1, 992, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1058, -1, -1, 1059, -1,
- -1, -1, 1060, 1061, -1, -1, -1, -1,
+ -1, -1, -1, -1, 993, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 994,
+ 995, -1, 996, -1, -1, -1, -1, -1,
+ -1, 997, -1, -1, -1, 998, -1, -1,
+ 999, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1062, -1, -1, -1, 1063, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1000, 1001, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1002, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1003, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1004,
+ 1005, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1006, -1,
+ -1, -1, -1, 1007, 1008, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1064, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1065, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1066, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1009, -1,
+ 1010, 1011, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1012, 1013, -1, -1, -1,
+ -1, -1, 1014, -1, -1, -1, 1015, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1067, -1, -1, -1, -1, -1, 1068,
- -1, -1, 1069, -1, -1, -1, -1, -1,
- -1, -1, 1070, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1071, -1, -1,
- -1, 1072, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1016, -1, -1, -1, -1,
+ -1, -1, 1017, -1, -1, -1, -1, -1,
+ 1018, -1, -1, 1019, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1020, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1073, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1074, -1, -1, -1,
+ 1021, -1, -1, -1, -1, -1, -1, 1022,
+ -1, -1, -1, -1, -1, -1, 1023, -1,
+ -1, -1, -1, 1024, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1025, -1, -1, -1, 1026, -1, 1027,
+ -1, -1, -1, -1, -1, 1028, -1, -1,
+ -1, -1, 1029, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1030, -1, -1, 1031, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1032, -1, 1033, -1, -1, -1, -1,
+ 1034, -1, -1, 1035, -1, -1, -1, 1036,
+ 1037, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1038, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1075, -1, -1, -1, -1, -1, -1,
- -1, 1076, -1, -1, -1, -1, -1, -1,
- -1, -1, 1077, -1, -1, -1, -1, -1,
- -1, 1078, 1079, -1, -1, -1, 1080, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1081, -1, -1, -1, -1, -1, 1082, -1,
- -1, -1, -1, -1, -1, -1, -1, 1083,
- -1, -1, -1, -1, -1, -1, 1084, -1,
+ -1, 1039, -1, -1, -1, -1, -1, 1040,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1041, 1042, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1085,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1086, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1043, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1044, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1045, -1, -1,
+ -1, -1, -1, -1, -1, 1046, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1047,
+ -1, -1, 1048, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1049, -1, -1,
+ -1, -1, 1050, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1087, -1, -1, -1, -1,
- -1, 1088, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1089, -1,
+ -1, -1, -1, 1051, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1090, 1091, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1052,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1092, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1093,
- -1, -1, -1, -1, -1, -1, 1094, -1,
- -1, -1, -1, -1, -1, 1095, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1053, -1,
+ 1054, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1055, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1096, -1, 1097, -1, -1, -1, -1, -1,
+ 1056, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1057, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1058, -1, -1, -1,
+ -1, -1, -1, 1059, 1060, -1, 1061, -1,
+ 1062, -1, -1, 1063, -1, -1, -1, -1,
+ 1064, -1, -1, -1, -1, 1065, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1066, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1067, -1,
+ -1, -1, -1, -1, -1, -1, 1068, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1069, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1070,
+ -1, -1, -1, -1, -1, -1, 1071, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1072, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1073,
+ -1, -1, -1, 1074, -1, -1, -1, -1,
+ -1, -1, 1075, -1, -1, -1, -1, 1076,
+ -1, -1, -1, -1, 1077, -1, -1, -1,
+ -1, -1, -1, -1, 1078, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1079,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1080, -1, -1, 1081, -1,
+ 1082, -1, 1083, -1, -1, 1084, -1, -1,
+ -1, -1, 1085, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1086, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1087, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1088, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1089, -1, 1090,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1091, -1, 1092, -1, -1, -1, 1093,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1094, -1, -1, -1, 1095, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1096, 1097,
-1, -1, 1098, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1099, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1100, -1,
+ 1101, -1, -1, -1, -1, -1, 1102, -1,
+ 1103, -1, -1, -1, -1, -1, -1, -1,
+ 1104, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1105, -1, -1, -1, -1,
+ -1, 1106, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1107, 1108, 1109, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1110, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1111, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1099, -1, 1100, -1,
+ -1, -1, -1, -1, 1112, 1113, 1114, -1,
+ -1, -1, -1, -1, 1115, -1, -1, -1,
+ -1, -1, -1, -1, 1116, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1117, -1, -1, -1, -1, -1,
+ 1118, -1, -1, 1119, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1120,
+ -1, -1, -1, -1, -1, -1, 1121, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1122, 1123, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1101, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1102, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1103, -1, -1,
- 1104, -1, -1, -1, -1, -1, -1, 1105,
- -1, -1, -1, -1, -1, -1, 1106, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1107, -1, -1, -1, -1, 1108, -1, -1,
- 1109, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1110, 1111,
+ -1, -1, -1, -1, -1, 1124, -1, -1,
+ -1, -1, 1125, -1, -1, -1, -1, -1,
+ -1, -1, 1126, -1, 1127, -1, 1128, -1,
+ -1, -1, 1129, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1112, -1, -1, -1, -1,
- -1, 1113, 1114, -1, -1, -1, -1, -1,
+ -1, -1, 1130, -1, -1, -1, -1, -1,
+ -1, 1131, -1, -1, 1132, -1, -1, -1,
+ 1133, -1, -1, -1, 1134, -1, -1, 1135,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1115, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1116, -1, -1, -1, -1,
+ 1136, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1137, -1, 1138, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1117,
- -1, -1, -1, -1, -1, -1, 1118, -1,
- -1, -1, -1, -1, -1, -1, 1119, 1120,
- 1121, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1139,
+ 1140, -1, -1, -1, 1141, -1, 1142, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1122, 1123, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1143, -1, 1144, -1, -1, -1,
+ -1, 1145, 1146, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1124, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1125, -1,
+ -1, -1, -1, 1147, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1148,
+ -1, -1, -1, -1, -1, 1149, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1150, -1, -1, -1,
+ -1, -1, 1151, -1, -1, -1, -1, -1,
+ -1, 1152, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1126, -1, -1, -1,
- 1127, 1128, 1129, -1, -1, 1130, -1, 1131,
- -1, 1132, -1, -1, -1, 1133, -1, -1,
- -1, -1, 1134, -1, -1, -1, -1, -1,
- -1, 1135, -1, 1136, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1153, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1154, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1137,
- -1, -1, -1, 1138, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1155,
+ -1, -1, -1, -1, 1156, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1139, -1, -1, -1, -1, 1140, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1141, 1142,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1143, -1, -1, -1, -1, -1,
- 1144, -1, -1, -1, -1, -1, -1, -1,
+ 1157, -1, -1, -1, -1, -1, 1158, -1,
+ -1, 1159, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1160, -1, -1, -1, -1, 1161,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1145, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1162, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1146, -1, 1147, -1,
- 1148, -1, -1, -1, -1, -1, -1, -1,
- -1, 1149, -1, 1150, -1, -1, -1, -1,
- -1, -1, -1, -1, 1151, -1, -1, -1,
- 1152, -1, -1, 1153, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1154, -1, 1155, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1163, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1164, 1165, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1156, -1, -1, -1, -1, -1, 1157, -1,
- -1, -1, -1, -1, 1158, -1, -1, -1,
- -1, -1, 1159, -1, -1, -1, -1, -1,
- 1160, -1, -1, -1, 1161, -1, -1, -1,
- -1, -1, -1, 1162, -1, -1, -1, 1163,
- -1, 1164, 1165, -1, -1, -1, 1166, -1,
- -1, -1, -1, -1, -1, -1, 1167, -1,
- -1, -1, -1, -1, -1, -1, 1168, 1169,
- 1170, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1166, -1, 1167, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1171, 1172, -1, 1173, -1,
- -1, -1, -1, -1, 1174, -1, -1, -1,
- -1, 1175, -1, -1, -1, -1, -1, 1176,
- 1177, -1, -1, -1, -1, -1, -1, 1178,
- -1, -1, -1, -1, -1, 1179, -1, -1,
- -1, -1, -1, -1, 1180, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1168, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1181, -1,
- -1, -1, 1182, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1183,
- -1, -1, -1, -1, -1, -1, 1184, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1185, -1, -1,
+ -1, -1, -1, -1, 1169, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1186, -1, -1,
- -1, -1, -1, -1, -1, 1187, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1188, -1, -1, -1,
- -1, 1189, -1, -1, -1, -1, -1, -1,
- 1190, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1191,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1192, -1, -1, 1193, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1170,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1171, -1, -1, -1, -1, -1, 1172,
+ 1173, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1174, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1175,
+ -1, -1, 1176, 1177, -1, -1, 1178, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1179, -1, -1, -1, -1, 1180, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1181, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1182, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1183, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1184, -1, -1, -1, 1185, -1,
+ -1, 1186, -1, -1, 1187, -1, -1, -1,
+ 1188, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1189, -1,
+ -1, -1, -1, -1, 1190, -1, 1191, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1192, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1193, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 1194,
- -1, -1, -1, 1195, -1, -1, -1, 1196,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1195, 1196, -1,
1197, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1198, -1, -1, 1199, -1,
- -1, -1, -1, 1200, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1198,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1199, -1,
+ -1, -1, -1, -1, -1, 1200, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 1201, -1, -1,
- 1202, -1, -1, -1, -1, -1, 1203, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1204, 1205, -1, -1, 1206, -1,
- -1, -1, -1, -1, -1, 1207, -1, 1208,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1209, -1, 1210, -1, 1211,
- -1, -1, -1, 1212, -1, -1, -1, 1213,
+ -1, -1, 1202, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1203, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1204, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1205, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1206, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1207, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1208,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1209, 1210, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1214, -1, 1215, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1216,
- 1217, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1218, -1, -1, 1219, -1, -1, -1, -1,
- 1220, -1, -1, -1, 1221, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1211, -1, 1212, -1,
+ -1, -1, -1, -1, 1213, -1, -1, -1,
+ 1214, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1222, 1223, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1215, -1, -1, -1,
+ -1, -1, -1, 1216, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1217, -1, -1, -1,
+ -1, -1, -1, -1, 1218, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1224, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1219, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1225, -1, -1, -1, 1226, -1, 1227, 1228,
- -1, 1229, -1, -1, -1, -1, -1, -1,
- 1230, -1, -1, -1, 1231, -1, -1, 1232,
+ -1, -1, -1, -1, -1, -1, -1, 1220,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1233, 1234, -1, -1, -1,
- 1235, -1, -1, -1, -1, -1, -1, 1236,
+ -1, -1, -1, -1, -1, 1221, -1, 1222,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1223, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1237, -1, -1, -1, 1238, -1,
+ -1, -1, -1, -1, -1, 1224, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1239, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1240, 1241, -1, -1, -1, -1, -1, -1,
- -1, -1, 1242, -1, 1243, -1, -1, -1,
+ 1225, 1226, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1244, -1, -1, -1,
- -1, -1, -1, -1, 1245, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1246, -1,
- -1, -1, -1, -1, -1, 1247, -1, -1,
- -1, -1, 1248, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1249, -1, -1, -1, -1, -1, -1, -1,
- -1, 1250, -1, -1, 1251, -1, -1, -1,
- 1252, -1, -1, 1253, -1, -1, 1254, -1,
+ -1, -1, -1, -1, 1227, -1, 1228, -1,
+ 1229, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1230, -1, -1,
+ -1, -1, -1, -1, -1, 1231, 1232, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1255, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1256, -1, -1, -1,
+ 1233, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1234, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1257, -1, -1, -1, -1, 1258, -1,
- -1, 1259, -1, -1, 1260, -1, -1, -1,
- -1, -1, -1, -1, 1261, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1262, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1263, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1264,
- -1, 1265, -1, 1266, -1, -1, -1, -1,
- 1267, -1, -1, -1, -1, -1, 1268, -1,
+ 1235, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1269,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1270, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1236, -1, -1, 1237, -1,
+ -1, -1, -1, -1, 1238, -1, 1239, -1,
+ -1, 1240, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1271, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1272, 1273, -1, -1, -1,
- 1274, -1, -1, -1, -1, -1, 1275, -1,
- -1, -1, -1, -1, -1, 1276, -1, -1,
- -1, -1, -1, 1277, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1241, -1, -1, -1,
+ 1242, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1243, -1, -1, -1, -1, -1, 1244, 1245,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1278, -1, 1279, -1, -1, 1280, -1,
- -1, -1, -1, -1, 1281, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1282, -1,
- -1, -1, -1, 1283, -1, -1, 1284, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1285, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1286, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1246, -1, -1, -1, -1, 1247, -1, -1,
+ 1248, 1249, -1, 1250, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1251, -1, -1, -1, -1, -1, -1, 1252,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1287, -1, -1, -1, -1, -1, -1,
- -1, 1288, -1, -1, 1289, -1, -1, -1,
- -1, -1, -1, -1, -1, 1290, -1, -1,
- -1, 1291, -1, -1, -1, -1, -1, -1,
+ 1253, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1254, -1, -1,
+ -1, -1, 1255, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1292, -1, -1, -1, -1,
- -1, -1, -1, -1, 1293, -1, -1, -1,
- -1, -1, 1294, -1, -1, -1, -1, -1,
- 1295, -1, -1, 1296, -1, 1297, -1, 1298,
- 1299, -1, -1, -1, -1, -1, 1300, -1,
- -1, -1, -1, -1, -1, 1301, -1, -1,
- -1, -1, -1, -1, -1, 1302, -1, 1303,
+ 1256, 1257, -1, -1, -1, -1, -1, 1258,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1304, -1, -1, -1, -1, -1, 1305, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1306, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1259, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1260, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1307, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1261, -1, -1,
+ -1, -1, -1, 1262, -1, -1, -1, -1,
+ -1, -1, -1, 1263, -1, -1, 1264, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1308, 1309, -1,
+ -1, -1, -1, 1265, -1, -1, -1, -1,
+ -1, -1, 1266, -1, -1, -1, 1267, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1268,
+ 1269, -1, -1, -1, -1, -1, -1, -1,
+ 1270, -1, -1, 1271, -1, -1, -1, -1,
+ -1, -1, -1, 1272, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1273, -1, -1,
+ -1, -1, -1, -1, -1, 1274, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1310, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1311, -1,
- -1, -1, -1, 1312, -1, -1, 1313, -1,
+ 1275, -1, -1, -1, -1, -1, -1, -1,
+ 1276, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1277, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1278, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1279, -1, 1280,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1281, 1282, -1, -1, -1,
+ 1283, 1284, 1285, -1, -1, -1, 1286, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1287, -1, -1, -1,
+ -1, 1288, -1, -1, -1, -1, -1, -1,
+ -1, 1289, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1314, -1, -1, -1,
- -1, 1315, -1, 1316, -1, -1, -1, -1,
- 1317, -1, 1318, -1, 1319, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1290, -1,
+ -1, -1, -1, -1, 1291, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1320, -1,
- -1, -1, -1, 1321, -1, -1, -1, -1,
- 1322, -1, 1323, -1, 1324, -1, -1, -1,
- -1, -1, 1325, -1, 1326, -1, -1, -1,
+ -1, -1, -1, 1292, -1, 1293, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1327, -1, -1, -1, 1328,
- 1329, -1, -1, -1, -1, -1, -1, -1,
- 1330, -1, -1, -1, -1, -1, 1331, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1332, -1, -1, -1, -1, -1,
+ -1, 1294, -1, -1, -1, -1, 1295, 1296,
+ -1, -1, -1, 1297, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1298, -1, -1, -1, -1,
+ 1299, -1, -1, -1, 1300, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1301,
+ -1, -1, 1302, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1303, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1333, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1334, 1335, -1, -1,
- -1, -1, 1336, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1337, -1, -1, -1,
- -1, -1, 1338, -1, -1, -1, -1, -1,
+ -1, 1304, -1, -1, -1, -1, 1305, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1339, -1,
- -1, -1, -1, 1340, -1, -1, 1341, -1,
- -1, -1, 1342, 1343, -1, -1, 1344, -1,
- 1345, -1, -1, -1, -1, 1346, 1347, -1,
- -1, -1, -1, -1, -1, 1348, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1349, -1, -1, -1, -1, -1, 1350,
+ 1306, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1307, -1, -1,
+ -1, -1, -1, -1, 1308, -1, -1, -1,
+ -1, 1309, -1, -1, -1, -1, -1, -1,
+ 1310, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1311, -1, 1312, -1, -1,
+ -1, 1313, 1314, -1, -1, -1, -1, 1315,
+ -1, -1, -1, 1316, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1351, -1, -1,
- 1352, -1, -1, -1, -1, -1, 1353, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1317,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1354,
+ -1, -1, -1, -1, 1318, -1, 1319, 1320,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1321, -1, -1, -1,
+ -1, 1322, -1, -1, 1323, -1, 1324, -1,
+ -1, -1, 1325, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1326, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1327,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1355, -1, -1, -1, -1, -1, -1, -1,
- -1, 1356, -1, -1, -1, -1, -1, -1,
- -1, -1, 1357, -1, -1, 1358, -1, -1,
- -1, -1, 1359, -1, -1, -1, 1360, -1,
- -1, -1, 1361, -1, -1, -1, -1, -1,
- -1, 1362, -1, 1363, -1, -1, -1, -1,
- -1, 1364, -1, 1365, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1366,
- -1, -1, -1, 1367, 1368, 1369, 1370, -1,
- -1, -1, -1, -1, -1, -1, 1371, 1372,
- 1373, -1, -1, -1, -1, 1374, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1375, -1,
+ -1, -1, -1, -1, -1, 1328, -1, 1329,
+ -1, -1, -1, -1, -1, -1, 1330, -1,
+ -1, 1331, -1, -1, -1, -1, -1, -1,
+ -1, 1332, 1333, -1, -1, -1, -1, 1334,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1376, -1, -1, -1,
- -1, 1377, -1, -1, -1, -1, 1378, -1,
- 1379, -1, -1, -1, -1, 1380, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1381, -1, 1382, -1, -1, -1, -1,
+ 1335, -1, 1336, -1, -1, -1, 1337, -1,
+ -1, -1, 1338, -1, -1, 1339, -1, -1,
+ -1, -1, -1, -1, -1, 1340, -1, -1,
+ 1341, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1383, 1384, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1342, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1343, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1385, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1386, 1387, -1,
- -1, -1, -1, -1, 1388, -1, -1, -1,
- -1, 1389, -1, -1, -1, -1, -1, 1390,
- -1, 1391, -1, -1, 1392, -1, -1, -1,
- 1393, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1394, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1395,
- -1, -1, -1, -1, -1, 1396, -1, -1,
+ -1, -1, -1, 1344, 1345, -1, -1, 1346,
+ -1, -1, -1, -1, 1347, -1, -1, -1,
+ 1348, -1, -1, -1, 1349, -1, -1, -1,
+ -1, 1350, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1351,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1397, -1, -1, 1398, -1, -1,
- -1, -1, 1399, -1, 1400, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1352,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1353, -1, -1, 1354, 1355, -1, -1, -1,
+ -1, -1, 1356, -1, -1, -1, -1, 1357,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1358, -1, -1, -1,
+ 1359, -1, -1, -1, -1, -1, 1360, -1,
+ -1, 1361, -1, -1, -1, -1, -1, 1362,
+ -1, -1, 1363, -1, -1, -1, 1364, -1,
+ -1, 1365, -1, -1, -1, -1, -1, -1,
+ -1, 1366, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1367, -1, -1, -1, 1368, -1,
+ -1, -1, -1, 1369, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1401, -1, -1, -1, -1,
+ -1, -1, 1370, -1, -1, -1, -1, 1371,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1402, -1, -1, 1403, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1372,
+ -1, -1, -1, -1, -1, -1, -1, 1373,
+ -1, 1374, 1375, 1376, -1, -1, -1, -1,
+ 1377, -1, -1, -1, 1378, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1379, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1404, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1405, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1406,
- 1407, -1, -1, -1, 1408, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1380, -1,
+ -1, -1, -1, 1381, -1, -1, -1, -1,
+ 1382, 1383, 1384, -1, -1, -1, 1385, -1,
+ -1, -1, -1, -1, 1386, 1387, -1, -1,
+ -1, -1, 1388, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1389, -1, -1, -1,
+ -1, -1, 1390, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1391, -1, 1392, -1,
+ 1393, -1, -1, 1394, -1, -1, -1, -1,
+ -1, -1, -1, 1395, -1, -1, -1, -1,
+ -1, -1, 1396, -1, -1, -1, 1397, -1,
+ -1, -1, -1, -1, 1398, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1409,
- 1410, -1, -1, 1411, -1, -1, -1, -1,
- -1, 1412, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1399, -1, -1, -1, -1,
+ -1, 1400, -1, -1, -1, -1, -1, 1401,
+ -1, -1, -1, 1402, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1403,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1413, -1, -1, -1, 1414, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1404, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1405,
+ -1, 1406, -1, -1, 1407, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1408, 1409, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1415, -1, -1, 1416, -1, 1417, -1, -1,
- -1, 1418, -1, 1419, -1, -1, -1, -1,
- -1, -1, -1, 1420, 1421, -1, -1, -1,
- -1, 1422, -1, -1, 1423, -1, -1, -1,
- -1, -1, -1, -1, 1424, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1425, -1,
- -1, -1, -1, 1426, -1, -1, -1, -1,
- -1, 1427, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1428, -1, -1, 1429, -1,
- -1, -1, -1, -1, -1, 1430, -1, -1,
- -1, -1, -1, -1, -1, -1, 1431, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1432,
- -1, -1, -1, -1, -1, 1433, -1, -1,
+ -1, -1, -1, 1410, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1411, -1, -1, -1,
+ -1, -1, -1, -1, 1412, -1, -1, -1,
+ -1, -1, -1, -1, 1413, -1, 1414, -1,
+ 1415, -1, -1, -1, -1, 1416, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1434, -1, -1,
- -1, 1435, -1, -1, 1436, -1, -1, 1437,
- -1, 1438, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1439, -1, -1,
- -1, -1, -1, -1, 1440, -1, -1, -1,
+ 1417, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1418, -1, -1,
+ 1419, -1, -1, 1420, -1, -1, -1, -1,
+ -1, -1, 1421, -1, 1422, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1441, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1423,
+ -1, -1, -1, 1424, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1425, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1426, 1427, -1,
+ -1, -1, -1, 1428, -1, 1429, -1, -1,
+ 1430, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1442, 1443, -1, -1, -1, 1444,
- -1, -1, -1, -1, -1, -1, -1, 1445,
- -1, -1, -1, 1446, -1, -1, -1, -1,
- -1, -1, 1447, -1, -1, -1, -1, 1448,
- 1449, -1, -1, 1450, -1, 1451, -1, 1452,
- -1, 1453, -1, -1, 1454, -1, 1455, -1,
- -1, 1456, 1457, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1458,
- 1459, 1460, -1, -1, -1, -1, -1, -1,
- -1, 1461, -1, -1, -1, -1, -1, 1462,
- -1, -1, -1, 1463, -1, -1, -1, -1,
+ 1431, -1, -1, 1432, -1, -1, 1433, -1,
+ -1, -1, -1, -1, -1, -1, 1434, 1435,
+ -1, 1436, -1, -1, 1437, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1464, -1, -1, -1,
- -1, 1465, 1466, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1467, -1, -1, -1, 1468, -1,
+ -1, -1, 1438, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1469, -1, -1,
- -1, -1, -1, -1, -1, 1470, -1, -1,
- 1471, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1472, 1473, -1, -1,
- -1, -1, -1, 1474, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1475, -1, -1, -1,
- -1, -1, -1, 1476, -1, -1, 1477, -1,
- -1, -1, -1, 1478, -1, 1479, -1, -1,
- -1, -1, -1, -1, 1480, -1, -1, -1,
- 1481, -1, -1, -1, -1, -1, 1482, -1,
- -1, -1, -1, -1, -1, -1, 1483, -1,
- -1, -1, 1484, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1439,
+ 1440, -1, -1, -1, -1, -1, -1, -1,
+ 1441, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1485, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1442, -1,
+ 1443, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1444, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1486, -1, -1, 1487, 1488,
- -1, -1, -1, -1, -1, 1489, -1, -1,
- 1490, -1, -1, -1, 1491, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1492, -1,
- -1, 1493, -1, 1494, -1, -1, -1, 1495,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1496, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1445, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1497, -1, -1,
+ 1446, 1447, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1448, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1449, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1498, -1, -1, -1, -1, 1499, 1500, 1501,
- -1, -1, -1, -1, -1, -1, -1, 1502,
- -1, -1, -1, 1503, -1, -1, 1504, -1,
+ 1450, -1, -1, -1, -1, 1451, -1, -1,
+ 1452, 1453, -1, -1, -1, -1, -1, -1,
+ -1, 1454, 1455, -1, -1, 1456, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1505,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1457, 1458, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1459, -1, -1, -1, -1, -1, -1,
+ -1, 1460, -1, -1, -1, -1, -1, -1,
+ -1, 1461, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1462, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1463, 1464,
+ -1, -1, -1, -1, -1, 1465, -1, -1,
+ -1, -1, -1, -1, 1466, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1467, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1468,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1469, -1, 1470, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1471, -1,
+ -1, -1, -1, 1472, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1473,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1474, -1, -1, 1475, -1, -1, -1, -1,
+ -1, 1476, -1, -1, 1477, -1, -1, 1478,
+ -1, -1, -1, -1, -1, 1479, -1, 1480,
+ -1, -1, 1481, -1, -1, -1, -1, -1,
+ -1, 1482, 1483, -1, -1, -1, 1484, -1,
+ -1, -1, -1, -1, -1, -1, 1485, -1,
+ -1, -1, -1, -1, -1, -1, 1486, -1,
+ -1, -1, -1, 1487, 1488, -1, -1, -1,
+ -1, -1, 1489, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1490, -1,
+ -1, -1, 1491, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1492,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1493, 1494, 1495,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1496, -1, -1, 1497, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1498, -1,
+ -1, -1, -1, 1499, -1, -1, -1, -1,
+ -1, -1, 1500, 1501, -1, -1, 1502, -1,
+ -1, -1, -1, -1, 1503, -1, -1, 1504,
+ 1505, -1, -1, -1, -1, -1, -1, -1,
1506, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1507, -1, -1, -1, -1,
- -1, -1, 1508, -1, 1509, -1, -1, -1,
- -1, -1, -1, -1, 1510, -1, -1, -1,
- -1, -1, -1, -1, 1511, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1507, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1512, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1508, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1509, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1510, -1, -1, -1, -1, -1, -1, -1,
+ 1511, -1, -1, -1, 1512, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1513, -1, -1, -1, -1, -1, -1, 1514,
+ 1513, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1514, -1, -1, -1, -1, -1, -1,
+ 1515, 1516, -1, -1, -1, -1, -1, -1,
+ -1, 1517, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1518,
+ -1, -1, -1, 1519, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1515, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1516, -1, -1,
- -1, -1, -1, -1, 1517, -1, 1518, -1,
- -1, -1, -1, -1, -1, -1, 1519, -1,
+ 1520, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1520, -1, 1521, -1, -1, -1, 1522, -1,
- -1, -1, -1, -1, -1, -1, -1, 1523,
- -1, -1, -1, -1, -1, -1, -1, 1524,
- -1, -1, -1, -1, -1, 1525, -1, -1,
- -1, -1, -1, 1526, -1, -1, -1, -1,
- -1, 1527, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1528, -1, -1, -1, -1,
+ 1521, 1522, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1523, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1524, 1525, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1526, 1527, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1528, -1, -1,
1529, -1, -1, -1, 1530, -1, -1, -1,
- -1, -1, 1531, -1, -1, -1, 1532, -1,
- -1, -1, -1, -1, -1, -1, -1, 1533,
+ -1, -1, -1, -1, -1, 1531, -1, -1,
+ -1, -1, -1, 1532, -1, -1, -1, 1533,
+ 1534, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1535,
+ -1, -1, -1, 1536, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1537, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1538, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1539, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1540, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1541, -1, -1, 1542, -1, -1, -1, -1,
+ 1543, -1, -1, 1544, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1545, -1, -1, -1,
+ 1546, -1, -1, -1, 1547, -1, -1, -1,
+ -1, 1548, -1, 1549, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1550, 1551, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1552, -1, -1, 1553, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1554, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1555, -1, -1,
+ -1, 1556, -1, -1, 1557, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1558,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1559, -1, -1, -1, -1, -1, 1560, 1561,
+ -1, 1562, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1563, -1, -1, 1564,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1565,
+ -1, -1, -1, 1566, -1, -1, -1, -1,
+ -1, -1, 1567, -1, -1, -1, -1, 1568,
+ -1, -1, -1, -1, -1, -1, 1569, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1570, -1, -1, -1, -1,
+ -1, -1, 1571, -1, -1, -1, 1572, 1573,
+ -1, -1, 1574, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1575, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1576,
+ -1, -1, -1, -1, -1, 1577, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1578,
+ 1579, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1580, -1, 1581, -1, -1, -1, 1582, -1,
+ -1, 1583, -1, -1, -1, 1584, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1585, -1, -1, -1, -1, -1,
+ 1586, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1587, -1, 1588, -1, -1, -1,
+ -1, -1, 1589, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1590, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1591, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1592, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1593, -1, -1, -1, -1, 1594,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1595, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1596, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1597, -1, -1,
+ -1, -1, -1, 1598, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1599, -1, -1, -1, 1600, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1601,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1602, -1, 1603, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1604, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1605, 1606, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1607, -1, -1, -1, 1608, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1534, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1535, -1, -1, -1,
- -1, -1, 1536, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1537, -1, 1538, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1539, -1, -1,
+ -1, -1, -1, -1, -1, 1609, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1540, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1541, -1,
- -1, -1, -1, -1, 1542, -1, -1, -1,
- -1, -1, 1543, 1544, -1, -1, -1, -1,
- 1545, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1546, -1,
- -1, 1547, 1548, -1, -1, -1, 1549, -1,
- -1, -1, -1, -1, 1550, -1, -1, 1551,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1552,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1553, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1610, -1, 1611, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1554, 1555, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1556, -1, 1557,
- -1, -1, 1558, -1, 1559, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1560, -1, -1, -1, -1, 1561, -1, -1,
+ -1, -1, -1, -1, -1, 1612, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1562, 1563,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1564, -1, 1565, -1, -1, 1566, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1567, -1, 1568, -1, -1,
- 1569, -1, -1, -1, 1570, -1, -1, -1,
- 1571, 1572, -1, -1, 1573, -1, -1, -1,
- -1, -1, 1574, 1575, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1576, -1,
- -1, 1577, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1578, 1579, 1580, -1, -1, -1, -1,
- -1, -1, 1581, -1, -1, -1, -1, -1,
- -1, -1, -1, 1582, -1, -1, -1, 1583,
- -1, 1584, -1, -1, -1, -1, -1, -1,
- 1585, 1586, 1587, 1588, -1, -1, -1, 1589,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1590, 1591, -1, -1, -1,
- 1592, -1, -1, -1, -1, -1, -1, -1,
- -1, 1593, -1, -1, -1, 1594, -1, -1,
- -1, -1, 1595, -1, -1, -1, -1, -1,
- -1, -1, 1596, -1, -1, -1, 1597, -1,
- -1, -1, 1598, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1599, 1600, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1613,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1601, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1602,
- -1, -1, -1, 1603, -1, -1, 1604, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1605, -1, -1, -1, -1, 1606, -1,
- 1607, -1, -1, -1, 1608, -1, 1609, -1,
- -1, -1, -1, -1, -1, -1, 1610, -1,
- -1, -1, 1611, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1614,
+ -1, -1, -1, 1615, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1612, -1, -1, -1, -1, -1,
+ -1, 1616, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1613, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1614, -1, -1, -1, 1615, -1, -1, -1,
- -1, -1, 1616, -1, -1, -1, -1, 1617,
+ -1, -1, -1, -1, -1, -1, -1, 1617,
+ 1618, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1619, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1620, -1, -1, -1, -1, 1621, 1622, -1,
+ 1623, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1624, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1625,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1618, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1619, 1620, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1621, -1,
- -1, -1, 1622, -1, -1, -1, -1, 1623,
- -1, 1624, -1, -1, -1, 1625, -1, -1,
- -1, -1, -1, -1, -1, 1626, -1, -1,
- -1, -1, 1627, -1, -1, -1, -1, -1,
- -1, -1, 1628, 1629, -1, -1, -1, -1,
- -1, -1, -1, -1, 1630, -1, -1, -1,
- -1, 1631, -1, -1, -1, -1, -1, -1,
- 1632, -1, -1, -1, 1633, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1634,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1635, -1, -1,
- -1, -1, -1, -1, 1636, -1, -1, -1,
+ -1, 1626, -1, 1627, 1628, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1637, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1638, -1, -1, -1,
- 1639, -1, -1, -1, -1, -1, -1, -1,
- -1, 1640, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1641, -1, -1, 1642,
- -1, 1643, 1644, 1645, -1, -1, -1, -1,
- -1, 1646, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1647, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1629, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1630, -1, -1, -1, -1,
+ 1631, -1, 1632, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1633, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1648, -1, 1649,
- -1, 1650, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1634, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1651, -1, -1, -1, -1, -1, 1652,
+ -1, -1, -1, -1, 1635, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1636,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1653, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1654, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1655, -1, -1,
+ -1, -1, -1, 1637, -1, -1, -1, -1,
+ -1, 1638, -1, -1, -1, -1, -1, -1,
+ -1, 1639, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1656, -1, -1, -1, -1, -1, -1, 1657,
- 1658, -1, -1, -1, -1, -1, -1, 1659,
- -1, -1, -1, -1, -1, 1660, -1, -1,
+ -1, -1, -1, -1, -1, 1640, 1641, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1642,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1661, -1,
- -1, -1, -1, 1662, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1663, -1,
- -1, -1, -1, -1, -1, 1664, 1665, -1,
- -1, 1666, -1, -1, -1, -1, -1, -1,
- 1667, -1, -1, -1, -1, -1, -1, 1668,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1643, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1669, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1644, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1645, -1, -1, -1, -1,
+ 1646, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1647, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1648, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1649,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1650, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1651, -1, -1,
+ -1, -1, -1, -1, -1, 1652, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1653, -1, -1,
+ 1654, -1, -1, -1, 1655, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1656,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1657, -1, -1, 1658, -1,
+ 1659, 1660, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1661, -1, -1,
+ -1, 1662, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1663, -1, -1, -1,
+ -1, -1, -1, 1664, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1665, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1666,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1667, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1668, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1669,
-1, -1, -1, -1, 1670, -1, 1671, -1,
- 1672, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1673, 1674, -1,
+ -1, 1672, -1, -1, 1673, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1674, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1675, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1676, -1, -1, -1,
+ -1, -1, 1677, 1678, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1679, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1680, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1681, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1682, -1, -1, -1, 1683,
+ -1, -1, -1, -1, -1, 1684, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1675, 1676, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1677, -1, -1,
- -1, -1, -1, 1678, 1679, -1, -1, -1,
+ 1685, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1680, 1681, -1,
- -1, -1, -1, 1682, 1683, -1, -1, -1,
- -1, -1, 1684, -1, -1, 1685, -1, -1,
- -1, -1, -1, -1, -1, -1, 1686, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1686, 1687, -1,
+ -1, -1, 1688, -1, 1689, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1687, -1, -1, -1,
- 1688, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1689, 1690, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1691, -1, -1, -1, -1,
- -1, -1, 1692, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1690, -1,
+ -1, -1, -1, 1691, -1, 1692, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1693,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1693, -1, -1, -1, 1694, -1,
- -1, -1, -1, -1, 1695, 1696, 1697, -1,
- 1698, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1699,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1700,
- -1, 1701, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1702, -1, -1, -1, -1, -1, -1,
- 1703, -1, -1, 1704, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1705, -1, 1706, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1707, -1, -1, -1, -1, -1,
- -1, -1, 1708, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1709,
- -1, -1, 1710, -1, -1, -1, -1, -1,
- -1, 1711, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1712, -1, 1713, -1,
- -1, -1, -1, 1714, -1, -1, 1715, -1,
- -1, -1, -1, -1, 1716, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1717, -1, -1, -1,
- -1, -1, -1, 1718, -1, -1, 1719, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1720, -1, -1, 1721, -1, -1, -1,
- -1, -1, -1, -1, 1722, -1, -1, -1,
- -1, 1723, -1, -1, -1, 1724, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1725, -1, 1726, -1, -1, -1, -1,
- -1, -1, -1, 1727, -1, -1, -1, -1,
+ 1694, -1, 1695, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1696,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1697, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1698, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1699, -1, 1700,
+ 1701, -1, -1, -1, -1, -1, -1, -1,
+ 1702, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1703, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1704, -1, -1,
+ -1, -1, -1, -1, -1, 1705, -1, -1,
+ -1, -1, 1706, -1, -1, -1, -1, -1,
+ -1, -1, 1707, -1, -1, 1708, 1709, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1710, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1711, -1, -1, -1, -1, -1,
+ -1, -1, 1712, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1713, -1, -1, -1, 1714,
+ -1, 1715, -1, -1, -1, -1, -1, -1,
+ -1, 1716, -1, 1717, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1718, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1719, -1, -1, 1720,
+ -1, -1, -1, -1, -1, 1721, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1722, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1723, -1, -1, -1,
+ -1, 1724, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1725,
+ -1, -1, -1, 1726, -1, -1, -1, -1,
+ 1727, -1, -1, 1728, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1728, -1, -1, -1, -1,
-1, 1729, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1730, -1, -1, -1, 1731,
+ 1730, -1, -1, -1, 1731, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 1732, -1,
- 1733, -1, -1, -1, -1, -1, 1734, -1,
- -1, -1, -1, -1, 1735, -1, -1, -1,
- -1, -1, 1736, -1, -1, -1, -1, -1,
- -1, 1737, -1, -1, -1, -1, -1, -1,
- 1738, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1739, -1, 1740, 1741,
- 1742, -1, -1, -1, -1, 1743, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1733, 1734, -1,
+ -1, 1735, 1736, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1737, -1, 1738,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1739, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1740, -1, -1, -1, -1, -1, -1,
+ -1, 1741, -1, -1, -1, 1742, 1743, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1744, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1744, -1, -1, -1, -1, 1745, -1,
- -1, -1, -1, -1, -1, -1, -1, 1746,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1745,
+ 1746, 1747, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1747, -1, -1, -1, -1, -1,
- 1748, -1, -1, -1, -1, -1, 1749, -1,
- -1, -1, -1, -1, -1, -1, 1750, -1,
- -1, 1751, -1, -1, -1, -1, -1, -1,
- 1752, 1753, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1748,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1754, 1755,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1756, -1, -1,
- 1757, -1, 1758, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1759, -1,
+ -1, -1, -1, -1, 1749, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1760, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1761, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1750,
+ 1751, -1, -1, 1752, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1753, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1754, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1755, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1762,
+ -1, -1, 1756, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1757, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1758, -1, -1, -1, 1759, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1760,
+ -1, -1, 1761, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1763, -1, -1,
- -1, -1, -1, -1, -1, 1764, -1, -1,
- -1, -1, -1, -1, -1, -1, 1765, -1,
- -1, -1, -1, -1, 1766, -1, -1, -1,
- -1, 1767, -1, -1, 1768, -1, -1, -1,
+ -1, -1, -1, 1762, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1769, -1, -1, 1770, 1771, 1772,
+ -1, 1763, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1773, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1764, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1765, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1766,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1774,
+ 1767, 1768, -1, -1, -1, -1, -1, -1,
+ 1769, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1775, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1776, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1777, -1, -1, -1,
- -1, 1778, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1779, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1770, 1771, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1772, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1773, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1774, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1775, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1776, -1, -1,
+ 1777, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1778, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1779, -1, -1,
-1, -1, -1, 1780, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1781,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1781, -1,
-1, -1, -1, -1, -1, -1, 1782, -1,
- -1, 1783, -1, -1, -1, -1, 1784, -1,
- -1, -1, -1, -1, 1785, -1, -1, 1786,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1787, -1, -1, 1788, -1, -1, -1,
- -1, 1789, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1790, 1791,
- -1, -1, -1, -1, 1792, -1, -1, -1,
- -1, -1, -1, 1793, -1, -1, -1, -1,
- 1794, -1, -1, -1, -1, -1, -1, 1795,
- -1, 1796, -1, 1797, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1798,
- 1799, -1, -1, 1800, -1, -1, -1, 1801,
- -1, -1, -1, -1, -1, -1, 1802, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1803, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1783, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1784, -1, -1, -1, 1785,
+ -1, 1786, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1787, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1788, -1,
+ -1, -1, -1, -1, -1, -1, 1789, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1790, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1791, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1792, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1793,
+ 1794, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1795, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1796, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1797, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1798, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1799, -1, -1, 1800, -1, -1,
+ -1, -1, -1, -1, 1801, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1802, -1,
+ -1, 1803, -1, -1, -1, -1, -1, -1,
-1, 1804, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1805, -1, -1, -1, -1, -1, 1806, 1807,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1808, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1809, -1, -1, -1, 1810, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1811, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1812, -1, -1, -1, -1, -1,
+ -1, -1, 1813, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1814, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1815, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1816, 1817, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1818, -1, -1, -1, -1, -1, 1819,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1820, 1821, 1822, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1823, -1, -1, -1, -1, -1, -1, -1,
+ 1824, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1825, -1, -1, -1, -1,
+ -1, -1, 1826, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1827, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1828,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1829, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1805, -1, -1, -1, -1,
- 1806, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1830, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1831, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1832, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1833,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1807, -1, -1, 1808,
- -1, -1, -1, -1, -1, -1, 1809, -1,
- -1, 1810, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1834, 1835,
+ -1, -1, -1, -1, -1, -1, 1836, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1811,
- -1, -1, -1, 1812, -1, -1, -1, -1,
- 1813, -1, -1, -1, -1, -1, -1, -1,
- 1814, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1815, -1, 1816, -1, 1817, -1,
+ -1, -1, 1837, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1838, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1818, -1,
- -1, -1, 1819, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1820,
- -1, -1, -1, -1, -1, -1, -1, 1821,
- 1822, -1, 1823, -1, -1, -1, -1, -1,
- -1, 1824, -1, -1, -1, -1, -1, -1,
- 1825, -1, -1, -1, -1, -1, -1, 1826,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1827, -1, -1, -1,
+ -1, -1, -1, -1, 1839, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1840, -1, -1,
+ -1, -1, -1, -1, -1, 1841, -1, -1,
+ -1, -1, -1, -1, -1, 1842, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1843,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1828, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1844, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1829, -1, -1,
+ -1, -1, -1, -1, 1845, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1830, -1, -1, -1, -1, 1831, -1,
- 1832, -1, -1, -1, -1, -1, 1833, -1,
- -1, 1834, -1, -1, -1, -1, -1, 1835,
- -1, -1, -1, -1, -1, -1, -1, 1836,
- 1837, -1, -1, -1, -1, -1, -1, -1,
+ 1846, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1838, 1839, -1, -1, -1,
- -1, -1, -1, -1, 1840, -1, -1, -1,
+ -1, 1847, -1, -1, -1, -1, -1, 1848,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1841, -1, -1, -1,
- -1, 1842, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1849, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1850, -1, -1, -1,
+ -1, -1, -1, 1851, -1, -1, -1, 1852,
+ -1, -1, -1, -1, 1853, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1843, -1, 1844, -1, -1, 1845, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1846, -1, 1847, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1854, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1848, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1849, -1, -1, -1, -1,
- -1, -1, 1850, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1851, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1852, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1853, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1854, -1, -1, -1,
+ -1, 1855, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1856, 1857, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1858, -1, -1, 1859, -1, -1, -1, -1,
+ 1860, 1861, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1862, -1, -1,
+ -1, -1, -1, -1, 1863, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1855, -1, -1,
+ -1, 1864, -1, -1, -1, -1, -1, -1,
+ 1865, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1866, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1867, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1856, -1, -1, -1,
- -1, -1, 1857, -1, 1858, -1, -1, -1,
+ 1868, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1869, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1870, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1871, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1859, -1, -1, 1860, 1861,
- -1, -1, 1862, -1, -1, -1, -1, -1,
- -1, -1, 1863, -1, -1, -1, -1, -1,
- -1, -1, 1864, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1865, -1, -1,
- -1, -1, -1, -1, 1866, 1867, -1, 1868,
- -1, -1, -1, 1869, -1, -1, -1, -1,
- -1, 1870, -1, -1, -1, -1, -1, -1,
+ 1872, 1873, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1874, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1875,
+ -1, -1, -1, -1, -1, -1, -1, 1876,
+ 1877, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1871, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1872, -1, 1873, -1, -1, -1,
- 1874, -1, -1, -1, -1, -1, 1875, -1,
- 1876, -1, -1, 1877, -1, 1878, -1, -1,
- -1, -1, -1, -1, 1879, -1, -1, -1,
+ -1, -1, -1, 1878, -1, -1, -1, -1,
+ -1, -1, -1, 1879, -1, -1, -1, -1,
+ -1, 1880, -1, -1, -1, -1, -1, -1,
+ -1, 1881, -1, -1, -1, 1882, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1883, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1880, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1881, -1, -1, 1882, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1883, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1884, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1884,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 1885, 1886, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1885,
- -1, -1, -1, -1, -1, -1, 1886, -1,
-1, -1, -1, -1, -1, -1, 1887, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 1888, -1, -1,
- -1, -1, -1, -1, -1, 1889, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1889, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1890,
+ -1, 1891, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1890, -1, -1, -1, 1891,
+ -1, -1, -1, -1, -1, 1892, -1, -1,
+ -1, -1, -1, -1, -1, 1893, -1, 1894,
+ -1, -1, -1, -1, -1, 1895, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1892, -1, 1893, 1894,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1895, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1896, -1, -1,
- -1, -1, 1897, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1898,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1896, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1899, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1900,
- -1, 1901, -1, 1902, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1903, -1, -1, 1904, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1897,
+ -1, 1898, -1, -1, -1, -1, -1, -1,
+ -1, 1899, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1900, -1, -1, -1, -1, -1,
+ -1, -1, 1901, -1, -1, -1, 1902, -1,
+ -1, 1903, -1, 1904, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1905,
- 1906, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1905, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1906, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1907, -1, -1, -1, -1, -1, -1, -1,
- -1, 1908, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1907, -1,
+ -1, -1, -1, 1908, -1, -1, -1, 1909,
+ -1, 1910, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1911, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1909, -1, -1, -1, -1, -1, -1, 1910,
- 1911, -1, 1912, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1913,
+ -1, -1, -1, 1912, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1914, -1, -1, 1915, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1916, -1, -1, 1917, -1, -1, -1, 1918,
+ 1913, -1, -1, -1, -1, -1, -1, -1,
+ 1914, -1, -1, 1915, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1916, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1917,
+ -1, -1, -1, -1, -1, -1, -1, 1918,
-1, -1, -1, -1, -1, -1, -1, 1919,
+ -1, -1, -1, 1920, -1, -1, -1, 1921,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1920, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1922, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1923, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1924, -1, -1, -1, 1925, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1926, -1,
+ -1, -1, 1927, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1928, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1921, -1, -1, -1, -1, -1, -1,
- 1922, -1, -1, -1, -1, -1, 1923, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 1929, -1,
+ -1, -1, 1930, -1, -1, -1, -1, -1,
+ -1, 1931, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1924, -1, -1, -1, -1,
+ -1, 1932, -1, -1, -1, -1, -1, -1,
+ 1933, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1934, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1935, -1, 1936, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1925, -1,
+ -1, 1937, -1, -1, -1, -1, -1, -1,
+ -1, -1, 1938, -1, -1, 1939, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1926, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1927, -1, -1, -1, 1928, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1929,
- -1, -1, -1, -1, 1930, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1931, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1940,
+ -1, -1, -1, -1, -1, -1, 1941, -1,
+ 1942, -1, 1943, -1, 1944, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1932, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1945, -1, -1, -1, -1, -1, -1, -1,
+ 1946, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1933, -1, -1, -1, -1, -1, 1934, -1,
+ -1, -1, -1, -1, 1947, -1, -1, -1,
+ -1, -1, 1948, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1935, 1936, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1949, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1950,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1937, -1,
+ 1951, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1952, -1, 1953, 1954,
+ -1, -1, -1, -1, 1955, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1956, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1957, -1, -1, 1958, -1, -1, -1,
+ 1959, -1, -1, -1, -1, -1, -1, 1960,
+ -1, -1, 1961, 1962, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1938, -1, -1, -1, -1, -1, 1939, -1,
- -1, -1, -1, -1, -1, -1, -1, 1940,
- -1, -1, 1941, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1942, -1, -1, -1,
- -1, -1, 1943, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1963, -1, -1, -1, -1, -1, -1,
+ 1964, -1, -1, -1, -1, -1, -1, -1,
+ 1965, -1, -1, -1, -1, -1, 1966, -1,
+ -1, -1, -1, 1967, 1968, 1969, -1, -1,
+ -1, -1, 1970, 1971, -1, -1, -1, -1,
+ 1972, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1973, -1, -1, -1,
+ 1974, -1, -1, -1, -1, -1, 1975, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 1944, -1, -1,
- -1, 1945, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1976, 1977, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1978, -1, -1,
+ -1, -1, 1979, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 1980, 1981, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 1982,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 1983, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1984, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1985, 1986, -1, -1, -1,
+ 1987, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1988, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1946, -1, -1, -1, 1947, -1, 1948, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 1989, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1949, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1950,
+ -1, -1, -1, -1, 1990, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 1991, -1, -1,
+ -1, 1992, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1993, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 1994, -1, -1, -1, -1,
+ -1, 1995, -1, -1, -1, -1, 1996, -1,
+ -1, -1, 1997, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1951, -1, -1, -1,
- 1952, -1, -1, -1, -1, 1953, -1, -1,
- -1, -1, -1, -1, -1, -1, 1954, -1,
- -1, -1, 1955, 1956, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1957, -1, -1, 1958, -1, -1, -1, 1959,
- -1, -1, -1, 1960, -1, -1, -1, -1,
+ -1, 1998, -1, 1999, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1961, -1, -1, 1962, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1963,
+ -1, 2000, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2001, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1964, -1, -1, -1, -1, -1,
- -1, -1, -1, 1965, -1, -1, -1, -1,
+ -1, -1, 2002, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2003, -1, -1,
+ 2004, -1, -1, -1, 2005, -1, -1, -1,
+ -1, 2006, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2007, -1, -1, -1, -1, 2008, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 1966, -1, -1, 1967, -1, -1, -1, -1,
- -1, -1, -1, 1968, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2009, -1,
+ 2010, 2011, 2012, -1, -1, -1, -1, 2013,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2014, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2015, -1, -1,
+ 2016, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2017, -1, -1, -1, -1, -1,
+ 2018, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2019, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2020, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1969, -1, -1, -1, -1,
- -1, -1, 1970, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1971, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 1972, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1973, -1,
- -1, -1, -1, 1974, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1975,
- 1976, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2021, 2022, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 1977, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2023, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 1978,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2024,
+ -1, -1, -1, -1, -1, 2025, -1, -1,
+ -1, -1, -1, 2026, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1979, -1,
- 1980, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 1981, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1982, -1,
- -1, 1983, -1, 1984, -1, -1, -1, -1,
- -1, -1, -1, 1985, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1986, -1,
- -1, -1, -1, -1, -1, 1987, -1, 1988,
+ -1, -1, -1, 2027, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 1989, -1, -1, -1,
- -1, -1, -1, 1990, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 1991, -1,
- -1, -1, -1, -1, -1, 1992, 1993, 1994,
- -1, -1, -1, -1, -1, 1995, 1996, -1,
- -1, -1, -1, -1, -1, -1, -1, 1997,
- 1998, -1, -1, -1, -1, -1, -1, 1999,
- -1, -1, -1, -1, 2000, -1, -1, 2001,
- -1, -1, -1, -1, 2002, 2003, -1, -1,
+ -1, -1, -1, -1, -1, 2028, -1, 2029,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2004, 2005, -1, -1, -1, -1, 2006, 2007,
- -1, -1, -1, -1, -1, 2008, -1, 2009,
- -1, -1, -1, 2010, -1, -1, -1, -1,
- 2011, -1, 2012, -1, 2013, -1, 2014, 2015,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2016, -1, -1, -1, -1, -1, 2017,
- -1, -1, 2018, 2019, -1, -1, -1, -1,
- 2020, -1, -1, -1, -1, -1, -1, 2021,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2030,
+ -1, 2031, 2032, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2022, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2023, -1,
- -1, 2024, 2025, 2026, -1, 2027, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2028, -1, -1, 2029, -1, -1, 2030, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2031, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2033,
+ -1, -1, -1, 2034, -1, -1, -1, 2035,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2032, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2033, -1, -1, -1, -1, -1,
+ 2036, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2037, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2034, -1, -1, 2035, 2036,
- -1, -1, -1, 2037, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2038, 2039, 2040,
+ -1, -1, -1, -1, -1, 2038, -1, -1,
+ -1, -1, -1, -1, 2039, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2041, -1, -1, 2042,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2043, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2044,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2045, -1, -1, -1, -1, -1,
- -1, 2046, 2047, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2048, -1, 2049, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2050, -1, -1, -1, -1, 2051, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2052,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2053, -1,
- -1, 2054, -1, -1, 2055, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2056, -1,
- -1, -1, 2057, -1, -1, 2058, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2059, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2060, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2040, -1, -1, -1, -1, -1,
+ 2041, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2061, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2062, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2042, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2063, -1, -1, 2064,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2065, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2066, -1, -1, -1,
- -1, 2067, -1, 2068, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2043, 2044, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2045, 2046, -1, -1,
+ 2047, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2048, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2049, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2050, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2051, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2052,
+ -1, 2053, -1, 2054, -1, 2055, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2069, -1, -1, -1, 2070, -1, -1,
- -1, 2071, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2056, -1, -1, -1, -1, -1,
+ -1, -1, 2057, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2058, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2072, -1, -1, -1, -1,
- -1, -1, -1, -1, 2073, -1, 2074, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2075, -1, -1, -1, -1, -1, 2076, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2059, -1, -1, -1,
+ -1, 2060, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2061, -1,
+ -1, -1, -1, 2062, -1, -1, -1, -1,
+ 2063, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2064, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2077, -1, 2078, -1, -1, -1, -1, -1,
- -1, 2079, -1, -1, -1, -1, -1, -1,
- -1, -1, 2080, -1, -1, -1, -1, -1,
- 2081, -1, -1, -1, -1, -1, -1, -1,
- 2082, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2083, 2084, -1, -1, -1, -1,
- 2085, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2065, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2066,
+ 2067, -1, -1, -1, -1, -1, 2068, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2086, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2087, -1, -1, -1,
- -1, 2088, -1, 2089, -1, -1, -1, -1,
+ -1, 2069, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2090, -1, -1, -1,
- -1, -1, -1, -1, -1, 2091, -1, -1,
+ -1, -1, -1, 2070, -1, -1, 2071, -1,
+ -1, -1, -1, -1, -1, 2072, -1, -1,
+ -1, -1, -1, 2073, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2074, -1,
+ 2075, -1, -1, 2076, -1, 2077, -1, -1,
+ -1, -1, -1, -1, 2078, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2079, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2080, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2092, -1, -1, -1,
- -1, -1, -1, 2093, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2081, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2094, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2095,
- -1, -1, -1, 2096, -1, -1, -1, -1,
+ -1, -1, 2082, 2083, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2084, 2085, -1, -1, -1, -1,
+ 2086, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2087, -1, 2088, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2097, -1, -1, -1, -1,
+ 2089, 2090, -1, -1, 2091, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2092, -1, -1, -1, 2093, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2098, -1, -1, -1, 2099,
+ 2094, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2100, -1,
- -1, -1, -1, -1, -1, -1, 2101, -1,
+ -1, -1, -1, 2095, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2102, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2096, -1, -1, 2097, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2098,
+ -1, -1, -1, 2099, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2100,
+ -1, 2101, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2102, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2103, -1, -1, -1, 2104, -1, -1,
+ -1, -1, -1, -1, -1, 2105, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2106, -1, -1, 2107, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2103, -1, -1, 2104, -1, -1,
- -1, -1, 2105, -1, -1, -1, -1, -1,
- -1, -1, 2106, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2108, -1, -1,
+ -1, -1, -1, -1, -1, 2109, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2107, -1, 2108, -1, -1, 2109,
- -1, -1, -1, -1, -1, -1, -1, 2110,
- -1, -1, 2111, 2112, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2113, -1, -1,
- -1, 2114, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2115,
- -1, 2116, -1, 2117, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2118, -1, -1, -1, -1, 2119, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2120, -1, 2121, -1,
+ -1, 2110, 2111, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2112, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2122, -1, -1, -1, -1, -1, -1,
- 2123, 2124, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2113, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2125, 2126, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2114, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2115, -1, -1,
+ -1, -1, -1, 2116, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2127, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2128, -1, -1, 2129, -1,
- -1, -1, -1, -1, -1, -1, 2130, -1,
- -1, -1, -1, -1, 2131, -1, 2132, -1,
- -1, -1, -1, -1, -1, -1, -1, 2133,
+ -1, -1, -1, -1, -1, -1, 2117, -1,
+ -1, -1, -1, -1, -1, -1, 2118, -1,
+ 2119, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2120, -1, 2121, -1, -1, -1,
+ -1, -1, -1, -1, 2122, -1, -1, -1,
+ 2123, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2124, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2125, 2126, -1,
+ -1, 2127, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2134, -1,
- -1, -1, 2135, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2136, 2137, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2128, -1, -1, -1, 2129,
+ -1, 2130, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2131, -1, -1, -1,
+ 2132, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2133, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2134, -1, -1, -1, 2135, -1, -1, -1,
+ -1, -1, -1, -1, 2136, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2137, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2138, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2139,
+ -1, -1, -1, -1, -1, -1, 2140, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2138, -1, 2139, -1, -1, 2140,
-1, -1, -1, -1, 2141, -1, -1, -1,
- -1, -1, -1, -1, -1, 2142, -1, -1,
- -1, -1, -1, 2143, -1, -1, -1, -1,
- -1, -1, 2144, 2145, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 2146, -1, -1, -1, 2147, 2148, -1, -1,
- -1, -1, -1, -1, 2149, 2150, -1, -1,
- -1, -1, -1, 2151, -1, -1, 2152, -1,
- -1, -1, -1, 2153, -1, 2154, -1, -1,
- -1, -1, -1, 2155, -1, -1, 2156, -1,
- -1, -1, -1, 2157, 2158, -1, -1, 2159,
- -1, -1, -1, -1, -1, -1, -1, 2160,
- -1, -1, -1, -1, 2161, -1, -1, -1,
- 2162, -1, -1, -1, -1, 2163, -1, -1,
- -1, -1, 2164, -1, -1, -1, -1, -1,
- 2165, 2166, -1, 2167, -1, -1, 2168, -1,
- 2169, 2170, -1, -1, -1, 2171, -1, -1,
- -1, -1, -1, -1, -1, 2172, 2173, -1,
- -1, -1, 2174, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2175, 2176,
- -1, 2177, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2178, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2179, -1, 2180,
- 2181, -1, 2182, -1, 2183, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 2184, -1, 2185, -1, 2186, -1, -1, -1,
- 2187, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2188, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2142, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2143, 2144, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2145, -1, -1, -1,
+ 2146, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2147, -1,
+ 2148, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2149, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2150, -1, -1,
+ -1, -1, -1, -1, 2151, -1, 2152, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2153, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2154, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2155,
+ -1, -1, 2156, -1, -1, -1, -1, -1,
+ -1, -1, 2157, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2158, -1,
+ -1, -1, 2159, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2160, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2161, -1, -1, -1, 2162, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2163, -1, -1, -1, -1, 2164, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2165, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2166, 2167, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2168, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2169, -1, -1, -1, -1,
+ 2170, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2171, -1, -1,
+ -1, 2172, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2173, -1,
+ -1, -1, -1, -1, -1, 2174, -1, -1,
+ -1, -1, -1, -1, 2175, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2176, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2177, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2178, -1, -1, -1,
+ -1, 2179, 2180, -1, -1, -1, -1, 2181,
+ -1, -1, -1, -1, 2182, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2183, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2184, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2185, -1, 2186,
+ -1, -1, -1, -1, -1, 2187, -1, -1,
+ 2188, -1, -1, -1, -1, -1, -1, -1,
2189, -1, -1, -1, -1, -1, -1, -1,
- -1, 2190, -1, 2191, 2192, -1, -1, 2193,
- -1, -1, -1, -1, -1, -1, -1, 2194,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2195, 2196, 2197, -1, -1,
+ 2190, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2191, 2192, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2193, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2194, -1, -1, -1, -1,
+ 2195, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2196, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2197, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 2198, -1,
+ -1, -1, -1, 2199, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2200,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2199, -1, -1, -1, -1, -1,
+ 2201, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2200, -1, -1,
- -1, -1, -1, -1, -1, -1, 2201, -1,
- -1, 2202, -1, -1, -1, -1, -1, 2203,
+ -1, -1, -1, 2202, -1, 2203, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 2204, -1,
- -1, -1, 2205, -1, -1, -1, -1, -1,
- -1, 2206, -1, -1, -1, -1, -1, -1,
- 2207, 2208, 2209, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2210, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2205, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2206, -1,
+ -1, -1, -1, -1, -1, -1, 2207, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2208, -1, -1,
+ -1, -1, -1, -1, -1, 2209, 2210, -1,
+ -1, -1, 2211, -1, 2212, -1, -1, -1,
+ 2213, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2214, -1, -1,
+ -1, -1, -1, -1, 2215, 2216, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2217, -1, -1, 2218, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2219, 2220,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2221, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2222, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2223, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2224,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2211, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2225, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2212, 2213, 2214, -1, 2215,
- 2216, -1, -1, 2217, -1, -1, 2218, 2219,
- -1, -1, -1, -1, -1, 2220, 2221, -1,
- -1, -1, -1, -1, -1, -1, 2222, -1,
- -1, 2223, -1, -1, -1, -1, -1, -1,
+ 2226, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2224, -1, -1, 2225, -1, -1,
- -1, 2226, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2227, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2228, -1, -1, -1, -1, 2229,
+ 2227, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2228, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2229, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2230, -1, 2231,
+ -1, 2232, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2230, -1, 2231, -1, 2232, -1,
-1, 2233, -1, -1, -1, -1, -1, -1,
- -1, 2234, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2234, -1, -1,
-1, -1, -1, -1, 2235, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2236, -1, -1,
- 2237, -1, -1, -1, -1, -1, -1, -1,
- 2238, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2239, 2240, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2241, 2242, -1, -1, -1, -1, -1,
- 2243, 2244, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2245, -1, 2246,
- 2247, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2248, -1, -1, 2249, -1, -1, -1, -1,
- 2250, -1, -1, -1, -1, -1, 2251, -1,
+ -1, 2236, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2252, -1, -1, -1, -1, -1, 2253,
- -1, -1, -1, -1, -1, -1, -1, 2254,
- -1, -1, -1, 2255, -1, -1, -1, -1,
- 2256, 2257, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2258,
- -1, -1, 2259, -1, -1, -1, 2260, 2261,
- -1, 2262, 2263, -1, -1, 2264, -1, -1,
- -1, 2265, -1, -1, -1, -1, -1, 2266,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2267, -1, -1, -1, -1, -1, -1,
- 2268, -1, -1, -1, -1, -1, -1, 2269,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2270, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2271, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2272, -1, -1, -1,
+ -1, -1, 2237, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2238, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2273, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2274, -1, 2275, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2276, -1, 2277,
- -1, 2278, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2239, -1, -1, -1, -1, -1,
+ -1, -1, 2240, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2241, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2279, -1, -1, 2280,
- -1, -1, 2281, -1, -1, -1, -1, -1,
- -1, -1, 2282, -1, -1, -1, -1, -1,
- -1, -1, 2283, -1, -1, -1, 2284, -1,
- -1, -1, -1, -1, -1, -1, 2285, 2286,
- -1, 2287, -1, 2288, -1, -1, -1, -1,
- -1, -1, -1, -1, 2289, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2290, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2291, -1,
- -1, -1, 2292, 2293, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2242, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2243, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2244, -1, -1, -1, -1, -1, 2245,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2294, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2295,
- 2296, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2297, 2298, -1, -1, -1, -1,
- -1, -1, -1, -1, 2299, -1, -1, -1,
+ -1, -1, -1, -1, 2246, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2247, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2248,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2300, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2301, -1, 2302, 2303, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2304, 2305, -1, -1, 2306, -1,
- -1, 2307, -1, -1, -1, -1, -1, -1,
- 2308, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2309, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2310, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2249, -1, -1, -1, -1, -1, -1, -1,
+ 2250, -1, 2251, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2252, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2253, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2254, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2255, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2256, 2257,
+ -1, 2258, -1, -1, -1, -1, 2259, -1,
+ -1, -1, 2260, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2261, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2311, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2312,
- -1, -1, -1, -1, -1, -1, -1, 2313,
- -1, -1, -1, 2314, -1, -1, -1, 2315,
- -1, 2316, -1, -1, -1, -1, -1, -1,
- -1, -1, 2317, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2318, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2319, -1, -1, -1, -1,
+ -1, 2262, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2263, 2264, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2265,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2320, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2321,
- -1, -1, -1, -1, 2322, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2323, -1, -1,
- -1, -1, -1, -1, -1, -1, 2324, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2325, -1, 2326,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2266, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2327, -1, -1, -1, -1,
- -1, -1, -1, -1, 2328, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2329, -1, -1, -1, -1, -1,
+ -1, -1, 2267, -1, -1, -1, -1, -1,
+ -1, -1, 2268, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2269, -1,
+ -1, 2270, 2271, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2330, -1, -1, -1,
+ -1, -1, -1, 2272, -1, -1, -1, -1,
+ -1, 2273, -1, 2274, -1, -1, -1, 2275,
+ -1, -1, -1, -1, -1, -1, -1, 2276,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2331, -1, -1, -1,
- -1, -1, -1, -1, 2332, -1, 2333, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2277, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2278, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2279, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2280, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2281,
+ -1, 2282, 2283, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2284, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2285,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2286, 2287, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2288, -1, 2289, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2290,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2291, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2334, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2335, -1, -1, -1, -1, -1,
- 2336, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2337, 2338,
- -1, -1, 2339, -1, -1, -1, -1, -1,
+ -1, 2292, -1, -1, -1, -1, 2293, -1,
+ 2294, -1, 2295, -1, -1, -1, -1, -1,
+ -1, -1, 2296, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2297, -1,
+ -1, -1, -1, -1, -1, -1, 2298, -1,
+ 2299, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2300, -1, -1, -1, -1, 2301,
+ -1, -1, -1, -1, 2302, -1, -1, 2303,
+ -1, -1, -1, -1, -1, 2304, 2305, -1,
+ -1, 2306, -1, 2307, 2308, -1, -1, -1,
+ -1, -1, 2309, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2310,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2340, -1, 2341, -1, -1, -1,
+ 2311, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2312, -1, -1, -1, -1, -1,
+ -1, 2313, -1, -1, -1, 2314, -1, -1,
+ 2315, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2316, -1, -1, -1, -1, -1,
+ -1, 2317, -1, -1, -1, -1, 2318, -1,
+ 2319, -1, -1, 2320, -1, -1, -1, -1,
+ -1, 2321, -1, -1, 2322, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2342, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2323,
+ -1, -1, 2324, -1, -1, -1, 2325, -1,
+ -1, -1, -1, 2326, -1, -1, 2327, -1,
+ -1, -1, 2328, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2329,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2330, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2343, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2344, -1,
- -1, -1, -1, 2345, 2346, -1, -1, -1,
- -1, 2347, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2348,
- -1, -1, -1, -1, 2349, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2350,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2331, -1, -1, -1, 2332, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2351, -1, -1, -1, -1, -1, 2352, -1,
+ 2333, 2334, -1, -1, -1, -1, -1, 2335,
+ -1, -1, 2336, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2337, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2338, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2339, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2340, -1,
+ 2341, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2342, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2343, -1, -1, 2344, 2345,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2346, 2347, -1,
+ -1, -1, -1, -1, -1, -1, 2348, -1,
+ -1, 2349, 2350, 2351, -1, -1, 2352, -1,
+ 2353, -1, 2354, -1, 2355, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2356, -1, -1, -1, -1,
+ 2357, -1, -1, -1, -1, -1, -1, 2358,
+ -1, -1, -1, 2359, -1, -1, 2360, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2353, -1, -1, -1, -1, -1,
+ 2361, 2362, 2363, -1, -1, 2364, -1, -1,
+ -1, -1, -1, -1, 2365, -1, -1, -1,
+ 2366, -1, -1, 2367, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2368, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2354, 2355, -1, -1, -1, -1, -1,
- 2356, 2357, 2358, -1, -1, -1, -1, -1,
- -1, 2359, -1, -1, -1, -1, -1, -1,
- -1, 2360, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2361, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2369, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2362, -1, -1, 2363, 2364,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2365, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2370, -1, -1, 2371, -1,
+ -1, -1, -1, 2372, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2366,
- -1, -1, -1, 2367, 2368, -1, -1, -1,
- -1, 2369, -1, -1, -1, -1, 2370, 2371,
- 2372, -1, 2373, -1, -1, -1, -1, -1,
- -1, 2374, -1, -1, -1, -1, 2375, -1,
+ -1, -1, -1, -1, -1, -1, 2373, -1,
+ -1, -1, -1, 2374, -1, -1, -1, -1,
+ 2375, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 2376, -1, -1,
- -1, -1, -1, 2377, -1, 2378, -1, 2379,
- -1, -1, -1, -1, -1, 2380, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2381, -1, -1, -1, -1, -1, -1,
- 2382, -1, 2383, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2384,
- -1, -1, -1, -1, -1, -1, 2385, -1,
- -1, 2386, -1, -1, -1, -1, -1, -1,
- -1, 2387, -1, -1, -1, -1, -1, -1,
- -1, -1, 2388, -1, -1, -1, -1, 2389,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2390, -1,
- -1, 2391, 2392, -1, 2393, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2394,
- -1, -1, -1, -1, -1, 2395, -1, -1,
- 2396, -1, -1, -1, -1, -1, 2397, -1,
- -1, 2398, -1, -1, -1, -1, -1, -1,
- -1, -1, 2399, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2400, 2401, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2377, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2378, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2379, 2380,
+ 2381, -1, -1, -1, -1, -1, -1, 2382,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2383, -1, -1, -1, -1,
+ -1, -1, 2384, -1, -1, -1, -1, -1,
+ -1, 2385, -1, -1, -1, -1, -1, -1,
+ -1, 2386, 2387, -1, -1, -1, -1, -1,
+ 2388, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2389, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2390, -1, 2391,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2392, -1, -1,
+ 2393, -1, -1, 2394, -1, -1, 2395, -1,
+ 2396, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2397,
+ 2398, -1, -1, -1, -1, -1, 2399, -1,
+ -1, -1, 2400, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2401, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 2402, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 2403, -1, -1,
- -1, 2404, 2405, -1, -1, -1, 2406, -1,
- -1, -1, 2407, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2408, -1, -1, -1,
- -1, 2409, -1, -1, -1, -1, 2410, -1,
- 2411, -1, 2412, -1, -1, -1, -1, -1,
- -1, -1, -1, 2413, -1, -1, -1, 2414,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 2415, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2416, -1,
- -1, 2417, -1, -1, 2418, 2419, -1, -1,
- 2420, -1, 2421, -1, -1, -1, -1, 2422,
- -1, -1, -1, -1, -1, -1, 2423, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- 2424, -1, 2425, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2426,
- -1, -1, -1, -1, -1, -1, -1, 2427,
- -1, -1, 2428, -1, 2429, -1, 2430, -1,
- 2431, 2432, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2433, -1, 2434, -1, -1, -1, -1,
- -1, -1, 2435, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2436, 2437, -1, 2438,
- -1, -1, -1, -1, -1, 2439, -1, -1,
- -1, 2440, 2441, -1, -1, -1, 2442, -1,
- -1, 2443, -1, -1, 2444, -1, -1, -1,
- 2445, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2446, -1,
- -1, 2447, -1, -1, -1, 2448, -1, -1,
+ -1, 2404, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2405, -1, -1, -1, -1, 2406,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2407, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2408, -1, -1, -1, -1, -1,
+ -1, -1, 2409, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2410, -1, -1, -1,
+ -1, -1, -1, -1, 2411, -1, -1, -1,
+ -1, 2412, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2413, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2414, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2415, 2416, -1, -1, 2417, -1, -1,
+ -1, -1, -1, 2418, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2419, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2420,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2421, -1, -1, -1, -1, -1, -1,
+ -1, 2422, -1, 2423, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2424, 2425, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2426, -1, -1,
+ -1, 2427, -1, -1, 2428, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2429, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2430,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2431, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2432, -1, 2433, -1,
+ -1, -1, -1, 2434, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2435, -1, 2436, 2437, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2438, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2439, -1, -1, -1, -1, -1,
+ 2440, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2441, -1, -1, -1,
+ -1, -1, -1, -1, 2442, -1, 2443, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2444, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2445, 2446, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2447, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2448, -1, -1, -1, -1,
-1, -1, 2449, -1, -1, -1, -1, -1,
- -1, 2450, -1, -1, -1, -1, -1, -1,
- 2451, -1, 2452, -1, -1, -1, -1, -1,
- -1, -1, -1, 2453, 2454, 2455, 2456, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2457, 2458, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2450, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2451,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2452, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 2453, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2454, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2455,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2456, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2457, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2458, -1, -1,
2459, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2460, -1, -1,
+ -1, 2460, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2461, -1, -1, -1, -1, -1, -1,
+ -1, 2462, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2463, 2464, -1, -1,
+ -1, 2465, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2466, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2461, -1, -1,
- -1, -1, -1, 2462, -1, -1, -1, -1,
- 2463, 2464, -1, -1, -1, -1, -1, -1,
- -1, -1, 2465, -1, -1, 2466, -1, -1,
+ -1, -1, -1, 2467, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2467,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2468, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2468, -1, -1, -1, -1, 2469, -1, -1,
- 2470, -1, -1, 2471, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2472, -1, 2473,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2469, -1, 2470, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2471, 2472, -1, 2473, -1,
2474, -1, -1, -1, -1, -1, -1, -1,
- 2475, -1, -1, -1, -1, -1, -1, 2476,
- -1, -1, -1, -1, -1, -1, 2477, 2478,
+ -1, -1, 2475, -1, -1, -1, -1, 2476,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2479, -1, 2480,
- 2481, -1, -1, -1, -1, 2482, -1, -1,
- 2483, -1, -1, -1, -1, -1, 2484, -1,
- -1, -1, -1, -1, -1, 2485, -1, -1,
- -1, -1, -1, 2486, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2487, -1, -1, -1, -1,
- 2488, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2489,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2490, 2491, -1, 2492, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2477, -1, -1, -1,
+ -1, -1, 2478, -1, -1, -1, 2479, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2493, -1, -1,
- -1, -1, -1, -1, -1, -1, 2494, -1,
- -1, -1, -1, 2495, -1, -1, -1, 2496,
- -1, -1, -1, -1, -1, -1, 2497, -1,
- -1, -1, 2498, -1, -1, -1, -1, -1,
- 2499, -1, -1, -1, -1, -1, 2500, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2501, -1, -1, -1, -1, -1, 2502, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2503, 2504, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2505, -1,
- -1, -1, 2506, -1, -1, 2507, -1, 2508,
- -1, 2509, -1, -1, -1, -1, 2510, -1,
- 2511, -1, -1, -1, -1, -1, -1, 2512,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2513, -1, -1, 2514, -1, -1, -1,
+ -1, -1, -1, -1, 2480, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2481,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2515, -1, -1, -1, -1, -1, -1, -1,
- -1, 2516, -1, -1, -1, 2517, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2482, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2518, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2519, -1, -1, 2520,
+ -1, -1, 2483, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2521, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2522, -1, -1, -1, 2523,
- -1, -1, -1, -1, -1, -1, -1, 2524,
+ -1, -1, -1, -1, -1, 2484, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2485, -1,
+ -1, -1, -1, -1, -1, 2486, -1, -1,
+ -1, -1, -1, -1, 2487, -1, -1, -1,
+ -1, -1, -1, 2488, -1, -1, -1, -1,
+ -1, -1, 2489, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2525, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2526,
- -1, -1, -1, -1, 2527, -1, 2528, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2529,
- 2530, -1, -1, -1, -1, 2531, -1, -1,
- 2532, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2533, -1, -1, 2534, 2535, -1,
- -1, -1, -1, -1, -1, -1, 2536, -1,
- -1, -1, 2537, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2490,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2491, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2492, -1, -1, -1, -1, -1, -1,
+ -1, 2493, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2494, 2495, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2538, -1, 2539, -1, -1, 2540, 2541,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2496, -1, 2497, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2542, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2543,
- -1, -1, 2544, -1, -1, -1, -1, 2545,
+ 2498, -1, -1, -1, -1, -1, -1, 2499,
+ 2500, -1, 2501, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2502, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2503, -1, -1,
+ -1, 2504, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2546, -1, -1, -1,
+ -1, -1, -1, -1, 2505, -1, -1, 2506,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2507, -1, -1, -1, -1, -1, 2508,
+ -1, -1, -1, -1, -1, 2509, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2510,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2547, -1, -1, 2548,
- -1, -1, -1, -1, -1, -1, 2549, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2550, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2551, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2552, -1, -1,
- 2553, -1, -1, -1, -1, 2554, -1, -1,
- -1, -1, -1, -1, -1, 2555, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2556, -1, -1, -1, -1,
+ -1, -1, -1, 2511, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2512, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2513,
+ -1, -1, -1, -1, -1, -1, -1, 2514,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2557, -1, -1, -1, -1, 2558, -1,
- -1, -1, -1, 2559, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2515, 2516, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2560, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2561, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2517, -1, 2518, 2519, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2562, -1, -1, -1, -1, -1, -1, -1,
- -1, 2563, -1, -1, -1, -1, 2564, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2565, -1, -1, -1, -1, -1, 2566,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2567, -1, -1,
+ -1, -1, -1, -1, -1, 2520, -1, -1,
+ 2521, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2568, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2569, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2522, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2523, -1,
+ -1, -1, -1, 2524, -1, -1, -1, -1,
+ 2525, -1, -1, -1, -1, -1, -1, -1,
+ 2526, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2527, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2570, -1, -1, -1, 2571,
- -1, -1, -1, -1, 2572, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2573, -1,
+ -1, -1, 2528, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2529, -1,
+ -1, -1, -1, -1, 2530, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2531, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2574, -1,
- -1, -1, -1, -1, 2575, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2576, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2577, -1, -1, -1,
- -1, -1, 2578, -1, 2579, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2532, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2580,
- -1, 2581, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2582,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2533, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2583, 2584, 2585, -1, -1, -1, -1, -1,
- -1, -1, 2586, -1, -1, 2587, -1, -1,
- -1, -1, -1, -1, -1, -1, 2588, 2589,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2590,
+ -1, -1, 2534, 2535, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2591, -1, -1, 2592, 2593, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2594, -1,
- -1, -1, -1, -1, 2595, -1, 2596, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2597, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2598, -1, -1, -1, -1, 2599,
+ -1, -1, -1, 2536, -1, 2537, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2600, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2601, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2602, -1, -1, -1,
- -1, -1, -1, -1, -1, 2603, -1, 2604,
- -1, -1, -1, 2605, -1, 2606, -1, -1,
+ -1, -1, -1, -1, 2538, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2539, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2540,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2607,
- -1, -1, -1, -1, -1, 2608, -1, -1,
- 2609, -1, -1, -1, -1, -1, -1, -1,
- -1, 2610, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2611, 2612, -1, -1, 2613,
+ -1, -1, -1, -1, -1, -1, -1, 2541,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2614, -1, -1, -1, -1, -1,
- -1, -1, -1, 2615, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2616, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2542, -1, -1,
+ -1, 2543, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2544, 2545, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2546,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2617, -1, -1, -1,
+ -1, -1, -1, 2547, -1, -1, 2548, -1,
+ -1, 2549, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2550,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2618, -1, 2619, -1, -1, -1, 2620,
- -1, -1, -1, -1, 2621, -1, 2622, -1,
+ -1, 2551, 2552, -1, -1, -1, -1, -1,
+ -1, 2553, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2554, -1, -1,
+ -1, -1, 2555, -1, 2556, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2557, -1, -1, -1,
+ 2558, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2623, -1, -1, -1, 2624, -1,
- -1, -1, -1, -1, -1, -1, 2625, -1,
+ 2559, -1, -1, -1, -1, -1, -1, 2560,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2626, -1, -1,
- -1, -1, 2627, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2628, -1, -1, -1,
- -1, 2629, -1, -1, -1, -1, -1, 2630,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2631,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2632, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2633, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2561, 2562, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2563, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2634, -1, -1, -1, -1,
- 2635, -1, -1, -1, 2636, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2637,
- -1, 2638, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2564,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2639, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2640, -1,
- -1, -1, -1, -1, 2641, 2642, -1, -1,
- -1, 2643, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2565, -1, -1, -1, -1,
+ -1, -1, -1, 2566, 2567, 2568, -1, 2569,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2644, -1, -1, -1, -1, 2645, -1, -1,
- -1, -1, -1, -1, -1, 2646, -1, -1,
- 2647, -1, -1, 2648, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2649, -1, -1, -1, -1, -1, -1,
- 2650, -1, -1, -1, -1, -1, -1, -1,
- 2651, -1, -1, 2652, -1, 2653, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2570,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2654, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2571, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2655, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2572, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2656, -1, -1,
+ -1, 2573, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2574, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2657, -1, -1, 2658, -1, -1, -1,
- -1, -1, -1, 2659, -1, 2660, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2575,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2661, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2576, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2662, -1, -1, -1,
- 2663, -1, -1, -1, 2664, -1, -1, -1,
- 2665, -1, -1, -1, -1, -1, -1, -1,
- 2666, 2667, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2668,
- -1, -1, 2669, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2577, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2578, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2670, 2671, -1, -1, -1,
+ -1, -1, -1, -1, 2579, -1, 2580, 2581,
+ -1, -1, -1, -1, -1, -1, -1, 2582,
+ 2583, 2584, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2672, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2673, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2674,
- -1, -1, 2675, -1, -1, -1, 2676, -1,
- -1, -1, -1, -1, -1, 2677, -1, -1,
- -1, -1, -1, -1, 2678, -1, -1, -1,
- -1, -1, -1, -1, 2679, -1, -1, -1,
- -1, -1, -1, -1, 2680, -1, -1, -1,
- -1, 2681, -1, -1, -1, -1, -1, -1,
- 2682, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2683, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2585, -1,
+ -1, -1, 2586, -1, -1, -1, -1, -1,
+ 2587, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2684, -1, 2685, -1, -1,
- -1, 2686, 2687, -1, -1, 2688, -1, 2689,
- -1, 2690, 2691, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2692, -1,
- -1, -1, 2693, -1, -1, -1, -1, -1,
- -1, -1, -1, 2694, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2695, -1, -1,
- 2696, -1, -1, -1, -1, 2697, -1, -1,
+ -1, -1, -1, -1, 2588, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2698, -1, -1, 2699, -1, -1,
+ -1, -1, 2589, -1, -1, -1, -1, 2590,
+ -1, -1, -1, -1, 2591, -1, -1, -1,
+ -1, 2592, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2700, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2701, 2702, -1, -1, -1, -1,
- 2703, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2704, -1, -1, -1,
- -1, -1, 2705, -1, 2706, -1, 2707, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2708, -1, -1, -1, -1, -1,
- -1, -1, -1, 2709, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2710, -1, -1,
- -1, -1, -1, -1, -1, 2711, -1, -1,
- -1, 2712, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2713,
- -1, -1, -1, -1, 2714, -1, 2715, -1,
+ 2593, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2716, 2717, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2718, -1, -1, -1,
- -1, -1, -1, -1, 2719, -1, -1, -1,
- -1, -1, 2720, -1, -1, -1, -1, -1,
- -1, -1, 2721, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2722, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2723, -1, -1,
- -1, -1, -1, -1, -1, 2724, -1, -1,
- -1, -1, -1, -1, -1, 2725, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2594, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2726, -1, -1, -1, 2727, -1,
- -1, -1, -1, 2728, -1, -1, 2729, -1,
- 2730, -1, 2731, -1, -1, -1, -1, 2732,
+ -1, 2595, -1, -1, 2596, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2597, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2733, -1, -1, -1, -1, -1, -1, -1,
- 2734, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2598, -1, -1, -1, -1, -1, -1,
+ -1, 2599, -1, -1, -1, -1, -1, -1,
+ -1, 2600, 2601, -1, 2602, -1, -1, 2603,
+ -1, 2604, -1, -1, 2605, 2606, 2607, -1,
+ -1, -1, 2608, -1, -1, -1, -1, -1,
+ -1, -1, 2609, -1, -1, -1, -1, -1,
+ -1, 2610, -1, -1, -1, -1, -1, -1,
+ 2611, -1, -1, -1, -1, -1, -1, -1,
+ 2612, -1, 2613, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2614, -1, -1,
+ -1, -1, 2615, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2616, -1,
+ 2617, -1, -1, 2618, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2619, -1, 2620,
+ -1, -1, -1, 2621, -1, -1, 2622, -1,
+ -1, -1, -1, -1, -1, -1, 2623, -1,
+ -1, -1, 2624, -1, -1, -1, -1, -1,
+ 2625, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2626, -1, -1,
+ -1, -1, 2627, -1, 2628, 2629, -1, -1,
+ -1, -1, -1, 2630, -1, -1, -1, 2631,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2735, -1, -1, -1, 2736,
- -1, -1, -1, 2737, -1, -1, 2738, -1,
- -1, 2739, 2740, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2741,
- -1, -1, -1, -1, 2742, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2743, -1,
- -1, -1, -1, 2744, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2745, -1,
+ -1, -1, -1, 2632, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2633, -1, 2634,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2746, -1, -1, -1,
- -1, -1, 2747, 2748, -1, -1, -1, -1,
- -1, -1, -1, -1, 2749, -1, -1, -1,
- -1, -1, -1, 2750, 2751, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2752, -1, -1, -1, -1, -1,
- -1, -1, 2753, -1, -1, -1, -1, -1,
- -1, -1, 2754, -1, -1, -1, -1, -1,
- -1, -1, -1, 2755, -1, -1, 2756, -1,
+ -1, -1, -1, -1, -1, -1, 2635, -1,
+ -1, -1, -1, -1, 2636, -1, -1, 2637,
+ 2638, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2639, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2640,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2757, -1, -1, -1, -1, -1, -1, -1,
- -1, 2758, -1, -1, -1, -1, -1, 2759,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2760, -1, 2761, -1, 2762, -1, -1, -1,
- 2763, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2764, -1, -1,
- -1, -1, -1, 2765, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2766, -1,
- -1, -1, -1, -1, -1, -1, 2767, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2641, -1, -1, -1, -1, -1,
+ -1, -1, 2642, -1, 2643, 2644, -1, -1,
+ -1, -1, -1, 2645, -1, 2646, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2647, -1,
+ -1, -1, -1, 2648, 2649, -1, -1, -1,
+ -1, -1, 2650, -1, 2651, 2652, -1, 2653,
+ -1, 2654, -1, -1, -1, -1, -1, -1,
+ -1, 2655, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2768, -1, 2769, -1,
+ -1, -1, 2656, -1, -1, -1, 2657, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2770, 2771, -1, -1, -1, -1,
- -1, -1, -1, -1, 2772, -1, 2773, -1,
- -1, -1, -1, -1, 2774, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2775, -1, -1, -1,
- 2776, -1, -1, 2777, -1, -1, 2778, -1,
- -1, -1, -1, -1, 2779, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2658, -1, 2659, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2780, -1, 2781, -1, 2782,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2783, -1, -1, -1, -1, -1, -1, 2784,
- -1, -1, -1, -1, -1, 2785, -1, -1,
- -1, -1, 2786, -1, -1, -1, 2787, -1,
+ 2660, 2661, -1, -1, -1, 2662, -1, 2663,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2664, 2665,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2666, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2667,
+ -1, 2668, 2669, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2670, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2671, -1, -1,
+ -1, -1, -1, 2672, 2673, -1, -1, 2674,
+ -1, 2675, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2676, -1, -1, -1, 2677,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2788, -1, 2789,
+ 2678, -1, -1, -1, -1, -1, -1, 2679,
+ -1, -1, -1, -1, 2680, -1, -1, -1,
+ -1, 2681, 2682, -1, -1, -1, 2683, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2790, -1, -1, -1, -1, -1, 2791,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2792, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2793, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2684, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2685, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2686,
+ -1, 2687, -1, -1, -1, 2688, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2689, -1, -1, 2690, -1, -1, -1,
+ -1, -1, -1, 2691, -1, -1, -1, -1,
+ 2692, -1, 2693, -1, -1, -1, -1, -1,
+ 2694, 2695, -1, -1, -1, -1, -1, 2696,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2697, 2698, 2699, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2700,
+ -1, -1, -1, -1, -1, -1, 2701, -1,
+ -1, -1, -1, 2702, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2703, -1,
+ -1, -1, -1, -1, -1, 2704, 2705, 2706,
+ -1, 2707, -1, -1, -1, 2708, -1, 2709,
+ -1, -1, 2710, -1, 2711, -1, 2712, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2713, 2714, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2794, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2795, -1, -1, -1, -1,
- -1, -1, -1, -1, 2796, 2797, -1, -1,
- 2798, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2799, -1,
- -1, -1, -1, -1, 2800, 2801, -1, -1,
- -1, -1, -1, -1, 2802, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2803,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2804, -1, -1, -1, -1, -1, -1,
- -1, 2805, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2715,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2806, -1, -1, -1,
- 2807, -1, -1, -1, 2808, -1, -1, -1,
- 2809, -1, -1, -1, 2810, 2811, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2812,
- -1, -1, -1, -1, -1, 2813, -1, -1,
- -1, -1, -1, -1, -1, -1, 2814, -1,
- -1, -1, -1, 2815, -1, -1, 2816, -1,
- -1, -1, -1, -1, 2817, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2716, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2717, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2818, -1, -1, -1, -1, -1, -1,
+ 2718, -1, -1, 2719, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2819, 2820, 2821,
- -1, 2822, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2720, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2721, -1, -1, -1, -1, 2722, 2723,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2724, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2725, -1, 2726, -1, 2727,
+ -1, -1, 2728, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2729, -1, 2730, 2731, -1, 2732, 2733, -1,
+ -1, -1, 2734, -1, -1, -1, 2735, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2823, -1, -1, -1, -1, -1, -1, -1,
+ 2736, 2737, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2738, 2739, 2740,
+ -1, -1, -1, 2741, -1, -1, 2742, -1,
+ -1, -1, 2743, -1, -1, -1, -1, 2744,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2745,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2824, -1, 2825, -1, -1, -1, -1,
+ -1, 2746, -1, -1, 2747, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2748, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2826, 2827, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2828, 2829, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2830,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2831, -1, -1, -1,
+ -1, -1, -1, -1, 2749, -1, 2750, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2751, -1, -1, 2752, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2753, -1,
+ -1, -1, -1, -1, -1, 2754, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2832, -1,
- -1, -1, 2833, -1, -1, -1, 2834, 2835,
+ 2755, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2836, -1, -1, -1, -1, -1, 2837,
- -1, -1, -1, -1, -1, -1, 2838, -1,
- -1, -1, -1, -1, -1, 2839, 2840, 2841,
- 2842, -1, -1, -1, -1, -1, -1, -1,
- 2843, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2756, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2757,
+ -1, -1, -1, -1, -1, 2758, -1, 2759,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2844, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2845, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2846, -1, -1,
- -1, -1, -1, 2847, 2848, -1, -1, -1,
- 2849, -1, -1, -1, -1, -1, -1, -1,
- -1, 2850, -1, -1, -1, -1, -1, -1,
- -1, -1, 2851, -1, -1, -1, -1, -1,
- -1, -1, -1, 2852, 2853, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2854, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2760, -1, -1,
+ -1, -1, 2761, 2762, -1, -1, -1, 2763,
+ -1, 2764, 2765, 2766, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2767,
+ -1, 2768, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2855, -1,
- -1, 2856, -1, -1, -1, -1, -1, -1,
+ -1, 2769, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2770, -1, -1, 2771, -1,
+ -1, -1, -1, -1, 2772, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2857, -1, -1, -1, -1, -1,
- -1, 2858, -1, -1, -1, -1, -1, 2859,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2860, -1,
- -1, -1, 2861, -1, -1, -1, -1, -1,
- -1, -1, 2862, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2863, -1,
- -1, 2864, 2865, -1, -1, -1, 2866, -1,
- -1, -1, -1, 2867, 2868, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2773, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2869, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2774, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2870, -1, -1, -1, 2871, -1, -1,
+ -1, -1, 2775, -1, 2776, -1, -1, -1,
+ 2777, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2778, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2779,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2780, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2872, -1, -1,
- 2873, -1, -1, -1, -1, -1, -1, -1,
- 2874, 2875, -1, -1, -1, -1, -1, -1,
- 2876, -1, -1, -1, -1, -1, -1, 2877,
- -1, -1, -1, -1, -1, -1, 2878, -1,
- -1, -1, -1, -1, -1, 2879, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2880,
- -1, -1, -1, -1, -1, 2881, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2781,
+ -1, -1, -1, 2782, -1, -1, 2783, -1,
+ -1, 2784, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2785, -1, -1, 2786, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2787, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2788, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2789, 2790, -1,
+ -1, -1, -1, 2791, -1, -1, -1, 2792,
+ -1, 2793, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2882, -1, -1, -1, -1, 2883, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2884, 2885, -1, -1,
- 2886, -1, 2887, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2888,
+ 2794, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2795, -1, -1, -1, -1, -1,
+ -1, 2796, -1, -1, -1, -1, 2797, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2798,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2799, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2800, -1, -1, -1,
+ 2801, -1, 2802, -1, -1, -1, -1, -1,
+ 2803, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2889, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2804, 2805,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2890,
+ -1, -1, -1, -1, -1, -1, -1, 2806,
+ -1, -1, -1, -1, -1, 2807, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2808, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2809, -1, -1, -1, 2810, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2891,
- -1, -1, 2892, -1, -1, -1, -1, -1,
- -1, 2893, -1, 2894, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2811, -1, 2812,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2895, -1, -1, -1, 2896, -1,
- -1, -1, -1, 2897, -1, -1, 2898, -1,
- -1, -1, -1, -1, 2899, -1, -1, -1,
- -1, -1, 2900, -1, -1, -1, -1, -1,
+ -1, 2813, -1, -1, -1, -1, 2814, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2901, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2902, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2815,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2903, -1, -1, -1,
- -1, -1, -1, 2904, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2905, -1, -1, 2906,
- 2907, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2816, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2817, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2818, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2908, -1, 2909, -1,
- -1, 2910, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2819, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2911, 2912, -1, -1, 2913, 2914, -1,
+ 2820, -1, -1, -1, -1, 2821, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2915,
+ -1, -1, -1, -1, 2822, -1, 2823, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2824, -1, -1, -1, -1,
+ -1, 2825, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2916, -1, -1, -1, -1, -1,
+ -1, 2826, -1, -1, -1, -1, -1, 2827,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2917, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2918, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2919,
+ -1, -1, -1, -1, 2828, 2829, -1, -1,
+ -1, -1, -1, 2830, -1, 2831, -1, 2832,
+ -1, -1, -1, -1, 2833, -1, 2834, -1,
+ -1, -1, -1, -1, -1, -1, 2835, -1,
+ -1, -1, -1, -1, -1, 2836, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2920, -1, -1, -1,
- -1, -1, -1, -1, 2921, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2837, -1, 2838, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2922, -1, 2923, -1,
- 2924, -1, -1, -1, -1, 2925, -1, -1,
+ -1, 2839, -1, 2840, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2926, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2927, -1, 2928, 2929,
- -1, -1, 2930, 2931, -1, -1, 2932, -1,
+ -1, -1, 2841, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2842, -1,
+ 2843, -1, 2844, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2845, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2846, -1, 2847, -1, -1, -1, -1,
+ -1, 2848, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2933, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2934, -1, -1, 2935, 2936, -1, -1,
+ -1, 2849, -1, -1, -1, -1, -1, 2850,
+ -1, -1, 2851, -1, -1, -1, -1, -1,
+ 2852, -1, -1, -1, -1, -1, 2853, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2854,
+ -1, -1, -1, -1, -1, 2855, -1, -1,
+ -1, -1, -1, -1, -1, 2856, 2857, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2858, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2937, -1, -1,
+ -1, -1, 2859, -1, 2860, -1, -1, -1,
+ -1, -1, 2861, -1, -1, -1, -1, 2862,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2938, -1, -1, -1, -1, 2939, 2940,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2941, -1, -1,
- -1, -1, -1, -1, -1, 2942, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2863, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2943, 2944, -1, -1,
- 2945, -1, -1, -1, -1, 2946, -1, -1,
- -1, 2947, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2864,
+ -1, 2865, 2866, -1, 2867, -1, -1, -1,
+ -1, -1, -1, 2868, 2869, 2870, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2948, -1, -1,
- -1, 2949, -1, -1, 2950, -1, -1, -1,
- -1, -1, 2951, -1, -1, -1, -1, -1,
- -1, -1, -1, 2952, 2953, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 2954,
- -1, 2955, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2956, -1, -1, -1, 2957, -1,
- -1, 2958, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2959, -1, -1, -1, -1, -1,
- -1, -1, 2960, -1, -1, -1, 2961, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2962, -1,
- -1, 2963, 2964, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 2965, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2871, -1, -1, 2872, -1, 2873, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2966, -1, 2967, -1, -1, -1, -1, 2968,
- -1, -1, -1, -1, -1, -1, -1, 2969,
- -1, -1, -1, -1, -1, -1, 2970, -1,
- -1, -1, -1, -1, -1, 2971, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2874, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2972, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2973, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2875, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2876,
+ 2877, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2974, -1, -1, -1, -1, -1, 2975,
- -1, 2976, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2977, -1, -1, -1, 2978,
- -1, 2979, 2980, -1, -1, -1, -1, 2981,
- -1, -1, -1, -1, -1, -1, -1, 2982,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2983, -1, -1, -1, -1, -1,
+ -1, 2878, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2879, -1, -1,
+ 2880, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2881,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2882,
+ 2883, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 2984, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2884, -1, -1, -1,
+ 2885, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2985, -1, -1, -1, 2986, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 2987, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2886, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 2988, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2887,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 2989, 2990, -1, -1,
+ -1, -1, -1, -1, -1, 2888, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 2991, -1, -1, -1, 2992, -1, 2993, -1,
- -1, 2994, 2995, -1, -1, 2996, -1, 2997,
- 2998, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 2999, 3000, 3001,
- 3002, -1, -1, -1, -1, -1, 3003, -1,
- 3004, -1, -1, -1, -1, 3005, -1, -1,
- -1, -1, -1, -1, 3006, -1, -1, -1,
- -1, -1, 3007, -1, -1, -1, -1, -1,
- -1, -1, -1, 3008, -1, 3009, -1, -1,
+ 2889, 2890, 2891, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3010, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2892, -1, 2893, 2894, -1, 2895, -1,
+ -1, 2896, -1, -1, 2897, 2898, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3011, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3012, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3013,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3014, -1, 3015, 3016, -1, -1, -1, -1,
- -1, 3017, -1, -1, -1, 3018, -1, 3019,
- -1, -1, -1, -1, -1, -1, -1, 3020,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2899,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2900,
+ -1, -1, -1, -1, -1, 2901, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3021, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3022, -1,
+ -1, -1, 2902, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2903, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3023, 3024, -1, -1,
- -1, -1, -1, -1, -1, 3025, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3026, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3027,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3028, -1, -1, -1,
- -1, 3029, -1, -1, -1, -1, 3030, -1,
- -1, 3031, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2904, 2905, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3032, -1, -1, -1, -1, 3033, -1, 3034,
- -1, -1, -1, -1, -1, -1, -1, 3035,
+ 2906, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2907, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2908, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3036, -1, -1, -1, -1, -1, -1,
- -1, 3037, -1, -1, -1, -1, -1, -1,
- -1, 3038, -1, -1, -1, -1, -1, 3039,
- -1, 3040, -1, -1, -1, -1, 3041, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3042, -1, -1, -1, -1, -1, -1, 3043,
+ -1, 2909, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3044, -1, -1, -1, -1, -1, -1,
- 3045, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3046, -1,
- -1, -1, -1, -1, -1, -1, -1, 3047,
- -1, -1, -1, 3048, -1, 3049, -1, -1,
- -1, 3050, -1, -1, -1, -1, -1, 3051,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2910, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2911, 2912, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3052, -1, -1, -1,
+ 2913, -1, -1, -1, -1, -1, 2914, -1,
+ -1, -1, -1, -1, -1, 2915, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3053, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2916, -1,
+ 2917, 2918, -1, -1, -1, -1, -1, -1,
+ 2919, -1, -1, -1, 2920, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3054, -1, -1, -1, -1, 3055,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2921, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2922, 2923, 2924, -1,
+ -1, -1, -1, -1, 2925, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2926, -1, -1,
+ 2927, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3056, -1, -1,
+ 2928, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3057, -1,
- -1, 3058, -1, -1, 3059, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3060,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3061, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3062, -1, -1, -1, 3063,
- -1, -1, -1, 3064, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2929,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3065, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3066, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3067, 3068, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3069, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2930,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3070, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3071, 3072, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3073, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3074, -1,
+ -1, -1, 2931, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2932, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3075, -1,
- -1, -1, 3076, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3077,
- -1, 3078, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3079, -1, -1, -1, -1,
- -1, -1, 3080, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3081, -1,
+ -1, -1, -1, 2933, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2934, -1, -1, -1,
+ -1, -1, -1, 2935, -1, -1, -1, -1,
+ 2936, -1, -1, -1, -1, 2937, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2938, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2939, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2940, -1, -1,
+ -1, -1, -1, -1, 2941, -1, -1, 2942,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3082,
- -1, -1, -1, -1, 3083, -1, -1, -1,
- -1, -1, -1, -1, 3084, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3085, -1, -1,
- -1, 3086, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 2943, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2944, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3087, -1, -1,
- -1, -1, -1, -1, -1, 3088, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2945, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3089, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3090, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3091,
- -1, -1, -1, -1, 3092, -1, 3093, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3094, -1, -1, -1, -1, -1, -1, -1,
- -1, 3095, -1, -1, -1, -1, -1, -1,
- -1, 3096, -1, -1, -1, -1, -1, -1,
- -1, -1, 3097, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3098, -1, -1, -1, -1,
- -1, -1, -1, 3099, -1, -1, -1, -1,
- 3100, -1, 3101, -1, 3102, -1, -1, -1,
- 3103, -1, -1, -1, -1, -1, -1, 3104,
+ 2946, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2947, 2948,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3105, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3106, -1, -1, -1, -1, 3107, -1, -1,
+ -1, -1, -1, -1, -1, -1, 2949, -1,
+ -1, 2950, -1, -1, 2951, -1, 2952, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3108, -1,
+ -1, -1, -1, -1, -1, 2953, -1, -1,
+ -1, -1, -1, -1, -1, 2954, -1, -1,
+ -1, -1, -1, 2955, 2956, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2957,
+ -1, -1, -1, -1, 2958, -1, 2959, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2960,
+ 2961, -1, 2962, -1, -1, 2963, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3109,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3110,
- 3111, -1, -1, -1, -1, -1, -1, -1,
- -1, 3112, -1, -1, -1, -1, 3113, 3114,
- -1, -1, -1, -1, 3115, 3116, -1, 3117,
- -1, -1, -1, -1, 3118, -1, -1, 3119,
+ 2964, -1, -1, 2965, 2966, -1, -1, 2967,
+ -1, 2968, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2969, -1, -1, -1, -1, -1,
+ 2970, -1, 2971, -1, -1, -1, 2972, -1,
+ -1, -1, 2973, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2974, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 2975, -1, -1, -1,
+ -1, -1, -1, -1, 2976, -1, -1, 2977,
+ -1, -1, -1, -1, -1, 2978, -1, 2979,
+ 2980, 2981, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3120, 3121, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3122,
- -1, -1, 3123, -1, 3124, -1, 3125, -1,
- 3126, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3127, -1,
+ -1, -1, 2982, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3128, -1, -1,
- -1, 3129, -1, -1, -1, -1, -1, -1,
+ -1, -1, 2983, -1, -1, -1, 2984, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3130, -1, 3131, -1, -1, -1,
+ -1, -1, -1, -1, -1, 2985, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2986,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3132, -1,
- -1, -1, -1, -1, 3133, -1, -1, 3134,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3135, -1, -1, -1, -1,
- -1, -1, 3136, -1, -1, -1, -1, -1,
+ -1, 2987, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 2988, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 2989,
+ -1, 2990, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3137, -1, -1, -1, -1, 3138,
- -1, -1, -1, -1, -1, 3139, -1, -1,
- -1, -1, 3140, 3141, -1, -1, -1, -1,
- -1, 3142, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3143, -1, -1, -1, -1,
- -1, 3144, -1, -1, -1, -1, -1, -1,
- -1, 3145, -1, -1, -1, -1, -1, -1,
- 3146, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3147, -1, 3148,
- 3149, -1, -1, 3150, -1, 3151, 3152, -1,
- -1, -1, -1, -1, 3153, -1, -1, -1,
- -1, 3154, -1, -1, -1, -1, -1, -1,
- 3155, -1, 3156, -1, -1, -1, -1, -1,
- 3157, -1, -1, -1, -1, -1, 3158, -1,
- -1, -1, -1, -1, -1, -1, -1, 3159,
- -1, -1, -1, -1, 3160, -1, -1, 3161,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3162, -1, -1, 3163, -1, -1,
+ -1, -1, -1, -1, 2991, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 2992, -1, -1, -1, -1, 2993, 2994, -1,
+ 2995, -1, -1, -1, 2996, -1, -1, -1,
+ -1, -1, 2997, -1, 2998, -1, 2999, 3000,
+ -1, -1, 3001, -1, -1, -1, -1, 3002,
+ -1, 3003, -1, -1, -1, -1, -1, -1,
+ 3004, -1, -1, 3005, -1, 3006, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3007, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3008, -1, 3009, -1, -1, -1,
+ 3010, -1, -1, -1, -1, -1, -1, -1,
+ 3011, 3012, -1, 3013, 3014, -1, -1, 3015,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3016, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3017,
+ -1, -1, 3018, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3019, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3020, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3164, -1,
- -1, 3165, -1, -1, -1, -1, -1, 3166,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3021, -1, 3022, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3167, 3168, -1, -1, -1, -1, -1,
- 3169, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3170, -1, 3171, 3172, -1,
+ -1, -1, 3023, -1, -1, 3024, -1, -1,
+ -1, -1, -1, 3025, -1, -1, 3026, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3173, -1, 3174, -1, -1, -1, -1,
- -1, -1, -1, -1, 3175, -1, -1, -1,
- -1, -1, 3176, -1, 3177, -1, -1, -1,
- -1, 3178, 3179, -1, 3180, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3027, -1, -1, -1,
+ -1, -1, -1, 3028, -1, -1, -1, -1,
+ -1, -1, 3029, -1, -1, -1, -1, -1,
+ 3030, -1, -1, 3031, -1, -1, 3032, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3181, 3182, -1, -1, -1, -1,
+ -1, -1, -1, 3033, -1, -1, -1, -1,
+ 3034, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3035, -1, -1, -1,
+ -1, -1, -1, -1, 3036, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3183, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3184,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3185, -1, -1, -1, -1,
- 3186, 3187, -1, 3188, -1, -1, -1, -1,
- -1, -1, 3189, -1, 3190, 3191, 3192, -1,
+ -1, -1, -1, -1, -1, 3037, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3038, -1, -1, 3039, -1, -1, -1, -1,
+ -1, 3040, -1, -1, -1, -1, 3041, -1,
+ 3042, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3193, 3194, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3195, -1, -1, -1, -1, -1, -1, -1,
+ 3043, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3044, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3045, -1, -1, -1, -1, -1, 3046, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3196, 3197, -1, -1, -1, -1, -1,
+ -1, 3047, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3048, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3049,
+ 3050, 3051, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3052, 3053,
+ -1, -1, -1, -1, 3054, 3055, 3056, -1,
+ -1, -1, -1, -1, -1, 3057, -1, -1,
+ -1, 3058, 3059, -1, -1, -1, 3060, -1,
+ 3061, -1, -1, 3062, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3198, -1, 3199, -1, -1, -1,
- -1, -1, 3200, -1, 3201, -1, -1, -1,
- -1, -1, -1, -1, 3202, -1, 3203, -1,
- 3204, -1, -1, -1, 3205, -1, -1, -1,
- -1, -1, 3206, -1, -1, -1, -1, -1,
- 3207, -1, -1, 3208, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3209,
- -1, 3210, -1, -1, -1, 3211, -1, -1,
- -1, 3212, -1, -1, -1, -1, -1, -1,
- -1, -1, 3213, -1, -1, -1, -1, 3214,
- -1, -1, -1, 3215, 3216, -1, -1, -1,
- -1, -1, -1, 3217, 3218, -1, -1, -1,
- -1, 3219, -1, -1, -1, -1, -1, -1,
- -1, -1, 3220, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3221,
- -1, -1, 3222, -1, -1, -1, -1, -1,
- 3223, -1, 3224, -1, -1, -1, -1, -1,
- 3225, -1, -1, -1, -1, -1, 3226, -1,
- -1, -1, -1, -1, -1, -1, -1, 3227,
+ -1, -1, -1, -1, -1, -1, 3063, -1,
+ -1, -1, -1, -1, 3064, -1, -1, -1,
+ -1, -1, -1, 3065, -1, -1, -1, -1,
+ -1, -1, 3066, -1, 3067, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3068, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3069,
+ -1, -1, -1, 3070, -1, -1, -1, -1,
+ 3071, -1, -1, -1, -1, 3072, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3073, -1, 3074, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3075,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3228, -1, -1,
+ -1, 3076, -1, -1, -1, -1, -1, -1,
+ 3077, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3078, -1, 3079,
+ -1, -1, 3080, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3081, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3082, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3083,
+ -1, -1, -1, -1, -1, -1, 3084, 3085,
+ -1, 3086, -1, 3087, -1, -1, 3088, -1,
+ -1, -1, -1, 3089, -1, -1, -1, 3090,
+ 3091, -1, -1, -1, -1, -1, -1, -1,
+ 3092, -1, -1, -1, -1, -1, 3093, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3229, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3094, -1, -1, -1,
+ 3095, -1, 3096, 3097, -1, -1, -1, -1,
+ 3098, 3099, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3100, -1, -1, -1, 3101, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3230, -1, -1, -1,
- 3231, -1, -1, -1, 3232, -1, -1, -1,
+ 3102, -1, 3103, -1, -1, -1, -1, 3104,
+ -1, -1, -1, 3105, -1, 3106, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3107, -1, -1, -1, -1, -1, 3108, -1,
+ -1, 3109, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3233, -1, -1, -1, -1, -1,
+ -1, -1, 3110, -1, -1, -1, -1, 3111,
+ -1, -1, -1, -1, -1, -1, -1, 3112,
+ -1, -1, -1, -1, -1, -1, -1, 3113,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3234,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3114, -1, -1, 3115,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3116, -1, -1, -1, 3117, -1,
+ -1, 3118, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3119,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3120, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3121, 3122, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3235, -1, -1, -1,
- -1, -1, 3236, 3237, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3238, -1,
+ 3123, 3124, -1, -1, -1, -1, -1, 3125,
+ -1, -1, -1, -1, -1, -1, -1, 3126,
+ -1, -1, -1, -1, -1, 3127, -1, -1,
+ -1, 3128, 3129, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3130, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3239, -1,
+ -1, -1, -1, -1, 3131, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3132, -1, -1, -1, -1, -1, 3133,
+ 3134, -1, -1, -1, 3135, -1, -1, -1,
+ -1, 3136, -1, -1, 3137, -1, -1, -1,
+ 3138, -1, -1, -1, -1, -1, -1, 3139,
+ -1, 3140, -1, -1, -1, -1, -1, 3141,
+ -1, 3142, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3143, -1, -1, -1, -1, -1,
+ 3144, -1, -1, 3145, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3240, -1, -1, -1,
+ 3146, 3147, -1, -1, -1, 3148, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3241, -1, -1, -1, -1,
- -1, -1, 3242, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3243, -1,
- -1, -1, 3244, -1, 3245, -1, -1, -1,
- 3246, -1, -1, 3247, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3248,
+ -1, 3149, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3150, -1, -1,
+ -1, -1, -1, 3151, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3152, -1, -1,
+ -1, 3153, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3154, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3155, -1, 3156, -1, -1,
+ -1, -1, -1, 3157, -1, -1, -1, 3158,
+ -1, -1, -1, -1, 3159, -1, -1, 3160,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3161, -1, 3162, -1,
+ -1, -1, -1, 3163, -1, -1, 3164, -1,
+ -1, -1, -1, -1, -1, 3165, -1, -1,
+ -1, -1, 3166, -1, -1, 3167, -1, -1,
+ -1, -1, -1, -1, -1, 3168, -1, -1,
+ -1, -1, -1, -1, -1, 3169, 3170, -1,
+ -1, 3171, 3172, -1, -1, 3173, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3249, -1, -1, -1, -1,
- -1, -1, -1, -1, 3250, -1, -1, 3251,
+ -1, -1, -1, -1, 3174, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3252, 3253, -1, 3254, -1,
+ -1, -1, -1, -1, -1, 3175, -1, -1,
+ -1, 3176, 3177, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3178, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3179,
+ -1, 3180, -1, -1, 3181, 3182, -1, 3183,
+ -1, -1, -1, -1, -1, -1, -1, 3184,
+ 3185, -1, -1, -1, -1, -1, 3186, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3255, -1, -1, -1,
+ -1, 3187, -1, -1, -1, -1, -1, -1,
+ 3188, -1, 3189, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3256, -1, 3257, 3258, -1, -1, 3259,
- -1, 3260, -1, 3261, -1, -1, -1, -1,
- 3262, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3263, -1,
- -1, 3264, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3265, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3190, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3191, -1, -1, -1, 3192,
+ 3193, 3194, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3195, -1, -1, 3196, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3197, 3198, -1, -1, -1, -1, -1,
+ -1, -1, 3199, 3200, -1, -1, -1, -1,
+ -1, -1, -1, 3201, -1, -1, -1, -1,
+ -1, 3202, -1, 3203, 3204, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3205, -1,
+ -1, -1, 3206, -1, -1, -1, -1, -1,
+ -1, 3207, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3208, -1, -1, -1, 3209,
+ -1, -1, -1, -1, 3210, -1, -1, 3211,
+ -1, -1, -1, -1, 3212, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3213, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3214, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3215,
+ -1, -1, -1, -1, -1, -1, -1, 3216,
+ -1, -1, -1, -1, -1, -1, -1, 3217,
+ -1, 3218, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3219, 3220, -1, -1, -1,
+ -1, -1, -1, 3221, -1, 3222, -1, -1,
+ -1, 3223, -1, -1, -1, -1, 3224, -1,
+ -1, -1, -1, 3225, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3226, -1, -1,
+ -1, -1, -1, -1, -1, 3227, -1, -1,
+ -1, -1, 3228, -1, -1, -1, -1, 3229,
+ -1, 3230, -1, 3231, -1, -1, -1, -1,
+ -1, -1, 3232, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3233, -1, -1, -1,
+ -1, 3234, -1, -1, -1, -1, -1, -1,
+ 3235, -1, -1, -1, -1, -1, 3236, -1,
+ -1, -1, 3237, -1, -1, -1, -1, -1,
+ 3238, -1, -1, -1, -1, 3239, 3240, -1,
+ 3241, -1, -1, 3242, -1, -1, -1, -1,
+ -1, -1, -1, 3243, -1, -1, -1, 3244,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3245, -1, -1, -1, -1, 3246,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3247, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3248, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3249, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3250, -1, -1,
+ 3251, -1, -1, -1, -1, -1, 3252, -1,
+ -1, -1, -1, -1, -1, 3253, -1, -1,
+ -1, 3254, -1, -1, -1, -1, -1, 3255,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3256, -1, -1, -1,
+ -1, -1, 3257, -1, -1, -1, -1, 3258,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3259, -1, -1, -1, -1, 3260, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3261, -1, -1, -1, -1, -1,
+ -1, 3262, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3263, -1,
+ -1, -1, -1, -1, 3264, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3265,
-1, -1, -1, -1, -1, -1, -1, 3266,
+ 3267, -1, -1, -1, -1, 3268, -1, -1,
+ -1, 3269, -1, -1, -1, -1, -1, 3270,
+ -1, -1, -1, -1, -1, -1, -1, 3271,
+ -1, -1, -1, 3272, -1, 3273, 3274, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3267, -1, -1, -1, -1,
+ -1, -1, 3275, -1, -1, -1, -1, -1,
+ -1, -1, 3276, -1, -1, -1, 3277, -1,
+ -1, -1, 3278, -1, -1, -1, -1, -1,
+ -1, 3279, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3268, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3269, -1, 3270, -1, 3271, -1,
- 3272, 3273, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3280, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3274, -1, -1, -1, -1, -1, -1, -1,
- -1, 3275, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3276, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3277, -1, -1, -1,
- -1, -1, -1, -1, -1, 3278, -1, -1,
- 3279, -1, -1, -1, -1, -1, -1, 3280,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 3281, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3282, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3283, -1,
+ 3282, -1, -1, -1, 3283, -1, 3284, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3284, -1,
- -1, -1, -1, -1, -1, -1, -1, 3285,
- -1, 3286, -1, -1, -1, -1, -1, 3287,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3288, 3289, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3290,
- -1, -1, -1, -1, -1, 3291, -1, -1,
- -1, -1, -1, -1, -1, -1, 3292, -1,
- -1, -1, -1, -1, -1, -1, -1, 3293,
- -1, -1, -1, 3294, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3295, -1, -1, -1, 3296, -1,
- -1, -1, -1, 3297, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3298, -1, -1, -1, -1, 3299,
- -1, -1, -1, -1, -1, -1, 3300, -1,
- -1, -1, -1, -1, 3301, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3302, -1,
- -1, -1, 3303, -1, -1, -1, -1, -1,
- -1, -1, -1, 3304, -1, -1, -1, -1,
- -1, 3305, -1, -1, -1, -1, -1, -1,
- 3306, -1, -1, -1, -1, -1, -1, -1,
- -1, 3307, -1, -1, 3308, -1, -1, -1,
- -1, -1, -1, -1, -1, 3309, -1, -1,
- -1, -1, -1, 3310, -1, -1, 3311, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3312, 3313, -1, -1, 3314, -1, -1, -1,
+ -1, -1, -1, 3285, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3286, -1, -1,
+ 3287, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3315, -1, 3316, -1, -1, -1, -1,
- -1, -1, 3317, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3288, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3318,
+ -1, 3289, -1, 3290, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3291, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3319, -1, -1, -1, -1,
- 3320, -1, -1, -1, 3321, -1, -1, -1,
- -1, -1, -1, 3322, -1, -1, -1, -1,
- -1, 3323, 3324, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3325, -1,
- -1, -1, -1, -1, -1, -1, -1, 3326,
- -1, -1, 3327, -1, -1, 3328, -1, -1,
+ -1, 3292, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3293, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3294, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3295, -1, -1, -1, -1, -1, -1,
+ -1, 3296, -1, -1, -1, 3297, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3298, -1,
+ 3299, -1, -1, -1, -1, -1, -1, 3300,
+ -1, 3301, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3302, -1, -1, 3303,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3304, -1, 3305, -1, -1, -1, -1, -1,
+ -1, -1, 3306, -1, 3307, -1, 3308, -1,
+ -1, 3309, -1, -1, -1, -1, -1, -1,
+ -1, 3310, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3311, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3312, -1, -1, -1, -1, 3313, -1,
+ -1, -1, 3314, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3315,
+ -1, -1, -1, -1, -1, 3316, 3317, -1,
+ -1, 3318, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3319, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3320,
+ -1, -1, -1, 3321, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3322, 3323, -1,
+ -1, -1, -1, -1, 3324, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3325, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3326, -1, -1, -1, 3327, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3328, -1, -1, -1,
-1, -1, -1, -1, 3329, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3330, -1, -1, -1, -1, 3331, -1, -1,
- -1, -1, 3332, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3330, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3333, -1, -1, -1, 3334, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3335,
- -1, -1, 3336, -1, -1, -1, -1, -1,
- -1, -1, 3337, -1, -1, 3338, -1, -1,
- 3339, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3331, -1, -1, -1,
+ -1, -1, -1, 3332, 3333, -1, -1, -1,
+ -1, 3334, -1, -1, -1, -1, -1, -1,
+ 3335, -1, -1, -1, -1, -1, -1, 3336,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3337,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3340, -1, -1, 3341, -1, 3342,
- -1, -1, -1, -1, 3343, -1, -1, -1,
- -1, 3344, -1, -1, -1, 3345, -1, -1,
- -1, -1, 3346, -1, 3347, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3348, -1, 3349, 3350, -1, -1, -1, -1,
- -1, -1, -1, -1, 3351, 3352, -1, -1,
- -1, -1, 3353, -1, 3354, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3355, -1, -1, -1, -1, -1,
- -1, -1, 3356, 3357, -1, -1, -1, -1,
- -1, 3358, -1, -1, -1, 3359, 3360, -1,
+ 3338, -1, -1, -1, -1, 3339, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3361, -1, -1,
- -1, 3362, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3340, 3341, -1, -1, -1,
+ -1, 3342, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3343, -1, -1,
+ 3344, -1, -1, -1, -1, 3345, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3363, -1, -1, -1, -1, -1,
- -1, -1, -1, 3364, -1, 3365, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3346, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3366, -1, 3367, 3368, -1,
- -1, -1, -1, -1, -1, -1, -1, 3369,
- -1, -1, -1, -1, -1, 3370, -1, -1,
- -1, -1, -1, -1, -1, -1, 3371, -1,
- 3372, -1, -1, -1, -1, 3373, -1, -1,
- -1, -1, -1, 3374, -1, -1, 3375, -1,
- -1, -1, -1, 3376, 3377, 3378, -1, 3379,
+ 3347, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3348, 3349, -1, -1, -1, -1, -1,
+ 3350, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3380, -1, -1, -1, -1, -1, -1, 3381,
- -1, -1, -1, -1, 3382, -1, -1, -1,
- -1, -1, -1, -1, -1, 3383, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3384,
+ -1, -1, 3351, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3385, -1, -1, -1, -1, 3386, -1, -1,
- 3387, -1, -1, -1, -1, -1, 3388, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3389, -1, -1, -1, 3390, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3391, -1, -1, -1, -1,
- -1, -1, 3392, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3393, -1, -1,
- -1, 3394, -1, -1, -1, 3395, -1, -1,
- 3396, -1, -1, -1, -1, -1, -1, 3397,
- -1, 3398, -1, -1, -1, 3399, -1, -1,
- -1, -1, -1, -1, -1, 3400, -1, -1,
- 3401, -1, -1, -1, -1, -1, 3402, 3403,
- -1, -1, -1, 3404, -1, -1, -1, -1,
- -1, -1, 3405, -1, -1, -1, -1, -1,
- -1, -1, 3406, -1, -1, -1, 3407, -1,
+ 3352, 3353, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3354, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3408, -1, -1, -1, -1, -1,
- -1, 3409, 3410, -1, -1, -1, 3411, -1,
+ -1, 3355, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3356, -1, 3357,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3412,
+ -1, -1, -1, -1, -1, -1, -1, 3358,
+ -1, -1, -1, -1, -1, 3359, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3413, -1, -1, -1, 3414, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3415, 3416, -1, -1, -1,
- 3417, 3418, -1, -1, -1, -1, 3419, -1,
- -1, -1, 3420, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3421,
- -1, -1, 3422, -1, -1, -1, -1, -1,
- 3423, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3424, -1, -1, 3425,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3426, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3360, 3361,
+ -1, -1, -1, -1, -1, -1, -1, 3362,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3427, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3428, -1,
- -1, -1, -1, -1, 3429, -1, 3430, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3363, 3364, 3365, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3431, -1, -1, 3432, -1, 3433, -1,
- -1, -1, -1, -1, -1, 3434, -1, -1,
- -1, -1, -1, 3435, -1, -1, -1, -1,
- -1, -1, -1, -1, 3436, -1, -1, -1,
- -1, 3437, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3366, -1, -1, -1,
+ -1, 3367, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3368, -1, -1,
+ -1, 3369, -1, 3370, -1, 3371, -1, -1,
+ -1, -1, -1, 3372, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3373, -1,
+ -1, -1, -1, -1, -1, -1, 3374, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3438, -1, -1, 3439, 3440,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3441, -1, -1, 3442, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3443, -1, 3444, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3445, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3446, -1, -1,
- -1, -1, -1, -1, 3447, -1, -1, -1,
- 3448, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3449,
- -1, 3450, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3375, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3376, -1, -1, -1, -1,
+ -1, 3377, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3451, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3452, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3453, -1, -1,
+ 3378, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3454,
- -1, -1, -1, 3455, 3456, -1, -1, -1,
- 3457, -1, -1, 3458, -1, -1, -1, -1,
- -1, -1, 3459, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3460, -1, -1, -1,
- -1, 3461, -1, 3462, -1, -1, -1, 3463,
+ -1, -1, -1, -1, -1, 3379, -1, -1,
+ -1, -1, -1, 3380, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3464, -1, -1, -1, -1,
- -1, -1, -1, -1, 3465, -1, -1, -1,
- -1, 3466, -1, -1, -1, -1, -1, 3467,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3468, -1, -1, -1, -1, 3469, -1, 3470,
- -1, -1, 3471, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3472, -1, -1, -1,
+ -1, -1, 3381, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3473, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3382, -1, -1, 3383,
+ -1, -1, -1, 3384, 3385, 3386, -1, -1,
+ 3387, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3474, -1,
+ -1, -1, -1, -1, -1, -1, 3388, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3389, -1, 3390,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3475, 3476, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3391, -1, -1, -1, 3392,
+ 3393, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3394, -1, -1, -1, 3395,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3396, -1, 3397, -1, -1, -1, -1, 3398,
+ -1, -1, -1, -1, 3399, -1, -1, 3400,
+ -1, -1, 3401, -1, -1, -1, 3402, -1,
+ 3403, -1, -1, -1, -1, -1, -1, 3404,
+ 3405, -1, -1, -1, -1, -1, -1, 3406,
+ -1, -1, -1, 3407, -1, -1, 3408, 3409,
+ -1, 3410, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3411, -1, 3412,
+ 3413, 3414, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3415, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3416,
+ -1, 3417, -1, 3418, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3419, 3420, -1,
+ -1, -1, -1, 3421, -1, -1, -1, -1,
+ -1, 3422, -1, -1, -1, 3423, -1, -1,
+ -1, -1, -1, 3424, -1, -1, -1, -1,
+ -1, -1, -1, 3425, -1, -1, -1, -1,
+ -1, 3426, -1, -1, -1, -1, 3427, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3428,
+ -1, 3429, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3430, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3477, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3478, -1,
+ -1, -1, -1, -1, -1, 3431, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3432,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3433, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3479, -1, -1, 3480, -1, -1, -1,
- 3481, -1, 3482, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3434, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3483,
+ -1, 3435, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3436, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3437, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3484, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3485, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3438, -1, -1, -1, -1,
+ 3439, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3486, 3487, -1, -1, -1,
- -1, -1, -1, -1, -1, 3488, -1, -1,
+ -1, -1, -1, 3440, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3441,
+ 3442, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3443, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3444, -1, -1,
+ -1, 3445, -1, 3446, -1, -1, 3447, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3489, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3448, 3449, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3450, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3490, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3451, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3491, -1, -1, -1, -1, 3492, -1, -1,
- -1, 3493, -1, -1, -1, -1, 3494, -1,
- -1, -1, -1, 3495, -1, -1, -1, -1,
- -1, 3496, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3497, -1, -1,
- -1, -1, -1, 3498, -1, 3499, -1, -1,
- -1, -1, -1, -1, -1, 3500, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3501,
- -1, -1, -1, -1, 3502, 3503, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3504, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3505, -1, 3506, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3507, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3508,
- -1, -1, -1, 3509, -1, -1, -1, -1,
- 3510, 3511, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3452, 3453, -1, -1, -1, -1, -1, 3454,
+ -1, -1, -1, -1, 3455, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3456, -1,
+ -1, -1, -1, -1, 3457, -1, -1, -1,
+ -1, -1, -1, -1, 3458, -1, -1, -1,
+ -1, -1, 3459, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3512, 3513, -1, -1, -1, -1,
- -1, -1, -1, -1, 3514, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3515, -1, -1, 3516, -1, -1,
- -1, -1, -1, -1, -1, 3517, 3518, -1,
- -1, -1, -1, 3519, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3520,
+ -1, 3460, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3461,
+ -1, -1, -1, -1, 3462, -1, -1, -1,
+ -1, 3463, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3464, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3521, -1, -1, -1, 3522, -1, -1, -1,
- 3523, -1, -1, -1, -1, -1, 3524, 3525,
- -1, -1, 3526, -1, -1, -1, -1, -1,
- -1, 3527, -1, -1, -1, 3528, -1, -1,
- 3529, 3530, 3531, -1, 3532, -1, -1, -1,
- -1, -1, -1, 3533, -1, 3534, -1, 3535,
- -1, 3536, -1, -1, -1, -1, 3537, 3538,
- -1, -1, -1, -1, 3539, 3540, 3541, -1,
- -1, -1, -1, -1, -1, -1, 3542, -1,
- -1, -1, 3543, -1, -1, -1, 3544, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3545, -1, -1, -1, -1, 3546, -1,
- -1, -1, -1, -1, 3547, -1, -1, -1,
+ -1, -1, 3465, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3466, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3548, -1, -1, 3549, -1, -1, -1,
- -1, -1, -1, -1, 3550, -1, 3551, -1,
- -1, -1, -1, 3552, -1, -1, -1, -1,
- 3553, -1, 3554, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3555, 3556, -1,
- 3557, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3467, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3558, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3559, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3468, 3469, -1,
+ 3470, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3471, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3472, -1,
+ -1, -1, -1, -1, -1, -1, 3473, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3474, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3560, 3561, -1, 3562, -1, -1,
- -1, -1, 3563, -1, -1, -1, -1, -1,
+ -1, -1, 3475, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3476, -1, -1, -1, -1,
+ -1, -1, 3477, -1, -1, -1, -1, -1,
+ 3478, -1, -1, -1, -1, -1, 3479, 3480,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3564,
+ -1, 3481, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3565, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3566,
- -1, 3567, -1, 3568, -1, -1, -1, -1,
- 3569, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3570, -1,
- -1, -1, -1, -1, -1, -1, -1, 3571,
- -1, -1, -1, -1, 3572, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3573, -1, -1, -1, -1,
- -1, -1, -1, -1, 3574, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3575, -1,
- -1, -1, -1, -1, -1, -1, -1, 3576,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3577, -1, 3578, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3579, -1, -1, -1, -1, 3580,
- -1, -1, -1, -1, -1, 3581, -1, 3582,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3583, -1, -1,
- -1, -1, -1, -1, -1, 3584, -1, 3585,
+ -1, -1, 3482, -1, -1, -1, -1, 3483,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3586, -1, -1, 3587, -1,
- -1, 3588, -1, 3589, -1, -1, -1, -1,
- -1, -1, -1, 3590, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3591, -1, -1, -1, -1,
- 3592, -1, -1, -1, -1, -1, -1, 3593,
- -1, -1, 3594, -1, -1, -1, -1, -1,
- -1, -1, -1, 3595, -1, -1, -1, 3596,
- -1, -1, -1, 3597, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3484, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3485, -1, -1, 3486, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3598, -1, -1, -1, -1, -1, -1, -1,
- 3599, -1, -1, -1, -1, -1, -1, -1,
- 3600, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3601,
+ -1, -1, 3487, -1, -1, -1, -1, -1,
+ 3488, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3489, -1, -1, 3490,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3602, 3603, 3604, -1, -1, -1,
+ -1, -1, 3491, -1, -1, -1, -1, -1,
+ -1, -1, 3492, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3605, -1, -1, -1, -1, 3606, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3607, -1,
- 3608, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3609, -1, 3610, -1, -1, -1,
- -1, -1, -1, 3611, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3612, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3493, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3494, -1,
+ -1, 3495, 3496, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3613, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3614, -1, -1, -1,
- -1, 3615, -1, -1, -1, -1, 3616, -1,
- 3617, -1, 3618, -1, 3619, 3620, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3621,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3622, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3623,
+ -1, -1, 3497, -1, -1, -1, -1, -1,
+ 3498, -1, -1, -1, 3499, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3500,
+ -1, -1, -1, -1, -1, -1, 3501, -1,
+ -1, 3502, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3503, -1, 3504, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3505,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3624, 3625, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3506, -1, -1, 3507, -1, -1, -1,
+ -1, -1, 3508, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3509, -1, -1, 3510, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3626, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3627, -1,
- -1, -1, 3628, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3629, 3630,
- -1, -1, -1, -1, 3631, -1, -1, -1,
- 3632, -1, -1, -1, -1, -1, 3633, 3634,
- -1, -1, -1, -1, -1, -1, -1, 3635,
+ 3511, -1, -1, -1, -1, 3512, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3636, -1, 3637, -1,
+ -1, 3513, -1, 3514, -1, -1, -1, -1,
+ -1, 3515, 3516, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3638, 3639, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3517, -1,
+ 3518, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3519,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3640, -1, -1, -1, -1, -1,
- 3641, -1, -1, 3642, 3643, 3644, -1, 3645,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3646, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3647, -1, -1, 3648,
- -1, -1, 3649, -1, 3650, -1, -1, -1,
- -1, -1, -1, -1, -1, 3651, -1, -1,
- -1, -1, -1, -1, 3652, -1, -1, -1,
- -1, -1, -1, 3653, -1, -1, -1, -1,
- 3654, 3655, -1, -1, -1, -1, 3656, -1,
+ 3520, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3657, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3658, 3659, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3521, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3660, 3661, -1,
+ 3522, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3662, 3663, -1, -1, -1,
- -1, -1, 3664, 3665, -1, -1, 3666, -1,
- -1, -1, -1, -1, -1, -1, -1, 3667,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3668,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3669, -1,
- -1, -1, 3670, -1, -1, 3671, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3523, -1, -1, -1, -1, 3524, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3525, 3526, -1, -1, -1,
+ -1, -1, -1, -1, 3527, -1, -1, -1,
+ -1, -1, 3528, -1, -1, -1, -1, -1,
+ 3529, -1, -1, -1, -1, -1, -1, -1,
+ 3530, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3531, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3672, 3673, -1, -1,
+ -1, 3532, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3533,
+ -1, -1, -1, -1, 3534, -1, -1, -1,
+ -1, -1, -1, -1, 3535, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3536, -1, -1, 3537,
+ -1, -1, -1, -1, -1, -1, 3538, 3539,
+ 3540, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3541, -1, -1, -1,
+ 3542, -1, -1, -1, 3543, -1, -1, 3544,
+ -1, 3545, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3546, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3547, -1, -1, -1, -1, -1, -1, 3548,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3674, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3675,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3676, -1, -1, -1, -1,
+ -1, -1, -1, 3549, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3677, 3678, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3679, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3680, 3681, -1, -1, 3682, -1, -1,
- -1, -1, -1, 3683, 3684, -1, -1, -1,
- -1, -1, 3685, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3550, -1, -1,
+ -1, -1, -1, -1, 3551, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3552, -1, -1, -1, -1,
+ 3553, -1, 3554, -1, 3555, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3556,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3557, 3558, -1, -1,
+ -1, -1, -1, -1, -1, 3559, -1, -1,
+ -1, 3560, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3561,
+ -1, -1, -1, -1, -1, 3562, -1, -1,
+ -1, -1, -1, -1, -1, 3563, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3564, -1, -1, -1,
+ -1, -1, -1, -1, 3565, -1, -1, -1,
+ -1, -1, -1, -1, 3566, -1, -1, -1,
+ 3567, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3568, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3569, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3570, -1, -1, -1, -1, -1, -1, -1,
+ 3571, -1, -1, -1, -1, -1, 3572, -1,
+ -1, -1, -1, -1, 3573, -1, -1, -1,
+ 3574, -1, -1, -1, -1, -1, -1, 3575,
+ -1, -1, -1, -1, -1, -1, -1, 3576,
+ 3577, 3578, -1, -1, -1, -1, 3579, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3580,
+ -1, -1, 3581, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3582, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3583,
+ -1, -1, -1, -1, -1, 3584, 3585, -1,
+ -1, 3586, 3587, 3588, -1, 3589, -1, -1,
+ -1, -1, 3590, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3591, -1, 3592,
+ -1, -1, -1, 3593, -1, -1, -1, -1,
+ 3594, 3595, -1, 3596, -1, -1, 3597, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3598,
+ 3599, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3600, -1, -1, -1, 3601, -1, -1, -1,
+ -1, -1, -1, -1, 3602, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3603, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3604, -1, -1, -1, 3605,
+ -1, -1, -1, -1, -1, 3606, -1, -1,
+ -1, 3607, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3608, -1, -1, -1, -1, -1,
+ -1, 3609, -1, -1, -1, -1, 3610, -1,
+ -1, 3611, -1, -1, 3612, -1, -1, -1,
+ -1, 3613, -1, -1, -1, -1, 3614, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3615, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3686, 3687, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3688, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3689, -1, -1, -1,
- 3690, -1, -1, -1, -1, -1, 3691, -1,
- -1, 3692, -1, -1, -1, -1, -1, 3693,
- -1, -1, -1, -1, 3694, -1, -1, -1,
- -1, 3695, -1, 3696, -1, -1, -1, -1,
- -1, 3697, -1, -1, -1, -1, -1, 3698,
+ -1, -1, -1, -1, -1, 3616, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3617, -1, 3618, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3699,
- -1, 3700, -1, -1, -1, -1, -1, -1,
+ 3619, -1, -1, -1, -1, -1, 3620, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3701, -1, 3702, -1, -1, -1, -1, 3703,
- -1, -1, 3704, -1, -1, -1, -1, -1,
- -1, -1, -1, 3705, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3621, -1, -1, -1, -1, -1,
+ -1, -1, 3622, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3623, -1, 3624, 3625,
+ -1, -1, -1, -1, -1, 3626, -1, -1,
+ -1, -1, -1, -1, 3627, -1, -1, -1,
+ -1, -1, -1, -1, 3628, 3629, -1, 3630,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3631, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3632, -1, -1, -1, -1, -1,
+ -1, 3633, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3634, -1, -1,
+ -1, -1, -1, -1, -1, 3635, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3636, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3637, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3638, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3639, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3640, -1, 3641, -1,
+ -1, -1, 3642, -1, 3643, -1, -1, -1,
+ -1, -1, -1, -1, 3644, -1, -1, -1,
+ -1, -1, 3645, -1, -1, 3646, -1, -1,
+ -1, -1, 3647, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3648, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3649, -1, -1, -1,
+ 3650, -1, -1, -1, 3651, -1, -1, -1,
+ -1, -1, -1, -1, 3652, -1, -1, -1,
+ -1, 3653, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3654, -1, 3655,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3656, -1, -1, 3657, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3658, 3659, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3660, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3661, -1, -1, -1, -1, -1,
+ 3662, -1, 3663, 3664, -1, -1, 3665, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3666, -1, -1, -1, 3667, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3706, -1, -1, -1, -1,
- -1, -1, -1, -1, 3707, -1, -1, -1,
+ 3668, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3669,
+ -1, 3670, -1, -1, -1, 3671, 3672, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3708, -1,
- 3709, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3710, 3711,
- 3712, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3713, -1,
+ -1, -1, -1, -1, -1, 3673, -1, -1,
+ 3674, -1, -1, 3675, -1, -1, 3676, -1,
+ -1, -1, -1, -1, 3677, -1, -1, -1,
+ -1, -1, -1, 3678, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3679, -1, -1, -1,
+ 3680, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3681, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3682, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3683, -1, -1, -1,
+ -1, -1, -1, 3684, -1, -1, 3685, -1,
+ -1, -1, -1, -1, -1, 3686, -1, -1,
+ 3687, -1, 3688, -1, -1, -1, -1, -1,
+ -1, -1, 3689, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3690, -1, 3691, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3692, -1, 3693, -1, -1, -1, -1, -1,
+ 3694, 3695, -1, -1, -1, -1, -1, 3696,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3714, -1, -1, 3715, -1, -1,
- -1, -1, -1, -1, -1, 3716, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3697, -1, -1,
+ -1, 3698, -1, -1, -1, -1, -1, -1,
+ 3699, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3717, -1, -1, -1, -1, 3718, -1, 3719,
- 3720, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3721, -1, -1, -1, -1,
- -1, -1, 3722, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3700, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3723, -1, -1,
- -1, -1, 3724, 3725, -1, -1, -1, -1,
- 3726, -1, -1, -1, -1, -1, -1, 3727,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3728, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3729,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3701, -1, -1, 3702, 3703, -1,
+ -1, -1, -1, -1, -1, 3704, -1, -1,
+ -1, 3705, -1, -1, -1, -1, -1, 3706,
+ 3707, -1, -1, -1, 3708, -1, -1, 3709,
+ -1, -1, -1, -1, -1, 3710, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3730, -1, -1, -1, -1, 3731,
- -1, -1, 3732, -1, -1, 3733, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3734, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3735, -1,
- -1, -1, -1, -1, 3736, -1, -1, -1,
- -1, 3737, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3711, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3712, -1,
+ -1, -1, -1, 3713, -1, 3714, -1, -1,
+ -1, 3715, -1, -1, -1, -1, 3716, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3738, -1, -1, -1, -1,
- -1, -1, 3739, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3717, -1,
+ -1, 3718, -1, -1, -1, 3719, -1, -1,
+ -1, -1, -1, -1, -1, 3720, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3721, -1, -1, -1,
+ -1, -1, -1, -1, 3722, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3740,
- -1, -1, -1, -1, -1, -1, -1, 3741,
- -1, -1, 3742, -1, -1, -1, -1, 3743,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3744,
+ -1, -1, -1, 3723, -1, -1, -1, 3724,
+ -1, -1, -1, 3725, 3726, 3727, 3728, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3745, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3746, -1, -1, -1,
- 3747, 3748, -1, -1, -1, -1, -1, -1,
+ 3729, 3730, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3731, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3749, -1, -1, -1, -1, -1, -1,
- 3750, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3751, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3752,
- 3753, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3732, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3733, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3754,
- -1, -1, -1, -1, -1, -1, 3755, -1,
+ -1, -1, 3734, -1, -1, 3735, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3736,
+ -1, -1, -1, 3737, -1, -1, -1, -1,
+ -1, -1, 3738, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3739,
+ -1, -1, 3740, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3741, 3742, -1,
+ -1, -1, 3743, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3744, -1, 3745, -1, -1, 3746, 3747, -1,
+ -1, 3748, -1, 3749, -1, -1, -1, -1,
+ 3750, 3751, -1, -1, -1, 3752, -1, 3753,
+ 3754, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3755, -1, -1, -1, -1, -1, -1,
3756, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3757, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3758,
+ -1, -1, -1, -1, -1, 3757, -1, -1,
+ -1, -1, -1, -1, -1, 3758, 3759, -1,
+ 3760, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3759, -1,
- -1, -1, -1, 3760, -1, -1, -1, -1,
- 3761, -1, -1, 3762, -1, -1, 3763, -1,
- -1, -1, -1, -1, 3764, -1, 3765, -1,
- 3766, -1, -1, 3767, -1, -1, -1, 3768,
+ 3761, -1, -1, 3762, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3763, -1,
+ -1, -1, -1, 3764, -1, -1, -1, -1,
+ -1, -1, -1, 3765, -1, -1, 3766, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3767,
+ -1, -1, 3768, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3769, -1, -1,
+ -1, -1, -1, 3770, -1, -1, -1, -1,
+ -1, -1, 3771, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3769, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3770, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3771, -1,
- 3772, -1, -1, -1, -1, 3773, -1, -1,
- -1, 3774, -1, -1, -1, -1, 3775, -1,
- -1, -1, -1, 3776, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3772, 3773, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3777, -1, -1,
- 3778, -1, 3779, -1, -1, -1, -1, -1,
- -1, -1, 3780, -1, -1, -1, -1, 3781,
+ -1, 3774, -1, -1, -1, -1, -1, 3775,
+ -1, -1, -1, 3776, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3782, -1, -1,
- -1, -1, -1, 3783, -1, -1, -1, 3784,
- -1, -1, -1, -1, -1, -1, 3785, -1,
- -1, -1, -1, -1, 3786, -1, -1, 3787,
+ -1, -1, 3777, -1, -1, -1, -1, -1,
+ -1, 3778, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3779, -1, -1, -1, 3780, 3781, -1,
+ 3782, -1, -1, -1, -1, -1, 3783, -1,
+ -1, 3784, -1, 3785, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3786, -1, 3787,
+ -1, 3788, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3789,
+ 3790, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3788, -1, -1, 3789, 3790, -1, -1, -1,
- -1, -1, -1, 3791, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3792,
- -1, 3793, -1, 3794, -1, -1, -1, -1,
- 3795, 3796, -1, -1, -1, -1, -1, -1,
- -1, -1, 3797, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3791, -1, -1, -1, 3792,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3798, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3793, -1, -1, -1, -1,
+ 3794, -1, -1, -1, -1, -1, -1, 3795,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3799, -1, -1, -1, -1, -1,
+ 3796, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3797, -1, -1, -1,
+ 3798, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3799, -1, 3800, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3800, -1, -1, 3801, -1, -1,
- 3802, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3801, -1,
+ -1, -1, -1, -1, -1, 3802, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3803, 3804, 3805, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3806, -1,
- -1, -1, -1, -1, -1, -1, 3807, -1,
+ -1, -1, -1, -1, 3803, -1, -1, -1,
+ -1, -1, -1, -1, 3804, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3808, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3809, -1, 3810, -1, -1, -1,
+ 3805, -1, -1, 3806, 3807, -1, -1, 3808,
+ -1, -1, -1, -1, -1, -1, -1, 3809,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3810,
-1, -1, 3811, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3812, -1, -1, -1,
+ -1, -1, -1, 3812, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3813, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3813,
-1, -1, -1, -1, 3814, -1, -1, -1,
- -1, -1, -1, -1, -1, 3815, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3815, -1,
+ -1, 3816, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3817, -1,
+ 3818, -1, -1, -1, -1, -1, -1, 3819,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3816, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3820, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3817, -1, -1, -1, -1, -1,
- -1, -1, 3818, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3821, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3819, -1, -1, 3820, -1,
- -1, 3821, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3822, -1, -1, -1, -1,
+ -1, 3822, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3823,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3823, -1,
- -1, -1, -1, 3824, -1, -1, -1, -1,
- -1, 3825, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3826, -1, -1, 3827,
- -1, 3828, 3829, -1, -1, -1, -1, 3830,
- -1, -1, -1, -1, -1, 3831, -1, -1,
- 3832, -1, -1, 3833, -1, 3834, -1, -1,
+ -1, -1, -1, -1, 3824, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3835, -1, -1, 3836, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3825, -1, 3826, -1, -1, -1, 3827, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3828, -1, -1,
+ -1, -1, 3829, -1, -1, -1, -1, 3830,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3837, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3831, -1,
+ -1, -1, 3832, -1, -1, 3833, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3838, -1, -1, -1, -1,
- -1, -1, 3839, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3834, -1, -1, -1, 3835, -1, -1, -1,
+ 3836, -1, -1, -1, -1, -1, -1, -1,
+ 3837, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3838, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3840, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3841, -1, -1, -1, -1,
+ 3839, -1, -1, -1, -1, -1, -1, -1,
+ 3840, -1, 3841, 3842, -1, -1, -1, 3843,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3844, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3845, -1, -1,
+ 3846, -1, -1, 3847, -1, -1, -1, -1,
+ 3848, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3849, -1, -1, -1, -1, 3850,
+ -1, -1, -1, -1, -1, 3851, -1, -1,
+ -1, 3852, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3853, -1, -1, -1,
+ -1, -1, 3854, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3855, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3842, -1, -1, -1, -1, -1, -1,
- -1, 3843, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3844, -1, -1, -1,
- -1, -1, 3845, 3846, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3847, -1, -1, -1,
- -1, -1, -1, -1, 3848, 3849, -1, -1,
- -1, -1, -1, 3850, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3856, -1,
+ -1, -1, -1, -1, -1, -1, 3857, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3851, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3858, 3859, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3852, -1, 3853, -1, -1, 3854, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3855, -1, -1, -1, -1,
- -1, -1, -1, -1, 3856, -1, -1, -1,
- 3857, -1, -1, -1, -1, -1, 3858, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3859, -1, -1, 3860,
- -1, -1, 3861, 3862, -1, -1, -1, -1,
- -1, 3863, -1, -1, -1, -1, -1, -1,
- -1, -1, 3864, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3860, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3861, -1,
+ -1, -1, 3862, -1, -1, 3863, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3864, -1,
-1, 3865, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3866, -1, -1,
- -1, -1, 3867, 3868, 3869, 3870, -1, 3871,
- -1, -1, 3872, -1, -1, -1, -1, -1,
- -1, -1, 3873, -1, -1, -1, -1, -1,
- -1, -1, -1, 3874, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3875,
+ -1, -1, -1, -1, -1, -1, 3866, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3867, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3868, -1, -1, -1, -1,
+ -1, 3869, -1, -1, 3870, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3871, -1, -1,
+ -1, -1, 3872, -1, -1, -1, 3873, -1,
+ -1, -1, -1, -1, -1, -1, 3874, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3875, -1, -1, -1, -1,
-1, -1, -1, -1, 3876, -1, -1, -1,
- 3877, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3877, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3878, -1, -1, -1, 3879, -1, -1, 3880,
- -1, -1, -1, 3881, -1, -1, -1, -1,
- 3882, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3883, -1, 3884, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3878, -1, -1, -1, -1, 3879, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3880, -1, -1,
+ 3881, -1, 3882, -1, -1, -1, -1, -1,
+ 3883, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3884, -1, -1, -1,
-1, -1, -1, 3885, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3886, -1,
- -1, -1, -1, 3887, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3888, -1, -1,
- -1, 3889, -1, -1, -1, -1, -1, -1,
- -1, 3890, -1, -1, -1, 3891, -1, -1,
- 3892, 3893, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3886, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3887,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3888, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3889, -1, -1, -1, -1, -1, -1, 3890,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3891,
+ -1, -1, -1, 3892, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3893, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3894, -1, -1, 3895, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3896,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3897, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3898, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3899,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3900, 3901,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3894, -1, 3895, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3896, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3897, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3902, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3898, -1, -1, -1, -1, -1, 3899,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3903, -1, 3904, 3905, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3900, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3901, -1, -1, -1, -1, 3902, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3903, -1, -1, -1, 3904, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3906, -1, -1,
+ -1, -1, -1, -1, 3907, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3905, 3906, 3907, 3908, -1, -1, -1,
- -1, -1, -1, -1, 3909, 3910, -1, -1,
- -1, -1, -1, -1, -1, 3911, -1, -1,
+ 3908, -1, 3909, -1, -1, -1, -1, 3910,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3912, -1, 3913, -1, -1, -1, -1,
- -1, -1, -1, 3914, -1, -1, -1, -1,
- -1, -1, 3915, -1, -1, 3916, -1, -1,
+ -1, 3911, -1, -1, -1, -1, -1, -1,
+ -1, 3912, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3913, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 3914, -1, -1, 3915, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3917, -1, -1, -1,
- -1, 3918, -1, 3919, -1, -1, 3920, 3921,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3922, 3923, -1, -1, -1, 3924, 3925, -1,
- 3926, -1, -1, -1, 3927, -1, -1, 3928,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3929, -1, -1, -1, -1, -1, -1, -1,
- -1, 3930, -1, -1, 3931, -1, -1, 3932,
+ -1, -1, -1, -1, 3916, -1, -1, -1,
+ 3917, -1, -1, -1, 3918, -1, 3919, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3933, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3920, 3921, -1, -1,
+ -1, -1, -1, 3922, -1, -1, -1, -1,
+ -1, -1, 3923, -1, -1, 3924, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3934, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3935, -1,
- -1, -1, -1, -1, -1, 3936, -1, -1,
+ -1, -1, 3925, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3926, -1, 3927, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3937, -1, -1, -1, -1,
- 3938, 3939, -1, -1, -1, -1, 3940, -1,
- -1, -1, 3941, -1, -1, -1, -1, -1,
- 3942, -1, -1, -1, -1, -1, 3943, -1,
+ -1, -1, 3928, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3929, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3944, -1, -1, -1, 3945, -1, 3946,
- -1, -1, -1, -1, -1, -1, 3947, -1,
- -1, -1, 3948, -1, -1, -1, -1, -1,
- -1, 3949, -1, -1, -1, -1, 3950, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 3951, -1, 3952, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3953,
- -1, -1, -1, 3954, -1, 3955, -1, 3956,
+ -1, -1, 3930, -1, -1, -1, -1, -1,
+ 3931, -1, -1, -1, -1, -1, -1, 3932,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3957, -1, -1,
- -1, -1, 3958, -1, -1, -1, -1, -1,
- -1, -1, 3959, -1, -1, -1, -1, 3960,
- 3961, -1, 3962, -1, -1, 3963, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 3964, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 3965, -1, -1,
- -1, -1, 3966, -1, -1, -1, -1, -1,
- -1, 3967, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3968, -1, 3969, -1,
- -1, -1, -1, 3970, -1, -1, -1, 3971,
- 3972, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3973, -1, -1, 3974, -1,
- -1, -1, -1, -1, 3975, -1, 3976, -1,
- -1, -1, -1, 3977, -1, -1, -1, -1,
- -1, -1, 3978, -1, 3979, -1, 3980, -1,
- -1, -1, -1, -1, -1, -1, -1, 3981,
+ -1, -1, -1, 3933, -1, -1, -1, -1,
+ -1, -1, -1, 3934, -1, -1, 3935, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3936, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 3982, -1, -1, -1,
- -1, -1, 3983, -1, -1, -1, -1, -1,
- 3984, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3985, -1,
- -1, 3986, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 3987,
-1, -1, -1, -1, -1, -1, -1, -1,
- 3988, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 3989, -1,
- -1, -1, -1, -1, 3990, -1, -1, -1,
- -1, -1, -1, -1, -1, 3991, -1, -1,
- -1, -1, 3992, -1, -1, 3993, -1, -1,
- -1, -1, -1, -1, -1, -1, 3994, -1,
- -1, -1, -1, -1, -1, -1, -1, 3995,
+ -1, -1, -1, -1, 3937, -1, -1, -1,
+ -1, -1, -1, 3938, 3939, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3940, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3941, -1, 3942, -1, -1, -1, -1, -1,
+ -1, -1, 3943, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3944, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3945, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3946, -1, -1, -1, -1, -1, 3947,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3948, -1, -1, -1, 3949,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3950,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3951, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3952,
+ -1, -1, -1, -1, -1, -1, 3953, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3954,
+ 3955, 3956, -1, -1, -1, -1, 3957, -1,
+ -1, -1, -1, -1, 3958, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3959, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 3960, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3961, -1, -1, -1, -1, 3962, -1,
+ 3963, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 3964, -1, -1, -1, 3965,
+ -1, -1, -1, 3966, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3967,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3968, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3969, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3970, -1, 3971, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3972, -1, -1, -1, -1, -1,
+ 3973, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3974, -1, -1, -1, -1, 3975, -1,
+ -1, -1, -1, 3976, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3977, -1, -1,
+ -1, -1, -1, -1, 3978, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 3979, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3980,
+ 3981, -1, -1, -1, 3982, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3983, 3984, -1, -1, -1, 3985,
+ -1, -1, -1, -1, -1, 3986, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 3987, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 3988, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3989,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 3990, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 3991, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 3992,
+ -1, -1, -1, -1, -1, -1, 3993, -1,
+ -1, -1, -1, -1, 3994, -1, -1, -1,
+ -1, 3995, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 3996, -1, -1, -1,
- -1, -1, 3997, -1, 3998, -1, -1, -1,
- -1, -1, 3999, -1, -1, -1, -1, -1,
- 4000, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4001, -1, -1, -1,
+ -1, -1, -1, -1, 3997, -1, -1, -1,
+ -1, 3998, -1, -1, -1, -1, 3999, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4000, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4001, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4002, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4003, -1, -1,
- -1, -1, -1, -1, -1, -1, 4004, -1,
- -1, -1, -1, -1, 4005, -1, -1, -1,
- 4006, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4002, -1, -1, -1, -1, 4003, -1,
+ -1, -1, -1, -1, -1, 4004, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4005, -1, -1, -1, -1, 4006, -1, -1,
+ -1, -1, -1, -1, -1, 4007, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4007, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4008, -1,
- -1, -1, -1, -1, 4009, -1, -1, -1,
+ -1, -1, -1, 4008, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4010,
- -1, 4011, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4009, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4010, 4011, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 4012,
- -1, -1, -1, -1, -1, -1, 4013, -1,
- -1, -1, -1, -1, 4014, -1, -1, -1,
- -1, -1, 4015, 4016, -1, -1, -1, -1,
- -1, 4017, -1, -1, -1, -1, -1, -1,
- 4018, 4019, -1, -1, -1, 4020, -1, 4021,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4022, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4013, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4014, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4015, -1, -1, -1,
+ -1, 4016, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4017, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4018, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4019, -1, -1, -1,
+ -1, -1, -1, -1, 4020, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4021, -1, -1, -1, -1, -1, -1, -1,
+ 4022, -1, -1, -1, -1, -1, -1, 4023,
+ -1, -1, -1, -1, -1, -1, 4024, -1,
+ 4025, -1, -1, -1, -1, -1, -1, 4026,
+ 4027, -1, -1, -1, -1, 4028, 4029, -1,
+ 4030, -1, 4031, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4023, -1, 4024, -1,
- 4025, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4026, -1, -1, -1, -1, 4027,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4028, -1, -1, -1,
- -1, -1, -1, 4029, -1, -1, -1, -1,
- -1, -1, -1, 4030, -1, -1, -1, -1,
- 4031, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4032, 4033, -1, -1, -1, -1, -1,
+ -1, -1, 4032, -1, -1, -1, -1, -1,
+ 4033, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
4034, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4035, -1, -1, -1, -1,
+ 4036, 4037, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4038,
+ -1, -1, -1, -1, -1, -1, 4039, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4040, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4041,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4042, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4043, -1, -1, -1,
+ -1, -1, -1, 4044, -1, -1, -1, -1,
+ -1, -1, -1, 4045, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4046,
+ -1, 4047, -1, -1, -1, -1, -1, 4048,
+ -1, -1, 4049, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4050, -1, -1, 4051,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4052, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4053, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4054, -1, 4055, -1, -1,
+ 4056, -1, -1, -1, -1, 4057, -1, -1,
+ 4058, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4059, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4060,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4061, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4062, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4063, -1, -1,
+ 4064, -1, -1, -1, -1, -1, -1, 4065,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4066, -1, 4067, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4068, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4069,
+ -1, -1, -1, 4070, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4071, -1, -1, -1, 4072, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4073, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4035, -1, 4036,
- -1, -1, -1, -1, -1, -1, -1, 4037,
- -1, 4038, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4039, 4040, -1, 4041, -1, -1, 4042,
- -1, -1, -1, -1, 4043, -1, -1, 4044,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4045,
+ -1, -1, 4074, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4046, -1, -1, -1, -1,
- -1, -1, 4047, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4048, -1,
- -1, 4049, -1, -1, -1, 4050, -1, -1,
- 4051, -1, -1, -1, -1, -1, 4052, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4075,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4053, -1, 4054, 4055, -1, -1, -1,
+ -1, -1, 4076, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4056, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4077, -1, 4078, -1, -1,
+ -1, -1, -1, -1, 4079, -1, -1, -1,
+ -1, -1, 4080, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4057, 4058, -1, -1, -1, -1, -1, -1,
- -1, -1, 4059, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4081, -1, -1, -1,
+ -1, -1, -1, 4082, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4060, -1, 4061,
- -1, 4062, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4063, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4064, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4083,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4065, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4084, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4066, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4067,
+ 4085, -1, -1, 4086, 4087, -1, 4088, -1,
+ -1, -1, -1, -1, -1, 4089, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4068, -1, -1, -1, -1, -1,
+ -1, -1, 4090, -1, -1, -1, -1, -1,
+ -1, -1, 4091, 4092, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4069, -1, -1, -1, -1, -1, -1,
- 4070, -1, -1, -1, 4071, -1, -1, -1,
- 4072, -1, -1, -1, -1, -1, 4073, -1,
- -1, -1, -1, -1, -1, -1, 4074, 4075,
- -1, -1, -1, -1, -1, -1, -1, 4076,
- -1, -1, -1, -1, -1, -1, 4077, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4078, -1,
+ -1, -1, 4093, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4079, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4080,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4081, -1,
- -1, -1, -1, -1, -1, -1, 4082, -1,
- -1, -1, -1, -1, -1, -1, 4083, -1,
- -1, 4084, -1, 4085, -1, -1, -1, -1,
- -1, -1, -1, 4086, -1, -1, -1, -1,
- -1, -1, 4087, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4088, -1, -1, -1,
- -1, -1, -1, 4089, -1, 4090, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4091, -1, -1, -1, -1,
- -1, -1, 4092, -1, -1, -1, -1, -1,
- -1, -1, -1, 4093, -1, -1, -1, -1,
- -1, -1, -1, -1, 4094, -1, -1, -1,
- -1, 4095, -1, -1, -1, -1, -1, -1,
+ -1, 4094, -1, 4095, -1, -1, -1, -1,
+ 4096, -1, -1, 4097, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4098, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4096, -1, -1, 4097, -1, -1, -1,
+ -1, 4099, -1, -1, -1, -1, -1, -1,
+ -1, 4100, -1, -1, -1, 4101, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4098, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4102, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4099, 4100, -1, -1, 4101,
- -1, -1, -1, -1, 4102, -1, -1, -1,
- -1, -1, -1, 4103, -1, 4104, -1, -1,
- 4105, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4103, -1,
+ -1, -1, -1, 4104, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4106, -1, -1, -1, -1, -1,
+ -1, -1, 4105, -1, -1, 4106, -1, -1,
+ -1, -1, -1, 4107, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4107, -1, -1,
- -1, -1, 4108, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4109, -1, 4110, -1,
- -1, -1, -1, -1, 4111, -1, -1, -1,
- -1, 4112, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4108, -1, -1, -1, -1,
+ -1, -1, -1, 4109, -1, -1, -1, -1,
+ -1, -1, 4110, -1, -1, -1, -1, 4111,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4113, -1, -1, -1,
- -1, -1, -1, -1, 4114, -1, -1, 4115,
- -1, 4116, -1, -1, -1, -1, -1, -1,
- -1, 4117, -1, -1, 4118, 4119, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4120, -1,
+ -1, -1, -1, -1, -1, 4112, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4121, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4122, 4123,
- 4124, -1, -1, -1, -1, -1, -1, 4125,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4113, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4114, -1, 4115, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4126, -1,
- -1, -1, 4127, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4128, -1,
+ 4116, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4117, -1, -1,
+ -1, 4118, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4119,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4120, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4121, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4129,
- -1, 4130, -1, -1, 4131, -1, -1, -1,
+ -1, -1, -1, 4122, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4123, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4124, -1, -1, -1, -1, -1,
+ 4125, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4126, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4127, 4128,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4129, -1,
+ -1, -1, -1, -1, 4130, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4131,
-1, -1, 4132, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4133, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4133, -1, 4134,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4135, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4136,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4134, -1, -1, 4135, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4136, -1, -1, -1, -1, -1,
- 4137, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4138, -1, -1,
- -1, -1, -1, -1, -1, -1, 4139, -1,
- -1, -1, -1, -1, -1, -1, -1, 4140,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4141, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4137, -1, -1, -1, -1, 4138,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4142, -1, 4143, -1, -1, -1, -1,
- 4144, -1, -1, 4145, -1, -1, -1, -1,
- -1, -1, 4146, -1, -1, -1, -1, -1,
- 4147, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4148, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4139, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4149, -1, -1, -1, -1, -1, -1, -1,
- 4150, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4151, 4152, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4153, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4140, -1, -1, 4141, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4142, -1, -1,
+ -1, -1, -1, -1, -1, 4143, 4144, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4145,
+ 4146, -1, 4147, -1, 4148, -1, -1, 4149,
+ -1, -1, -1, -1, -1, 4150, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4151, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4152, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4153, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 4154, -1, -1, -1, -1,
- -1, -1, 4155, -1, -1, 4156, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4155, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4156, -1, -1, 4157, -1, -1, -1, -1,
+ -1, 4158, -1, 4159, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4160,
+ -1, -1, -1, -1, -1, -1, -1, 4161,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4162, -1, -1, -1, -1, 4163,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4164, -1, -1, -1, -1,
+ -1, 4165, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4166, -1, -1, -1, 4167, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4168,
+ -1, -1, 4169, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4170, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4171, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4157, -1, -1, -1, -1, -1,
- 4158, -1, -1, -1, 4159, -1, -1, -1,
+ -1, -1, -1, -1, 4172, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4160, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4161, 4162, -1, -1, -1, -1,
- 4163, 4164, -1, -1, -1, -1, -1, -1,
- 4165, -1, -1, -1, 4166, -1, -1, 4167,
- 4168, -1, -1, -1, -1, -1, 4169, -1,
- -1, 4170, 4171, -1, -1, -1, -1, -1,
- 4172, -1, 4173, -1, 4174, -1, 4175, 4176,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4177, -1, 4178, 4179, -1, -1, -1,
- 4180, -1, -1, -1, -1, 4181, -1, 4182,
- -1, -1, -1, -1, -1, -1, -1, 4183,
- -1, -1, -1, 4184, 4185, -1, -1, -1,
+ -1, 4173, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4174, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4175, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4176, -1, 4177,
+ -1, -1, -1, 4178, -1, 4179, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4180,
+ -1, -1, 4181, -1, -1, -1, -1, -1,
+ -1, -1, 4182, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4183, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4184, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4185,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 4186, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4187, -1, 4188, -1, -1, 4189, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4190, 4191,
- -1, -1, 4192, -1, -1, -1, -1, 4193,
- -1, 4194, -1, -1, -1, -1, 4195, -1,
- -1, 4196, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4197, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4187,
+ 4188, -1, -1, -1, 4189, 4190, -1, -1,
+ -1, -1, -1, -1, 4191, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4192, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4193, -1, -1, -1, -1, 4194,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4195, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4196, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4197,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4198, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4199,
+ 4200, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4201, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4202, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4203,
+ -1, -1, -1, -1, 4204, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4205, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4206, -1, 4207,
+ -1, -1, 4208, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4198, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4209, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4199, 4200, -1, -1, -1, -1, -1, -1,
- 4201, -1, -1, -1, -1, 4202, -1, -1,
- -1, -1, -1, -1, 4203, -1, -1, -1,
- -1, 4204, -1, 4205, -1, -1, -1, -1,
- 4206, -1, -1, -1, -1, -1, -1, -1,
- 4207, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4208, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4209, -1, 4210, 4211, -1,
- -1, -1, -1, -1, 4212, -1, -1, -1,
- -1, -1, -1, -1, 4213, -1, 4214, -1,
- -1, -1, -1, 4215, -1, -1, 4216, -1,
+ -1, 4210, -1, -1, -1, 4211, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4212,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4217, -1, 4218,
- -1, 4219, -1, -1, -1, 4220, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4221, -1, 4222, -1, -1,
- -1, -1, -1, 4223, -1, -1, -1, 4224,
- -1, 4225, -1, -1, -1, -1, -1, 4226,
- -1, 4227, -1, -1, -1, -1, -1, 4228,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4229, -1, -1, 4230, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4213, -1,
+ 4214, 4215, -1, 4216, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4217, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4231, -1, 4232, -1, -1, 4233, 4234,
- 4235, 4236, -1, -1, 4237, -1, 4238, -1,
- -1, -1, -1, -1, -1, 4239, -1, -1,
- -1, 4240, 4241, -1, -1, 4242, -1, 4243,
- -1, -1, -1, 4244, -1, 4245, -1, 4246,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4247, -1, 4248, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4249,
- -1, -1, -1, 4250, -1, -1, -1, -1,
- -1, 4251, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4252, -1, -1, -1,
- 4253, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4218, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4254, -1, 4255, -1, 4256, -1, -1, 4257,
- -1, -1, -1, 4258, 4259, 4260, -1, -1,
- -1, -1, -1, -1, -1, -1, 4261, -1,
- 4262, -1, 4263, 4264, -1, -1, -1, -1,
- -1, -1, 4265, -1, -1, -1, 4266, -1,
- -1, -1, 4267, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4268, -1, -1,
- -1, -1, -1, 4269, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4270, -1,
- -1, -1, -1, -1, 4271, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4272, -1, 4273, -1, -1,
+ -1, -1, -1, -1, -1, 4219, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4274, -1, 4275, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4276,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4220, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4221, -1, -1,
+ -1, -1, -1, -1, 4222, -1, -1, -1,
+ -1, -1, 4223, -1, -1, -1, -1, -1,
+ 4224, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4225, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4226, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4227, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4228, -1, -1, -1, -1,
+ -1, -1, 4229, -1, -1, -1, 4230, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4231, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4232, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4233, -1, -1, -1,
+ -1, -1, 4234, -1, -1, -1, -1, 4235,
+ -1, -1, 4236, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4237, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4238, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4239, -1, -1, -1, 4240, -1, 4241,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4242, -1, -1, -1, -1,
+ -1, -1, 4243, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4244, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4245, 4246, -1, 4247, -1, -1, 4248, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4249, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4250, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4251, -1, 4252, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4253, -1, -1,
+ -1, -1, -1, -1, -1, 4254, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4255, 4256, 4257, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4258, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4259, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4260, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4261,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4262, -1, -1, 4263, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4264, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4265, -1, -1, -1, 4266,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4267, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4268, -1, -1, -1, -1, -1, 4269,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4270, -1, -1, -1, 4271, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4272, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4273, -1, -1, -1, -1, -1, 4274, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4275, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4276, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 4277, -1, -1, -1, -1,
- -1, -1, 4278, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4279, -1, -1, -1,
- -1, -1, -1, -1, 4280, -1, -1, -1,
- -1, -1, -1, 4281, -1, -1, -1, -1,
- -1, -1, -1, 4282, -1, -1, -1, -1,
- 4283, -1, -1, -1, -1, -1, -1, -1,
- 4284, -1, -1, 4285, -1, -1, -1, 4286,
- -1, -1, -1, -1, -1, -1, 4287, -1,
+ -1, 4278, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4279, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4280,
+ -1, -1, -1, -1, -1, -1, -1, 4281,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4288, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4289, -1, -1, -1, -1,
- -1, 4290, 4291, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4292, -1, 4293, 4294, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4295, -1, -1, -1, -1, -1, 4296, -1,
- -1, -1, -1, -1, -1, -1, 4297, -1,
- -1, -1, 4298, -1, -1, -1, -1, 4299,
- -1, -1, 4300, -1, -1, -1, 4301, -1,
- -1, -1, -1, -1, -1, -1, -1, 4302,
- -1, -1, -1, 4303, 4304, -1, -1, -1,
- 4305, -1, -1, -1, -1, -1, -1, -1,
- -1, 4306, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4307, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4308, -1, -1, 4309, 4310,
- -1, 4311, -1, -1, 4312, -1, -1, -1,
- -1, 4313, -1, -1, -1, -1, -1, 4314,
- -1, -1, -1, 4315, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4316,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4317, -1, -1, -1, -1, -1, 4318, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4319,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4320, -1, -1,
- -1, -1, -1, -1, -1, -1, 4321, -1,
- 4322, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4323, -1, 4324,
- -1, -1, 4325, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4326, -1, 4327, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4282, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4283, -1, -1, 4284,
+ -1, -1, 4285, -1, -1, 4286, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4287, 4288, -1,
+ -1, -1, 4289, -1, -1, -1, 4290, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4328, 4329, -1, -1, 4330, -1, 4331,
- 4332, -1, 4333, -1, 4334, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4335,
- -1, -1, -1, -1, -1, 4336, -1, -1,
- -1, -1, -1, 4337, -1, 4338, -1, 4339,
- -1, -1, -1, -1, -1, 4340, -1, 4341,
- -1, -1, 4342, -1, -1, -1, -1, -1,
- 4343, -1, -1, -1, -1, -1, -1, -1,
- -1, 4344, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4345, -1, 4346, -1, -1, -1, -1, -1,
- 4347, -1, 4348, -1, -1, -1, -1, -1,
+ -1, 4291, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4292, -1, -1, 4293, -1, 4294,
+ -1, -1, -1, -1, -1, -1, 4295, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4349, -1, 4350, -1, -1, -1, -1,
- 4351, -1, -1, 4352, -1, -1, -1, -1,
- 4353, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4354, -1, -1, -1, -1, -1,
- -1, -1, 4355, -1, -1, -1, 4356, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4296, -1, -1, 4297, 4298, -1, 4299,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4357,
- 4358, -1, -1, -1, -1, -1, 4359, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4360, -1, -1, -1, -1, -1, 4361, 4362,
- 4363, -1, -1, -1, -1, -1, -1, 4364,
+ -1, -1, 4300, -1, -1, -1, -1, 4301,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4365, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4366, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4302, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4367, -1,
- -1, 4368, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4369, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4370,
- -1, -1, -1, -1, -1, 4371, -1, -1,
- 4372, -1, -1, -1, -1, -1, 4373, -1,
- 4374, -1, -1, -1, -1, -1, -1, -1,
- -1, 4375, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4376,
- 4377, -1, -1, -1, -1, -1, -1, 4378,
+ 4303, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4304, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4379, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4380, -1, -1, 4381, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4382, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4383, -1, -1, -1,
- 4384, -1, -1, -1, -1, -1, -1, -1,
- -1, 4385, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4386, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4387, -1, -1,
- 4388, -1, -1, -1, -1, -1, 4389, 4390,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4391, 4392, -1, 4393, -1, -1,
- -1, 4394, -1, -1, -1, -1, -1, -1,
- -1, -1, 4395, -1, -1, -1, -1, 4396,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4397, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4398, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4399, -1,
+ -1, 4305, -1, -1, -1, -1, 4306, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4307, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4308, -1, -1,
+ -1, 4309, -1, -1, -1, -1, -1, -1,
+ -1, 4310, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4311, 4312, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4313, -1, -1, 4314, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4315, -1, -1, -1, -1, -1,
+ -1, -1, 4316, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4400, -1, -1, -1, -1, -1, -1,
- 4401, -1, -1, -1, 4402, -1, -1, -1,
- -1, -1, -1, -1, -1, 4403, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4317, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4404, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4318, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4319, -1, -1,
+ -1, -1, -1, -1, 4320, -1, -1, -1,
+ -1, 4321, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4322, -1, -1, -1, -1, -1,
+ -1, 4323, -1, 4324, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4325, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4326, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4327, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4328, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4329, -1,
+ -1, 4330, -1, 4331, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4332, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4333, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4334, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4335, -1, -1, -1, -1,
+ -1, -1, 4336, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4337, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4338, -1, -1, 4339, -1,
+ 4340, -1, -1, 4341, 4342, -1, -1, -1,
+ -1, -1, -1, 4343, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4344, 4345,
+ -1, -1, 4346, -1, -1, -1, 4347, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4348, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4349,
+ -1, -1, -1, -1, -1, -1, 4350, -1,
+ -1, -1, -1, -1, -1, 4351, 4352, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4353, -1, -1, -1, 4354, -1, 4355, -1,
+ -1, -1, 4356, -1, -1, -1, -1, -1,
+ -1, -1, 4357, -1, -1, -1, 4358, -1,
+ -1, -1, -1, -1, -1, 4359, -1, -1,
+ -1, -1, -1, -1, 4360, -1, -1, -1,
+ -1, -1, -1, -1, 4361, -1, 4362, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4363, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4364, -1, -1, -1, -1, -1, -1,
+ -1, 4365, -1, 4366, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4367, -1, -1, -1,
+ -1, -1, -1, -1, 4368, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4369, 4370, -1,
+ -1, 4371, -1, -1, -1, -1, 4372, -1,
+ -1, -1, -1, 4373, 4374, -1, -1, -1,
+ -1, -1, 4375, -1, -1, -1, 4376, -1,
+ -1, -1, 4377, -1, -1, -1, -1, -1,
+ -1, -1, 4378, -1, -1, 4379, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4380, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4381, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4382, -1, -1, -1, 4383, -1, -1, 4384,
+ 4385, -1, -1, -1, -1, 4386, -1, -1,
+ -1, -1, -1, -1, 4387, -1, -1, 4388,
+ 4389, -1, -1, -1, -1, -1, 4390, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4391,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4392,
+ 4393, -1, -1, 4394, -1, -1, -1, -1,
+ 4395, -1, -1, 4396, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4397, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4398, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4399,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4400, -1, -1, -1,
+ -1, 4401, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4402, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4403, -1, -1,
+ -1, -1, -1, -1, 4404, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 4405,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4406, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4407,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4408, -1, -1,
+ -1, -1, -1, 4409, -1, -1, -1, -1,
+ 4410, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4406, 4407, -1, -1, -1, -1,
- -1, -1, -1, 4408, 4409, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4410, -1, -1, -1, -1,
- -1, 4411, -1, -1, -1, 4412, -1, -1,
- -1, -1, -1, -1, -1, -1, 4413, -1,
- 4414, -1, -1, -1, 4415, -1, 4416, -1,
- -1, -1, -1, -1, -1, -1, 4417, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4411, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4412, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4413,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4418, -1, -1, -1,
+ -1, -1, -1, 4414, -1, 4415, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4419, -1, -1, -1, -1, -1,
+ 4416, -1, -1, -1, -1, -1, -1, -1,
+ 4417, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4420, 4421, -1, 4422,
- 4423, -1, -1, -1, -1, -1, 4424, -1,
- -1, -1, -1, 4425, 4426, -1, -1, 4427,
+ -1, 4418, -1, -1, -1, 4419, -1, -1,
+ -1, -1, 4420, 4421, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4428, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4429, 4430, -1, -1, -1, -1, -1, -1,
+ 4422, 4423, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4424, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4431, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4432, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4425, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4426,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4427, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4428, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4429, -1,
+ -1, -1, 4430, -1, -1, -1, -1, -1,
+ -1, 4431, -1, -1, -1, -1, -1, 4432,
-1, -1, -1, -1, -1, 4433, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4434, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4435, -1, -1, -1, -1, -1, 4436,
+ -1, -1, -1, -1, 4437, 4438, -1, -1,
+ 4439, -1, -1, -1, -1, -1, -1, -1,
+ 4440, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4441, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4442, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4434, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4443, -1, -1,
+ -1, -1, -1, -1, 4444, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4435, -1, -1, -1, 4436, -1, -1,
- -1, -1, -1, 4437, -1, -1, -1, -1,
- -1, -1, 4438, -1, -1, -1, -1, 4439,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4440, -1,
- -1, 4441, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4445, -1, -1, -1, -1,
+ -1, -1, -1, 4446, -1, -1, -1, -1,
+ -1, -1, 4447, -1, -1, 4448, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4442, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4449, -1, -1, -1, -1, -1,
+ -1, 4450, -1, -1, 4451, -1, -1, -1,
+ -1, -1, -1, -1, 4452, -1, -1, -1,
+ -1, -1, -1, 4453, -1, -1, -1, -1,
+ -1, -1, 4454, -1, -1, 4455, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4456,
+ -1, -1, -1, -1, -1, -1, -1, 4457,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4443, -1, -1, -1, -1, -1, -1,
- -1, -1, 4444, 4445, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4458, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4459,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4446, 4447, -1, -1, -1, -1, 4448,
- -1, 4449, -1, -1, -1, -1, -1, -1,
- 4450, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4460,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4451, -1, -1, 4452, -1, -1,
- -1, -1, -1, -1, -1, 4453, -1, 4454,
- -1, -1, -1, -1, 4455, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4456, -1,
- -1, -1, -1, 4457, -1, 4458, -1, -1,
- -1, -1, -1, -1, 4459, 4460, -1, -1,
- -1, -1, 4461, -1, -1, -1, -1, -1,
- -1, -1, -1, 4462, -1, -1, 4463, -1,
- -1, -1, -1, -1, -1, 4464, -1, -1,
+ -1, 4461, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4462, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4463, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4464,
+ 4465, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4465, -1, -1, -1,
-1, 4466, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4467, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4467, -1, -1, -1, 4468, -1, 4469, -1,
- -1, -1, -1, -1, -1, -1, 4470, -1,
- -1, 4471, -1, 4472, 4473, -1, -1, 4474,
- -1, -1, -1, -1, 4475, -1, -1, -1,
- -1, -1, 4476, -1, 4477, -1, -1, 4478,
- -1, -1, -1, -1, -1, 4479, 4480, 4481,
- 4482, -1, -1, -1, 4483, -1, -1, 4484,
- 4485, -1, -1, -1, -1, -1, -1, -1,
- 4486, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4487, -1, -1, -1,
- -1, -1, 4488, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4489, 4490, -1, -1, -1,
- -1, -1, -1, -1, -1, 4491, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4492, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4493, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4468, -1, -1, 4469, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4470, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4494, 4495, -1, -1, -1, -1, -1, 4496,
+ -1, -1, -1, -1, 4471, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4497, -1, -1, -1, -1, -1, -1, 4498,
+ 4472, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4473, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4474, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4499, -1, -1, -1, -1, -1,
- -1, 4500, -1, -1, -1, -1, -1, 4501,
- -1, 4502, 4503, -1, -1, -1, -1, -1,
- -1, 4504, -1, -1, -1, -1, -1, -1,
- 4505, -1, -1, -1, -1, -1, 4506, -1,
- -1, 4507, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4508, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4475,
+ 4476, -1, -1, -1, -1, -1, -1, -1,
+ 4477, -1, -1, -1, -1, -1, 4478, -1,
+ -1, -1, 4479, -1, -1, -1, -1, -1,
+ -1, 4480, -1, -1, -1, -1, 4481, 4482,
+ -1, -1, -1, 4483, -1, 4484, -1, -1,
+ -1, -1, -1, 4485, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4509, -1, -1, -1, -1, -1, -1,
+ -1, 4486, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4510, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4487,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4511, -1, 4512, -1, -1, -1, -1, -1,
- -1, -1, 4513, -1, -1, -1, -1, -1,
- -1, -1, -1, 4514, -1, -1, 4515, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4516, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4517, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4518, -1, -1, -1,
- -1, -1, -1, 4519, 4520, -1, 4521, 4522,
- -1, -1, -1, 4523, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4524, -1, -1, -1, -1, -1, -1,
+ 4488, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4489,
+ -1, -1, -1, -1, -1, -1, -1, 4490,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4525, -1, -1, -1, -1, 4526, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4527, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4528, -1, -1,
- 4529, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4491,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4530, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4531,
- 4532, -1, -1, -1, -1, -1, 4533, -1,
- -1, -1, -1, -1, -1, 4534, -1, -1,
- -1, -1, -1, 4535, -1, -1, -1, 4536,
- -1, -1, -1, -1, 4537, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4492, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4538, -1, -1, -1, 4539, -1, -1,
- -1, -1, 4540, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4493, -1, 4494, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4495, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4541, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4542, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4543, -1, -1, -1, -1, -1,
- -1, -1, 4544, -1, -1, -1, 4545, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4546, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4496, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4547, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4497, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4498, -1,
+ -1, -1, -1, -1, -1, 4499, -1, 4500,
+ -1, -1, -1, -1, 4501, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4548, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4502, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4503, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4549, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4504, 4505, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4550, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4551, 4552, -1, -1, -1, -1,
- -1, -1, -1, 4553, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4554,
- -1, -1, -1, -1, -1, -1, 4555, -1,
- -1, -1, -1, -1, -1, -1, -1, 4556,
- -1, -1, -1, -1, -1, 4557, -1, -1,
- -1, -1, -1, -1, -1, 4558, 4559, -1,
+ -1, -1, -1, -1, -1, -1, 4506, 4507,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4508, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4509, -1, -1, -1, -1, -1, -1, -1,
+ 4510, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4511, -1, -1, -1, -1, -1, -1,
+ -1, 4512, -1, -1, -1, -1, 4513, -1,
+ -1, -1, -1, -1, -1, 4514, -1, -1,
+ 4515, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4560, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4561,
- 4562, -1, -1, -1, 4563, -1, -1, 4564,
- -1, -1, -1, -1, -1, -1, 4565, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4516, -1, -1, 4517, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4518, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4519, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4520, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4521, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4522, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4523,
+ -1, -1, 4524, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4525, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4526, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4527, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4528,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4529, 4530, -1,
+ -1, -1, -1, -1, 4531, 4532, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4533, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4534, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4535, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4536, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4537, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4538, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4539, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4540, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4541,
+ -1, -1, -1, -1, -1, 4542, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4543, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4544, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4545, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4546, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4547, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4548,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4549, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4566,
- -1, -1, -1, 4567, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4550, -1, -1, -1, 4551, -1,
+ -1, -1, 4552, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4568, 4569, -1, -1, -1,
- -1, -1, -1, -1, 4570, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4571, 4572, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4573, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4553, -1, 4554, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4555, -1, -1, -1,
+ -1, -1, 4556, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4557,
+ -1, -1, -1, -1, 4558, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4559, -1,
+ -1, -1, -1, -1, -1, 4560, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4561, -1, -1, -1,
+ -1, -1, -1, -1, 4562, -1, -1, -1,
+ -1, 4563, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4564, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4565, -1, -1, -1,
+ -1, 4566, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4567, -1, -1, -1, -1,
+ -1, -1, -1, 4568, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4569, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4570, -1, -1, 4571, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4572, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4573,
-1, -1, 4574, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4575,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4576, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4577, -1, -1, 4578,
- -1, -1, -1, 4579, -1, -1, -1, -1,
- -1, -1, 4580, -1, -1, -1, -1, -1,
- -1, -1, 4581, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4575, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4576, -1, -1, 4577,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4578, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4579,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4580, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4581, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4582, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4583, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4584, -1, -1, -1, 4585,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4586, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4587, -1, -1, 4588, -1, -1, 4589, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4582,
+ -1, -1, -1, -1, -1, -1, -1, 4590,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4583,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4584, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4585, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4586, -1, -1, 4587,
- -1, -1, -1, -1, -1, -1, -1, 4588,
- -1, -1, -1, -1, -1, -1, -1, 4589,
- -1, -1, -1, -1, -1, 4590, -1, -1,
- 4591, -1, -1, 4592, -1, -1, -1, -1,
- -1, -1, 4593, -1, -1, -1, 4594, -1,
+ -1, -1, -1, 4591, -1, -1, -1, -1,
+ -1, 4592, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4593, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4594, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 4595, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4596, -1, -1,
- -1, -1, 4597, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4598, -1, 4599,
- -1, 4600, -1, -1, -1, -1, -1, -1,
- -1, 4601, -1, 4602, -1, 4603, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4596, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4597, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4598,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4599, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4600, 4601,
+ 4602, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4603, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4604, -1, -1, -1, 4605,
+ -1, -1, -1, -1, -1, -1, 4606, 4607,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4608, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4609, -1, 4610, 4611, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4612, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4613, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4614, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4615, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4616, 4617,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4604, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4605, 4606, -1,
- -1, -1, -1, 4607, 4608, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4609, 4610, -1, -1, -1, -1, -1,
+ 4618, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4611, 4612, 4613,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4614, -1, -1, -1, -1, -1,
- -1, -1, -1, 4615, -1, -1, -1, -1,
- -1, -1, -1, 4616, -1, -1, -1, -1,
- -1, 4617, -1, -1, -1, -1, -1, -1,
- -1, 4618, -1, -1, -1, -1, -1, -1,
- 4619, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4620,
+ -1, -1, -1, -1, -1, 4619, -1, -1,
+ 4620, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4621, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4621, -1, 4622, -1, -1, -1, -1, -1,
- -1, 4623, -1, -1, -1, -1, -1, -1,
- 4624, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4625, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4622,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4626, -1, -1, -1, -1, -1, -1, -1,
- 4627, -1, -1, -1, -1, -1, 4628, 4629,
- -1, -1, 4630, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4623, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4631, -1, -1, -1, 4632, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4633, 4634,
- -1, -1, -1, -1, -1, -1, -1, 4635,
- 4636, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4637, 4638, -1, -1, -1,
- -1, 4639, -1, -1, -1, -1, 4640, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4641, -1, 4642, -1,
- -1, -1, -1, -1, -1, 4643, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4644,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4645, -1, -1, -1, -1, -1, -1, 4646,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4647, -1, -1,
- -1, 4648, -1, -1, -1, 4649, -1, -1,
- -1, 4650, -1, -1, -1, -1, 4651, -1,
- -1, 4652, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4653, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4624,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4654, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4625, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4626, -1, -1, -1,
+ 4627, -1, -1, -1, 4628, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4655, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4629, -1, -1, -1, -1, 4630, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4656, -1, 4657, -1, -1, -1, -1, -1,
- -1, -1, -1, 4658, -1, -1, -1, -1,
+ -1, -1, -1, 4631, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4659, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4660, -1, -1, -1,
- 4661, -1, -1, -1, -1, -1, -1, 4662,
+ -1, -1, -1, -1, -1, -1, -1, 4632,
+ -1, -1, -1, -1, -1, 4633, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4663, -1, -1, -1, 4664, 4665, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4634,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4666, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4635, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4636,
+ 4637, -1, -1, 4638, -1, -1, -1, -1,
+ -1, 4639, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4667, -1, -1, 4668, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4669, -1, -1, -1, -1, -1, 4670, 4671,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4640, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4641, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4642, -1, -1, 4643, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4644, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4645, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4646, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4647,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4648, -1, -1, -1, -1, 4649, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4650,
+ -1, -1, -1, -1, 4651, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4652, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4653, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4654, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4655, -1, -1, -1, -1, -1, -1, -1,
+ 4656, -1, -1, 4657, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4658, 4659, 4660,
+ -1, -1, -1, -1, 4661, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4662, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4663, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4664, -1, -1,
+ -1, -1, -1, -1, 4665, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4666, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4667, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4668, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4669, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4670, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4671, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, 4672, -1, -1, -1, -1, -1, -1,
- -1, -1, 4673, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4674, -1,
- -1, -1, -1, -1, 4675, -1, 4676, -1,
+ -1, -1, -1, -1, -1, 4673, -1, -1,
+ -1, -1, 4674, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4675, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4676, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4677, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4678, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4677, -1, -1, -1, -1, 4678, -1,
+ -1, -1, 4679, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4680,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4679, -1, 4680, -1, 4681, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4682, -1, -1, -1, 4683,
- -1, -1, -1, -1, 4684, -1, -1, -1,
- -1, -1, -1, 4685, -1, 4686, -1, -1,
- -1, 4687, -1, -1, 4688, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4689, -1, -1, -1, 4690,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4691, -1, -1, -1, -1,
- -1, 4692, -1, -1, -1, -1, -1, 4693,
+ -1, -1, -1, 4681, -1, -1, 4682, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4694, -1, -1, -1, -1,
+ -1, -1, -1, 4683, -1, -1, -1, -1,
+ -1, -1, 4684, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4685, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4686, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4687, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4695, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4696,
- -1, -1, -1, 4697, -1, -1, -1, -1,
+ 4688, -1, -1, -1, 4689, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4698, -1, -1, -1, 4699, -1, 4700, -1,
+ -1, -1, 4690, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4701, -1, -1, -1, -1, 4702,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4691,
+ -1, -1, -1, -1, -1, -1, 4692, -1,
+ -1, -1, 4693, -1, -1, -1, -1, -1,
+ -1, 4694, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4695, 4696, -1, -1, -1, -1, -1,
+ 4697, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4698,
+ -1, 4699, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4703, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4704, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4705, 4706, -1, -1, -1,
+ -1, -1, 4700, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4701, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4707, -1, -1, -1, -1, -1, 4708, 4709,
- -1, -1, -1, 4710, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4711, -1, -1, -1, -1, -1,
- -1, 4712, -1, -1, 4713, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4714, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4715, -1, -1, -1, -1, -1, -1,
- 4716, -1, 4717, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4702, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4718, -1,
+ -1, -1, -1, -1, -1, -1, 4703, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4704, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4705, -1, -1, -1, -1, -1,
+ -1, -1, 4706, -1, -1, 4707, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4708,
+ -1, -1, -1, -1, -1, -1, 4709, -1,
+ -1, -1, -1, -1, 4710, -1, -1, -1,
+ 4711, -1, -1, -1, -1, -1, -1, -1,
+ 4712, -1, -1, -1, -1, 4713, 4714, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4715, 4716, 4717, -1,
+ -1, -1, -1, -1, -1, 4718, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4719, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4720, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4721, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4719,
- -1, -1, -1, -1, -1, -1, 4720, -1,
- 4721, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 4722,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4723, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4723, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4724, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4725,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4724, -1, -1, -1,
+ 4726, -1, -1, -1, -1, -1, -1, 4727,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4725, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4726, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4728, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4729, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4730, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4731, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4732, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4733, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4727, 4728, -1, -1, -1, -1, -1,
- 4729, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4730, -1, -1,
- -1, -1, 4731, -1, 4732, -1, -1, 4733,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 4734, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4735, -1, -1, 4736, -1, -1, -1,
- -1, -1, -1, -1, 4737, -1, -1, 4738,
+ -1, -1, -1, 4735, -1, -1, -1, 4736,
+ -1, -1, -1, -1, -1, 4737, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4738, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4739, -1, -1, -1, 4740, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4741, -1, -1,
+ -1, -1, -1, 4742, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4739, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4743,
+ -1, -1, -1, -1, -1, 4744, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4740, -1, -1, -1, -1, -1,
- -1, -1, 4741, 4742, -1, -1, -1, -1,
- -1, 4743, -1, -1, -1, -1, -1, 4744,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4745, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4746, 4747, 4748,
- -1, 4749, -1, -1, -1, 4750, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4745,
+ 4746, -1, -1, -1, -1, -1, -1, 4747,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4751, -1, -1, -1, 4752,
- -1, -1, -1, -1, -1, -1, -1, 4753,
- -1, -1, -1, -1, -1, 4754, -1, -1,
+ -1, -1, -1, -1, 4748, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4755,
- -1, 4756, -1, -1, -1, -1, -1, -1,
- 4757, -1, -1, -1, 4758, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4759, -1,
+ -1, 4749, -1, -1, -1, -1, -1, -1,
+ 4750, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4751, -1, -1, 4752,
+ -1, -1, -1, 4753, -1, -1, -1, -1,
+ -1, -1, 4754, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4755, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4756, -1, -1, 4757, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4760, -1, -1, -1, -1, -1,
- 4761, -1, -1, -1, -1, -1, 4762, -1,
- -1, -1, -1, -1, -1, 4763, 4764, -1,
- 4765, 4766, -1, -1, -1, 4767, -1, 4768,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4769, -1, -1, -1, -1, -1,
- 4770, -1, -1, -1, -1, -1, -1, -1,
- -1, 4771, -1, -1, 4772, -1, -1, 4773,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4774, -1, -1, -1, -1, 4775, -1, -1,
+ -1, -1, 4758, -1, -1, -1, -1, -1,
+ -1, 4759, -1, -1, -1, -1, -1, -1,
+ -1, 4760, -1, -1, -1, -1, -1, 4761,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4776, 4777, -1,
- -1, -1, -1, -1, -1, 4778, -1, -1,
- 4779, 4780, -1, -1, -1, -1, -1, 4781,
- -1, -1, -1, 4782, -1, 4783, -1, -1,
- 4784, -1, -1, 4785, -1, -1, -1, 4786,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4787, -1, -1, -1, -1, -1,
+ 4762, -1, -1, -1, -1, -1, -1, -1,
+ 4763, -1, -1, -1, -1, 4764, -1, -1,
+ -1, -1, -1, -1, 4765, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4766, 4767,
+ -1, 4768, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4769, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4770, 4771, -1, 4772,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4773, -1, -1, -1, 4774, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4775, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4776, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4777, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4778, -1, -1, -1, -1, 4779,
+ -1, -1, -1, 4780, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4781,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4782, -1, -1, 4783, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4784, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4785, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4786, -1, -1, 4787, -1,
-1, -1, -1, -1, -1, 4788, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4789,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4790, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4791, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4789, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4790, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4791, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, 4792, -1, -1, -1, -1, -1, 4793,
- 4794, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4795, -1,
- -1, 4796, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4794, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4795, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4796, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 4797, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 4798, -1,
+ -1, 4799, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4800, -1, -1, -1, -1, -1,
+ 4801, -1, 4802, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4803, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4799, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4800, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4801, -1, -1,
- 4802, -1, -1, -1, 4803, -1, -1, -1,
- -1, -1, -1, 4804, -1, 4805, -1, -1,
- -1, -1, -1, -1, 4806, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4804, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4805, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4806, -1,
-1, -1, -1, -1, 4807, -1, -1, -1,
- -1, -1, 4808, -1, 4809, 4810, 4811, -1,
- -1, -1, -1, -1, -1, 4812, -1, 4813,
- 4814, -1, -1, -1, -1, 4815, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4816, -1, -1, -1, -1, -1, -1,
- 4817, -1, -1, -1, 4818, -1, 4819, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4820,
- -1, 4821, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4822, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4808, 4809, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4823, -1, -1, -1,
- 4824, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4825, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4826, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4827, -1, -1,
- -1, -1, -1, -1, 4828, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4829, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4830, -1, -1, 4831, -1, -1,
+ -1, -1, -1, -1, 4810, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4811, -1, -1,
+ -1, -1, -1, -1, -1, 4812, 4813, -1,
+ -1, -1, -1, -1, 4814, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4832, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4833, -1, -1,
- -1, -1, -1, -1, -1, 4834, -1, -1,
+ -1, -1, -1, 4815, -1, -1, -1, -1,
+ 4816, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4817, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4818,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4835, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4836, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4837, -1, -1,
- -1, -1, -1, -1, -1, -1, 4838, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4839, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4840, -1,
+ -1, -1, 4819, -1, -1, -1, -1, -1,
+ -1, -1, 4820, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4841, -1, -1, 4842, -1, -1,
- -1, -1, -1, -1, 4843, -1, -1, -1,
- -1, -1, -1, -1, 4844, -1, 4845, -1,
- -1, -1, -1, -1, -1, 4846, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4847, -1, -1, -1, -1, -1, -1, -1,
+ 4821, 4822, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4823, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4824, -1, -1, -1, -1, -1, -1, 4825,
+ -1, -1, -1, -1, -1, -1, -1, 4826,
+ -1, -1, -1, -1, -1, 4827, -1, -1,
+ 4828, 4829, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4830, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4831, -1,
+ -1, -1, 4832, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4833, -1,
+ -1, -1, 4834, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4835, -1, -1, -1,
+ -1, -1, -1, -1, 4836, 4837, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4848, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4838, -1, -1, 4839, 4840,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4849, -1, -1,
- -1, 4850, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4851, -1, -1, -1, -1, -1,
- 4852, 4853, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4841, -1,
+ -1, -1, -1, -1, -1, -1, 4842, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4854, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4855, -1, -1,
+ -1, -1, -1, 4843, -1, 4844, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4845, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4856, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4846, -1, -1, 4847, -1, -1,
+ -1, -1, -1, -1, 4848, -1, -1, 4849,
+ -1, -1, -1, -1, 4850, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4851, -1,
+ -1, -1, -1, -1, -1, -1, 4852, 4853,
+ -1, -1, 4854, -1, -1, -1, -1, -1,
+ 4855, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4856, -1, -1, -1,
4857, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4858, -1, -1, -1,
- 4859, -1, -1, 4860, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4861, -1, -1, -1, -1, -1,
- 4862, -1, 4863, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4858, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4859,
+ -1, -1, -1, -1, -1, 4860, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4861,
+ 4862, 4863, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 4864,
- 4865, -1, -1, -1, -1, -1, 4866, -1,
- -1, -1, 4867, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4865, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4866, -1, -1, -1, -1, 4867, -1,
+ -1, -1, -1, -1, -1, -1, 4868, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4869, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4870,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4868, -1, -1, -1, -1, -1, -1, 4869,
- -1, -1, -1, -1, 4870, 4871, 4872, -1,
- 4873, -1, -1, -1, 4874, -1, -1, -1,
- -1, -1, -1, -1, -1, 4875, -1, -1,
- 4876, -1, -1, 4877, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4878, -1, -1,
+ -1, -1, -1, -1, 4871, -1, 4872, -1,
+ -1, -1, 4873, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4874, 4875, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4879, 4880, -1, -1,
- 4881, -1, 4882, -1, -1, -1, -1, -1,
- -1, 4883, -1, -1, -1, 4884, -1, -1,
- -1, -1, -1, 4885, -1, -1, -1, -1,
+ -1, -1, -1, 4876, -1, -1, 4877, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4886, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4878, -1, -1, -1, -1, 4879,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4880, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4881, -1,
+ -1, 4882, 4883, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4884, -1, 4885,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4886, -1, -1, -1, -1,
-1, -1, -1, -1, 4887, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4888, -1, -1, -1, -1,
+ -1, -1, -1, 4889, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4890, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4891, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4892,
+ -1, -1, 4893, -1, -1, -1, -1, -1,
+ -1, -1, 4894, -1, -1, -1, -1, -1,
+ 4895, -1, -1, -1, -1, -1, -1, -1,
+ 4896, -1, -1, -1, -1, -1, 4897, 4898,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4899, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4900, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4901, 4902,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4888, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4889, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4903, -1, -1, -1, 4904, -1,
+ -1, -1, -1, -1, -1, 4905, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4906, 4907, -1, -1, 4908, -1,
+ -1, -1, -1, 4909, -1, -1, -1, 4910,
+ -1, -1, 4911, -1, -1, -1, -1, 4912,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4913, -1, -1, 4914, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4890, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4891,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4892, 4893, -1, -1, -1, -1, -1, 4894,
- -1, 4895, -1, 4896, -1, -1, 4897, 4898,
- -1, -1, -1, -1, -1, -1, -1, 4899,
- -1, 4900, -1, 4901, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4902, -1, 4903, 4904, -1, -1, 4905, -1,
- -1, -1, -1, -1, -1, -1, 4906, -1,
- -1, -1, -1, -1, -1, -1, 4907, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4908, -1, -1, -1, -1, 4909,
- -1, -1, -1, -1, -1, -1, 4910, -1,
- 4911, -1, -1, -1, -1, -1, -1, -1,
- -1, 4912, 4913, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4914,
- 4915, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4916, -1, 4917, -1, 4918, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4915, -1, -1, 4916,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4919, -1, -1, -1, -1, -1, 4920,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4921,
- -1, -1, -1, -1, 4922, -1, -1, -1,
- -1, 4923, -1, -1, -1, -1, 4924, -1,
- -1, -1, 4925, -1, -1, -1, -1, -1,
- -1, -1, -1, 4926, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4917, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4918, -1, -1, -1, -1,
+ -1, -1, -1, 4919, 4920, -1, -1, -1,
+ -1, -1, 4921, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4922, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 4923, -1, -1, -1, -1, 4924, -1, 4925,
+ -1, -1, -1, -1, -1, 4926, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 4927, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4928, -1, -1,
+ -1, -1, -1, -1, 4929, -1, 4930, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4931, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4928, -1, -1, -1, -1, -1, -1,
- -1, -1, 4929, -1, -1, -1, -1, 4930,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4931, 4932, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4933, -1, -1,
- -1, -1, -1, -1, 4934, -1, -1, -1,
+ -1, -1, -1, 4932, -1, 4933, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4934, -1, -1, -1, -1, -1,
-1, -1, -1, 4935, -1, -1, -1, -1,
- -1, -1, -1, -1, 4936, -1, -1, -1,
+ -1, 4936, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4937, -1, -1, -1, 4938, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4939,
+ -1, 4940, -1, -1, -1, -1, -1, -1,
+ -1, 4941, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4937, -1,
+ -1, -1, -1, -1, -1, -1, 4942, -1,
+ -1, -1, -1, -1, -1, 4943, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4938, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4939, -1, -1, -1, -1, -1,
- -1, 4940, 4941, -1, -1, -1, -1, 4942,
- -1, 4943, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4944, -1,
- -1, -1, -1, -1, 4945, 4946, -1, -1,
- -1, -1, 4947, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4944, 4945, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4946,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4947, -1, -1, -1,
-1, -1, 4948, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4949, -1, -1,
- -1, -1, -1, -1, -1, -1, 4950, -1,
- -1, -1, -1, -1, -1, -1, 4951, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4952, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4953, -1, -1,
- -1, 4954, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4955, -1, -1, -1, -1,
- -1, 4956, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4957, -1, -1, -1, -1, -1, -1, -1,
- -1, 4958, -1, -1, 4959, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4949, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4950, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4960, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4951, -1, 4952, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4961, -1, -1, -1, -1, -1, -1, -1,
- -1, 4962, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4953, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4963, -1, -1, -1, -1,
- -1, -1, -1, 4964, -1, -1, -1, -1,
- -1, -1, 4965, -1, 4966, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 4954, -1, -1, -1, -1, 4955,
+ -1, -1, -1, -1, -1, 4956, -1, 4957,
+ -1, -1, -1, 4958, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4959,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4967, -1, 4968, -1, -1, -1, -1, -1,
- -1, -1, 4969, -1, -1, -1, -1, -1,
+ 4960, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4961, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4970, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4971, -1, 4972, -1, -1,
- -1, -1, -1, -1, -1, 4973, -1, -1,
- -1, -1, -1, -1, -1, 4974, -1, 4975,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4976, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4977, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4962, -1, -1, -1, -1, 4963, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4964, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4965, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4966, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 4978, 4979, -1, -1,
- 4980, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4981, -1, -1, 4982, -1,
- -1, -1, -1, -1, 4983, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 4984, -1, -1, -1, -1, 4985, -1,
+ 4967, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4968,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4986, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4987,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4969,
+ -1, -1, -1, -1, -1, 4970, -1, -1,
+ -1, -1, -1, -1, -1, 4971, -1, 4972,
+ 4973, -1, -1, -1, -1, -1, -1, 4974,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 4988, -1, -1, -1, -1,
- -1, -1, -1, -1, 4989, -1, -1, 4990,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 4975, -1, -1, 4976, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4977, 4978, -1,
+ -1, -1, -1, -1, -1, -1, 4979, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 4991, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 4980, -1, -1,
+ -1, -1, -1, -1, 4981, -1, -1, -1,
+ 4982, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 4992, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 4993,
- -1, -1, -1, -1, -1, -1, -1, 4994,
- -1, -1, -1, -1, -1, -1, 4995, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 4996, -1,
- -1, -1, -1, -1, -1, 4997, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4983,
+ -1, -1, -1, -1, -1, 4984, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 4998, -1, 4999, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5000, -1,
- -1, -1, -1, 5001, -1, -1, -1, -1,
- 5002, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 4985,
+ -1, -1, -1, -1, -1, 4986, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4987, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5003, -1, -1, -1,
- 5004, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5005,
+ -1, -1, -1, -1, -1, -1, -1, 4988,
+ 4989, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5006, -1, -1, -1, -1, 5007, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5008, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5009, -1, -1, 5010, -1,
+ 4990, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4991, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 4992, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5011, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4993, 4994, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5012, 5013, -1, -1, -1, -1,
+ 4995, -1, -1, -1, 4996, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4997, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4998, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 4999, -1, -1, -1, -1,
+ 5000, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5001, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5014, 5015, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5002, -1, -1, -1, -1, 5003,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5016, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5017, -1, -1, -1,
- -1, 5018, -1, -1, 5019, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5020, -1, -1, -1,
- -1, 5021, -1, -1, -1, -1, -1, -1,
- -1, 5022, -1, -1, -1, 5023, -1, -1,
+ -1, -1, -1, -1, 5004, -1, 5005, -1,
+ -1, -1, -1, -1, 5006, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5024, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5007, -1, -1, -1, 5008, -1, -1,
+ -1, -1, 5009, 5010, -1, -1, -1, -1,
+ -1, -1, -1, 5011, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5012, -1, -1, -1, 5013,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5025, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5026, -1,
- -1, -1, -1, 5027, -1, 5028, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5029,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5030, -1, -1, -1, -1, -1,
- -1, 5031, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5032,
+ -1, -1, -1, 5014, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5015, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5016, -1, -1, -1,
+ -1, -1, 5017, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5033, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5018, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5019,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5034, 5035,
+ -1, -1, -1, -1, 5020, -1, -1, -1,
+ 5021, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5036, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5037, -1,
- -1, -1, -1, 5038, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5022, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5039, -1, -1, -1, -1, 5040, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5023, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5024, 5025, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5026, -1, -1, 5027,
+ -1, -1, 5028, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5029, -1, -1, -1, 5030, -1, -1, -1,
+ -1, -1, -1, -1, 5031, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5041, -1, -1, -1,
- 5042, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5032, -1, 5033, -1, 5034, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5035, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5043, -1, -1,
+ -1, -1, -1, -1, 5036, -1, 5037, -1,
+ -1, -1, -1, -1, -1, 5038, -1, -1,
+ -1, -1, 5039, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5040,
+ -1, -1, -1, 5041, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5044,
+ 5042, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5043, -1,
+ -1, -1, -1, -1, -1, 5044, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5045, -1, -1,
- -1, -1, -1, 5046, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5045,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5046, -1,
+ -1, -1, -1, 5047, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5047, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
5048, -1, -1, -1, -1, -1, -1, -1,
- -1, 5049, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5049, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 5050, -1, -1,
+ -1, 5051, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5052, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5051, -1, -1,
- 5052, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5053,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5054, -1, -1,
+ -1, -1, -1, -1, 5053, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5054, -1, -1, -1, -1, -1, -1, 5055,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5055, -1, -1, 5056, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5057, -1, -1,
- -1, 5058, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5056, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5059, -1, -1, -1, -1,
- -1, -1, -1, 5060, -1, -1, -1, -1,
- -1, -1, -1, 5061, -1, -1, -1, -1,
- -1, -1, 5062, -1, -1, -1, 5063, -1,
- -1, -1, -1, -1, -1, -1, 5064, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5065,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5066, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5057, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5058, -1, -1, -1, -1, -1,
+ -1, 5059, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5067,
- -1, -1, -1, -1, -1, -1, 5068, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5069, -1, -1, -1, 5070, -1,
+ -1, -1, -1, -1, -1, 5060, 5061, -1,
+ -1, -1, -1, -1, -1, 5062, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5071, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5072, -1, 5073, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5074, -1, -1, -1, -1, -1,
- 5075, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5063, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5064, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5065, -1,
+ -1, -1, -1, -1, 5066, -1, -1, -1,
+ -1, 5067, -1, -1, -1, -1, -1, -1,
+ 5068, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5069, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5070, -1, -1, -1, -1, -1,
+ 5071, -1, -1, -1, 5072, -1, -1, -1,
+ -1, -1, 5073, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5076, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5074, 5075,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5077, -1, -1, -1, -1, -1, 5078, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5079, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5076, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5077, -1, 5078, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5080, -1, -1, -1, -1,
+ 5079, 5080, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5081, -1, -1, -1, -1,
- -1, 5082, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5083, -1, -1, -1,
+ -1, -1, -1, -1, 5081, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5084, -1, 5085, -1, -1, -1, -1,
- -1, -1, -1, 5086, -1, -1, -1, -1,
- -1, 5087, -1, -1, 5088, -1, -1, -1,
+ -1, -1, -1, 5082, -1, -1, -1, -1,
+ -1, 5083, -1, -1, -1, -1, -1, -1,
+ 5084, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5089, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5085, -1, 5086,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5087,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5090,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5091, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5088, -1, -1, 5089, -1, -1, -1, -1,
+ 5090, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5091, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 5092, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 5093, -1, -1,
- -1, -1, 5094, -1, 5095, -1, -1, -1,
- -1, 5096, 5097, -1, -1, -1, -1, -1,
- -1, -1, -1, 5098, -1, -1, 5099, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5100, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5101, -1, 5102, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5103, -1,
+ -1, -1, 5094, 5095, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5096, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5097, -1, -1, -1, 5098, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5099, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5104, 5105, -1, -1, 5106, -1,
- -1, -1, -1, -1, -1, 5107, -1, -1,
+ -1, -1, -1, -1, -1, 5100, -1, -1,
+ 5101, -1, -1, -1, 5102, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5103, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5108, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5109, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5104, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5105, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5106, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5110, 5111, 5112, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5113, -1, -1, -1, -1, -1, 5114,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5107, 5108, 5109, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5115, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5110, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5111, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5112, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5113, 5114, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5115, -1, -1, -1,
-1, -1, 5116, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 5117, -1, -1, -1,
- 5118, -1, -1, -1, -1, -1, -1, 5119,
- -1, -1, -1, -1, -1, 5120, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5121, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5122, -1, -1, -1,
+ -1, 5118, -1, -1, 5119, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5120,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5121, -1, -1, -1,
+ -1, -1, 5122, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5123,
+ -1, -1, -1, 5124, -1, -1, -1, 5125,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5126,
+ 5127, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5128, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5129, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5123, -1, -1, -1, -1, -1, 5124,
- -1, -1, -1, 5125, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5126, -1, -1, 5127,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5130, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5131, 5132, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5128, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5129, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5130, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5133, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5134,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5131, -1, -1,
- -1, -1, -1, -1, -1, 5132, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5133, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5134, -1, -1, -1, -1, -1, -1,
-1, 5135, -1, -1, -1, -1, -1, -1,
- 5136, -1, 5137, -1, -1, 5138, -1, -1,
- -1, -1, -1, 5139, -1, 5140, -1, -1,
- 5141, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5136, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5137, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5138, 5139, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5140, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5141, -1, 5142, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5143, -1, -1, 5144, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5145,
+ 5146, -1, -1, -1, -1, -1, 5147, -1,
+ -1, 5148, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5142, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5143, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5144, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5149, -1, -1, -1, -1,
+ 5150, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5145, -1, -1, -1,
- -1, -1, -1, -1, 5146, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5151, -1,
+ -1, -1, -1, 5152, -1, -1, -1, -1,
+ -1, -1, 5153, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5147, 5148, -1, -1, -1,
- -1, -1, 5149, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5150, 5151, -1, -1, -1, -1,
- 5152, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5153, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5154,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5155,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5154, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -29926,37 +32659,34 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5156, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5157, -1, -1, -1, -1,
- -1, -1, -1, -1, 5158, -1, -1, -1,
- 5159, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5160, -1, -1,
+ -1, -1, -1, 5155, -1, -1, -1, -1,
+ -1, 5156, -1, -1, -1, -1, -1, -1,
+ 5157, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5158, -1, 5159, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5160, -1, 5161,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5161, -1, -1,
- 5162, -1, -1, -1, -1, -1, -1, -1,
- -1, 5163, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5164, -1, -1, -1, -1,
+ 5162, -1, -1, -1, -1, -1, 5163, 5164,
+ -1, -1, -1, 5165, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5165, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5166, -1, -1, -1, -1, -1,
+ 5167, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5166, -1, -1, -1, -1, -1, -1,
- 5167, -1, 5168, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5169, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5170, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5168, -1, 5169,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5171, -1, -1, -1, -1, -1,
+ -1, -1, 5170, -1, -1, -1, -1, 5171,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5172, -1, -1, -1, -1, -1, 5173, -1,
+ -1, 5174, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5172, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5173, -1, -1, -1,
- 5174, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -29964,141 +32694,152 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 5175, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5176, -1, -1, -1, -1, -1,
- -1, -1, 5177, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5176, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5177, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5178,
- -1, 5179, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5180, 5181, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5182, 5183, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5184, 5185, -1, -1, -1, 5186,
+ -1, -1, -1, -1, -1, -1, 5178, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5179, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5180, -1, -1, -1, -1,
+ -1, -1, -1, 5181, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5182, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5183,
+ -1, -1, 5184, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5185, -1, -1, -1, 5186,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5187, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5187,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5188, -1, -1,
- -1, -1, 5189, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5188, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5189,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, 5190, -1,
- -1, -1, -1, -1, 5191, -1, 5192, -1,
+ -1, -1, 5191, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5192, 5193, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5194,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5193, -1, -1,
- 5194, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5195, -1,
+ 5195, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5196, -1, -1,
- 5197, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5198, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5196,
+ -1, -1, 5197, -1, -1, 5198, -1, -1,
+ -1, -1, -1, -1, -1, 5199, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5199, -1, -1, -1, -1, -1, -1,
+ -1, 5200, -1, -1, -1, -1, -1, -1,
+ 5201, -1, -1, -1, -1, 5202, -1, -1,
+ 5203, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5200, -1, -1, 5201, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5202, -1, -1, -1, -1, -1, -1, 5203,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 5204, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5205,
+ -1, -1, -1, -1, -1, 5205, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5206, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5207,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5206, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5207, -1,
-1, -1, 5208, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5209,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5209, -1, 5210, -1,
- -1, 5211, -1, -1, -1, -1, -1, -1,
- -1, 5212, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5213, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5210, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5214, -1, 5215, -1, -1, -1, -1, -1,
- 5216, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5217, -1, -1, -1, -1,
- -1, -1, 5218, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5219, -1,
+ -1, -1, -1, 5211, -1, -1, 5212, -1,
+ -1, -1, 5213, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5214, 5215, -1, 5216, -1, -1, -1,
+ 5217, -1, -1, -1, -1, -1, -1, 5218,
+ -1, -1, 5219, 5220, -1, 5221, -1, -1,
+ -1, -1, -1, -1, -1, 5222, -1, -1,
+ -1, -1, 5223, -1, -1, -1, -1, -1,
+ -1, -1, 5224, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5225, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5226, -1, 5227, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5228, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5220, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5221, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5222, 5223, -1,
- -1, -1, -1, -1, -1, 5224, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5229, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5230, -1, -1, -1, -1, 5231,
+ -1, -1, 5232, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5233,
+ -1, -1, -1, -1, -1, -1, -1, 5234,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5225, -1, -1,
+ -1, -1, 5235, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5236, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5226, -1, 5227, 5228, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5229, -1,
- -1, -1, -1, -1, -1, -1, 5230, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5231,
- -1, -1, -1, -1, -1, 5232, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5237, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5238, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5233, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5239, -1, -1, -1, 5240, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5234, -1, -1, -1, -1, 5235,
+ -1, -1, -1, -1, -1, -1, 5241, -1,
+ -1, -1, -1, -1, -1, -1, 5242, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5236, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5237, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5238, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5239,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5240, -1,
+ -1, -1, -1, -1, -1, -1, 5243, -1,
+ -1, -1, -1, -1, -1, 5244, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -30106,127 +32847,107 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5241, -1,
+ -1, 5245, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5242, -1, -1, -1, -1, -1, -1,
+ 5246, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5243, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5244, -1,
- -1, -1, -1, 5245, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5246, -1,
- 5247, -1, -1, -1, -1, -1, -1, 5248,
- -1, -1, -1, -1, -1, 5249, -1, -1,
- -1, -1, -1, -1, -1, 5250, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5247, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5251, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5248, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5252, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5253, -1, -1, -1, -1, -1,
- -1, 5254, -1, -1, -1, -1, -1, -1,
+ -1, 5249, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5250, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5255, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5256, -1, -1, -1,
- -1, -1, 5257, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5258,
- -1, -1, -1, -1, -1, -1, -1, 5259,
- -1, 5260, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5251, -1,
+ -1, -1, -1, -1, 5252, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5261, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5262, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5263, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5264, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5265, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5266, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5267,
- 5268, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5269, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5270,
- -1, 5271, -1, -1, -1, -1, -1, 5272,
- -1, -1, -1, -1, -1, 5273, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5253,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5274, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5254, -1, -1, -1, -1, 5255,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5275, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5276, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5277, -1, -1, 5278, -1, -1,
+ -1, -1, -1, 5256, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5279, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5280, -1, 5281,
+ -1, -1, -1, -1, 5257, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5258, -1,
+ -1, 5259, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5260,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5282, -1, -1,
+ -1, -1, -1, 5261, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5262, 5263, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5264, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5265, -1, 5266, -1, -1, 5267,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5268, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5269, -1, -1, -1,
+ -1, -1, 5270, -1, 5271, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5283, -1, -1,
- -1, -1, 5284, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5272, -1, -1, -1,
+ 5273, -1, -1, -1, 5274, -1, -1, -1,
+ 5275, -1, -1, -1, -1, -1, -1, 5276,
+ -1, -1, -1, -1, 5277, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5285, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5286, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5287, -1, -1, -1, -1, 5288,
- -1, -1, -1, -1, -1, -1, -1, 5289,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5290, 5291, -1, -1, -1, -1, 5292,
- 5293, -1, -1, -1, 5294, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5295, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5278, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5296, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5279,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5297, -1, -1, -1,
+ -1, 5280, -1, 5281, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5298, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5282,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5283, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5299, -1, -1, -1, -1,
- -1, -1, -1, -1, 5300, -1, -1, -1,
+ -1, -1, -1, 5284, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5301, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5285, -1, -1, -1, -1, 5286, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -30234,741 +32955,770 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5287, -1, -1, -1, -1, -1,
+ -1, 5288, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5302, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5289,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5290, -1, 5291,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5292, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5293, -1, 5294, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5295,
+ -1, -1, -1, 5296, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5303, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5304, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5297, -1,
+ -1, -1, -1, -1, -1, -1, 5298, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5299, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5300, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5305, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5301, -1, -1, -1, -1, -1, 5302, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5303, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5304, -1, -1, -1, 5305, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5306, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5306, -1, 5307, -1, -1, -1, -1, 5308,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5309, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5310, -1, -1, -1, -1, -1, -1, -1,
- 5311, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5312, -1, -1, -1,
+ -1, -1, -1, 5307, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5313, -1, 5314, -1, -1, -1, -1,
- 5315, -1, -1, -1, -1, -1, -1, 5316,
- -1, -1, -1, -1, 5317, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5318, -1, -1, -1, -1, -1,
+ -1, 5308, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5319, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5309, -1, -1, -1, -1,
+ -1, -1, 5310, -1, -1, -1, -1, 5311,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5312, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5320, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5321, -1,
+ -1, -1, -1, -1, 5313, -1, -1, 5314,
+ -1, -1, 5315, -1, -1, -1, -1, -1,
+ 5316, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5317, -1, -1, -1, -1, -1, -1,
+ -1, 5318, -1, -1, -1, -1, -1, -1,
+ 5319, -1, -1, -1, -1, -1, -1, 5320,
+ -1, -1, 5321, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5322, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5322, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5323, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5323, -1, -1,
5324, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5325, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5325, -1, -1, 5326, -1,
- -1, -1, 5327, -1, -1, -1, -1, -1,
- -1, -1, 5328, 5329, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5330,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5331,
- -1, 5332, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5333, -1, -1, -1, -1, -1, 5334, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5335, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5336,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5326, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5327, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5328, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5329, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5337, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5338, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5339,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5330, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5340, -1, -1, -1, 5341,
- -1, -1, -1, -1, -1, -1, -1, 5342,
+ -1, -1, -1, 5331, -1, -1, -1, -1,
+ -1, -1, -1, 5332, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5333, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5334, -1,
+ -1, -1, -1, -1, 5335, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5343, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5344,
+ -1, -1, -1, -1, -1, 5336, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5345, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5346, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5347, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5337,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5338, -1, 5339, -1, -1,
+ -1, -1, 5340, -1, -1, -1, -1, 5341,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5342, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5348, -1, 5349, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5350,
- -1, -1, -1, -1, -1, 5351, -1, -1,
- -1, -1, -1, -1, 5352, -1, 5353, -1,
- -1, -1, -1, 5354, -1, -1, -1, -1,
+ -1, -1, -1, 5343, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5355, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5344, -1, -1, 5345, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5356, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5357, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5358, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5359, -1, -1, -1, -1, -1,
- 5360, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5361, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5346, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5362, -1, -1, -1,
- -1, -1, 5363, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5347, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5364, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5365, -1, -1, -1, -1, -1,
- 5366, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5367, -1, -1, -1,
+ -1, -1, -1, -1, 5348, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5349, -1, -1, -1, -1, -1, 5350,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5351,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5352, -1, -1, -1, -1,
+ -1, 5353, -1, -1, 5354, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5355, -1, -1, 5356, -1, -1,
+ -1, -1, -1, -1, -1, 5357, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5358, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5359, -1, -1, -1,
+ -1, -1, -1, -1, 5360, 5361, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5362, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5363, 5364, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5368, -1, 5369, -1, -1,
- -1, -1, -1, -1, 5370, -1, -1, -1,
+ -1, -1, -1, -1, 5365, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5366, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5367,
+ -1, -1, 5368, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5371, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5372,
- -1, -1, -1, -1, -1, -1, 5373, -1,
- -1, 5374, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5369, -1, -1, -1, -1, -1,
+ 5370, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5375, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5371, -1, -1,
+ -1, -1, -1, 5372, -1, -1, -1, -1,
+ -1, 5373, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5374, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5376, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5377, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5378, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5375, -1,
+ 5376, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5377, 5378, -1, -1, 5379, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5380, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5379, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5380,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, 5381, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5382, -1, -1, -1, -1,
- 5383, -1, 5384, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5385, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5382, -1, -1, -1, -1, -1,
+ -1, -1, 5383, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5386, -1, 5387, -1, -1,
+ -1, 5384, -1, -1, -1, -1, -1, -1,
+ 5385, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5388, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5386, -1, -1,
+ -1, 5387, -1, -1, -1, -1, -1, -1,
+ -1, 5388, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5389,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5389, -1, -1, -1,
+ -1, 5390, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5391, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5392,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5390, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5391,
+ 5393, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5392, 5393,
+ -1, -1, -1, -1, -1, 5394, -1, 5395,
+ 5396, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5394,
+ 5397, -1, -1, -1, 5398, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5395, -1,
- -1, -1, 5396, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5397,
+ -1, -1, -1, -1, -1, 5399, -1, -1,
+ -1, -1, -1, 5400, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5401,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5398, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5402,
+ -1, -1, -1, -1, -1, -1, -1, 5403,
+ -1, -1, -1, -1, -1, 5404, -1, 5405,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5399, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5406, -1, -1, -1,
+ -1, -1, -1, -1, 5407, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5400, -1, -1, -1, -1, -1, -1, -1,
+ 5408, -1, 5409, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5401, -1, -1, 5402, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5410,
+ -1, -1, -1, 5411, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5403, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5412,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5404, -1, -1, -1, 5405,
+ -1, -1, -1, 5413, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5414, -1, 5415, -1, -1, 5416, -1,
+ -1, -1, -1, -1, 5417, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5418, -1,
+ -1, -1, 5419, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5406, -1, -1, 5407, -1, -1,
- -1, 5408, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5409, -1, -1,
- -1, -1, -1, -1, -1, -1, 5410, -1,
+ -1, -1, 5420, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5421, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5411, 5412,
- -1, -1, -1, -1, -1, 5413, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5422,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5414, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5423, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5415, -1, -1,
- -1, -1, 5416, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5424,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5425, -1, 5426, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5417, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5418,
+ -1, -1, -1, -1, -1, -1, 5427, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5419, -1, -1, -1, -1, -1, -1,
+ -1, 5428, -1, -1, 5429, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5420, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5421, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5422, -1, -1,
+ -1, -1, -1, -1, -1, 5430, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5423, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5424, -1, 5425, -1, 5426, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5431, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5432, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5427,
- -1, 5428, -1, -1, 5429, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5430, -1, 5431, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5432,
-1, -1, -1, -1, 5433, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5434, -1, -1, -1, -1,
- -1, 5435, -1, 5436, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5437, -1, 5438, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5439, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5434, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5440, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5441, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5442,
+ -1, -1, -1, -1, -1, 5435, -1, -1,
+ -1, -1, 5436, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5443,
+ 5437, -1, -1, -1, -1, -1, -1, 5438,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5439,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5444,
- -1, -1, -1, 5445, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5446, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5447, -1, -1, -1, 5448,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5440, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5449, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5441, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5450, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5442, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5443, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5451, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5444, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5452, -1, 5453, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5454, -1, -1,
- -1, -1, -1, -1, 5455, -1, -1, 5456,
- 5457, -1, -1, 5458, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5459, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5460,
- 5461, -1, 5462, -1, -1, -1, -1, -1,
- -1, -1, 5463, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5464,
- -1, -1, -1, -1, -1, -1, -1, 5465,
- -1, -1, -1, -1, -1, -1, -1, 5466,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5467, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5445, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5446, -1, -1,
+ -1, -1, -1, 5447, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5468, -1, -1, -1,
- -1, -1, 5469, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5448, -1, -1, 5449, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5450, -1, -1, -1, -1, -1,
+ 5451, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5470, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5471, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5452, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5453, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5454, -1, -1, -1,
+ 5455, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5456,
+ -1, -1, -1, -1, 5457, -1, -1, -1,
+ -1, -1, 5458, -1, 5459, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5460, -1, -1, -1, -1, 5461, 5462,
+ -1, -1, -1, -1, -1, -1, -1, 5463,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5464,
+ -1, 5465, -1, -1, -1, -1, -1, 5466,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5472, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5467, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5468, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5469,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5470, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5473, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5474, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5471, 5472, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5475, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5473, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5474, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5476, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5477,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5478, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5475, -1, -1, -1, -1, -1, -1, 5476,
+ -1, -1, -1, -1, -1, 5477, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5478,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5479, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5479, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5480, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5481, -1, -1, -1, 5482, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5483,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5480, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5481, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5484, 5485, -1, -1, -1,
+ 5486, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5482, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5487, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5483, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5484, -1, -1, -1,
+ -1, -1, 5488, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5489, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5490,
+ -1, -1, -1, -1, -1, -1, -1, 5491,
+ -1, -1, -1, 5492, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5493, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5485, 5486, -1, 5487,
- -1, -1, -1, -1, -1, 5488, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5489, 5490,
- -1, -1, -1, -1, -1, 5491, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5492,
- -1, -1, -1, 5493, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5494, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5494, -1, -1, -1,
+ -1, -1, -1, -1, 5495, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5496, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5495, -1, -1,
- -1, -1, -1, -1, -1, -1, 5496, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5497,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5497, -1, -1,
- 5498, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5498, -1,
5499, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5500, 5501, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5500, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5501,
-1, -1, -1, -1, 5502, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5503,
+ -1, -1, -1, 5504, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5505, -1, -1, -1, -1, -1,
+ -1, 5506, -1, 5507, 5508, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5503, -1,
- 5504, -1, -1, -1, 5505, -1, -1, -1,
+ -1, -1, -1, 5509, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5510, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5506, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5511, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5512, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5513, -1,
+ 5514, -1, -1, -1, -1, 5515, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5516, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5507, 5508, -1,
- -1, -1, 5509, 5510, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5511, -1,
+ -1, -1, -1, -1, -1, 5517, -1, -1,
+ -1, -1, 5518, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5519, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5512, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5513,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5520, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5514, 5515, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5516, -1, -1, 5517, 5518,
+ -1, -1, 5521, 5522, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5523, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5524, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5525,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5519, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5520, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5526, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5527, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5521, -1, -1, -1, -1, -1, -1,
+ 5528, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5529, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5530, -1, -1, -1, 5531, -1, 5532,
+ -1, -1, -1, -1, 5533, -1, -1, -1,
+ -1, 5534, 5535, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5522, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5523, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5536, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5524, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5537, -1, -1, -1, 5538, -1,
+ 5539, 5540, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5525, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5526, -1, -1, -1, -1,
- -1, 5527, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5541, 5542, -1, -1,
+ -1, -1, -1, 5543, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5544, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5545, -1, -1,
+ -1, 5546, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5528, -1, -1,
+ -1, -1, 5547, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5548,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5529, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5530, -1, -1,
- 5531, -1, -1, -1, -1, 5532, -1, 5533,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5534,
- -1, -1, -1, -1, 5535, -1, -1, -1,
- -1, 5536, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5549, -1, -1,
+ -1, -1, -1, -1, -1, 5550, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5537, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5538, -1, 5539,
- 5540, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5551, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5552, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5541, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5542, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5553, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5554, 5555,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5543, -1, -1,
- -1, 5544, -1, -1, -1, -1, -1, -1,
- 5545, 5546, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5556, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5557, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5547, -1, -1, -1, -1, -1, -1, 5548,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5549, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5558, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5550, -1, -1, -1,
+ -1, -1, -1, -1, 5559, -1, -1, -1,
+ 5560, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5561, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5551, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5562, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5563,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5552, -1, -1, -1, -1, -1, 5553,
- -1, -1, -1, 5554, -1, -1, -1, -1,
- -1, -1, -1, -1, 5555, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5556, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5564, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5565, -1, 5566, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5557, -1, -1, -1, -1, -1, -1,
+ 5567, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5568, -1, -1, -1,
+ -1, -1, 5569, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5570, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5571,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5558, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5572,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5559, -1, -1, -1, -1, 5560, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5561, -1, -1, -1, -1,
+ -1, -1, 5573, -1, 5574, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5575, -1, -1, 5576, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5562, -1, -1, 5563, 5564,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5565, 5566, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5567, 5568,
- -1, -1, -1, -1, -1, 5569, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5570, -1, -1,
+ 5577, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5571, -1, -1, -1, -1, -1,
+ 5578, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5579, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5572, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5580, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5573, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5574, -1, -1, -1, 5575,
- -1, -1, -1, -1, -1, -1, 5576, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5581, -1, -1, -1, -1, 5582,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5577, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5578, -1, -1, -1,
- -1, -1, -1, -1, -1, 5579, -1, 5580,
- -1, -1, 5581, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5582, 5583, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5584, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5585, -1, -1, -1, -1, -1, -1, -1,
+ 5583, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5584, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5585, -1, -1, -1,
+ -1, -1, 5586, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5587, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5586,
- -1, 5587, 5588, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5589, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5590, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5591,
+ -1, -1, 5588, -1, -1, 5589, -1, -1,
+ -1, -1, -1, -1, 5590, -1, -1, -1,
+ -1, -1, -1, 5591, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5592, -1, -1,
- -1, -1, 5593, -1, -1, 5594, -1, -1,
- -1, -1, 5595, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5592, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5593, -1, -1,
+ 5594, -1, -1, -1, -1, -1, -1, 5595,
+ -1, -1, -1, -1, 5596, -1, -1, -1,
+ -1, -1, -1, -1, 5597, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5596, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5597, -1, -1, 5598, -1, -1, 5599,
+ -1, -1, -1, -1, -1, -1, 5598, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5599, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5600, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5601, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5602, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5603, -1,
- -1, -1, -1, -1, -1, 5604, -1, -1,
- -1, -1, -1, 5605, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5600, -1,
+ 5601, -1, 5602, -1, -1, -1, -1, 5603,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5604, -1, 5605, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -30977,16 +33727,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5606, 5607, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5608, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5606, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5607, -1, -1, 5608,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5609, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5609, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -30994,173 +33744,176 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5610, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5611, 5612, -1, -1,
+ -1, -1, -1, -1, 5610, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5611, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5612, -1, -1, -1, -1,
+ -1, 5613, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5614, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5615, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5613, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5616,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5614, -1, -1, -1, -1, -1, -1,
- -1, 5615, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5616,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5617, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5617, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5618,
+ -1, -1, -1, 5618, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5619, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5619, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5620, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5620, -1, -1, -1,
+ -1, 5621, -1, -1, -1, -1, 5622, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5621, 5622, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5623, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5623,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5624, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5624, -1,
+ -1, -1, -1, -1, 5625, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5625, -1, 5626, -1, -1,
+ -1, -1, -1, -1, -1, 5626, -1, -1,
+ -1, -1, -1, -1, 5627, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5627, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5628, -1, -1, -1, -1,
+ 5629, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5630,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5631, 5632, -1, -1, -1, -1, 5633,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5628, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5634, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5629, 5630, -1, -1, -1,
- -1, -1, -1, -1, 5631, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5635, -1, -1, -1, -1, 5636,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5632, -1, -1, -1, -1, -1,
+ -1, -1, 5637, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5633,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5634, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5638, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5639, -1, -1, -1, -1, -1, 5640,
+ -1, -1, 5641, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5642,
+ -1, -1, -1, -1, 5643, -1, -1, -1,
+ 5644, -1, -1, -1, -1, -1, 5645, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5635, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5636, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5637, -1, -1, -1, -1, 5638,
+ -1, -1, -1, -1, -1, 5646, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5647, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5639, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5640,
+ -1, -1, 5648, -1, 5649, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5650,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5641, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5651, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5642, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5652,
+ -1, -1, -1, -1, 5653, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5643, 5644,
- -1, 5645, -1, -1, -1, -1, -1, -1,
- -1, -1, 5646, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5654,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5647, -1, -1, -1,
+ 5655, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5656, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5657, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5648, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5649, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5650, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5651, -1, -1, -1, -1,
+ -1, -1, -1, 5658, -1, -1, -1, -1,
+ -1, -1, 5659, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5652, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5660, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5661, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5662, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5653, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5654, -1, -1,
+ 5663, -1, -1, 5664, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5665, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5666, -1, -1, -1, -1, -1, 5667,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5668, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5669, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5655, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5656, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5657, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5658, 5659, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5670, -1, 5671, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5660, -1, -1,
- -1, 5661, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5662, -1, -1, -1,
+ -1, -1, -1, -1, 5672, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5663, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5664, -1, -1,
- -1, -1, -1, -1, 5665, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5666, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5667,
- -1, -1, -1, -1, 5668, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5673, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5674, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31168,38 +33921,30 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5669, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5670, -1, -1, -1, -1, -1,
- 5671, -1, -1, -1, 5672, -1, -1, -1,
- -1, -1, -1, 5673, -1, -1, -1, -1,
- -1, 5674, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5675,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5675, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5676, 5677, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5676, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5678, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5677,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5678, -1,
+ -1, -1, -1, 5679, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5679, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5680, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5681, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5682,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5683, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5684, -1, -1, -1, -1,
+ -1, -1, 5680, -1, -1, -1, -1, 5681,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31211,45 +33956,78 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5682, -1, -1, -1,
+ -1, -1, -1, 5683, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5684, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 5685, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5686, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5686, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5687, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5688, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5689, -1, -1, -1, -1, -1,
+ -1, 5690, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5687, -1, -1, 5688, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5689, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5690, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5691, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5691, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 5692, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5693, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5693, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5694, -1, -1,
+ 5695, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5696, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5694,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31257,13 +34035,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5695, -1, -1, -1, -1,
- 5696, -1, -1, -1, -1, -1, -1, -1,
- -1, 5697, -1, -1, -1, -1, -1, 5698,
- 5699, -1, -1, -1, -1, -1, -1, -1,
- -1, 5700, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5701, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31273,21 +34045,25 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5702, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5697, -1, -1, -1, -1, 5698, -1, -1,
+ -1, 5699, -1, -1, -1, -1, -1, 5700,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5701, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5702,
+ -1, -1, 5703, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5704, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5703,
- -1, 5704, -1, -1, 5705, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5705, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5706,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5706, -1, -1, -1, -1, 5707, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31295,56 +34071,99 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5708,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5709, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5710, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5707, 5708, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5709,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5710, -1, -1,
-1, -1, -1, -1, -1, 5711, -1, -1,
+ -1, 5712, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5713, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5712, -1, -1,
- 5713, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5714,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5715, -1, -1, -1, 5716, -1,
+ -1, -1, 5714, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5715, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5716, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, 5717, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5718, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5718, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, 5719, -1, -1, -1, -1, -1, -1,
- -1, 5720, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5721, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5720, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5721, -1,
-1, -1, -1, -1, 5722, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5723, -1, -1, -1,
- -1, 5724, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5723, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5724, -1, -1, -1,
+ -1, -1, 5725, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5726,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5727, -1, -1, -1, -1, -1, -1,
+ -1, 5728, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5725, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31352,13 +34171,13 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5726, -1, -1, -1,
+ -1, -1, -1, 5729, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5727, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5730, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31366,7 +34185,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5728, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5731, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31374,18 +34193,17 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5729, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5732, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5730, -1, -1, -1, -1, -1,
- 5731, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5732, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5733,
+ -1, 5733, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5734, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5735,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31398,20 +34216,19 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5734, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5735,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5736, -1, 5737, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5738, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5736, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5737, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5738,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31419,8 +34236,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5739, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5740, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5741, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31428,13 +34248,13 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5742, -1, -1, -1, 5743, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5739, 5740, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5741, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5744, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31445,55 +34265,70 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5745, -1, -1, -1, -1, -1, -1, 5746,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5747,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5742,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5743, -1, -1, -1, -1, -1, -1,
- 5744, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5745, -1,
- -1, -1, -1, -1, -1, 5746, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5748, -1, -1, -1, -1, -1, -1, -1,
+ 5749, -1, -1, -1, -1, 5750, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5747, -1, 5748, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5749, -1, -1, -1,
- -1, -1, 5750, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5751, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5752, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5751, 5752, -1, -1,
+ -1, 5753, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5754, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5753,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5754, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5755, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5755,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 5756,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5757, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5758, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5759, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5757, -1, 5758, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5759, -1, -1, -1,
+ -1, 5760, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5761, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5762, -1, -1, -1, -1, -1, -1,
+ -1, 5763, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5764, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5765, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5766,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5767, -1, -1, -1, -1, -1, -1,
+ -1, 5768, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31501,18 +34336,19 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5769, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5770, -1,
+ -1, -1, -1, -1, -1, 5771, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5760, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5772,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5761, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5762, -1, 5763,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31521,107 +34357,128 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5764, -1, -1,
- -1, -1, 5765, -1, -1, -1, -1, -1,
- -1, -1, 5766, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5767, -1, -1, -1, -1, -1,
- 5768, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5769,
- 5770, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5773, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5771, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5772, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5773, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5774, -1, -1, -1, -1, -1, -1,
- -1, 5775, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5776, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5774, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5775,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5777,
+ -1, -1, 5776, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5778, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5779, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5780, -1, -1, -1, -1,
- -1, -1, -1, 5781, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5782, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5783, -1, -1,
+ -1, -1, -1, 5777, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5778, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5784, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5779, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5780,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5781, -1, -1, 5782, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5783, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5785, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5784, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5785, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, 5786,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5787, 5788, -1, -1, -1, -1, -1, 5789,
+ -1, -1, -1, -1, -1, -1, -1, 5790,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5791, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5787, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5788, -1, -1, -1,
- -1, 5789, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5790, -1, 5791, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5792, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5793, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5792, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5793, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5794, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5795, -1, -1, -1, -1, -1, -1,
+ 5796, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5797, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5794, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31629,42 +34486,38 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5795, 5796, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5797, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 5798, -1, -1, -1, -1, -1,
+ -1, 5799, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5800, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5799, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5800, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5801, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5802, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5803, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5804, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5801, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5805, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5806, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31674,9 +34527,26 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5807, -1, -1, 5808, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5802, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5803, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5804, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31687,44 +34557,41 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5809, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5810, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5811, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5812, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5813, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5805, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5806, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5814, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5815, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5807, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5808, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5809, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5816,
- -1, -1, -1, -1, -1, -1, 5817, -1,
+ -1, -1, -1, 5810, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31732,40 +34599,41 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5818, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5811, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5819, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5820, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5812, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5813, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5821, -1, -1, -1,
- -1, -1, 5822, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5823,
+ -1, -1, -1, -1, -1, -1, -1, 5814,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5824,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5815, 5816, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5817, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5825, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5818, -1, -1, -1,
+ -1, -1, 5819, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5820, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5821,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5826, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31779,7 +34647,19 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5827, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5822, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5823, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5824, -1, -1,
+ -1, 5825, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5826, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5827,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31793,11 +34673,10 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5829, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5830, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5829, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31805,14 +34684,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5831, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5830,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5831, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5832, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31821,17 +34702,15 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5832, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5833, -1, -1,
- 5834, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5833,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31839,50 +34718,67 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5835, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5836, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5837, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5834, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5838,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5835, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5839,
+ -1, -1, 5836, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5837, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5840, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5841, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5838, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5839, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5840,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5842, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5843,
- 5844, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5845, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5846,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5847, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5848, -1, 5849, 5850, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5841,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31890,16 +34786,24 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5851, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5852, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5842, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5843, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31910,6 +34814,15 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5844, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5845, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31919,6 +34832,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5846, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31929,18 +34843,22 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5847, -1, -1, -1, -1, -1, -1,
+ -1, 5848, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5853, -1, -1, -1, -1,
- -1, -1, 5854, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5849,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5850, -1, -1, 5851,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5852, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5853, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5854, -1, -1, -1, -1, 5855,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5855, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31952,8 +34870,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5856, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5856, -1, -1, -1,
-1, -1, -1, 5857, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31964,25 +34885,22 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5858, -1, -1,
+ -1, 5858, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5859, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5860, -1, -1,
- -1, 5861, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5862, -1, -1, -1, -1, -1, -1,
- -1, -1, 5863, -1, 5864, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5859, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5860, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -31990,58 +34908,61 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5865, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5866, -1,
+ -1, -1, -1, -1, -1, -1, 5861, -1,
+ -1, -1, 5862, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5863,
+ 5864, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5867, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5868,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5865, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5866, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5869, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5870, -1, -1, -1, 5871,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5872, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5867, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5868, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5869,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5873, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5874, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5870, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5871, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5875, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5872,
+ -1, -1, -1, -1, -1, -1, 5873, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5876, -1, -1, -1, -1, -1, -1, -1,
- -1, 5877, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5878, 5879, -1,
- 5880, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32053,7 +34974,19 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5874, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5875, -1, -1, -1, -1,
+ 5876, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 5877, -1, -1, -1, -1, -1, -1, 5878,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5879,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32062,25 +34995,34 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5880, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5881, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5881, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5882,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5882, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
5883, -1, -1, -1, -1, -1, -1, -1,
- -1, 5884, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5885, 5886, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5884,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5885, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5886, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5887, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32091,24 +35033,26 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5887, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5888, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5889,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5888, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5890, -1, -1, -1, -1, -1,
+ -1, -1, 5891, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5892, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5889, 5890,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5891, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5892, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32117,152 +35061,196 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5893, -1, -1,
+ 5894, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5893, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5894, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5895, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5895,
-1, -1, -1, -1, 5896, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5897, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5898,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5897, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5899, -1, -1, -1, -1, -1, -1,
+ 5900, -1, 5901, -1, 5902, -1, -1, -1,
+ 5903, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5904, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5905, -1, -1,
+ -1, 5906, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5907, 5908, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5909, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5910, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5911, -1, -1, 5912, -1, 5913, -1, -1,
+ -1, 5914, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5915, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5916, 5917,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5898, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5918, -1, -1, -1, -1, -1, 5919,
+ 5920, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5921, -1, -1, -1, 5922, -1,
+ -1, -1, -1, -1, 5923, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5924, -1,
+ 5925, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5926, -1, -1, -1, 5927, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5928, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5899, -1, -1, -1, 5900,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5929, -1,
+ -1, 5930, -1, -1, 5931, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5932, -1, -1, -1,
+ -1, -1, 5933, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5901,
+ -1, -1, -1, -1, -1, -1, -1, 5934,
+ -1, -1, -1, -1, -1, 5935, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5936, -1, -1, -1, -1, 5937, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5938, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5902,
- -1, 5903, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5939,
+ -1, -1, -1, -1, -1, -1, -1, 5940,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5941, -1, -1, -1, -1, 5942, -1, -1,
+ -1, -1, -1, -1, -1, 5943, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5944, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5904, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5905, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5945, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5946, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5947, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5906, -1, -1,
+ -1, 5948, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5907,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5949, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5950, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5951, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5952, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5953, 5954, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5908, -1, -1,
+ -1, -1, -1, -1, -1, 5955, -1, -1,
+ -1, -1, 5956, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5957, -1, -1, -1, -1, -1, -1, -1,
+ 5958, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5909, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 5959, -1, -1, -1, -1, -1, 5960, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5961,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5910, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5962, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5911, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5912, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5963, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5913, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32272,6 +35260,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5964, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32279,6 +35268,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5965, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32286,8 +35276,10 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5966, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5967, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32295,43 +35287,40 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5968, -1,
+ -1, -1, -1, -1, 5969, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5914, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5970, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5915, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5916,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5917, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5918, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5919, -1, -1, -1, -1,
+ -1, -1, 5971, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5920, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 5972, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5921, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5973, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5974,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5922, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5923, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32339,17 +35328,17 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5975, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5924, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5925, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5976, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32358,6 +35347,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5977, -1, -1, -1, -1,
+ -1, 5978, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32365,49 +35356,61 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5926, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5979, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5980, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5981, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5982, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5983, -1, -1,
+ -1, -1, -1, -1, -1, -1, 5984, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5927, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5985, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5928, -1, -1, -1, 5929,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5986, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5930, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 5987, -1, -1, -1, 5988,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5989,
+ -1, -1, -1, -1, -1, -1, -1, 5990,
+ -1, -1, -1, -1, -1, -1, -1, 5991,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5992, -1, -1,
+ -1, 5993, -1, -1, -1, -1, -1, 5994,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 5995, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 5996, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32417,11 +35420,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5931, -1, -1, -1, -1, -1, -1,
+ 5997, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 5998,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32429,28 +35433,28 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5932, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5933, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5934, -1, -1, -1, -1,
+ 5999, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6000, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6001, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6002, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5935, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32459,12 +35463,13 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5936, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6003, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6004, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32473,62 +35478,64 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5937, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6005, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5938, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5939, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6006, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6007, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5940, -1,
- -1, -1, -1, -1, -1, 5941, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5942, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5943, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5944,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6008, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5945, -1, -1,
+ -1, -1, -1, -1, -1, 6009, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6010, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6011, -1,
+ -1, 6012, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5946, -1, -1,
+ -1, -1, -1, -1, -1, 6013, -1, -1,
+ -1, -1, -1, -1, -1, 6014, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5947, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6015, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6016, 6017, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6018, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32538,34 +35545,40 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5948, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6019, -1,
+ -1, -1, -1, -1, 6020, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5949, -1, -1,
- -1, -1, -1, -1, -1, 5950, -1, -1,
+ -1, -1, -1, -1, 6021, -1, -1, -1,
+ -1, -1, 6022, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6023, -1, -1, -1, -1, 6024, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6025, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6026, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6027, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6028, -1, -1, -1, -1, 6029, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5951, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6030, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32577,8 +35590,10 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6031, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6032, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32589,42 +35604,47 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6033, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6034,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5952, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6035, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6036, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6037, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6038, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5953, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6039, -1, -1, -1, 6040,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6041, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5954, -1, -1, -1, -1, -1,
- 5955, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5956, -1, -1,
+ -1, -1, -1, -1, 6042, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6043,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6044,
+ -1, 6045, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5957, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5958, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32632,9 +35652,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6046, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6047, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32645,34 +35667,41 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5959, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5960, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6048, -1,
+ -1, 6049, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6050, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6051, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6052, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6053,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6054, -1,
+ 6055, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6056, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32680,15 +35709,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5961, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5962, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5963, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32696,31 +35722,31 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5964, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5965, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6057,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6058, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5966, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6059, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32734,45 +35760,43 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5967, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5968, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6060, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6061, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5969, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6062, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5970, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6063, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5971, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5972, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32788,32 +35812,36 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6064, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5973, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5974, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6065, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6066, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6067, -1, -1, -1, -1, -1, -1, -1,
+ 6068, -1, -1, -1, -1, -1, -1, -1,
+ 6069, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6070, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6071, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5975, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5976,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32821,21 +35849,25 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6072, -1, -1, -1, -1, -1,
+ -1, 6073, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6074, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6075, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5977, -1, -1, -1, -1, -1, -1,
+ 6076, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6077, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5978, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32849,11 +35881,14 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6078, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6079, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5979, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6080, -1, -1, -1, -1, -1,
+ -1, 6081, -1, -1, -1, -1, 6082, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32872,14 +35907,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5980, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5981, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 5982,
+ -1, 6083, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6084, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5983, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32890,52 +35923,56 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5984, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5985, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6085, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6086, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6087, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5986, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6088, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6089,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5987, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6090, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5988, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6091, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6092, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5989, -1, -1, -1, -1, -1, 5990,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6093, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6094, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32944,11 +35981,9 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5991, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 5992, -1, -1, -1, -1,
+ 6095, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 5993, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -32958,54 +35993,54 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 5994, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5995, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6096, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6097, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6098, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 5996, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 5997, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6099, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6100, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 5998, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 5999, -1, -1,
- -1, -1, -1, -1, -1, 6000, -1, -1,
- -1, -1, -1, -1, -1, -1, 6001, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6101,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6102, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6103, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6002, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6104, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33031,12 +36066,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6105, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6106,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6107, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6108, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33049,6 +36088,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6109, -1,
+ -1, -1, 6110, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33064,21 +36105,21 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6111, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6003, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6112, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6004, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6005, -1, -1, -1, -1, -1,
+ -1, 6113, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33087,16 +36128,15 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6006,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6114,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6007, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33109,7 +36149,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6008, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33118,6 +36157,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6115, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33127,19 +36167,17 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6009, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6010, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6011, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6116, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33151,6 +36189,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6117, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33162,21 +36201,24 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6118, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6119, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6120,
+ -1, -1, -1, -1, -1, -1, -1, 6121,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6012, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6122, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6013, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33187,12 +36229,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6014, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6123, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33200,30 +36242,31 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6015, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6016, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6124, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6125, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6126, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6127, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6017, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33234,12 +36277,9 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6018, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6019, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6020, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33247,8 +36287,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6021,
- -1, -1, -1, -1, -1, -1, 6022, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33258,6 +36296,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6128, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33266,14 +36305,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6129, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6023, -1, -1, -1,
+ -1, 6130, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6131, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33281,24 +36322,24 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6024, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6132, -1, -1, 6133, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6134, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6025,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33308,10 +36349,10 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6135, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6026, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33323,20 +36364,21 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6136,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6027, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6137, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6138, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6028, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33347,6 +36389,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6139,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33363,9 +36406,9 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6029, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6140,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33374,30 +36417,31 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6141, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6030, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6142, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6143, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6144, 6145, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6031, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6032, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33406,7 +36450,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6033,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33421,7 +36464,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6034, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33433,19 +36475,19 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6146, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6035, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6147, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6036,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33458,16 +36500,18 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6148, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6037, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6149, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6150, -1, -1, -1, -1, -1, 6151,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33477,18 +36521,23 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6152, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6153, -1, -1, -1, -1, -1,
+ 6154, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6155, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6156,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6038, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6157, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33496,6 +36545,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6158, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33503,6 +36553,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6159, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6160, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33511,11 +36563,13 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6161, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6162,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33527,7 +36581,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6039, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33538,25 +36591,27 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6163,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6164, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6040, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6165, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6041, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6166, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33572,35 +36627,40 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6167, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6168, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6042, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6169,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6043, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6170, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6171, 6172,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6044, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6173, -1, -1, -1, -1, -1,
+ 6174, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6175, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33611,19 +36671,27 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6176, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6177, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6178, -1, -1, -1,
+ -1, 6179, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6180, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6181, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6182, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6183, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33638,6 +36706,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6184, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33673,11 +36742,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6045, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6185,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33685,6 +36754,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6186, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33702,34 +36772,46 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6187, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6188, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6189, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6190, -1, -1, 6191,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6192, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6193, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6194,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6195, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6196, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6197,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6198, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6199,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6046, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6200, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33739,9 +36821,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6047, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6201, -1,
+ -1, -1, -1, -1, -1, 6202, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6203, -1,
+ -1, -1, -1, -1, -1, 6204, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33749,16 +36834,18 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6205, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6206, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6048,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6207, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33768,9 +36855,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6049, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6050, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33779,17 +36864,19 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6051, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6208, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6209, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6210, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33801,17 +36888,17 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6211,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6052, -1, -1, -1, -1, -1, -1,
- 6053, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6054, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6212, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6213, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33827,6 +36914,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6214, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33836,6 +36924,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6215, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6216, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33845,24 +36935,27 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6217, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6055, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6218, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6219, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6220, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33882,7 +36975,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6056, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33897,11 +36989,14 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6221, -1,
+ 6222, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6223, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6224, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6057, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33916,6 +37011,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6225, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33932,6 +37028,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6226, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33942,15 +37039,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6227, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6228, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6058, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33961,7 +37059,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6059, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33975,9 +37072,9 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6060, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6229,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -33987,24 +37084,24 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6061, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6062, -1, -1, -1, -1, 6063, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6064, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6230, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6231, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6232,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34015,6 +37112,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6233, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34022,15 +37120,13 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6234, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6065, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6066, -1, -1, -1, -1, -1, -1,
- -1, 6067, -1, -1, -1, -1, 6068, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34039,16 +37135,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6069, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6235, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6070, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6236, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34068,6 +37164,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6237, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34083,7 +37180,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6071, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34099,8 +37195,10 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6238, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6239, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34108,7 +37206,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6072,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34132,13 +37229,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6073, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6074, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34148,10 +37243,9 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6240,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6075, -1,
- -1, -1, -1, -1, -1, -1, 6076, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34183,6 +37277,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6241, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34196,6 +37291,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6242, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34203,7 +37299,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6077, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34236,14 +37331,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6243, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6244, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6245, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6078, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34257,6 +37354,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6246, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34289,6 +37387,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6247, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34296,7 +37395,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6079, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34308,11 +37406,13 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6248, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6249, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34339,14 +37439,15 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6250, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6251,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6080, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34360,6 +37461,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6252, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34371,6 +37473,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6253, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34396,12 +37499,14 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6254, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6255, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34422,6 +37527,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6256, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6257, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34433,11 +37540,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6258,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6259, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6081, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34447,7 +37555,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6082, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34487,6 +37594,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6260, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34505,12 +37613,14 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6261, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6262, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34539,6 +37649,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6263, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34546,6 +37657,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6264, -1, -1, -1,
+ -1, 6265, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34570,10 +37683,10 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6266, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6083, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34596,6 +37709,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6267, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34604,10 +37718,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6268, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6084, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6269, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34644,9 +37759,11 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6270,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6271, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34657,10 +37774,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6272, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6273, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34673,6 +37792,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6274, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34693,7 +37813,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6085, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34701,13 +37820,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6275, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6276,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6277, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34716,16 +37838,16 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6278, -1, 6279, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6086, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6280,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6087, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34736,6 +37858,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6281, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34771,7 +37894,3736 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, 6088, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6282, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6283, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6284, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6285,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6286, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6287, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6288, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6289,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6290,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6291, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6292, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6293, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6294, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6295,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6296, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6297, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6298, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6299, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6300,
+ -1, -1, -1, -1, 6301, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6302, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6303, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6304, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6305,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6306, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6307,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6308,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6309, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6310,
+ -1, -1, 6311, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6312, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6313, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6314, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6315, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6316,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6317, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6318, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6319, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6320, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6321, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6322, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6323, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6324, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6325,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6326,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6327, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6328, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6329, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6330, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6331,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6332, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6333, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6334, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6335, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6336, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6337, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6338, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6339, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6340, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6341, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6342,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6343,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6344, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6345, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6346, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6347, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6348, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6349, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6350, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6351, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6352,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6353, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 6354,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6355, -1, -1, -1, -1, -1, -1,
+ 6356, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6357, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6358, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 6359, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6360, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6361, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6362, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6363, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ 6364, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6365, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34874,7 +41726,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 6089, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34924,7 +41775,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6090, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -34965,7 +41815,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6091,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35002,10 +41851,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6092, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6093, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35069,10 +41916,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6094, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6095, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35195,13 +42040,12 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 6096, -1, -1, -1, -1,
- 6097, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ 6366, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35218,7 +42062,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 6098, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35498,6 +42341,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 6367, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35565,10 +42409,8 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- 6099, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 6100,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35809,7 +42651,6 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 6101, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -35818,6 +42659,7 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6368, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -36004,7 +42846,4190 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 6102
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 6369, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6370, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6371, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 6372, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 6373, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 6374
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -36026,5 +47051,5 @@ Perfect_Hash::FindDomain (register const char *str, register unsigned int len)
}
return 0;
}
-#line 6117 "effective_tld_names.gperf"
+#line 6389 "effective_tld_names.gperf"
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 4a39bf94935..038e25d4e64 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.dat
@@ -3,8 +3,7 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Chromium note: this is based on Mozilla's file:
-// http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1
-
+// http://hg.mozilla.org/mozilla-central/raw-file/tip/netwerk/dns/effective_tld_names.dat
// ===BEGIN ICANN DOMAINS===
@@ -179,17 +178,16 @@ it.ao
// aq : http://en.wikipedia.org/wiki/.aq
aq
-// ar : http://en.wikipedia.org/wiki/.ar
-*.ar
-!congresodelalengua3.ar
-!educ.ar
-!gobiernoelectronico.ar
-!mecon.ar
-!nacion.ar
-!nic.ar
-!promocion.ar
-!retina.ar
-!uba.ar
+// ar : https://nic.ar/normativa-vigente.xhtml
+ar
+com.ar
+edu.ar
+gob.ar
+int.ar
+mil.ar
+net.ar
+org.ar
+tur.ar
// arpa : http://en.wikipedia.org/wiki/.arpa
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
@@ -225,6 +223,8 @@ edu.au
gov.au
asn.au
id.au
+// Chromium - Carve a hole for CSIRO. Requested by Kalman Dee <kalman.dee@csiro.au>
+!csiro.au
// Historic 2LDs (closed to new registration, but sites still exist)
info.au
conf.au
@@ -248,9 +248,8 @@ tas.edu.au
vic.edu.au
wa.edu.au
act.gov.au
-// Removed at request of Shae.Donelan@services.nsw.gov.au, 2010-03-04
-// nsw.gov.au
-nt.gov.au
+// nsw.gov.au Bug 547985 - Removed at request of <Shae.Donelan@services.nsw.gov.au>
+// nt.gov.au Bug 940478 - Removed at request of Greg Connors <Greg.Connors@nt.gov.au>
qld.gov.au
sa.gov.au
tas.gov.au
@@ -405,7 +404,7 @@ mil.bo
tv.bo
// br : http://registro.br/dominio/dpn.html
-// Updated by registry <fneves@registro.br> 2011-03-01
+// Submitted by registry <fneves@registro.br> 2011-03-01
br
adm.br
adv.br
@@ -890,13 +889,12 @@ pvt.ge
// gf : http://en.wikipedia.org/wiki/.gf
gf
-// gg : http://www.channelisles.net/applic/avextn.shtml
+// gg : http://www.channelisles.net/register-domains/
+// Confirmed by registry <nigel@channelisles.net> 2013-11-28
gg
co.gg
-org.gg
net.gg
-sch.gg
-gov.gg
+org.gg
// gh : http://en.wikipedia.org/wiki/.gh
// see also: http://www.nic.gh/reg_now.php
@@ -1103,16 +1101,18 @@ gov.ie
// il : http://en.wikipedia.org/wiki/.il
*.il
-// im : https://www.nic.im/pdfs/imfaqs.pdf
+// im : https://www.nic.im/
+// Submitted by registry <info@nic.im> 2013-11-15
im
+ac.im
co.im
+com.im
ltd.co.im
-plc.co.im
net.im
-gov.im
org.im
-nic.im
-ac.im
+plc.co.im
+tt.im
+tv.im
// in : http://en.wikipedia.org/wiki/.in
// see also: http://www.inregistry.in/policies/
@@ -1465,13 +1465,12 @@ vi.it
viterbo.it
vt.it
-// je : http://www.channelisles.net/applic/avextn.shtml
+// je : http://www.channelisles.net/register-domains/
+// Confirmed by registry <nigel@channelisles.net> 2013-11-28
je
co.je
-org.je
net.je
-sch.je
-gov.je
+org.je
// jm : http://www.com.jm/register.html
*.jm
@@ -1492,7 +1491,7 @@ jobs
// jp : http://en.wikipedia.org/wiki/.jp
// http://jprs.co.jp/en/jpdomain.html
-// Updated by registry <info@jprs.jp> 2012-05-28
+// Submitted by registry <info@jprs.jp> 2012-05-28
jp
// jp organizational type names
ac.jp
@@ -3566,8 +3565,13 @@ gov.mr
// ms : http://en.wikipedia.org/wiki/.ms
ms
-// mt : https://www.nic.org.mt/dotmt/
-*.mt
+// mt : https://www.nic.org.mt/go/policy
+// Submitted by registry <help@nic.org.mt> 2013-11-19
+mt
+com.mt
+edu.mt
+net.mt
+org.mt
// mu : http://en.wikipedia.org/wiki/.mu
mu
@@ -4234,13 +4238,16 @@ other.nf
store.nf
// ng : http://psg.com/dns/ng/
-// Submitted by registry <randy@psg.com> 2008-06-17
-ac.ng
+ng
com.ng
edu.ng
-gov.ng
+name.ng
net.ng
org.ng
+sch.ng
+gov.ng
+mil.ng
+mobi.ng
// ni : http://www.nic.ni/dominios.htm
*.ni
@@ -5041,17 +5048,16 @@ nu
*.nz
// om : http://en.wikipedia.org/wiki/.om
-*.om
-!mediaphone.om
-!nawrastelecom.om
-!nawras.om
-!omanmobile.om
-!omanpost.om
-!omantel.om
-!rakpetroleum.om
-!siemens.om
-!songfest.om
-!statecouncil.om
+om
+co.om
+com.om
+edu.om
+gov.om
+med.om
+museum.om
+net.om
+org.om
+pro.om
// org : http://en.wikipedia.org/wiki/.org
org
@@ -5745,8 +5751,13 @@ store.st
// su : http://en.wikipedia.org/wiki/.su
su
-// sv : http://www.svnet.org.sv/svpolicy.html
-*.sv
+// sv : http://www.svnet.org.sv/niveldos.pdf
+sv
+com.sv
+edu.sv
+gob.sv
+org.sv
+red.sv
// sx : http://en.wikipedia.org/wiki/.sx
// Confirmed by registry <jcvignes@openregistry.com> 2012-05-31
@@ -6129,7 +6140,7 @@ k12.de.us
k12.fl.us
k12.ga.us
k12.gu.us
-// k12.hi.us Hawaii has a state-wide DOE login: bug 614565
+// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login
k12.ia.us
k12.id.us
k12.il.us
@@ -6160,7 +6171,7 @@ k12.pa.us
k12.pr.us
k12.ri.us
k12.sc.us
-k12.sd.us
+// k12.sd.us Bug 934131 - Removed at request of James Booze <James.Booze@k12.sd.us>
k12.tn.us
k12.tx.us
k12.ut.us
@@ -6281,7 +6292,7 @@ lib.vt.us
lib.va.us
lib.wa.us
lib.wi.us
-lib.wv.us
+// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold <arnold@wvlc.lib.wv.us>
lib.wy.us
// k12.ma.us contains school districts in Massachusetts. The 4LDs are
@@ -6558,23 +6569,770 @@ xxx
// zw : http://en.wikipedia.org/wiki/.zw
*.zw
+
+// xn--80asehdb : 2013-07-14 CORE Association
+онлайн
+
+// xn--80aswg : 2013-07-14 CORE Association
+Ñайт
+
+// xn--ngbc5azd : 2013-07-14 International Domain Registry Pty. Ltd.
+شبكة
+
+// xn--unup4y : 2013-07-14 Spring Fields, LLC
+游æˆ
+
+// xn--vhquv : 2013-08-28 Dash McCook, LLC
+ä¼ä¸š
+
+// camera : 2013-08-28 Atomic Maple, LLC
+camera
+
+// clothing : 2013-08-28 Steel Lake, LLC
+clothing
+
+// lighting : 2013-08-28 John McCook, LLC
+lighting
+
+// singles : 2013-08-28 Fern Madison, LLC
+singles
+
+// ventures : 2013-08-28 Binky Lake, LLC
+ventures
+
+// voyage : 2013-08-28 Ruby House, LLC
+voyage
+
+// guru : 2013-08-28 Pioneer Cypress, LLC
+guru
+
+// holdings : 2013-08-28 John Madison, LLC
+holdings
+
+// equipment : 2013-08-28 Corn Station, LLC
+equipment
+
+// bike : 2013-08-28 Grand Hollow, LLC
+bike
+
+// estate : 2013-08-28 Trixy Park, LLC
+estate
+
+// tattoo : 2013-08-30 Uniregistry,Corp.
+tattoo
+
+// xn--3ds443g : 2013-09-09 TLD Registry Limited
+在线
+
+// xn--fiq228c5hs : 2013-09-09 TLD Registry Limited
+中文网
+
+// land : 2013-09-10 Pine Moon, LLC
+land
+
+// plumbing : 2013-09-10 Spring Tigers, LLC
+plumbing
+
+// contractors : 2013-09-10 Magic Woods, LLC
+contractors
+
+// sexy : 2013-09-11 Uniregistry,Corp.
+sexy
+
+// menu : 2013-09-11 Wedding TLD2, LLC
+menu
+
+// xn--rhqv96g : 2013-09-11 Stable Tone Limited
+世界
+
+// uno : 2013-09-11 Dot Latin, LLC
+uno
+
+// gallery : 2013-09-13 Sugar House, LLC
+gallery
+
+// technology : 2013-09-13 Auburn Falls
+technology
+
+// xn--3bst00m : 2013-09-13 Eagle Horizon Limited
+集团
+
+// reviews : 2013-09-13 Extra Cover, LLC
+reviews
+
+// guide : 2013-09-13 Snow Moon, LLC
+guide
+
+// xn--6qq986b3x1 : 2013-09-13 Tycoon Treasure Limited
+我爱你
+
+// graphics : 2013-09-13 Over Madison, LLC
+graphics
+
+// construction : 2013-09-13 Fox Dynamite, LLC
+construction
+
+// onl : 2013-09-16 I-Registry Ltd.
+onl
+
+// xn--q9jyb4c : 2013-09-17 Charleston Road Registry
+ã¿ã‚“ãª
+
+// diamonds : 2013-09-23 John Edge, LLC
+diamonds
+
+// kiwi : 2013-09-23 Dot Kiwi Limited
+kiwi
+
+// enterprises : 2013-09-23 Snow Oaks LLC
+enterprises
+
+// today : 2013-09-23 Pearl Woods, LLC
+today
+
+// futbol : 2013-09-23 Atomic Falls, LLC
+futbol
+
+// photography : 2013-09-23 Sugar Glen, LLC
+photography
+
+// tips : 2013-09-23 Corn Willow, LLC
+tips
+
+// directory : 2013-09-23 Extra Madison, LLC
+directory
+
+// kitchen : 2013-09-23 Just Goodbye, LLC
+kitchen
+
+// xn--6frz82g : 2013-09-24 Afilias Limited
+移动
+
+// kim : 2013-09-24 Afilias Limited
+kim
+
+// xn--cg4bki : 2013-09-27 Samsung SDS Co., LTD
+삼성
+
+// monash : 2013-10-01 Monash University
+monash
+
+// wed : 2013-10-02 Atgron, Inc.
+wed
+
+// pink : 2013-10-02 Afilias Limited
+pink
+
+// ruhr : 2013-10-02 regiodot GmbH & Co. KG
+ruhr
+
+// buzz : 2013-10-03 DOTSTRATEGY CO.
+buzz
+
+// careers : 2013-10-03 Wild Corner, LLC
+careers
+
+// shoes : 2013-10-03 Binky Galley, LLC
+shoes
+
+// xn--4gbrim : 2013-10-07 Suhub Electronic Establishment
+موقع
+
+// career : 2013-10-09 dotCareer, LLC
+career
+
+// otsuka : 2013-10-11 Otsuka Holdings Co. Ltd.
+otsuka
+
+// xn--fiQ64b : 2013-10-14 CITIC Group Corporation
+中信
+
+// gift : 2013-10-18 Uniregistry Corp.
+gift
+
+// recipes : 2013-10-18 Grand Island, LLC
+recipes
+
+// coffee : 2013-10-18 Trixy Cover, LLC
+coffee
+
+// luxury : 2013-10-18 Luxury Partners, LLC
+luxury
+
+// domains : 2013-10-18 Sugar Cross, LLC
+domains
+
+// photos : 2013-10-18 Sea Corner, LLC
+photos
+
+// limo : 2013-10-18 Hidden Frostbite, LLC
+limo
+
+// viajes : 2013-10-18 Black Madison, LLC
+viajes
+
+// wang : 2013-10-24 Zodiac Leo Limited
+wang
+
+// democrat : 2013-10-24 United TLD Holdco Ltd.
+democrat
+
+// mango : 2013-10-25 PUNTO FA S.L.
+mango
+
+// cab : 2013-10-25 Half Sunset, LLC
+cab
+
+// support : 2013-10-25 Grand Orchard, LLC
+support
+
+// dance : 2013-10-25 United TLD Holdco Ltd.
+dance
+
+// nagoya : 2013-10-25 GMO Registry, Inc.
+nagoya
+
+// computer : 2013-10-25 Pine Mill, LLC
+computer
+
+// wien : 2013-10-28 punkt.wien GmbH
+wien
+
+// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG
+berlin
+
+// codes : 2013-10-31 Puff Willow, LLC
+codes
+
+// email : 2013-10-31 Spring Madison, LLC
+email
+
+// xn--mgbab2bd : 2013-10-31 CORE Association
+بازار
+
+// repair : 2013-11-07 Lone Sunset, LLC
+repair
+
+// holiday : 2013-11-07 Goose Woods, LLC
+holiday
+
+// center : 2013-11-07 Tin Mill, LLC
+center
+
+// systems : 2013-11-07 Dash Cypress, LLC
+systems
+
+// wiki : 2013-11-07 Top Level Design, LLC
+wiki
+
+// ceo : 2013-11-07 CEOTLD Pty Ltd
+ceo
+
+// international : 2013-11-07 Wild Way, LLC
+international
+
+// solar : 2013-11-07 Ruby Town, LLC
+solar
+
+// company : 2013-11-07 Silver Avenue, LLC
+company
+
+// education : 2013-11-07 Brice Way, LLC
+education
+
+// training : 2013-11-07 Wild Willow, LLC
+training
+
+// academy : 2013-11-07 Half Oaks, LLC
+academy
+
+// marketing : 2013-11-07 Fern Pass, LLC
+marketing
+
+// florist : 2013-11-08 Half Cypress, LLC
+florist
+
+// solutions : 2013-11-07 Silver Cover, LLC
+solutions
+
+// build : 2013-11-07 Plan Bee LLC
+build
+
+// institute : 2013-11-07 Outer Maple, LLC
+institute
+
+// builders : 2013-11-07 Atomic Madison, LLC
+builders
+
+// red : 2013-11-07 Afilias Limited
+red
+
+// blue : 2013-11-07 Afilias Limited
+blue
+
+// ninja : 2013-11-07 United TLD Holdco Ltd.
+ninja
+
+// business : 2013-11-07 Spring Cross, LLC
+business
+
+// gal : 2013-11-07 Asociación puntoGAL
+gal
+
+// social : 2013-11-07 United TLD Holdco Ltd.
+social
+
+// house : 2013-11-07 Sugar Park, LLC
+house
+
+// camp : 2013-11-07 Delta Dynamite, LLC
+camp
+
+// immobilien : 2013-11-07 United TLD Holdco Ltd.
+immobilien
+
+// moda : 2013-11-07 United TLD Holdco Ltd.
+moda
+
+// glass : 2013-11-07 Black Cover, LLC
+glass
+
+// management : 2013-11-07 John Goodbye, LLC
+management
+
+// kaufen : 2013-11-07 United TLD Holdco Ltd.
+kaufen
+
+// farm : 2013-11-07 Just Maple, LLC
+farm
+
+// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center
+公益
+
+// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
+政务
+
+// club : 2013-11-08 .CLUB DOMAINS, LLC
+club
+
+// voting : 2013-11-13 Valuetainment Corp.
+voting
+
+// TOKYO : 2013-11-13 GMO Registry, Inc.
+TOKYO
+
+// moe : 2013-11-13 Interlink Co., Ltd.
+moe
+
+// guitars : 2013-11-14 Uniregistry, Corp.
+guitars
+
+// bargains : 2013-11-14 Half Hallow, LLC
+bargains
+
+// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry
+组织机构
+
+// desi : 2013-11-14 Desi Networks LLC
+desi
+
+// cool : 2013-11-14 Koko Lake, LLC
+cool
+
+// boutique : 2013-11-14 Over Galley, LLC
+boutique
+
+// pics : 2013-11-14 Uniregistry, Corp.
+pics
+
+// xn--c1avg : 2013-11-14 Public Interest Registry
+орг
+
+// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center)
+å…¬å¸
+
+// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center)
+网络
+
+// cheap : 2013-11-14 Sand Cover, LLC
+cheap
+
+// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd.
+广东
+
+// photo : 2013-11-14 Uniregistry, Corp.
+photo
+
+// network : 2013-11-14 Trixy Manor, LLC
+network
+
+// zone : 2013-11-14 Outer Falls, LLC
+zone
+
+// xn--nqv7f : 2013-11-14 Public Interest Registry
+机构
+
+// link : 2013-11-14 Uniregistry, Corp.
+link
+
+// QPON : 2013-11-14 dotCOOL, Inc.
+qpon
+
+// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry
+संगठन
+
+// agency : 2013-11-14 Steel Falls, LLC
+agency
+
+// tienda : 2013-11-14 Victor Manor, LLC
+tienda
+
+// works : 2013-11-14 Little Dynamite, LLC
+works
+
+// london : 2013-11-14 Dot London Domains Limited
+london
+
+// watch : 2013-11-14 Sand Shadow, LLC
+watch
+
+// rocks : 2013-11-14 Ruby Moon, LLC
+rocks
+
+// SHIKSHA : 2013-11-14 Afilias Limited
+shiksha
+
+// xn--d1acj3b : 2013-11-21 The Foundation for Network Initiatives “The Smart Internetâ€
+дети
+
+// budapest : 2013-11-21 Top Level Domain Holdings Limited
+budapest
+
+// nrw : 2013-11-21 Minds + Machines GmbH
+nrw
+
+// VOTE : 2013-11-21 Monolith Registry LLC
+vote
+
+// fishing : 2013-11-21 Top Level Domain Holdings Limited
+fishing
+
+// expert : 2013-11-21 Magic Pass, LLC
+expert
+
+// horse : 2013-11-21 Top Level Domain Holdings Limited
+horse
+
+// christmas : 2013-11-21 Uniregistry, Corp.
+christmas
+
+// cooking : 2013-11-21 Top Level Domain Holdings Limited
+cooking
+
+// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited
+商城
+
+// casa : 2013-11-21 Top Level Domain Holdings Limited
+casa
+
+// rich : 2013-11-21 I-REGISTRY Ltd., Niederlassung Deutschland
+rich
+
+// VOTO : 2013-11-21 Monolith Registry LLC
+voto
+
+// tools : 2013-11-21 Pioneer North, LLC
+tools
+
+// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited
+å…«å¦
+
+// praxi : 2013-12-05 Praxi S.p.A.
+praxi
+
+// events : 2013-12-05 Pioneer Maple, LLC
+events
+
+// flights : 2013-12-05 Fox Station, LLC
+flights
+
+// report : 2013-12-05 Binky Glen, LLC
+report
+
+// partners : 2013-12-05 Magic Glen, LLC
+partners
+
+// neustar : 2013-12-05 NeuStar, Inc.
+neustar
+
+// rentals : 2013-12-05 Big Hollow,LLC
+rentals
+
+// catering : 2013-12-05 New Falls. LLC
+catering
+
+// community : 2013-12-05 Fox Orchard, LLC
+community
+
+// maison : 2013-12-05 Victor Frostbite, LLC
+maison
+
+// parts : 2013-12-05 Sea Goodbye, LLC
+parts
+
+// cleaning : 2013-12-05 Fox Shadow, LLC
+cleaning
+
+// okinawa : 2013-12-05 BusinessRalliart inc.
+okinawa
+
+// foundation : 2013-12-05 John Dale, LLC
+foundation
+
+// properties : 2013-12-05 Big Pass, LLC
+properties
+
+// vacations : 2013-12-05 Atomic Tigers, LLC
+vacations
+
+// productions : 2013-12-05 Magic Birch, LLC
+productions
+
+// industries : 2013-12-05 Outer House, LLC
+industries
+
+// haus : 2013-12-05 Pixie Edge, LLC
+haus
+
+// vision : 2013-12-05 Koko Station, LLC
+vision
+
+// mormon : 2013-12-05 IRI Domain Management, LLC (""Applicant"")
+mormon
+
+// cards : 2013-12-05 Foggy Hollow, LLC
+cards
+
+// ink : 2013-12-05 Top Level Design, LLC
+ink
+
+// villas : 2013-12-05 New Sky, LLC
+villas
+
+// consulting : 2013-12-05 Pixie Station, LLC
+consulting
+
+// cruises : 2013-12-05 Spring Way, LLC
+cruises
+
+// krd : 2013-12-05 KRG Department of Information Technology
+krd
+
+// xyz : 2013-12-05 XYZ.COM LLC
+xyz
+
+// dating : 2013-12-05 Pine Fest, LLC
+dating
+
+// exposed : 2013-12-05 Victor Beach, LLC
+exposed
+
+// condos : 2013-12-05 Pine House, LLC
+condos
+
+// eus : 2013-12-12 Puntueus Fundazioa
+eus
+
+// Caravan : 2013-12-12 Caravan International, Inc.
+caravan
+
+// actor : 2013-12-12 United TLD Holdco Ltd.
+actor
+
+// saarland : 2013-12-12 dotSaarland GmbH
+saarland
+
+// yokohama : 2013-12-12 GMO Registry, Inc.
+yokohama
+
+// pub : 2013-12-12 United TLD Holdco Ltd.
+pub
+
+// xn--p1acf : 2013-12-12 Rusnames Limited
+руÑ
+
+// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd.
+ren
+
+// fish : 2013-12-12 Fox Woods, LLC
+fish
+
+// BAR : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+bar
+
+// DNP : 2013-12-13 Dai Nippon Printing Co., Ltd.
+dnp
+
+// bid : 2013-12-19 dot Bid Limited
+bid
+
+// supply : 2013-12-19 Half Falls, LLC
+supply
+
+// Miami : 2013-12-19 Top Level Domain Holdings Limited
+miami
+
+// supplies : 2013-12-19 Atomic Fields, LLC
+supplies
+
+// quebec : 2013-12-19 PointQuébec Inc
+quebec
+
+// MOSCOW : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+moscow
+
+// globo : 2013-12-19 Globo Comunicação e Participações S.A
+globo
+
+// AXA : 2013-12-19 AXA SA
+axa
+
+// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+моÑква
+
+// xn--czrs0t : 2013-12-19 Wild Island, LLC
+商店
+
+// vodka : 2013-12-19 Top Level Domain Holdings Limited
+vodka
+
+// REST : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+rest
+
+// frogans : 2013-12-19 OP3FT
+frogans
+
+// WTC : 2013-12-19 World Trade Centers Association, Inc.
+wtc
+
+// rodeo : 2013-12-19 Top Level Domain Holdings Limited
+rodeo
+
+// sohu : 2013-12-19 Sohu.com Limited
+sohu
+
+// BEST : 2013-12-19 BestTLD Pty Ltd
+best
+
+// country : 2013-12-19 Top Level Domain Holdings Limited
+country
+
+// KRED : 2013-12-19 KredTLD Pty Ltd
+kred
+
+// feedback : 2013-12-19 Top Level Spectrum, Inc.
+feedback
+
+// work : 2013-12-19 Top Level Domain Holdings Limited
+work
+
+// luxe : 2014-01-09 Top Level Domain Holdings Limited
+luxe
+
+// ryukyu : 2014-01-09 BusinessRalliart inc.
+ryukyu
+
+// autos : 2014-01-09 DERAutos, LLC
+autos
+
+// homes : 2014-01-09 DERHomes, LLC
+homes
+
+// jetzt : 2014-01-09 New TLD Company AB
+jetzt
+
+// yachts : 2014-01-09 DERYachts, LLC
+yachts
+
+// motorcycles : 2014-01-09 DERMotorcycles, LLC
+motorcycles
+
+// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
+mini
+
+// ggee : 2014-01-09 GMO Internet, Inc.
+ggee
+
+// beer : 2014-01-09 Top Level Domain Holdings Limited
+beer
+
+// xn--1qqw23a : 2014-01-13 Guangzhou YU Wei Information Technology Co., Ltd.
+佛山
+
+// college : 2014-01-16 XYZ.COM LLC
+college
+
+// ovh : 2014-01-16 OVH SAS
+ovh
+
+// meet : 2014-01-16 Afilias Limited
+meet
+
+// xn--ses554g : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED
+网å€
+
+// gop : 2014-01-16 Republican State Leadership Committee, Inc.
+gop
+
+// blackfriday : 2014-01-16 Uniregistry, Corp.
+blackfriday
+
+// lacaixa : 2014-01-16 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA
+lacaixa
+
+// xn--czr694b : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES(HOLDING) COMPANY.HONGKONG LIMITED
+商标
+
+// vegas : 2014-01-16 Dot Vegas, Inc.
+vegas
+
+// black : 2014-01-16 Afilias Limited
+black
+
+
// ===END ICANN DOMAINS===
// ===BEGIN PRIVATE DOMAINS===
// Amazon CloudFront : https://aws.amazon.com/cloudfront/
-// Requested by Donavan Miller <donavanm@amazon.com> 2013-03-22
+// Submitted by Donavan Miller <donavanm@amazon.com> 2013-03-22
cloudfront.net
+// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/
+// Submitted by Osman Surkatty <osmans@amazon.com> 2013-04-02
+compute.amazonaws.com
+us-east-1.amazonaws.com
+compute-1.amazonaws.com
+z-1.compute-1.amazonaws.com
+z-2.compute-1.amazonaws.com
+ap-northeast-1.compute.amazonaws.com
+ap-southeast-1.compute.amazonaws.com
+ap-southeast-2.compute.amazonaws.com
+eu-west-1.compute.amazonaws.com
+sa-east-1.compute.amazonaws.com
+us-gov-west-1.compute.amazonaws.com
+us-west-1.compute.amazonaws.com
+us-west-2.compute.amazonaws.com
+
// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
-// Requested by Adam Stein <astein@amazon.com> 2013-04-02
+// Submitted by Adam Stein <astein@amazon.com> 2013-04-02
elasticbeanstalk.com
// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/
-// Requested by Scott Vidmar <svidmar@amazon.com> 2013-03-27
+// Submitted by Scott Vidmar <svidmar@amazon.com> 2013-03-27
elb.amazonaws.com
// Amazon S3 : https://aws.amazon.com/s3/
-// Requested by Courtney Eckhardt <coec@amazon.com> 2013-03-22
+// Submitted by Courtney Eckhardt <coec@amazon.com> 2013-03-22
s3.amazonaws.com
s3-us-west-2.amazonaws.com
s3-us-west-1.amazonaws.com
@@ -6596,11 +7354,11 @@ s3-website-sa-east-1.amazonaws.com
s3-website-us-gov-west-1.amazonaws.com
// BetaInABox
-// Requested by adrian@betainabox.com 2012-09-13
+// Submitted by adrian@betainabox.com 2012-09-13
betainabox.com
// CentralNic : http://www.centralnic.com/names/domains
-// Requested by registry <gavin.brown@centralnic.com> 2012-09-27
+// Submitted by registry <gavin.brown@centralnic.com> 2012-09-27
ae.org
ar.com
br.com
@@ -6632,6 +7390,11 @@ za.com
// c.la : http://www.c.la/
c.la
+// cloudControl : https://www.cloudcontrol.com/
+// Submitted by Tobias Wilken <tw@cloudcontrol.com> 2013-07-23
+cloudcontrolled.com
+cloudcontrolapp.com
+
// co.ca : http://registry.co.ca/
co.ca
@@ -6639,8 +7402,12 @@ co.ca
co.nl
co.no
+// Cupcake : https://cupcake.io/
+// Submitted by Jonathan Rudenberg <jonathan@cupcake.io> 2013-10-08
+cupcake.is
+
// DreamHost : http://www.dreamhost.com/
-// Requested by Andrew Farmer <andrew.farmer@dreamhost.com> 2012-10-02
+// Submitted by Andrew Farmer <andrew.farmer@dreamhost.com> 2012-10-02
dreamhosters.com
// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
@@ -6924,12 +7691,24 @@ webhop.org
worse-than.tv
writesthisblog.com
+// Fastly Inc. http://www.fastly.com/
+// Submitted by Vladimir Vuksan <vladimir@fastly.com> 2013-05-31
+a.ssl.fastly.net
+b.ssl.fastly.net
+global.ssl.fastly.net
+a.prod.fastly.net
+global.prod.fastly.net
+
// GitHub, Inc.
-// Requested by Ben Toews <btoews@github.com> 2013-04-18
+// Submitted by Ben Toews <btoews@github.com> 2013-04-18
github.io
+// GlobeHosting, Inc.
+// Submitted by Zoltan Egresi <egresi@globehosting.com> 2013-07-12
+ro.com
+
// Google, Inc.
-// Requested by Eduardo Vela <evn@google.com> 2012-10-24
+// Submitted by Eduardo Vela <evn@google.com> 2012-10-24
appspot.com
blogspot.be
blogspot.bj
@@ -6975,8 +7754,13 @@ codespot.com
googleapis.com
googlecode.com
+// Heroku : https://www.heroku.com/
+// Submitted by Tom Maher <tmaher@heroku.com> 2013-05-02
+herokuapp.com
+herokussl.com
+
// iki.fi
-// Requested by Hannu Aronsson <haa@iki.fi> 2009-11-05
+// Submitted by Hannu Aronsson <haa@iki.fi> 2009-11-05
iki.fi
// info.at : http://www.info.at/
@@ -6987,23 +7771,23 @@ info.at
co.pl
// NYC.mn : http://www.information.nyc.mn
-// Requested by Matthew Brown <mattbrown@nyc.mn> 2013-03-11
+// Submitted by Matthew Brown <mattbrown@nyc.mn> 2013-03-11
nyc.mn
// Opera Software, A.S.A.
-// Requested by Yngve Pettersen <yngve@opera.com> 2009-11-26
+// Submitted by Yngve Pettersen <yngve@opera.com> 2009-11-26
operaunite.com
// Red Hat, Inc. OpenShift : https://openshift.redhat.com/
-// Requested by Tim Kramer <tkramer@rhcloud.com> 2012-10-24
+// Submitted by Tim Kramer <tkramer@rhcloud.com> 2012-10-24
rhcloud.com
// priv.at : http://www.nic.priv.at/
-// Requested by registry <lendl@nic.at> 2008-06-09
+// Submitted by registry <lendl@nic.at> 2008-06-09
priv.at
// ZaNiC : http://www.za.net/
-// Requested by registry <hostmaster@nic.za.net> 2009-10-03
+// Submitted by registry <hostmaster@nic.za.net> 2009-10-03
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 7412aba1736..890f814d844 100644
--- a/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
+++ b/chromium/net/base/registry_controlled_domains/effective_tld_names.gperf
@@ -24,7 +24,9 @@ struct DomainRule {
8.bg, 0
9.bg, 0
a.bg, 0
+a.prod.fastly.net, 4
a.se, 0
+a.ssl.fastly.net, 4
aa.no, 0
aarborte.no, 0
ab.ca, 0
@@ -52,7 +54,6 @@ ac.ma, 0
ac.me, 0
ac.mu, 0
ac.mw, 0
-ac.ng, 0
ac.pa, 0
ac.pr, 0
ac.rs, 0
@@ -66,6 +67,7 @@ ac.tz, 0
ac.ug, 0
ac.vn, 0
aca.pro, 0
+academy, 0
academy.museum, 0
accident-investigation.aero, 0
accident-prevention.aero, 0
@@ -73,6 +75,7 @@ achi.nagano.jp, 0
act.au, 0
act.edu.au, 0
act.gov.au, 0
+actor, 0
ad, 0
ad.jp, 0
adachi.tokyo.jp, 0
@@ -98,6 +101,7 @@ aga.niigata.jp, 0
agano.niigata.jp, 0
agdenes.no, 0
agematsu.nagano.jp, 0
+agency, 0
agents.aero, 0
agr.br, 0
agrar.hu, 0
@@ -214,13 +218,16 @@ aomori.aomori.jp, 0
aomori.jp, 0
aosta.it, 0
aoste.it, 0
+ap-northeast-1.compute.amazonaws.com, 4
+ap-southeast-1.compute.amazonaws.com, 4
+ap-southeast-2.compute.amazonaws.com, 4
ap.it, 0
appspot.com, 4
aq, 0
aq.it, 0
aquarium.museum, 0
aquila.it, 0
-ar, 2
+ar, 0
ar.com, 4
ar.it, 0
ar.us, 0
@@ -339,6 +346,7 @@ austrheim.no, 0
author.aero, 0
auto.pl, 0
automotive.museum, 0
+autos, 0
av.it, 0
avellino.it, 0
averoy.no, 0
@@ -348,6 +356,7 @@ avoues.fr, 0
aw, 0
awaji.hyogo.jp, 0
ax, 0
+axa, 0
axis.museum, 0
aya.miyazaki.jp, 0
ayabe.kyoto.jp, 0
@@ -359,6 +368,7 @@ azumino.nagano.jp, 0
b.bg, 0
b.br, 0
b.se, 0
+b.ssl.fastly.net, 4
ba, 0
ba.it, 0
babia-gora.pl, 0
@@ -382,9 +392,11 @@ baltimore.museum, 0
bamble.no, 0
bandai.fukushima.jp, 0
bando.ibaraki.jp, 0
+bar, 0
bar.pro, 0
barcelona.museum, 0
bardu.no, 0
+bargains, 0
bari.it, 0
barletta-trani-andria.it, 0
barlettatraniandria.it, 0
@@ -409,6 +421,7 @@ beardu.no, 0
beauxarts.museum, 0
bedzin.pl, 0
beeldengeluid.museum, 0
+beer, 0
beiarn.no, 0
belau.pw, 0
belgorod.ru, 0
@@ -422,9 +435,11 @@ bergbau.museum, 0
bergen.no, 0
berkeley.museum, 0
berlevag.no, 0
+berlin, 0
berlin.museum, 0
bern.museum, 0
beskidy.pl, 0
+best, 0
betainabox.com, 4
better-than.tv, 4
bf, 0
@@ -437,6 +452,7 @@ bialowieza.pl, 0
bialystok.pl, 0
bibai.hokkaido.jp, 0
bible.museum, 0
+bid, 0
biei.hokkaido.jp, 0
bielawa.pl, 0
biella.it, 0
@@ -444,6 +460,7 @@ bieszczady.pl, 0
bievat.no, 0
bifuka.hokkaido.jp, 0
bihoro.hokkaido.jp, 0
+bike, 0
bilbao.museum, 0
bill.museum, 0
bindal.no, 0
@@ -476,6 +493,8 @@ bjerkreim.no, 0
bjugn.no, 0
bl.it, 0
bl.uk, 1
+black, 0
+blackfriday, 0
blog.br, 0
blogdns.com, 4
blogdns.net, 4
@@ -521,6 +540,7 @@ blogspot.sg, 4
blogspot.sk, 4
blogspot.td, 4
blogspot.tw, 4
+blue, 0
bm, 0
bmd.br, 0
bn, 2
@@ -543,6 +563,7 @@ botanical.museum, 0
botanicalgarden.museum, 0
botanicgarden.museum, 0
botany.museum, 0
+boutique, 0
bozen.it, 0
br, 0
br.com, 4
@@ -574,7 +595,10 @@ bs.it, 0
bt, 0
bt.it, 0
bu.no, 0
+budapest, 0
budejju.no, 0
+build, 0
+builders, 0
building.museum, 0
bungoono.oita.jp, 0
bungotakada.oita.jp, 0
@@ -584,8 +608,10 @@ buryatia.ru, 0
bus.museum, 0
busan.kr, 0
bushey.museum, 0
+business, 0
buyshouses.net, 4
buzen.fukuoka.jp, 0
+buzz, 0
bv.nl, 0
bw, 0
by, 0
@@ -603,25 +629,33 @@ ca.it, 0
ca.na, 0
ca.us, 0
caa.aero, 0
+cab, 0
cadaques.museum, 0
cagliari.it, 0
cahcesuolo.no, 0
california.museum, 0
caltanissetta.it, 0
cambridge.museum, 0
+camera, 0
+camp, 0
campidano-medio.it, 0
campidanomedio.it, 0
campobasso.it, 0
can.museum, 0
canada.museum, 0
capebreton.museum, 0
+caravan, 0
carbonia-iglesias.it, 0
carboniaiglesias.it, 0
+cards, 0
+career, 0
+careers, 0
cargo.aero, 0
carrara-massa.it, 0
carraramassa.it, 0
carrier.museum, 0
cartoonart.museum, 0
+casa, 0
casadelamoneda.museum, 0
caserta.it, 0
casino.hu, 0
@@ -630,6 +664,7 @@ castres.museum, 0
cat, 0
catania.it, 0
catanzaro.it, 0
+catering, 0
catering.aero, 0
cb.it, 0
cbg.ru, 0
@@ -695,7 +730,9 @@ cd, 0
ce.it, 0
cechire.com, 4
celtic.museum, 0
+center, 0
center.museum, 0
+ceo, 0
certification.aero, 0
cesena-forli.it, 0
cesenaforli.it, 0
@@ -707,6 +744,7 @@ chambagri.fr, 0
championship.aero, 0
charter.aero, 0
chattanooga.museum, 0
+cheap, 0
chel.ru, 0
cheltenham.museum, 0
chelyabinsk.ru, 0
@@ -753,6 +791,7 @@ chosei.chiba.jp, 0
choshi.chiba.jp, 0
choyo.kumamoto.jp, 0
christiansburg.museum, 0
+christmas, 0
chtr.k12.ma.us, 0
chukotka.ru, 0
chungbuk.kr, 0
@@ -786,9 +825,14 @@ ck, 2
ck.ua, 0
cl, 0
cl.it, 0
+cleaning, 0
clinton.museum, 0
clock.museum, 0
+clothing, 0
+cloudcontrolapp.com, 4
+cloudcontrolled.com, 4
cloudfront.net, 4
+club, 0
club.aero, 0
club.tw, 0
cm, 0
@@ -831,6 +875,7 @@ co.mw, 0
co.na, 0
co.nl, 4
co.no, 4
+co.om, 0
co.pl, 4
co.pn, 0
co.pw, 0
@@ -851,10 +896,13 @@ co.ve, 0
co.vi, 0
coal.museum, 0
coastaldefence.museum, 0
+codes, 0
codespot.com, 4
cody.museum, 0
+coffee, 0
coldwar.museum, 0
collection.museum, 0
+college, 0
colonialwilliamsburg.museum, 0
coloradoplateau.museum, 0
columbia.museum, 0
@@ -866,6 +914,7 @@ com.ag, 0
com.ai, 0
com.al, 0
com.an, 0
+com.ar, 0
com.au, 0
com.aw, 0
com.az, 0
@@ -906,6 +955,7 @@ com.hk, 0
com.hn, 0
com.hr, 0
com.ht, 0
+com.im, 0
com.io, 0
com.iq, 0
com.is, 0
@@ -927,6 +977,7 @@ com.mg, 0
com.mk, 0
com.ml, 0
com.mo, 0
+com.mt, 0
com.mu, 0
com.mv, 0
com.mw, 0
@@ -936,6 +987,7 @@ com.na, 0
com.nf, 0
com.ng, 0
com.nr, 0
+com.om, 0
com.pa, 0
com.pe, 0
com.pf, 0
@@ -961,6 +1013,7 @@ com.sl, 0
com.sn, 0
com.so, 0
com.st, 0
+com.sv, 0
com.sy, 0
com.tj, 0
com.tm, 0
@@ -979,21 +1032,31 @@ com.vn, 0
com.ws, 0
communication.museum, 0
communications.museum, 0
+community, 0
community.museum, 0
como.it, 0
+company, 0
+compute-1.amazonaws.com, 4
+compute.amazonaws.com, 4
+computer, 0
computer.museum, 0
computerhistory.museum, 0
+condos, 0
conf.au, 0
conf.lv, 0
conference.aero, 0
-congresodelalengua3.ar, 1
+construction, 0
consulado.st, 0
consultant.aero, 0
+consulting, 0
consulting.aero, 0
contemporary.museum, 0
contemporaryart.museum, 0
+contractors, 0
control.aero, 0
convent.museum, 0
+cooking, 0
+cool, 0
coop, 0
coop.br, 0
coop.ht, 0
@@ -1008,6 +1071,7 @@ corvette.museum, 0
cosenza.it, 0
costume.museum, 0
council.aero, 0
+country, 0
countryestate.museum, 0
county.museum, 0
cpa.pro, 0
@@ -1022,7 +1086,9 @@ cremona.it, 0
crew.aero, 0
crimea.ua, 0
crotone.it, 0
+cruises, 0
cs.it, 0
+csiro.au, 1
ct.it, 0
ct.us, 0
cu, 0
@@ -1030,6 +1096,7 @@ cultural.museum, 0
culturalcenter.museum, 0
culture.museum, 0
cuneo.it, 0
+cupcake.is, 4
cv, 0
cv.ua, 0
cw, 0
@@ -1052,9 +1119,11 @@ daito.osaka.jp, 0
daiwa.hiroshima.jp, 0
dali.museum, 0
dallas.museum, 0
+dance, 0
database.museum, 0
date.fukushima.jp, 0
date.hokkaido.jp, 0
+dating, 0
davvenjarga.no, 0
davvesiida.no, 0
dazaifu.fukuoka.jp, 0
@@ -1070,15 +1139,19 @@ delaware.museum, 0
dell-ogliastra.it, 0
dellogliastra.it, 0
delmenhorst.museum, 0
+democrat, 0
denmark.museum, 0
dep.no, 0
depot.museum, 0
+desi, 0
design.aero, 0
design.museum, 0
detroit.museum, 0
dgca.aero, 0
+diamonds, 0
dielddanuorri.no, 0
dinosaur.museum, 0
+directory, 0
discovery.museum, 0
divtasvuodna.no, 0
divttasvuotna.no, 0
@@ -1090,6 +1163,7 @@ dn.ua, 0
dnepropetrovsk.ua, 0
dni.us, 0
dnipropetrovsk.ua, 0
+dnp, 0
dnsalias.com, 4
dnsalias.net, 4
dnsalias.org, 4
@@ -1101,6 +1175,7 @@ does-it.net, 4
doesntexist.com, 4
doesntexist.org, 4
dolls.museum, 0
+domains, 0
dominic.ua, 0
donetsk.ua, 0
donna.no, 0
@@ -1173,6 +1248,7 @@ edu.ac, 0
edu.af, 0
edu.al, 0
edu.an, 0
+edu.ar, 0
edu.au, 0
edu.az, 0
edu.ba, 0
@@ -1232,12 +1308,14 @@ edu.mk, 0
edu.ml, 0
edu.mn, 0
edu.mo, 0
+edu.mt, 0
edu.mv, 0
edu.mw, 0
edu.mx, 0
edu.my, 0
edu.ng, 0
edu.nr, 0
+edu.om, 0
edu.pa, 0
edu.pe, 0
edu.pf, 0
@@ -1261,6 +1339,7 @@ edu.sg, 0
edu.sl, 0
edu.sn, 0
edu.st, 0
+edu.sv, 0
edu.sy, 0
edu.tj, 0
edu.tm, 0
@@ -1273,7 +1352,7 @@ edu.vc, 0
edu.ve, 0
edu.vn, 0
edu.ws, 0
-educ.ar, 1
+education, 0
education.museum, 0
educational.museum, 0
educator.aero, 0
@@ -1298,6 +1377,7 @@ elburg.museum, 0
elk.pl, 0
elvendrell.museum, 0
elverum.no, 0
+email, 0
embaixada.st, 0
embetsu.hokkaido.jp, 0
embroidery.museum, 0
@@ -1319,11 +1399,13 @@ england.museum, 0
eniwa.hokkaido.jp, 0
enna.it, 0
ens.tn, 0
+enterprises, 0
entertainment.aero, 0
entomology.museum, 0
environment.museum, 0
environmentalconservation.museum, 0
epilepsy.museum, 0
+equipment, 0
equipment.aero, 0
er, 2
erimo.hokkaido.jp, 0
@@ -1340,6 +1422,7 @@ est-a-la-masion.com, 4
est-le-patron.com, 4
est-mon-blogueur.com, 4
est.pr, 0
+estate, 0
estate.museum, 0
et, 2
etajima.hiroshima.jp, 0
@@ -1349,16 +1432,21 @@ eti.br, 0
etne.no, 0
etnedal.no, 0
eu, 0
+eu-west-1.compute.amazonaws.com, 4
eu.com, 4
eu.int, 0
eun.eg, 0
+eus, 0
evenassi.no, 0
evenes.no, 0
+events, 0
evje-og-hornnes.no, 0
exchange.aero, 0
exeter.museum, 0
exhibition.museum, 0
+expert, 0
experts-comptables.fr, 0
+exposed, 0
express.aero, 0
f.bg, 0
f.se, 0
@@ -1366,6 +1454,7 @@ fam.pk, 0
family.museum, 0
far.br, 0
fareast.ru, 0
+farm, 0
farm.museum, 0
farmequipment.museum, 0
farmers.museum, 0
@@ -1377,6 +1466,7 @@ fe.it, 0
fed.us, 0
federation.aero, 0
fedje.no, 0
+feedback, 0
fermo.it, 0
ferrara.it, 0
fet.no, 0
@@ -1407,6 +1497,8 @@ firm.ht, 0
firm.in, 0
firm.nf, 0
firm.ro, 0
+fish, 0
+fishing, 0
fitjar.no, 0
fj, 2
fj.cn, 0
@@ -1421,10 +1513,12 @@ flatanger.no, 0
flekkefjord.no, 0
flesberg.no, 0
flight.aero, 0
+flights, 0
flog.br, 0
flora.no, 0
florence.it, 0
florida.museum, 0
+florist, 0
floro.no, 0
fm, 0
fm.br, 0
@@ -1452,6 +1546,7 @@ fortworth.museum, 0
forum.hu, 0
fosnes.no, 0
fot.br, 0
+foundation, 0
foundation.museum, 0
fr, 0
fr.it, 0
@@ -1466,6 +1561,7 @@ freiburg.museum, 0
freight.aero, 0
fribourg.museum, 0
frog.museum, 0
+frogans, 0
frogn.no, 0
froland.no, 0
from-ak.com, 4
@@ -1579,6 +1675,7 @@ fusa.no, 0
fuso.aichi.jp, 0
fussa.tokyo.jp, 0
futaba.fukushima.jp, 0
+futbol, 0
futsu.nagasaki.jp, 0
futtsu.chiba.jp, 0
fylkesbibl.no, 0
@@ -1589,6 +1686,8 @@ g12.br, 0
ga, 0
ga.us, 0
gaivuotna.no, 0
+gal, 0
+gallery, 0
gallery.museum, 0
galsa.no, 0
gamagori.aichi.jp, 0
@@ -1628,11 +1727,13 @@ getmyip.com, 4
gets-it.net, 4
gf, 0
gg, 0
+ggee, 0
ggf.br, 0
gh, 0
gi, 0
giehtavuoatna.no, 0
giessen.museum, 0
+gift, 0
gifu.gifu.jp, 0
gifu.jp, 0
gildeskal.no, 0
@@ -1648,9 +1749,13 @@ gjesdal.no, 0
gjovik.no, 0
gl, 0
glas.museum, 0
+glass, 0
glass.museum, 0
gliding.aero, 0
gliwice.pl, 0
+global.prod.fastly.net, 4
+global.ssl.fastly.net, 4
+globo, 0
glogow.pl, 0
gloppen.no, 0
gm, 0
@@ -1669,6 +1774,7 @@ go.th, 0
go.tj, 0
go.tz, 0
go.ug, 0
+gob.ar, 0
gob.bo, 0
gob.cl, 0
gob.do, 0
@@ -1680,7 +1786,7 @@ gob.mx, 0
gob.pa, 0
gob.pe, 0
gob.pk, 0
-gobiernoelectronico.ar, 1
+gob.sv, 0
gobo.wakayama.jp, 0
godo.gifu.jp, 0
gojome.akita.jp, 0
@@ -1691,6 +1797,7 @@ gon.pk, 0
gonohe.aomori.jp, 0
googleapis.com, 4
googlecode.com, 4
+gop, 0
gop.pk, 0
gorge.museum, 0
gorizia.it, 0
@@ -1745,20 +1852,17 @@ gov.ec, 0
gov.ee, 0
gov.eg, 0
gov.ge, 0
-gov.gg, 0
gov.gh, 0
gov.gi, 0
gov.gn, 0
gov.gr, 0
gov.hk, 0
gov.ie, 0
-gov.im, 0
gov.in, 0
gov.iq, 0
gov.ir, 0
gov.is, 0
gov.it, 0
-gov.je, 0
gov.jo, 0
gov.kg, 0
gov.ki, 0
@@ -1790,6 +1894,7 @@ gov.my, 0
gov.nc.tr, 0
gov.ng, 0
gov.nr, 0
+gov.om, 0
gov.ph, 0
gov.pk, 0
gov.pl, 0
@@ -1836,6 +1941,7 @@ gran.no, 0
grandrapids.museum, 0
grane.no, 0
granvin.no, 0
+graphics, 0
gratangen.no, 0
graz.museum, 0
greta.fr, 0
@@ -1878,10 +1984,13 @@ gu, 2
gu.us, 0
gub.uy, 0
guernsey.museum, 0
+guide, 0
+guitars, 0
gujo.gifu.jp, 0
gulen.no, 0
gunma.jp, 0
guovdageaidnu.no, 0
+guru, 0
gushikami.okinawa.jp, 0
gv.ao, 0
gv.at, 0
@@ -1961,6 +2070,7 @@ hatoyama.saitama.jp, 0
hatsukaichi.hiroshima.jp, 0
hattfjelldal.no, 0
haugesund.no, 0
+haus, 0
hawaii.museum, 0
hayakawa.yamanashi.jp, 0
hayashima.okayama.jp, 0
@@ -1981,6 +2091,8 @@ hemsedal.no, 0
herad.no, 0
here-for-more.info, 4
heritage.museum, 0
+herokuapp.com, 4
+herokussl.com, 4
heroy.more-og-romsdal.no, 0
heroy.nordland.no, 0
hi.cn, 0
@@ -2084,7 +2196,9 @@ hokuryu.hokkaido.jp, 0
hokuto.hokkaido.jp, 0
hokuto.yamanashi.jp, 0
hol.no, 0
+holdings, 0
hole.no, 0
+holiday, 0
holmestrand.no, 0
holtalen.no, 0
home.dyndns.org, 4
@@ -2096,6 +2210,7 @@ homeip.net, 4
homelinux.com, 4
homelinux.net, 4
homelinux.org, 4
+homes, 0
homeunix.com, 4
homeunix.net, 4
homeunix.org, 4
@@ -2110,10 +2225,12 @@ hornindal.no, 0
horokanai.hokkaido.jp, 0
horology.museum, 0
horonobe.hokkaido.jp, 0
+horse, 0
horten.no, 0
hotel.hu, 0
hotel.lk, 0
hotel.tz, 0
+house, 0
house.museum, 0
hoyanger.no, 0
hoylandet.no, 0
@@ -2198,6 +2315,7 @@ imakane.hokkaido.jp, 0
imari.saga.jp, 0
imb.br, 0
imizu.toyama.jp, 0
+immobilien, 0
imperia.it, 0
in, 0
in-addr.arpa, 0
@@ -2229,6 +2347,7 @@ indian.museum, 0
indiana.museum, 0
indianapolis.museum, 0
indianmarket.museum, 0
+industries, 0
ine.kyoto.jp, 0
inf.br, 0
inf.cu, 0
@@ -2260,9 +2379,12 @@ info.ve, 0
info.vn, 0
ing.pa, 0
ingatlan.hu, 0
+ink, 0
ino.kochi.jp, 0
+institute, 0
insurance.aero, 0
int, 0
+int.ar, 0
int.az, 0
int.bo, 0
int.ci, 0
@@ -2280,6 +2402,7 @@ int.tt, 0
int.vn, 0
intelligence.museum, 0
interactive.museum, 0
+international, 0
intl.tn, 0
inuyama.aichi.jp, 0
inzai.chiba.jp, 0
@@ -2453,6 +2576,7 @@ jeonnam.kr, 0
jerusalem.museum, 0
jessheim.no, 0
jet.uk, 1
+jetzt, 0
jevnaker.no, 0
jewelry.museum, 0
jewish.museum, 0
@@ -2537,7 +2661,6 @@ k12.pa.us, 0
k12.pr.us, 0
k12.ri.us, 0
k12.sc.us, 0
-k12.sd.us, 0
k12.tn.us, 0
k12.tx.us, 0
k12.ut.us, 0
@@ -2671,6 +2794,7 @@ katsuragi.wakayama.jp, 0
katsushika.tokyo.jp, 0
katsuura.chiba.jp, 0
katsuyama.fukui.jp, 0
+kaufen, 0
kautokeino.no, 0
kawaba.gunma.jp, 0
kawachinagano.osaka.jp, 0
@@ -2735,6 +2859,7 @@ kijo.miyazaki.jp, 0
kikonai.hokkaido.jp, 0
kikuchi.kumamoto.jp, 0
kikugawa.shizuoka.jp, 0
+kim, 0
kimino.wakayama.jp, 0
kimitsu.chiba.jp, 0
kimobetsu.hokkaido.jp, 0
@@ -2773,7 +2898,9 @@ kitanakagusuku.okinawa.jp, 0
kitashiobara.fukushima.jp, 0
kitaura.miyazaki.jp, 0
kitayama.wakayama.jp, 0
+kitchen, 0
kiwa.mie.jp, 0
+kiwi, 0
kiyama.saga.jp, 0
kiyokawa.kanagawa.jp, 0
kiyosato.hokkaido.jp, 0
@@ -2860,6 +2987,8 @@ kraanghke.no, 0
kragero.no, 0
krakow.pl, 0
krasnoyarsk.ru, 0
+krd, 0
+kred, 0
kristiansand.no, 0
kristiansund.no, 0
krodsherad.no, 0
@@ -2951,11 +3080,13 @@ la.us, 0
laakesvuemie.no, 0
labor.museum, 0
labour.museum, 0
+lacaixa, 0
lahppi.no, 0
lajolla.museum, 0
lakas.hu, 0
lanbib.se, 0
lancashire.museum, 0
+land, 0
land-4-sale.us, 4
landes.museum, 0
langevag.no, 0
@@ -3054,18 +3185,20 @@ lib.vi.us, 0
lib.vt.us, 0
lib.wa.us, 0
lib.wi.us, 0
-lib.wv.us, 0
lib.wy.us, 0
lier.no, 0
lierne.no, 0
+lighting, 0
likes-pie.com, 4
likescandy.com, 4
lillehammer.no, 0
lillesand.no, 0
limanowa.pl, 0
+limo, 0
lincoln.museum, 0
lindas.no, 0
lindesnes.no, 0
+link, 0
linz.museum, 0
lipetsk.ru, 0
living.museum, 0
@@ -3081,6 +3214,7 @@ lodingen.no, 0
logistics.aero, 0
lom.no, 0
lomza.pl, 0
+london, 0
london.museum, 0
loppa.no, 0
lorenskog.no, 0
@@ -3109,7 +3243,9 @@ lunner.no, 0
luroy.no, 0
luster.no, 0
lutsk.ua, 0
+luxe, 0
luxembourg.museum, 0
+luxury, 0
luzern.museum, 0
lv, 0
lv.ua, 0
@@ -3132,6 +3268,7 @@ magnitka.ru, 0
maibara.shiga.jp, 0
mail.pl, 0
maintenance.aero, 0
+maison, 0
maizuru.kyoto.jp, 0
makinohara.shizuoka.jp, 0
makurazaki.kagoshima.jp, 0
@@ -3142,8 +3279,10 @@ malopolska.pl, 0
malselv.no, 0
malvik.no, 0
mamurogawa.yamagata.jp, 0
+management, 0
manchester.museum, 0
mandal.no, 0
+mango, 0
maniwa.okayama.jp, 0
manno.kagawa.jp, 0
mansion.museum, 0
@@ -3157,6 +3296,7 @@ marine.ru, 0
maritime.museum, 0
maritimo.museum, 0
marker.no, 0
+marketing, 0
marketplace.aero, 0
marnardal.no, 0
marugame.kagawa.jp, 0
@@ -3205,12 +3345,12 @@ me, 0
me.it, 0
me.tz, 0
me.us, 0
-mecon.ar, 1
med.br, 0
med.ec, 0
med.ee, 0
med.ht, 0
med.ly, 0
+med.om, 0
med.pa, 0
med.pl, 0
med.pro, 0
@@ -3222,12 +3362,12 @@ media.aero, 0
media.hu, 0
media.museum, 0
media.pl, 0
-mediaphone.om, 1
medical.museum, 0
medio-campidano.it, 0
mediocampidano.it, 0
medizinhistorisches.museum, 0
meeres.museum, 0
+meet, 0
meguro.tokyo.jp, 0
meiwa.gunma.jp, 0
meiwa.mie.jp, 0
@@ -3236,6 +3376,7 @@ meldal.no, 0
melhus.no, 0
meloy.no, 0
memorial.museum, 0
+menu, 0
meraker.no, 0
merseine.nu, 4
mesaverde.museum, 0
@@ -3245,6 +3386,7 @@ mh, 0
mi.it, 0
mi.th, 0
mi.us, 0
+miami, 0
miasa.nagano.jp, 0
miasta.pl, 0
mibu.tochigi.jp, 0
@@ -3275,6 +3417,7 @@ mil, 0
mil.ac, 0
mil.ae, 0
mil.al, 0
+mil.ar, 0
mil.az, 0
mil.ba, 0
mil.bo, 0
@@ -3302,6 +3445,7 @@ mil.lv, 0
mil.mg, 0
mil.mv, 0
mil.my, 0
+mil.ng, 0
mil.no, 0
mil.pe, 0
mil.ph, 0
@@ -3355,6 +3499,7 @@ minato.tokyo.jp, 0
mincom.tn, 0
mine.nu, 4
miners.museum, 0
+mini, 0
mining.museum, 0
minnesota.museum, 0
mino.gifu.jp, 0
@@ -3426,20 +3571,24 @@ mobara.chiba.jp, 0
mobi, 0
mobi.gp, 0
mobi.na, 0
+mobi.ng, 0
mobi.tt, 0
mobi.tz, 0
mochizuki.nagano.jp, 0
mod.gi, 0
mod.uk, 1
+moda, 0
modalen.no, 0
modelling.aero, 0
modena.it, 0
modern.museum, 0
modum.no, 0
+moe, 0
moka.tochigi.jp, 0
molde.no, 0
moma.museum, 0
mombetsu.hokkaido.jp, 0
+monash, 0
money.museum, 0
monmouth.museum, 0
monticello.museum, 0
@@ -3457,8 +3606,10 @@ morioka.iwate.jp, 0
moriya.ibaraki.jp, 0
moriyama.shiga.jp, 0
moriyoshi.akita.jp, 0
+mormon, 0
morotsuka.miyazaki.jp, 0
moroyama.saitama.jp, 0
+moscow, 0
moscow.museum, 0
moseushi.hokkaido.jp, 0
mosjoen.no, 0
@@ -3469,6 +3620,7 @@ mosvik.no, 0
motegi.tochigi.jp, 0
motobu.okinawa.jp, 0
motorcycle.museum, 0
+motorcycles, 0
motosu.gifu.jp, 0
motoyama.kochi.jp, 0
mp, 0
@@ -3481,7 +3633,7 @@ ms.it, 0
ms.kr, 0
ms.us, 0
msk.ru, 0
-mt, 2
+mt, 0
mt.it, 0
mt.us, 0
mu, 0
@@ -3509,6 +3661,7 @@ museum, 0
museum.mv, 0
museum.mw, 0
museum.no, 0
+museum.om, 0
museum.tt, 0
museumcenter.museum, 0
museumvereniging.museum, 0
@@ -3534,7 +3687,6 @@ na.it, 0
naamesjevuemie.no, 0
nabari.mie.jp, 0
nachikatsuura.wakayama.jp, 0
-nacion.ar, 1
nagahama.shiga.jp, 0
nagai.yamagata.jp, 0
nagakute.aichi.jp, 0
@@ -3554,6 +3706,7 @@ nagawa.nagano.jp, 0
nagi.okayama.jp, 0
nagiso.nagano.jp, 0
nago.okinawa.jp, 0
+nagoya, 0
nagoya.jp, 2
naha.okinawa.jp, 0
nahari.kochi.jp, 0
@@ -3595,6 +3748,7 @@ name.mk, 0
name.mv, 0
name.my, 0
name.na, 0
+name.ng, 0
name.pr, 0
name.qa, 0
name.tj, 0
@@ -3653,8 +3807,6 @@ naustdal.no, 0
naval.museum, 0
navigation.aero, 0
navuotna.no, 0
-nawras.om, 1
-nawrastelecom.om, 1
nayoro.hokkaido.jp, 0
nb.ca, 0
nc, 0
@@ -3688,6 +3840,7 @@ net.ag, 0
net.ai, 0
net.al, 0
net.an, 0
+net.ar, 0
net.au, 0
net.az, 0
net.ba, 0
@@ -3744,6 +3897,7 @@ net.me, 0
net.mk, 0
net.ml, 0
net.mo, 0
+net.mt, 0
net.mu, 0
net.mv, 0
net.mw, 0
@@ -3752,6 +3906,7 @@ net.my, 0
net.nf, 0
net.ng, 0
net.nr, 0
+net.om, 0
net.pa, 0
net.pe, 0
net.ph, 0
@@ -3790,7 +3945,9 @@ net.ve, 0
net.vi, 0
net.vn, 0
net.ws, 0
+network, 0
neues.museum, 0
+neustar, 0
newhampshire.museum, 0
newjersey.museum, 0
newmexico.museum, 0
@@ -3807,8 +3964,6 @@ ngo.ph, 0
ngo.pl, 0
nh.us, 0
ni, 2
-nic.ar, 1
-nic.im, 0
nic.in, 0
nic.tj, 0
nic.tr, 1
@@ -3827,6 +3982,7 @@ nikaho.akita.jp, 0
niki.hokkaido.jp, 0
nikko.tochigi.jp, 0
nikolaev.ua, 0
+ninja, 0
ninohe.iwate.jp, 0
ninomiya.kanagawa.jp, 0
nirasaki.yamanashi.jp, 0
@@ -3919,6 +4075,7 @@ nowaruda.pl, 0
nozawaonsen.nagano.jp, 0
np, 2
nr, 0
+nrw, 0
nrw.museum, 0
ns.ca, 0
nsk.ru, 0
@@ -3928,7 +4085,6 @@ nsw.edu.au, 0
nt.au, 0
nt.ca, 0
nt.edu.au, 0
-nt.gov.au, 0
nt.no, 0
nt.ro, 0
ntr.br, 0
@@ -4024,6 +4180,7 @@ okazaki.aichi.jp, 0
okegawa.saitama.jp, 0
oketo.hokkaido.jp, 0
oki.fukuoka.jp, 0
+okinawa, 0
okinawa.jp, 0
okinawa.okinawa.jp, 0
okinoshima.shimane.jp, 0
@@ -4039,14 +4196,11 @@ olbiatempio.it, 0
olecko.pl, 0
olkusz.pl, 0
olsztyn.pl, 0
-om, 2
+om, 0
omachi.nagano.jp, 0
omachi.saga.jp, 0
omaezaki.shizuoka.jp, 0
omaha.museum, 0
-omanmobile.om, 1
-omanpost.om, 1
-omantel.om, 1
omasvuotna.no, 0
ome.tokyo.jp, 0
omi.nagano.jp, 0
@@ -4064,6 +4218,7 @@ on.ca, 0
onagawa.miyagi.jp, 0
onga.fukuoka.jp, 0
onjuku.chiba.jp, 0
+onl, 0
online.museum, 0
onna.okinawa.jp, 0
ono.fukui.jp, 0
@@ -4107,6 +4262,7 @@ org.ag, 0
org.ai, 0
org.al, 0
org.an, 0
+org.ar, 0
org.au, 0
org.az, 0
org.ba, 0
@@ -4173,6 +4329,7 @@ org.mk, 0
org.ml, 0
org.mn, 0
org.mo, 0
+org.mt, 0
org.mu, 0
org.mv, 0
org.mw, 0
@@ -4181,6 +4338,7 @@ org.my, 0
org.na, 0
org.ng, 0
org.nr, 0
+org.om, 0
org.pa, 0
org.pe, 0
org.pf, 0
@@ -4207,6 +4365,7 @@ org.sl, 0
org.sn, 0
org.so, 0
org.st, 0
+org.sv, 0
org.sy, 0
org.sz, 0
org.tj, 0
@@ -4271,12 +4430,14 @@ otoineppu.hokkaido.jp, 0
otoyo.kochi.jp, 0
otsu.shiga.jp, 0
otsuchi.iwate.jp, 0
+otsuka, 0
otsuki.kochi.jp, 0
otsuki.yamanashi.jp, 0
ouchi.saga.jp, 0
ouda.nara.jp, 0
oumu.hokkaido.jp, 0
overhalla.no, 0
+ovh, 0
ovre-eiker.no, 0
owani.aomori.jp, 0
owariasahi.aichi.jp, 0
@@ -4315,6 +4476,8 @@ parliament.uk, 1
parma.it, 0
paroch.k12.ma.us, 0
parti.se, 0
+partners, 0
+parts, 0
pasadena.museum, 0
passenger-association.aero, 0
pavia.it, 0
@@ -4349,12 +4512,17 @@ philadelphia.museum, 0
philadelphiaarea.museum, 0
philately.museum, 0
phoenix.museum, 0
+photo, 0
+photography, 0
photography.museum, 0
+photos, 0
pi.it, 0
piacenza.it, 0
+pics, 0
pila.pl, 0
pilot.aero, 0
pilots.museum, 0
+pink, 0
pippu.hokkaido.jp, 0
pisa.it, 0
pistoia.it, 0
@@ -4370,6 +4538,7 @@ plaza.museum, 0
plc.co.im, 0
plc.ly, 0
plo.ps, 0
+plumbing, 0
pm, 0
pn, 0
pn.it, 0
@@ -4407,6 +4576,7 @@ pr, 0
pr.it, 0
pr.us, 0
prato.it, 0
+praxi, 0
prd.fr, 0
prd.km, 0
prd.mg, 0
@@ -4434,14 +4604,16 @@ pro.ec, 0
pro.ht, 0
pro.mv, 0
pro.na, 0
+pro.om, 0
pro.pr, 0
pro.tt, 0
pro.vn, 0
prochowice.pl, 0
production.aero, 0
+productions, 0
prof.pr, 0
project.museum, 0
-promocion.ar, 1
+properties, 0
pruszkow.pl, 0
przeworsk.pl, 0
ps, 0
@@ -4452,6 +4624,7 @@ pt, 0
pt.it, 0
ptz.ru, 0
pu.it, 0
+pub, 0
pub.sa, 0
publ.pt, 0
public.museum, 0
@@ -4472,7 +4645,9 @@ qh.cn, 0
qld.au, 0
qld.edu.au, 0
qld.gov.au, 0
+qpon, 0
qsl.br, 0
+quebec, 0
quebec.museum, 0
r.bg, 0
r.se, 0
@@ -4488,7 +4663,6 @@ railroad.museum, 0
railway.museum, 0
raisa.no, 0
rakkestad.no, 0
-rakpetroleum.om, 1
ralingen.no, 0
rana.no, 0
randaberg.no, 0
@@ -4508,7 +4682,10 @@ rec.br, 0
rec.co, 0
rec.nf, 0
rec.ro, 0
+recipes, 0
recreation.aero, 0
+red, 0
+red.sv, 0
reggio-calabria.it, 0
reggio-emilia.it, 0
reggiocalabria.it, 0
@@ -4516,21 +4693,27 @@ reggioemilia.it, 0
reklam.hu, 0
rel.ht, 0
rel.pl, 0
+ren, 0
rendalen.no, 0
rennebu.no, 0
rennesoy.no, 0
+rentals, 0
rep.kp, 0
+repair, 0
repbody.aero, 0
+report, 0
res.aero, 0
res.in, 0
research.aero, 0
research.museum, 0
resistance.museum, 0
-retina.ar, 1
+rest, 0
+reviews, 0
rg.it, 0
rhcloud.com, 4
ri.it, 0
ri.us, 0
+rich, 0
rieti.it, 0
rifu.miyagi.jp, 0
riik.ee, 0
@@ -4556,10 +4739,13 @@ rnrt.tn, 0
rns.tn, 0
rnu.tn, 0
ro, 0
+ro.com, 4
ro.it, 0
roan.no, 0
rochester.museum, 0
rockart.museum, 0
+rocks, 0
+rodeo, 0
rodoy.no, 0
rokunohe.aomori.jp, 0
rollag.no, 0
@@ -4580,6 +4766,7 @@ rs.ba, 0
ru, 0
ru.com, 4
rubtsovsk.ru, 0
+ruhr, 0
ruovat.no, 0
russia.museum, 0
rv.ua, 0
@@ -4589,6 +4776,7 @@ rybnik.pl, 0
rygge.no, 0
ryokami.saitama.jp, 0
ryugasaki.ibaraki.jp, 0
+ryukyu, 0
ryuoh.shiga.jp, 0
rzeszow.pl, 0
s.bg, 0
@@ -4613,12 +4801,14 @@ s3-website-us-west-1.amazonaws.com, 4
s3-website-us-west-2.amazonaws.com, 4
s3.amazonaws.com, 4
sa, 0
+sa-east-1.compute.amazonaws.com, 4
sa.au, 0
sa.com, 4
sa.cr, 0
sa.edu.au, 0
sa.gov.au, 0
sa.it, 0
+saarland, 0
sabae.fukui.jp, 0
sado.niigata.jp, 0
safety.aero, 0
@@ -4719,13 +4909,12 @@ sc.tz, 0
sc.ug, 0
sc.us, 0
sch.ae, 0
-sch.gg, 0
sch.id, 0
sch.ir, 0
-sch.je, 0
sch.jo, 0
sch.lk, 0
sch.ly, 0
+sch.ng, 0
sch.qa, 0
sch.sa, 0
sch.uk, 2
@@ -4803,6 +4992,7 @@ settsu.osaka.jp, 0
sevastopol.ua, 0
sex.hu, 0
sex.pl, 0
+sexy, 0
sf.no, 0
sg, 0
sh, 0
@@ -4830,6 +5020,7 @@ shikaoi.hokkaido.jp, 0
shikatsu.aichi.jp, 0
shiki.saitama.jp, 0
shikokuchuo.ehime.jp, 0
+shiksha, 0
shima.mie.jp, 0
shimabara.nagasaki.jp, 0
shimada.shizuoka.jp, 0
@@ -4896,6 +5087,7 @@ shizukuishi.iwate.jp, 0
shizuoka.jp, 0
shizuoka.shizuoka.jp, 0
shobara.hiroshima.jp, 0
+shoes, 0
shonai.fukuoka.jp, 0
shonai.yamagata.jp, 0
shoo.okayama.jp, 0
@@ -4912,13 +5104,13 @@ si.it, 0
sibenik.museum, 0
siedlce.pl, 0
siellak.no, 0
-siemens.om, 1
siena.it, 0
sigdal.no, 0
siljan.no, 0
silk.museum, 0
simbirsk.ru, 0
simple-url.com, 4
+singles, 0
siracusa.it, 0
sirdal.no, 0
sk, 0
@@ -4963,24 +5155,27 @@ so.gov.pl, 0
so.it, 0
sobetsu.hokkaido.jp, 0
soc.lk, 0
+social, 0
society.museum, 0
sodegaura.chiba.jp, 0
soeda.fukuoka.jp, 0
software.aero, 0
sogndal.no, 0
sogne.no, 0
+sohu, 0
soja.okayama.jp, 0
soka.saitama.jp, 0
sokndal.no, 0
sola.no, 0
+solar, 0
sologne.museum, 0
solund.no, 0
+solutions, 0
soma.fukushima.jp, 0
somna.no, 0
sondre-land.no, 0
sondrio.it, 0
songdalen.no, 0
-songfest.om, 1
soni.nara.jp, 0
soo.kagoshima.jp, 0
sopot.pl, 0
@@ -5026,7 +5221,6 @@ starnberg.museum, 0
starostwo.gov.pl, 0
stat.no, 0
state.museum, 0
-statecouncil.om, 1
stateofdelaware.museum, 0
stathelle.no, 0
station.museum, 0
@@ -5080,6 +5274,9 @@ sumy.ua, 0
sunagawa.hokkaido.jp, 0
sund.no, 0
sunndal.no, 0
+supplies, 0
+supply, 0
+support, 0
surgeonshall.museum, 0
surgut.ru, 0
surnadal.no, 0
@@ -5091,7 +5288,7 @@ suwalki.pl, 0
suzaka.nagano.jp, 0
suzu.ishikawa.jp, 0
suzuka.mie.jp, 0
-sv, 2
+sv, 0
sv.it, 0
svalbard.no, 0
sveio.no, 0
@@ -5106,6 +5303,7 @@ sx.cn, 0
sy, 0
sydney.museum, 0
sykkylven.no, 0
+systems, 0
syzran.ru, 0
sz, 0
szczecin.pl, 0
@@ -5210,6 +5408,7 @@ tateyama.chiba.jp, 0
tateyama.toyama.jp, 0
tatsuno.hyogo.jp, 0
tatsuno.nagano.jp, 0
+tattoo, 0
tawaramoto.nara.jp, 0
taxi.aero, 0
taxi.br, 0
@@ -5219,6 +5418,7 @@ td, 0
te.it, 0
te.ua, 0
teaches-yoga.com, 4
+technology, 0
technology.museum, 0
tel, 0
teledata.mz, 1
@@ -5245,11 +5445,13 @@ tgory.pl, 0
th, 0
theater.museum, 0
thruhere.net, 4
+tienda, 0
time.museum, 0
time.no, 0
timekeeping.museum, 0
tingvoll.no, 0
tinn.no, 0
+tips, 0
tj, 0
tj.cn, 0
tjeldsund.no, 0
@@ -5280,6 +5482,7 @@ tochigi.jp, 0
tochigi.tochigi.jp, 0
tochio.niigata.jp, 0
toda.saitama.jp, 0
+today, 0
toei.aichi.jp, 0
toga.toyama.jp, 0
togakushi.nagano.jp, 0
@@ -5302,6 +5505,7 @@ tokorozawa.saitama.jp, 0
tokushima.jp, 0
tokushima.tokushima.jp, 0
tokuyama.yamaguchi.jp, 0
+tokyo, 0
tokyo.jp, 0
tolga.no, 0
tom.ru, 0
@@ -5323,6 +5527,7 @@ tone.ibaraki.jp, 0
tono.iwate.jp, 0
tonosho.kagawa.jp, 0
tonsberg.no, 0
+tools, 0
toon.ehime.jp, 0
topology.museum, 0
torahime.shiga.jp, 0
@@ -5370,6 +5575,7 @@ trader.aero, 0
trading.aero, 0
traeumtgerade.de, 4
trainer.aero, 0
+training, 0
trana.no, 0
tranby.no, 0
trani-andria-barletta.it, 0
@@ -5428,7 +5634,9 @@ tsushima.nagasaki.jp, 0
tsuwano.shimane.jp, 0
tsuyama.okayama.jp, 0
tt, 0
+tt.im, 0
tula.ru, 0
+tur.ar, 0
tur.br, 0
turek.pl, 0
turen.tn, 0
@@ -5438,6 +5646,7 @@ tuva.ru, 0
tv, 0
tv.bo, 0
tv.br, 0
+tv.im, 0
tv.it, 0
tv.na, 0
tv.sd, 0
@@ -5458,7 +5667,6 @@ tz, 0
u.bg, 0
u.se, 0
ua, 0
-uba.ar, 1
ube.yamaguchi.jp, 0
uchihara.ibaraki.jp, 0
uchiko.ehime.jp, 0
@@ -5501,6 +5709,7 @@ univ.sn, 0
university.museum, 0
unjarga.no, 0
unnan.shimane.jp, 0
+uno, 0
unsa.ba, 0
unzen.nagasaki.jp, 0
uonuma.niigata.jp, 0
@@ -5519,6 +5728,10 @@ urn.arpa, 0
uruma.okinawa.jp, 0
uryu.hokkaido.jp, 0
us, 0
+us-east-1.amazonaws.com, 4
+us-gov-west-1.compute.amazonaws.com, 4
+us-west-1.compute.amazonaws.com, 4
+us-west-2.compute.amazonaws.com, 4
us.com, 4
us.na, 0
us.org, 4
@@ -5560,6 +5773,7 @@ va.it, 0
va.no, 0
va.us, 0
vaapste.no, 0
+vacations, 0
vadso.no, 0
vaga.no, 0
vagan.no, 0
@@ -5585,9 +5799,11 @@ ve.it, 0
vefsn.no, 0
vega.no, 0
vegarshei.no, 0
+vegas, 0
venezia.it, 0
venice.it, 0
vennesla.no, 0
+ventures, 0
verbania.it, 0
vercelli.it, 0
verdal.no, 0
@@ -5609,6 +5825,7 @@ vgs.no, 0
vi, 0
vi.it, 0
vi.us, 0
+viajes, 0
vibo-valentia.it, 0
vibovalentia.it, 0
vic.au, 0
@@ -5620,12 +5837,14 @@ vik.no, 0
viking.museum, 0
vikna.no, 0
village.museum, 0
+villas, 0
vindafjord.no, 0
vinnica.ua, 0
vinnytsia.ua, 0
virginia.museum, 0
virtual.museum, 0
virtuel.museum, 0
+vision, 0
viterbo.it, 0
vlaanderen.museum, 0
vladikavkaz.ru, 0
@@ -5635,6 +5854,7 @@ vlog.br, 0
vn, 0
vn.ua, 0
voagat.no, 0
+vodka, 0
volda.no, 0
volgograd.ru, 0
volkenkunde.museum, 0
@@ -5643,6 +5863,10 @@ volyn.ua, 0
voronezh.ru, 0
voss.no, 0
vossevangen.no, 0
+vote, 0
+voting, 0
+voto, 0
+voyage, 0
vr.it, 0
vrn.ru, 0
vs.it, 0
@@ -5670,6 +5894,7 @@ wakuya.miyagi.jp, 0
walbrzych.pl, 0
wales.museum, 0
wallonie.museum, 0
+wang, 0
wanouchi.gifu.jp, 0
war.museum, 0
warabi.saitama.jp, 0
@@ -5679,6 +5904,7 @@ washingtondc.museum, 0
wassamu.hokkaido.jp, 0
watarai.mie.jp, 0
watari.miyagi.jp, 0
+watch, 0
watch-and-clock.museum, 0
watchandclock.museum, 0
waw.pl, 0
@@ -5695,6 +5921,7 @@ webhop.biz, 4
webhop.info, 4
webhop.net, 4
webhop.org, 4
+wed, 0
wegrow.pl, 0
western.museum, 0
westfalen.museum, 0
@@ -5702,6 +5929,8 @@ wf, 0
whaling.museum, 0
wi.us, 0
wielun.pl, 0
+wien, 0
+wiki, 0
wiki.br, 0
wildlife.museum, 0
williamsburg.museum, 0
@@ -5710,7 +5939,9 @@ wlocl.pl, 0
wloclawek.pl, 0
wodzislaw.pl, 0
wolomin.pl, 0
+work, 0
workinggroup.aero, 0
+works, 0
works.aero, 0
workshop.museum, 0
worse-than.tv, 4
@@ -5719,6 +5950,7 @@ wroc.pl, 0
wroclaw.pl, 0
ws, 0
ws.na, 0
+wtc, 0
wv.us, 0
www.ck, 1
www.ro, 0
@@ -5726,11 +5958,23 @@ wy.us, 0
x.bg, 0
x.se, 0
xj.cn, 0
+xn--1qqw23a, 0
+xn--3bst00m, 0
+xn--3ds443g, 0
xn--3e0b707e, 0
xn--45brj9c, 0
+xn--45q11c, 0
+xn--4gbrim, 0
xn--54b7fta0cc, 0
+xn--55qw42g, 0
+xn--55qx5d, 0
xn--55qx5d.cn, 0
xn--55qx5d.hk, 0
+xn--6frz82g, 0
+xn--6qq986b3xl, 0
+xn--80adxhks, 0
+xn--80asehdb, 0
+xn--80aswg, 0
xn--90a3ac, 0
xn--9dbhblg6di.museum, 0
xn--andy-ira.no, 0
@@ -5756,17 +6000,25 @@ xn--brnny-wuac.no, 0
xn--brnnysund-m8ac.no, 0
xn--brum-voa.no, 0
xn--btsfjord-9za.no, 0
+xn--c1avg, 0
+xn--cg4bki, 0
xn--ciqpn.hk, 0
xn--clchc0ea0b2g2a9gcd, 0
xn--comunicaes-v6a2o.museum, 0
xn--correios-e-telecomunicaes-ghc29a.museum, 0
+xn--czr694b, 0
+xn--czrs0t, 0
+xn--czru2d, 0
xn--czrw28b.tw, 0
+xn--d1acj3b, 0
xn--davvenjrga-y4a.no, 0
xn--dnna-gra.no, 0
xn--drbak-wua.no, 0
xn--dyry-ira.no, 0
xn--eveni-0qa01ga.no, 0
xn--finny-yua.no, 0
+xn--fiq228c5hs, 0
+xn--fiq64b, 0
xn--fiqs8s, 0
xn--fiqz9s, 0
xn--fjord-lra.no, 0
@@ -5800,7 +6052,9 @@ xn--holtlen-hxa.no, 0
xn--hpmir-xqa.no, 0
xn--hyanger-q1a.no, 0
xn--hylandet-54a.no, 0
+xn--i1b6b1a6a2e, 0
xn--indery-fya.no, 0
+xn--io0a7i, 0
xn--io0a7i.cn, 0
xn--io0a7i.hk, 0
xn--j1amh, 0
@@ -5849,6 +6103,7 @@ xn--mgba3a4f16a.ir, 0
xn--mgba3a4fra, 0
xn--mgba3a4fra.ir, 0
xn--mgbaam7a8h, 0
+xn--mgbab2bd, 0
xn--mgbayh7gpa, 0
xn--mgbbh1a71e, 0
xn--mgbc0a9azcg, 0
@@ -5869,9 +6124,12 @@ xn--msy-ula0h.no, 0
xn--mtta-vrjjat-k7af.no, 0
xn--muost-0qa.no, 0
xn--mxtq1m.hk, 0
+xn--ngbc5azd, 0
xn--nmesjevuemie-tcba.no, 0
xn--nnx388a, 0
xn--node, 0
+xn--nqv7f, 0
+xn--nqv7fs00ema, 0
xn--nry-yla5g.no, 0
xn--nttery-byae.no, 0
xn--nvuotna-hwa.no, 0
@@ -5883,9 +6141,11 @@ xn--ogbpf8fl, 0
xn--oppegrd-ixa.no, 0
xn--ostery-fya.no, 0
xn--osyro-wua.no, 0
+xn--p1acf, 0
xn--p1ai, 0
xn--pgbs0dh, 0
xn--porsgu-sta26f.no, 0
+xn--q9jyb4c, 0
xn--rady-ira.no, 0
xn--rdal-poa.no, 0
xn--rde-ula.no, 0
@@ -5893,6 +6153,7 @@ xn--rdy-0nab.no, 0
xn--rennesy-v1a.no, 0
xn--rhkkervju-01af.no, 0
xn--rholt-mra.no, 0
+xn--rhqv96g, 0
xn--risa-5na.no, 0
xn--risr-ira.no, 0
xn--rland-uua.no, 0
@@ -5909,6 +6170,7 @@ xn--s9brj9c, 0
xn--sandnessjen-ogb.no, 0
xn--sandy-yua.no, 0
xn--seral-lra.no, 0
+xn--ses554g, 0
xn--sgne-gra.no, 0
xn--skierv-uta.no, 0
xn--skjervy-v1a.no, 0
@@ -5945,6 +6207,7 @@ xn--uc0atv.hk, 0
xn--uc0atv.tw, 0
xn--uc0ay4a.hk, 0
xn--unjrga-rta.no, 0
+xn--unup4y, 0
xn--vads-jra.no, 0
xn--vard-jra.no, 0
xn--vegrshei-c0a.no, 0
@@ -5952,6 +6215,7 @@ xn--vestvgy-ixa6o.no, 0
xn--vg-yiab.no, 0
xn--vgan-qoa.no, 0
xn--vgsy-qoa0j.no, 0
+xn--vhquv, 0
xn--vler-qoa.hedmark.no, 0
xn--vler-qoa.xn--stfold-9xa.no, 0
xn--vre-eiker-k8a.no, 0
@@ -5960,6 +6224,7 @@ xn--vry-yla5g.no, 0
xn--wcvs22d.hk, 0
xn--wgbh1c, 0
xn--wgbl6a, 0
+xn--xhq521b, 0
xn--xkc2al3hye2a, 0
xn--xkc2dl3a5ee0h, 0
xn--yer-zna.no, 0
@@ -5969,7 +6234,9 @@ xn--ygbi2ammx, 0
xn--ystre-slidre-ujb.no, 0
xn--zf0ao64a.tw, 0
xn--zf0avx.hk, 0
+xn--zfr164b, 0
xxx, 0
+xyz, 0
xz.cn, 0
y.bg, 0
y.se, 0
@@ -5978,6 +6245,7 @@ yabuki.fukushima.jp, 0
yachimata.chiba.jp, 0
yachiyo.chiba.jp, 0
yachiyo.ibaraki.jp, 0
+yachts, 0
yaese.okinawa.jp, 0
yahaba.iwate.jp, 0
yahiko.niigata.jp, 0
@@ -6044,6 +6312,7 @@ yoka.hyogo.jp, 0
yokaichiba.chiba.jp, 0
yokawa.hyogo.jp, 0
yokkaichi.mie.jp, 0
+yokohama, 0
yokohama.jp, 2
yokoshibahikari.chiba.jp, 0
yokosuka.kanagawa.jp, 0
@@ -6084,6 +6353,8 @@ yuu.yamaguchi.jp, 0
yuza.yamagata.jp, 0
yuzawa.niigata.jp, 0
yuzhno-sakhalinsk.ru, 0
+z-1.compute-1.amazonaws.com, 4
+z-2.compute-1.amazonaws.com, 4
z.bg, 0
z.se, 0
za, 2
@@ -6108,6 +6379,7 @@ zhytomyr.ua, 0
zj.cn, 0
zlg.br, 0
zm, 2
+zone, 0
zoological.museum, 0
zoology.museum, 0
zp.ua, 0
diff --git a/chromium/net/base/request_priority.cc b/chromium/net/base/request_priority.cc
new file mode 100644
index 00000000000..4f2ab7f7e06
--- /dev/null
+++ b/chromium/net/base/request_priority.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/request_priority.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+const char* RequestPriorityToString(RequestPriority priority) {
+ switch (priority) {
+ case IDLE:
+ return "IDLE";
+ case LOWEST:
+ return "LOWEST";
+ case LOW:
+ return "LOW";
+ case MEDIUM:
+ return "MEDIUM";
+ case HIGHEST:
+ return "HIGHEST";
+ }
+ NOTREACHED();
+ return "UNKNOWN_PRIORITY";
+}
+
+} // namespace net
diff --git a/chromium/net/base/request_priority.h b/chromium/net/base/request_priority.h
index 6efd3ab37b1..f6ff43e3655 100644
--- a/chromium/net/base/request_priority.h
+++ b/chromium/net/base/request_priority.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_REQUEST_PRIORITY_H__
-#define NET_BASE_REQUEST_PRIORITY_H__
+#ifndef NET_BASE_REQUEST_PRIORITY_H_
+#define NET_BASE_REQUEST_PRIORITY_H_
namespace net {
@@ -17,9 +17,18 @@ enum RequestPriority {
LOW,
MEDIUM,
HIGHEST,
- NUM_PRIORITIES,
+ MAXIMUM_PRIORITY = HIGHEST,
};
+// For simplicity, one can assume that one can index into array of
+// NUM_PRIORITIES elements with a RequestPriority (i.e.,
+// MINIMUM_PRIORITY == 0).
+enum RequestPrioritySize {
+ NUM_PRIORITIES = MAXIMUM_PRIORITY + 1,
+};
+
+const char* RequestPriorityToString(RequestPriority priority);
+
} // namespace net
-#endif // NET_BASE_REQUEST_PRIORITY_H__
+#endif // NET_BASE_REQUEST_PRIORITY_H_
diff --git a/chromium/net/base/upload_data_stream.cc b/chromium/net/base/upload_data_stream.cc
index 03946da6b1b..785d5e936c7 100644
--- a/chromium/net/base/upload_data_stream.cc
+++ b/chromium/net/base/upload_data_stream.cc
@@ -13,9 +13,10 @@
namespace net {
UploadDataStream::UploadDataStream(
- ScopedVector<UploadElementReader>* element_readers,
+ ScopedVector<UploadElementReader> element_readers,
int64 identifier)
- : element_index_(0),
+ : element_readers_(element_readers.Pass()),
+ element_index_(0),
total_size_(0),
current_position_(0),
identifier_(identifier),
@@ -24,7 +25,6 @@ UploadDataStream::UploadDataStream(
read_failed_(false),
initialized_successfully_(false),
weak_ptr_factory_(this) {
- element_readers_.swap(*element_readers);
}
UploadDataStream::UploadDataStream(Chunked /*chunked*/, int64 identifier)
@@ -47,7 +47,7 @@ UploadDataStream* UploadDataStream::CreateWithReader(
int64 identifier) {
ScopedVector<UploadElementReader> readers;
readers.push_back(reader.release());
- return new UploadDataStream(&readers, identifier);
+ return new UploadDataStream(readers.Pass(), identifier);
}
int UploadDataStream::Init(const CompletionCallback& callback) {
diff --git a/chromium/net/base/upload_data_stream.h b/chromium/net/base/upload_data_stream.h
index c8f2cc2a34f..ac14e38086f 100644
--- a/chromium/net/base/upload_data_stream.h
+++ b/chromium/net/base/upload_data_stream.h
@@ -25,8 +25,7 @@ class NET_EXPORT UploadDataStream {
enum Chunked { CHUNKED };
// Constructs a non-chunked data stream.
- // |element_readers| is cleared by this ctor.
- UploadDataStream(ScopedVector<UploadElementReader>* element_readers,
+ UploadDataStream(ScopedVector<UploadElementReader> element_readers,
int64 identifier);
// Constructs a chunked data stream.
@@ -95,10 +94,10 @@ class NET_EXPORT UploadDataStream {
// Adds the given chunk of bytes to be sent with chunked transfer encoding.
void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk);
- private:
// Resets this instance to the uninitialized state.
void Reset();
+ private:
// Runs Init() for all element readers.
// This method is used to implement Init().
int InitInternal(int start_index, const CompletionCallback& callback);
diff --git a/chromium/net/base/upload_data_stream_unittest.cc b/chromium/net/base/upload_data_stream_unittest.cc
index e0cbc27c106..24855a85ea4 100644
--- a/chromium/net/base/upload_data_stream_unittest.cc
+++ b/chromium/net/base/upload_data_stream_unittest.cc
@@ -142,7 +142,7 @@ class UploadDataStreamTest : public PlatformTest {
};
TEST_F(UploadDataStreamTest, EmptyUploadData) {
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
ASSERT_EQ(OK, stream.Init(CompletionCallback()));
EXPECT_TRUE(stream.IsInMemory());
EXPECT_EQ(0U, stream.size());
@@ -153,7 +153,7 @@ TEST_F(UploadDataStreamTest, EmptyUploadData) {
TEST_F(UploadDataStreamTest, ConsumeAllBytes) {
element_readers_.push_back(new UploadBytesElementReader(
kTestData, kTestDataSize));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
ASSERT_EQ(OK, stream.Init(CompletionCallback()));
EXPECT_TRUE(stream.IsInMemory());
EXPECT_EQ(kTestDataSize, stream.size());
@@ -171,8 +171,8 @@ TEST_F(UploadDataStreamTest, ConsumeAllBytes) {
TEST_F(UploadDataStreamTest, File) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
@@ -184,7 +184,7 @@ TEST_F(UploadDataStreamTest, File) {
base::Time()));
TestCompletionCallback init_callback;
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback()));
ASSERT_EQ(OK, init_callback.WaitForResult());
EXPECT_FALSE(stream.IsInMemory());
@@ -205,8 +205,8 @@ TEST_F(UploadDataStreamTest, File) {
TEST_F(UploadDataStreamTest, FileSmallerThanLength) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
const uint64 kFakeSize = kTestDataSize*2;
@@ -222,7 +222,7 @@ TEST_F(UploadDataStreamTest, FileSmallerThanLength) {
base::Time()));
TestCompletionCallback init_callback;
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback()));
ASSERT_EQ(OK, init_callback.WaitForResult());
EXPECT_FALSE(stream.IsInMemory());
@@ -259,7 +259,7 @@ TEST_F(UploadDataStreamTest, ReadErrorSync) {
element_readers_.push_back(new UploadBytesElementReader(
kTestData, kTestDataSize));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
// Run Init().
ASSERT_EQ(OK, stream.Init(CompletionCallback()));
@@ -294,7 +294,7 @@ TEST_F(UploadDataStreamTest, ReadErrorAsync) {
element_readers_.push_back(new UploadBytesElementReader(
kTestData, kTestDataSize));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
// Run Init().
TestCompletionCallback init_callback;
@@ -323,8 +323,8 @@ TEST_F(UploadDataStreamTest, ReadErrorAsync) {
TEST_F(UploadDataStreamTest, FileAndBytes) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
@@ -342,7 +342,7 @@ TEST_F(UploadDataStreamTest, FileAndBytes) {
const uint64 kStreamSize = kTestDataSize + kFileRangeLength;
TestCompletionCallback init_callback;
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback()));
ASSERT_EQ(OK, init_callback.WaitForResult());
EXPECT_FALSE(stream.IsInMemory());
@@ -408,7 +408,7 @@ TEST_F(UploadDataStreamTest, InitAsync) {
EXPECT_CALL(*reader, Init(_)).WillOnce(Return(OK));
element_readers_.push_back(reader);
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
// Run Init().
TestCompletionCallback callback;
@@ -425,7 +425,7 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureAsync) {
reader->SetAsyncInitExpectation(ERR_FAILED);
element_readers_.push_back(reader);
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
// Run Init().
TestCompletionCallback callback;
@@ -446,7 +446,7 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureSync) {
EXPECT_CALL(*reader, Init(_)).WillOnce(Return(ERR_FAILED));
element_readers_.push_back(reader);
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
// Run Init().
TestCompletionCallback callback;
@@ -458,7 +458,7 @@ TEST_F(UploadDataStreamTest, InitAsyncFailureSync) {
TEST_F(UploadDataStreamTest, ReadAsyncWithExactSizeBuffer) {
element_readers_.push_back(new UploadBytesElementReader(
kTestData, kTestDataSize));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
ASSERT_EQ(OK, stream.Init(CompletionCallback()));
EXPECT_TRUE(stream.IsInMemory());
@@ -497,7 +497,7 @@ TEST_F(UploadDataStreamTest, ReadAsync) {
reader->SetReadExpectation(kTestDataSize);
element_readers_.push_back(reader);
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
// Run Init().
TestCompletionCallback init_callback;
@@ -538,7 +538,7 @@ void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path,
base::MessageLoopProxy::current().get(), file_path, 1, 2, time));
TestCompletionCallback init_callback;
- UploadDataStream stream(&element_readers, 0);
+ UploadDataStream stream(element_readers.Pass(), 0);
ASSERT_EQ(ERR_IO_PENDING, stream.Init(init_callback.callback()));
int error_code = init_callback.WaitForResult();
if (error_expected)
@@ -549,13 +549,13 @@ void UploadDataStreamTest::FileChangedHelper(const base::FilePath& file_path,
TEST_F(UploadDataStreamTest, FileChanged) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
base::PlatformFileInfo file_info;
- ASSERT_TRUE(file_util::GetFileInfo(temp_file_path, &file_info));
+ ASSERT_TRUE(base::GetFileInfo(temp_file_path, &file_info));
// Test file not changed.
FileChangedHelper(temp_file_path, file_info.last_modified, false);
@@ -568,8 +568,8 @@ TEST_F(UploadDataStreamTest, FileChanged) {
TEST_F(UploadDataStreamTest, MultipleInit) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
@@ -582,7 +582,7 @@ TEST_F(UploadDataStreamTest, MultipleInit) {
0,
kuint64max,
base::Time()));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
std::string expected_data(kTestData, kTestData + kTestDataSize);
expected_data += expected_data;
@@ -612,8 +612,8 @@ TEST_F(UploadDataStreamTest, MultipleInit) {
TEST_F(UploadDataStreamTest, MultipleInitAsync) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
TestCompletionCallback test_callback;
@@ -627,7 +627,7 @@ TEST_F(UploadDataStreamTest, MultipleInitAsync) {
0,
kuint64max,
base::Time()));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
std::string expected_data(kTestData, kTestData + kTestDataSize);
expected_data += expected_data;
@@ -655,8 +655,8 @@ TEST_F(UploadDataStreamTest, MultipleInitAsync) {
TEST_F(UploadDataStreamTest, InitToReset) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
@@ -669,7 +669,7 @@ TEST_F(UploadDataStreamTest, InitToReset) {
0,
kuint64max,
base::Time()));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
expected_data.insert(expected_data.end(), expected_data.begin(),
@@ -712,8 +712,8 @@ TEST_F(UploadDataStreamTest, InitToReset) {
TEST_F(UploadDataStreamTest, InitDuringAsyncInit) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
@@ -726,7 +726,7 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncInit) {
0,
kuint64max,
base::Time()));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
expected_data.insert(expected_data.end(), expected_data.begin(),
@@ -760,8 +760,8 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncInit) {
TEST_F(UploadDataStreamTest, InitDuringAsyncRead) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path));
ASSERT_EQ(static_cast<int>(kTestDataSize),
file_util::WriteFile(temp_file_path, kTestData, kTestDataSize));
@@ -774,7 +774,7 @@ TEST_F(UploadDataStreamTest, InitDuringAsyncRead) {
0,
kuint64max,
base::Time()));
- UploadDataStream stream(&element_readers_, 0);
+ UploadDataStream stream(element_readers_.Pass(), 0);
std::vector<char> expected_data(kTestData, kTestData + kTestDataSize);
expected_data.insert(expected_data.end(), expected_data.begin(),
diff --git a/chromium/net/base/upload_file_element_reader.cc b/chromium/net/base/upload_file_element_reader.cc
index d1f2a12ac8c..ab7dd9eb1a1 100644
--- a/chromium/net/base/upload_file_element_reader.cc
+++ b/chromium/net/base/upload_file_element_reader.cc
@@ -32,28 +32,29 @@ int InitInternal(const base::FilePath& path,
int64 rv = file_stream->OpenSync(
path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
if (rv != OK) {
- // If the file can't be opened, we'll just upload an empty file.
+ // If the file can't be opened, the upload should fail.
DLOG(WARNING) << "Failed to open \"" << path.value()
<< "\" for reading: " << rv;
- file_stream.reset();
+ return rv;
} else if (range_offset) {
rv = file_stream->SeekSync(FROM_BEGIN, range_offset);
if (rv < 0) {
DLOG(WARNING) << "Failed to seek \"" << path.value()
<< "\" to offset: " << range_offset << " (" << rv << ")";
- file_stream.reset();
+ return rv;
}
}
int64 length = 0;
- if (file_stream.get() &&
- file_util::GetFileSize(path, &length) &&
- range_offset < static_cast<uint64>(length)) {
+ if (!base::GetFileSize(path, &length)) {
+ DLOG(WARNING) << "Failed to get file size of \"" << path.value() << "\"";
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ if (range_offset < static_cast<uint64>(length)) {
// Compensate for the offset.
length = std::min(length - range_offset, range_length);
}
- *out_content_length = length;
- out_file_stream->reset(file_stream.release());
// If the underlying file has been changed and the expected file modification
// time is set, treat it as error. Note that the expected modification time
@@ -61,12 +62,19 @@ int InitInternal(const base::FilePath& path,
// time_t to compare. This check is used for sliced files.
if (!expected_modification_time.is_null()) {
base::PlatformFileInfo info;
- if (file_util::GetFileInfo(path, &info) &&
- expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) {
+ if (!base::GetFileInfo(path, &info)) {
+ DLOG(WARNING) << "Failed to get file info of \"" << path.value() << "\"";
+ return ERR_FILE_NOT_FOUND;
+ }
+
+ if (expected_modification_time.ToTimeT() != info.last_modified.ToTimeT()) {
return ERR_UPLOAD_FILE_CHANGED;
}
}
+ *out_content_length = length;
+ out_file_stream->reset(file_stream.release());
+
return OK;
}
diff --git a/chromium/net/base/upload_file_element_reader_unittest.cc b/chromium/net/base/upload_file_element_reader_unittest.cc
index b0435019e9c..f3ccb4180f9 100644
--- a/chromium/net/base/upload_file_element_reader_unittest.cc
+++ b/chromium/net/base/upload_file_element_reader_unittest.cc
@@ -26,8 +26,8 @@ class UploadFileElementReaderTest : public PlatformTest {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path_));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path_));
ASSERT_EQ(
static_cast<int>(bytes_.size()),
file_util::WriteFile(temp_file_path_, &bytes_[0], bytes_.size()));
@@ -205,7 +205,7 @@ TEST_F(UploadFileElementReaderTest, Range) {
TEST_F(UploadFileElementReaderTest, FileChanged) {
base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(temp_file_path_, &info));
+ ASSERT_TRUE(base::GetFileInfo(temp_file_path_, &info));
// Expect one second before the actual modification time to simulate change.
const base::Time expected_modification_time =
@@ -231,9 +231,7 @@ TEST_F(UploadFileElementReaderTest, WrongPath) {
base::Time()));
TestCompletionCallback init_callback;
ASSERT_EQ(ERR_IO_PENDING, reader_->Init(init_callback.callback()));
- EXPECT_EQ(OK, init_callback.WaitForResult());
- EXPECT_EQ(0U, reader_->GetContentLength());
- EXPECT_EQ(0U, reader_->BytesRemaining());
+ EXPECT_EQ(ERR_FILE_NOT_FOUND, init_callback.WaitForResult());
}
@@ -246,8 +244,8 @@ class UploadFileElementReaderSyncTest : public PlatformTest {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir_.path(),
- &temp_file_path_));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(),
+ &temp_file_path_));
ASSERT_EQ(
static_cast<int>(bytes_.size()),
file_util::WriteFile(temp_file_path_, &bytes_[0], bytes_.size()));
@@ -352,7 +350,7 @@ TEST_F(UploadFileElementReaderSyncTest, Range) {
TEST_F(UploadFileElementReaderSyncTest, FileChanged) {
base::PlatformFileInfo info;
- ASSERT_TRUE(file_util::GetFileInfo(temp_file_path_, &info));
+ ASSERT_TRUE(base::GetFileInfo(temp_file_path_, &info));
// Expect one second before the actual modification time to simulate change.
const base::Time expected_modification_time =
@@ -366,9 +364,7 @@ TEST_F(UploadFileElementReaderSyncTest, WrongPath) {
const base::FilePath wrong_path(FILE_PATH_LITERAL("wrong_path"));
reader_.reset(new UploadFileElementReaderSync(
wrong_path, 0, kuint64max, base::Time()));
- ASSERT_EQ(OK, reader_->Init(CompletionCallback()));
- EXPECT_EQ(0U, reader_->GetContentLength());
- EXPECT_EQ(0U, reader_->BytesRemaining());
+ ASSERT_EQ(ERR_FILE_NOT_FOUND, reader_->Init(CompletionCallback()));
}
} // namespace net
diff --git a/chromium/net/base/url_util.cc b/chromium/net/base/url_util.cc
index c18fd179872..a7c89e9047d 100644
--- a/chromium/net/base/url_util.cc
+++ b/chromium/net/base/url_util.cc
@@ -4,6 +4,9 @@
#include "net/base/url_util.h"
+#include <utility>
+
+#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "net/base/escape.h"
#include "url/gurl.h"
@@ -68,30 +71,66 @@ GURL AppendOrReplaceQueryParameter(const GURL& url,
return url.ReplaceComponents(replacements);
}
+QueryIterator::QueryIterator(const GURL& url)
+ : url_(url),
+ at_end_(!url.is_valid()) {
+ if (!at_end_) {
+ query_ = url.parsed_for_possibly_invalid_spec().query;
+ Advance();
+ }
+}
+
+QueryIterator::~QueryIterator() {
+}
+
+std::string QueryIterator::GetKey() const {
+ DCHECK(!at_end_);
+ if (key_.is_nonempty())
+ return url_.spec().substr(key_.begin, key_.len);
+ return std::string();
+}
+
+std::string QueryIterator::GetValue() const {
+ DCHECK(!at_end_);
+ if (value_.is_nonempty())
+ return url_.spec().substr(value_.begin, value_.len);
+ return std::string();
+}
+
+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);
+ }
+ return unescaped_value_;
+}
+
+bool QueryIterator::IsAtEnd() const {
+ return at_end_;
+}
+
+void QueryIterator::Advance() {
+ DCHECK (!at_end_);
+ key_.reset();
+ value_.reset();
+ unescaped_value_.clear();
+ at_end_ = !url_parse::ExtractQueryKeyValue(url_.spec().c_str(),
+ &query_,
+ &key_,
+ &value_);
+}
+
bool GetValueForKeyInQuery(const GURL& url,
const std::string& search_key,
std::string* out_value) {
- if (!url.is_valid())
- return false;
-
- url_parse::Component query = url.parsed_for_possibly_invalid_spec().query;
- url_parse::Component key, value;
- while (url_parse::ExtractQueryKeyValue(
- url.spec().c_str(), &query, &key, &value)) {
- if (key.is_nonempty()) {
- std::string key_string = url.spec().substr(key.begin, key.len);
- if (key_string == search_key) {
- if (value.is_nonempty()) {
- *out_value = UnescapeURLComponent(
- url.spec().substr(value.begin, value.len),
- UnescapeRule::SPACES |
- UnescapeRule::URL_SPECIAL_CHARS |
- UnescapeRule::REPLACE_PLUS_WITH_SPACE);
- } else {
- *out_value = "";
- }
- return true;
- }
+ for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
+ if (it.GetKey() == search_key) {
+ *out_value = it.GetUnescapedValue();
+ return true;
}
}
return false;
diff --git a/chromium/net/base/url_util.h b/chromium/net/base/url_util.h
index 5d5e58bc617..83d03562f86 100644
--- a/chromium/net/base/url_util.h
+++ b/chromium/net/base/url_util.h
@@ -7,7 +7,9 @@
#include <string>
+#include "base/compiler_specific.h"
#include "net/base/net_export.h"
+#include "url/url_parse.h"
class GURL;
@@ -44,6 +46,30 @@ NET_EXPORT GURL AppendOrReplaceQueryParameter(const GURL& url,
const std::string& name,
const std::string& value);
+// Iterates over the key-value pairs in the query portion of |url|.
+class NET_EXPORT QueryIterator {
+ public:
+ explicit QueryIterator(const GURL& url);
+ ~QueryIterator();
+
+ std::string GetKey() const;
+ std::string GetValue() const;
+ const std::string& GetUnescapedValue();
+
+ bool IsAtEnd() const;
+ void Advance();
+
+ private:
+ const GURL& url_;
+ url_parse::Component query_;
+ bool at_end_;
+ url_parse::Component key_;
+ url_parse::Component value_;
+ std::string unescaped_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(QueryIterator);
+};
+
// Looks for |search_key| in the query portion of |url|. Returns true if the
// key is found and sets |out_value| to the unescaped value for the key.
// Returns false if the key is not found.
diff --git a/chromium/net/base/url_util_unittest.cc b/chromium/net/base/url_util_unittest.cc
index 83ac258650b..158e2740306 100644
--- a/chromium/net/base/url_util_unittest.cc
+++ b/chromium/net/base/url_util_unittest.cc
@@ -108,5 +108,56 @@ TEST(UrlUtilTest, GetValueForKeyInQueryInvalidURL) {
EXPECT_FALSE(GetValueForKeyInQuery(url, "test", &value));
}
+TEST(UrlUtilTest, ParseQuery) {
+ const GURL url("http://example.com/path?name=value&boolParam&"
+ "url=http://test.com/q?n1%3Dv1%26n2&"
+ "multikey=value1&multikey=value2&multikey");
+ QueryIterator it(url);
+
+ ASSERT_FALSE(it.IsAtEnd());
+ EXPECT_EQ("name", it.GetKey());
+ EXPECT_EQ("value", it.GetValue());
+ EXPECT_EQ("value", it.GetUnescapedValue());
+ it.Advance();
+
+ ASSERT_FALSE(it.IsAtEnd());
+ EXPECT_EQ("boolParam", it.GetKey());
+ EXPECT_EQ("", it.GetValue());
+ EXPECT_EQ("", it.GetUnescapedValue());
+ it.Advance();
+
+ ASSERT_FALSE(it.IsAtEnd());
+ EXPECT_EQ("url", it.GetKey());
+ EXPECT_EQ("http://test.com/q?n1%3Dv1%26n2", it.GetValue());
+ EXPECT_EQ("http://test.com/q?n1=v1&n2", it.GetUnescapedValue());
+ it.Advance();
+
+ ASSERT_FALSE(it.IsAtEnd());
+ EXPECT_EQ("multikey", it.GetKey());
+ EXPECT_EQ("value1", it.GetValue());
+ EXPECT_EQ("value1", it.GetUnescapedValue());
+ it.Advance();
+
+ ASSERT_FALSE(it.IsAtEnd());
+ EXPECT_EQ("multikey", it.GetKey());
+ EXPECT_EQ("value2", it.GetValue());
+ EXPECT_EQ("value2", it.GetUnescapedValue());
+ it.Advance();
+
+ ASSERT_FALSE(it.IsAtEnd());
+ EXPECT_EQ("multikey", it.GetKey());
+ EXPECT_EQ("", it.GetValue());
+ EXPECT_EQ("", it.GetUnescapedValue());
+ it.Advance();
+
+ EXPECT_TRUE(it.IsAtEnd());
+}
+
+TEST(UrlUtilTest, ParseQueryInvalidURL) {
+ const GURL url("http://%01/?test");
+ QueryIterator it(url);
+ EXPECT_TRUE(it.IsAtEnd());
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/cert/cert_database.cc b/chromium/net/cert/cert_database.cc
index db54172d070..f36562aadf7 100644
--- a/chromium/net/cert/cert_database.cc
+++ b/chromium/net/cert/cert_database.cc
@@ -30,10 +30,10 @@ void CertDatabase::NotifyObserversOfCertRemoved(const X509Certificate* cert) {
observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert));
}
-void CertDatabase::NotifyObserversOfCertTrustChanged(
+void CertDatabase::NotifyObserversOfCACertChanged(
const X509Certificate* cert) {
observer_list_->Notify(
- &Observer::OnCertTrustChanged, make_scoped_refptr(cert));
+ &Observer::OnCACertChanged, make_scoped_refptr(cert));
}
} // namespace net
diff --git a/chromium/net/cert/cert_database.h b/chromium/net/cert/cert_database.h
index c4ead812f2f..feadf4c1d08 100644
--- a/chromium/net/cert/cert_database.h
+++ b/chromium/net/cert/cert_database.h
@@ -40,8 +40,9 @@ class NET_EXPORT CertDatabase {
// Will be called when a certificate is removed.
virtual void OnCertRemoved(const X509Certificate* cert) {}
- // Will be called when a certificate's trust is changed.
- virtual void OnCertTrustChanged(const X509Certificate* cert) {}
+ // Will be called when a CA certificate was added, removed, or its trust
+ // changed. This can also mean that a client certificate's trust changed.
+ virtual void OnCACertChanged(const X509Certificate* cert) {}
protected:
Observer() {}
@@ -78,6 +79,12 @@ class NET_EXPORT CertDatabase {
void SetMessageLoopForKeychainEvents();
#endif
+#if defined(OS_ANDROID)
+ // On android, the system database is used. When the system notifies the
+ // application that the certificates changed, the observers must be notified.
+ void OnAndroidKeyChainChanged();
+#endif
+
private:
friend struct DefaultSingletonTraits<CertDatabase>;
@@ -87,7 +94,7 @@ class NET_EXPORT CertDatabase {
// Broadcasts notifications to all registered observers.
void NotifyObserversOfCertAdded(const X509Certificate* cert);
void NotifyObserversOfCertRemoved(const X509Certificate* cert);
- void NotifyObserversOfCertTrustChanged(const X509Certificate* cert);
+ void NotifyObserversOfCACertChanged(const X509Certificate* cert);
const scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_;
diff --git a/chromium/net/cert/cert_database_android.cc b/chromium/net/cert/cert_database_android.cc
index 9755805026b..350028fc753 100644
--- a/chromium/net/cert/cert_database_android.cc
+++ b/chromium/net/cert/cert_database_android.cc
@@ -36,4 +36,9 @@ int CertDatabase::AddUserCert(X509Certificate* cert) {
return ERR_NOT_IMPLEMENTED;
}
+void CertDatabase::OnAndroidKeyChainChanged() {
+ observer_list_->Notify(&Observer::OnCACertChanged,
+ scoped_refptr<X509Certificate>());
+}
+
} // namespace net
diff --git a/chromium/net/cert/cert_database_mac.cc b/chromium/net/cert/cert_database_mac.cc
index 76701963fd5..9427be316d2 100644
--- a/chromium/net/cert/cert_database_mac.cc
+++ b/chromium/net/cert/cert_database_mac.cc
@@ -103,7 +103,7 @@ OSStatus CertDatabase::Notifier::KeychainCallback(
switch (keychain_event) {
case kSecKeychainListChangedEvent:
case kSecTrustSettingsChangedEvent:
- that->cert_db_->NotifyObserversOfCertTrustChanged(NULL);
+ that->cert_db_->NotifyObserversOfCACertChanged(NULL);
break;
}
diff --git a/chromium/net/cert/cert_database_nss.cc b/chromium/net/cert/cert_database_nss.cc
index 5fa272134a2..a1677fe85a1 100644
--- a/chromium/net/cert/cert_database_nss.cc
+++ b/chromium/net/cert/cert_database_nss.cc
@@ -40,8 +40,8 @@ class CertDatabase::Notifier : public NSSCertDatabase::Observer {
cert_db_->NotifyObserversOfCertRemoved(cert);
}
- virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE {
- cert_db_->NotifyObserversOfCertTrustChanged(cert);
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE {
+ cert_db_->NotifyObserversOfCACertChanged(cert);
}
private:
diff --git a/chromium/net/cert/cert_status_flags.cc b/chromium/net/cert/cert_status_flags.cc
index 8cb736c5485..417a1833fd7 100644
--- a/chromium/net/cert/cert_status_flags.cc
+++ b/chromium/net/cert/cert_status_flags.cc
@@ -43,6 +43,12 @@ CertStatus MapNetErrorToCertStatus(int error) {
return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
case ERR_CERT_WEAK_KEY:
return CERT_STATUS_WEAK_KEY;
+ case ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN:
+ return CERT_STATUS_PINNED_KEY_MISSING;
+ case ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY:
+ return CERT_STATUS_WEAK_DH_KEY;
+ case ERR_CERT_NAME_CONSTRAINT_VIOLATION:
+ return CERT_STATUS_NAME_CONSTRAINT_VIOLATION;
default:
return 0;
}
@@ -57,12 +63,18 @@ int MapCertStatusToNetError(CertStatus cert_status) {
return ERR_CERT_REVOKED;
if (cert_status & CERT_STATUS_INVALID)
return ERR_CERT_INVALID;
+ if (cert_status & CERT_STATUS_PINNED_KEY_MISSING)
+ return ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN;
+ if (cert_status & CERT_STATUS_WEAK_DH_KEY)
+ return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
// Recoverable errors
if (cert_status & CERT_STATUS_AUTHORITY_INVALID)
return ERR_CERT_AUTHORITY_INVALID;
if (cert_status & CERT_STATUS_COMMON_NAME_INVALID)
return ERR_CERT_COMMON_NAME_INVALID;
+ if (cert_status & CERT_STATUS_NAME_CONSTRAINT_VIOLATION)
+ return ERR_CERT_NAME_CONSTRAINT_VIOLATION;
if (cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM)
return ERR_CERT_WEAK_SIGNATURE_ALGORITHM;
if (cert_status & CERT_STATUS_WEAK_KEY)
diff --git a/chromium/net/cert/cert_status_flags.h b/chromium/net/cert/cert_status_flags.h
index 8431032f679..711474ff2b0 100644
--- a/chromium/net/cert/cert_status_flags.h
+++ b/chromium/net/cert/cert_status_flags.h
@@ -32,6 +32,9 @@ static const CertStatus CERT_STATUS_WEAK_SIGNATURE_ALGORITHM = 1 << 8;
// 1 << 9 was used for CERT_STATUS_NOT_IN_DNS
static const CertStatus CERT_STATUS_NON_UNIQUE_NAME = 1 << 10;
static const CertStatus CERT_STATUS_WEAK_KEY = 1 << 11;
+static const CertStatus CERT_STATUS_WEAK_DH_KEY = 1 << 12;
+static const CertStatus CERT_STATUS_PINNED_KEY_MISSING = 1 << 13;
+static const CertStatus CERT_STATUS_NAME_CONSTRAINT_VIOLATION = 1 << 14;
// Bits 16 to 31 are for non-error statuses.
static const CertStatus CERT_STATUS_IS_EV = 1 << 16;
diff --git a/chromium/net/cert/cert_verify_proc.cc b/chromium/net/cert/cert_verify_proc.cc
index 05f6c30b8f2..6c2d5d91c4d 100644
--- a/chromium/net/cert/cert_verify_proc.cc
+++ b/chromium/net/cert/cert_verify_proc.cc
@@ -10,11 +10,13 @@
#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/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/crl_set.h"
#include "net/cert/x509_certificate.h"
+#include "url/url_canon.h"
#if defined(USE_NSS) || defined(OS_IOS)
#include "net/cert/cert_verify_proc_nss.h"
@@ -206,6 +208,13 @@ int CertVerifyProc::Verify(X509Certificate* cert,
int rv = VerifyInternal(cert, hostname, flags, crl_set,
additional_trust_anchors, verify_result);
+ UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback",
+ verify_result->common_name_fallback_used);
+ if (!verify_result->is_issued_by_known_root) {
+ UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallbackPrivateCA",
+ verify_result->common_name_fallback_used);
+ }
+
// This check is done after VerifyInternal so that VerifyInternal can fill
// in the list of public key hashes.
if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
@@ -213,6 +222,16 @@ int CertVerifyProc::Verify(X509Certificate* cert,
rv = MapCertStatusToNetError(verify_result->cert_status);
}
+ std::vector<std::string> dns_names, ip_addrs;
+ cert->GetSubjectAltName(&dns_names, &ip_addrs);
+ if (HasNameConstraintsViolation(verify_result->public_key_hashes,
+ cert->subject().common_name,
+ dns_names,
+ ip_addrs)) {
+ verify_result->cert_status |= CERT_STATUS_NAME_CONSTRAINT_VIOLATION;
+ rv = MapCertStatusToNetError(verify_result->cert_status);
+ }
+
// Check for weak keys in the entire verified chain.
bool weak_key = ExaminePublicKeys(verify_result->verified_cert,
verify_result->is_issued_by_known_root);
@@ -332,7 +351,7 @@ bool CertVerifyProc::IsBlacklisted(X509Certificate* cert) {
// NOTE: This implementation assumes and enforces that the hashes are SHA1.
bool CertVerifyProc::IsPublicKeyBlacklisted(
const HashValueVector& public_key_hashes) {
- static const unsigned kNumHashes = 10;
+ static const unsigned kNumHashes = 11;
static const uint8 kHashes[kNumHashes][base::kSHA1Length] = {
// Subject: CN=DigiNotar Root CA
// Issuer: CN=Entrust.net x2 and self-signed
@@ -377,6 +396,10 @@ bool CertVerifyProc::IsPublicKeyBlacklisted(
// 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},
+ // ANSSI certificate under which a MITM proxy was mistakenly operated.
+ // Expires: Jul 18 10:05:28 2014 GMT
+ {0x3e, 0xcf, 0x4b, 0xbb, 0xe4, 0x60, 0x96, 0xd5, 0x14, 0xbb,
+ 0x53, 0x9b, 0xb9, 0x13, 0xd7, 0x7a, 0xa4, 0xef, 0x31, 0xbf},
};
for (unsigned i = 0; i < kNumHashes; i++) {
@@ -392,4 +415,124 @@ bool CertVerifyProc::IsPublicKeyBlacklisted(
return false;
}
+static const size_t kMaxTLDLength = 4;
+
+// CheckNameConstraints verifies that every name in |dns_names| is in one of
+// the domains specified by |tlds|. The |tlds| array is terminated by an empty
+// string.
+static bool CheckNameConstraints(const std::vector<std::string>& dns_names,
+ const char tlds[][kMaxTLDLength]) {
+ for (std::vector<std::string>::const_iterator i = dns_names.begin();
+ i != dns_names.end(); ++i) {
+ bool ok = false;
+ url_canon::CanonHostInfo host_info;
+ const std::string dns_name = CanonicalizeHost(*i, &host_info);
+ if (host_info.IsIPAddress())
+ continue;
+
+ const size_t registry_len = registry_controlled_domains::GetRegistryLength(
+ dns_name,
+ registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
+ registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ // If the name is not in a known TLD, ignore it. This permits internal
+ // names.
+ if (registry_len == 0)
+ continue;
+
+ for (size_t j = 0; tlds[j][0]; ++j) {
+ const size_t tld_length = strlen(tlds[j]);
+ // The DNS name must have "." + tlds[j] as a suffix.
+ if (i->size() <= (1 /* period before TLD */ + tld_length))
+ continue;
+
+ const char* suffix = &dns_name[i->size() - tld_length - 1];
+ if (suffix[0] != '.')
+ continue;
+ if (memcmp(&suffix[1], tlds[j], tld_length) != 0)
+ continue;
+ ok = true;
+ break;
+ }
+
+ if (!ok)
+ return false;
+ }
+
+ return true;
+}
+
+// PublicKeyTLDLimitation contains a SHA1, SPKI hash and a pointer to an array
+// of fixed-length strings that contain the TLDs that the SPKI is allowed to
+// issue for.
+struct PublicKeyTLDLimitation {
+ uint8 public_key[base::kSHA1Length];
+ const char (*tlds)[kMaxTLDLength];
+};
+
+// static
+bool CertVerifyProc::HasNameConstraintsViolation(
+ const HashValueVector& public_key_hashes,
+ const std::string& common_name,
+ const std::vector<std::string>& dns_names,
+ const std::vector<std::string>& ip_addrs) {
+ static const char kTLDsANSSI[][kMaxTLDLength] = {
+ "fr", // France
+ "gp", // Guadeloupe
+ "gf", // Guyane
+ "mq", // Martinique
+ "re", // Réunion
+ "yt", // Mayotte
+ "pm", // Saint-Pierre et Miquelon
+ "bl", // Saint Barthélemy
+ "mf", // Saint Martin
+ "wf", // Wallis et Futuna
+ "pf", // Polynésie française
+ "nc", // Nouvelle Calédonie
+ "tf", // Terres australes et antarctiques françaises
+ "",
+ };
+
+ static const char kTLDsTest[][kMaxTLDLength] = {
+ "com",
+ "",
+ };
+
+ static const PublicKeyTLDLimitation kLimits[] = {
+ // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI,
+ // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr
+ {
+ {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad,
+ 0xae, 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73},
+ kTLDsANSSI,
+ },
+ // Not a real certificate - just for testing. This is the SPKI hash of
+ // the keys used in net/data/ssl/certificates/name_constraint_*.crt.
+ {
+ {0x15, 0x45, 0xd7, 0x3b, 0x58, 0x6b, 0x47, 0xcf, 0xc1, 0x44,
+ 0xa2, 0xc9, 0xaa, 0xab, 0x98, 0x3d, 0x21, 0xcc, 0x42, 0xde},
+ kTLDsTest,
+ },
+ };
+
+ for (unsigned i = 0; i < arraysize(kLimits); ++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(), kLimits[i].public_key, base::kSHA1Length) == 0) {
+ if (dns_names.empty() && ip_addrs.empty()) {
+ std::vector<std::string> dns_names;
+ dns_names.push_back(common_name);
+ if (!CheckNameConstraints(dns_names, kLimits[i].tlds))
+ return true;
+ } else {
+ if (!CheckNameConstraints(dns_names, kLimits[i].tlds))
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
} // namespace net
diff --git a/chromium/net/cert/cert_verify_proc.h b/chromium/net/cert/cert_verify_proc.h
index 518adbc122a..95e464e1595 100644
--- a/chromium/net/cert/cert_verify_proc.h
+++ b/chromium/net/cert/cert_verify_proc.h
@@ -90,6 +90,15 @@ class NET_EXPORT CertVerifyProc
// are hashes of SubjectPublicKeyInfo structures) is explicitly blocked.
static bool IsPublicKeyBlacklisted(const HashValueVector& public_key_hashes);
+ // HasNameConstraintsViolation returns true iff one of |public_key_hashes|
+ // (which are hashes of SubjectPublicKeyInfo structures) has name constraints
+ // imposed on it and the names in |dns_names| are not permitted.
+ static bool HasNameConstraintsViolation(
+ const HashValueVector& public_key_hashes,
+ const std::string& common_name,
+ const std::vector<std::string>& dns_names,
+ const std::vector<std::string>& ip_addrs);
+
DISALLOW_COPY_AND_ASSIGN(CertVerifyProc);
};
diff --git a/chromium/net/cert/cert_verify_proc_android.cc b/chromium/net/cert/cert_verify_proc_android.cc
index 9a8acf76fa9..bca62bc70c4 100644
--- a/chromium/net/cert/cert_verify_proc_android.cc
+++ b/chromium/net/cert/cert_verify_proc_android.cc
@@ -91,8 +91,10 @@ int CertVerifyProcAndroid::VerifyInternal(
CRLSet* crl_set,
const CertificateList& additional_trust_anchors,
CertVerifyResult* verify_result) {
- if (!cert->VerifyNameMatch(hostname))
+ if (!cert->VerifyNameMatch(hostname,
+ &verify_result->common_name_fallback_used)) {
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
+ }
std::vector<std::string> cert_bytes;
if (!GetChainDEREncodedBytes(cert, &cert_bytes))
diff --git a/chromium/net/cert/cert_verify_proc_mac.cc b/chromium/net/cert/cert_verify_proc_mac.cc
index 4efdaacffed..542fba11514 100644
--- a/chromium/net/cert/cert_verify_proc_mac.cc
+++ b/chromium/net/cert/cert_verify_proc_mac.cc
@@ -656,8 +656,10 @@ int CertVerifyProcMac::VerifyInternal(
// Perform hostname verification independent of SecTrustEvaluate. In order to
// do so, mask off any reported name errors first.
verify_result->cert_status &= ~CERT_STATUS_COMMON_NAME_INVALID;
- if (!cert->VerifyNameMatch(hostname))
+ if (!cert->VerifyNameMatch(hostname,
+ &verify_result->common_name_fallback_used)) {
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
+ }
// TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be
// compatible with Windows, which in turn implements this behavior to be
diff --git a/chromium/net/cert/cert_verify_proc_nss.cc b/chromium/net/cert/cert_verify_proc_nss.cc
index 0a0743c150d..c401eba7837 100644
--- a/chromium/net/cert/cert_verify_proc_nss.cc
+++ b/chromium/net/cert/cert_verify_proc_nss.cc
@@ -127,6 +127,8 @@ int MapSecurityError(int err) {
case SEC_ERROR_REVOKED_CERTIFICATE:
case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked.
return ERR_CERT_REVOKED;
+ case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
+ return ERR_CERT_NAME_CONSTRAINT_VIOLATION;
case SEC_ERROR_BAD_DER:
case SEC_ERROR_BAD_SIGNATURE:
case SEC_ERROR_CERT_NOT_VALID:
@@ -136,7 +138,6 @@ int MapSecurityError(int err) {
case SEC_ERROR_INADEQUATE_CERT_TYPE: // Extended key usage and whether
// the certificate is a CA.
case SEC_ERROR_POLICY_VALIDATION_FAILED:
- case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
case SEC_ERROR_EXTENSION_VALUE_INVALID:
@@ -763,9 +764,10 @@ int CertVerifyProcNSS::VerifyInternal(
CERTCertificate* cert_handle = cert->os_cert_handle();
#endif // defined(OS_IOS)
- // Make sure that the hostname matches with the common name of the cert.
- if (!cert->VerifyNameMatch(hostname))
+ if (!cert->VerifyNameMatch(hostname,
+ &verify_result->common_name_fallback_used)) {
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
+ }
// Make sure that the cert is valid now.
SECCertTimeValidity validity = CERT_CheckCertValidTimes(
diff --git a/chromium/net/cert/cert_verify_proc_openssl.cc b/chromium/net/cert/cert_verify_proc_openssl.cc
index a67f194662d..906e4cb484e 100644
--- a/chromium/net/cert/cert_verify_proc_openssl.cc
+++ b/chromium/net/cert/cert_verify_proc_openssl.cc
@@ -172,8 +172,10 @@ int CertVerifyProcOpenSSL::VerifyInternal(
CertVerifyResult* verify_result) {
crypto::EnsureOpenSSLInit();
- if (!cert->VerifyNameMatch(hostname))
+ if (!cert->VerifyNameMatch(hostname,
+ &verify_result->common_name_fallback_used)) {
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
+ }
crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx(
X509_STORE_CTX_new());
diff --git a/chromium/net/cert/cert_verify_proc_unittest.cc b/chromium/net/cert/cert_verify_proc_unittest.cc
index 2f3afe06e6a..71a0c0ee990 100644
--- a/chromium/net/cert/cert_verify_proc_unittest.cc
+++ b/chromium/net/cert/cert_verify_proc_unittest.cc
@@ -111,7 +111,7 @@ class CertVerifyProcTest : public testing::Test {
scoped_refptr<CertVerifyProc> verify_proc_;
};
-TEST_F(CertVerifyProcTest, WithoutRevocationChecking) {
+TEST_F(CertVerifyProcTest, DISABLED_WithoutRevocationChecking) {
// Check that verification without revocation checking works.
CertificateList certs = CreateCertificateListFromFile(
GetTestCertsDirectory(),
@@ -524,6 +524,73 @@ TEST_F(CertVerifyProcTest, DigiNotarCerts) {
}
}
+TEST_F(CertVerifyProcTest, NameConstraintsOk) {
+ CertificateList ca_cert_list =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "root_ca_cert.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, ca_cert_list.size());
+ ScopedTestRoot test_root(ca_cert_list[0]);
+
+ CertificateList cert_list = CreateCertificateListFromFile(
+ GetTestCertsDirectory(), "name_constraint_ok.crt",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, cert_list.size());
+
+ X509Certificate::OSCertHandles intermediates;
+ scoped_refptr<X509Certificate> leaf =
+ X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(),
+ intermediates);
+
+ int flags = 0;
+ CertVerifyResult verify_result;
+ int error = Verify(leaf.get(),
+ "test.example.com",
+ flags,
+ NULL,
+ empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(0U, verify_result.cert_status);
+}
+
+#if defined(OS_ANDROID)
+// Disabled because Android isn't filling in SPKI hashes: crbug.com/116838.
+#define MAYBE_NameConstraintsFailure DISABLED_NameConstraintsFailure
+#else
+#define MAYBE_NameConstraintsFailure NameConstraintsFailure
+#endif
+TEST_F(CertVerifyProcTest, MAYBE_NameConstraintsFailure) {
+ CertificateList ca_cert_list =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "root_ca_cert.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, ca_cert_list.size());
+ ScopedTestRoot test_root(ca_cert_list[0]);
+
+ CertificateList cert_list = CreateCertificateListFromFile(
+ GetTestCertsDirectory(), "name_constraint_bad.crt",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, cert_list.size());
+
+ X509Certificate::OSCertHandles intermediates;
+ scoped_refptr<X509Certificate> leaf =
+ X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(),
+ intermediates);
+
+ int flags = 0;
+ CertVerifyResult verify_result;
+ int error = Verify(leaf.get(),
+ "test.example.com",
+ flags,
+ NULL,
+ empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(ERR_CERT_NAME_CONSTRAINT_VIOLATION, error);
+ EXPECT_EQ(CERT_STATUS_NAME_CONSTRAINT_VIOLATION,
+ verify_result.cert_status & CERT_STATUS_NAME_CONSTRAINT_VIOLATION);
+}
+
// The certse.pem certificate has been revoked. crbug.com/259723.
TEST_F(CertVerifyProcTest, TestKnownRoot) {
base::FilePath certs_dir = GetTestCertsDirectory();
@@ -1001,7 +1068,7 @@ TEST_F(CertVerifyProcTest, CybertrustGTERoot) {
#endif
#if defined(USE_NSS) || defined(OS_IOS) || defined(OS_WIN) || defined(OS_MACOSX)
-static const uint8 kCRLSetThawteSPKIBlocked[] = {
+static const uint8 kCRLSetLeafSPKIBlocked[] = {
0x8e, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
@@ -1009,14 +1076,14 @@ static const uint8 kCRLSetThawteSPKIBlocked[] = {
0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
0x30, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
- 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x36, 0x58, 0x36, 0x4d, 0x78, 0x52, 0x37,
- 0x58, 0x70, 0x4d, 0x51, 0x4b, 0x78, 0x49, 0x41, 0x39, 0x50, 0x6a, 0x36, 0x37,
- 0x36, 0x38, 0x76, 0x74, 0x55, 0x6b, 0x6b, 0x7a, 0x48, 0x79, 0x7a, 0x41, 0x6f,
- 0x6d, 0x6f, 0x4f, 0x68, 0x4b, 0x55, 0x6e, 0x7a, 0x73, 0x55, 0x3d, 0x22, 0x5d,
+ 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x43, 0x38, 0x4d, 0x4a, 0x46, 0x55, 0x55,
+ 0x5a, 0x38, 0x43, 0x79, 0x54, 0x2b, 0x4e, 0x57, 0x64, 0x68, 0x69, 0x7a, 0x51,
+ 0x68, 0x54, 0x49, 0x65, 0x46, 0x49, 0x37, 0x76, 0x41, 0x77, 0x7a, 0x64, 0x54,
+ 0x79, 0x52, 0x59, 0x45, 0x6e, 0x78, 0x6c, 0x33, 0x62, 0x67, 0x3d, 0x22, 0x5d,
0x7d,
};
-static const uint8 kCRLSetThawteSerialBlocked[] = {
+static const uint8 kCRLSetLeafSerialBlocked[] = {
0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
@@ -1024,17 +1091,14 @@ static const uint8 kCRLSetThawteSerialBlocked[] = {
0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
- 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xb1, 0x12, 0x41, 0x42, 0xa5, 0xa1,
- 0xa5, 0xa2, 0x88, 0x19, 0xc7, 0x35, 0x34, 0x0e, 0xff, 0x8c, 0x9e, 0x2f, 0x81,
- 0x68, 0xfe, 0xe3, 0xba, 0x18, 0x7f, 0x25, 0x3b, 0xc1, 0xa3, 0x92, 0xd7, 0xe2,
- // Note that this is actually blocking two serial numbers because on XP and
- // Vista, CryptoAPI finds a different Thawte certificate.
- 0x02, 0x00, 0x00, 0x00,
- 0x04, 0x30, 0x00, 0x00, 0x02,
- 0x04, 0x30, 0x00, 0x00, 0x06,
+ 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0x0f, 0x87, 0xe4, 0xc7, 0x75, 0xea,
+ 0x46, 0x7e, 0xf3, 0xfd, 0x82, 0xb7, 0x46, 0x7b, 0x10, 0xda, 0xc5, 0xbf, 0xd8,
+ 0xd1, 0x29, 0xb2, 0xc6, 0xac, 0x7f, 0x51, 0x42, 0x15, 0x28, 0x51, 0x06, 0x7f,
+ 0x01, 0x00, 0x00, 0x00, // number of serials
+ 0x01, 0xed, // serial 0xed
};
-static const uint8 kCRLSetGoogleSerialBlocked[] = {
+static const uint8 kCRLSetQUICSerialBlocked[] = {
0x60, 0x00, 0x7b, 0x22, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a,
0x30, 0x2c, 0x22, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70,
0x65, 0x22, 0x3a, 0x22, 0x43, 0x52, 0x4c, 0x53, 0x65, 0x74, 0x22, 0x2c, 0x22,
@@ -1042,47 +1106,47 @@ static const uint8 kCRLSetGoogleSerialBlocked[] = {
0x44, 0x65, 0x6c, 0x74, 0x61, 0x46, 0x72, 0x6f, 0x6d, 0x22, 0x3a, 0x30, 0x2c,
0x22, 0x4e, 0x75, 0x6d, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a,
0x31, 0x2c, 0x22, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x53, 0x50, 0x4b,
- 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d, 0xe9, 0x7e, 0x8c, 0xc5, 0x1e, 0xd7,
- 0xa4, 0xc4, 0x0a, 0xc4, 0x80, 0x3d, 0x3e, 0x3e, 0xbb, 0xeb, 0xcb, 0xed, 0x52,
- 0x49, 0x33, 0x1f, 0x2c, 0xc0, 0xa2, 0x6a, 0x0e, 0x84, 0xa5, 0x27, 0xce, 0xc5,
- 0x01, 0x00, 0x00, 0x00, 0x10, 0x4f, 0x9d, 0x96, 0xd9, 0x66, 0xb0, 0x99, 0x2b,
- 0x54, 0xc2, 0x95, 0x7c, 0xb4, 0x15, 0x7d, 0x4d,
+ 0x49, 0x73, 0x22, 0x3a, 0x5b, 0x5d, 0x7d,
+ // Issuer SPKI SHA-256 hash:
+ 0xe4, 0x3a, 0xa3, 0xdb, 0x98, 0x31, 0x61, 0x05, 0xdd, 0x57, 0x6d, 0xc6, 0x2f,
+ 0x71, 0x26, 0xba, 0xdd, 0xf4, 0x98, 0x3e, 0x62, 0x22, 0xf8, 0xf9, 0xe4, 0x18,
+ 0x62, 0x77, 0x79, 0xdb, 0x9b, 0x31,
+ 0x01, 0x00, 0x00, 0x00, // number of serials
+ 0x01, 0x03, // serial 3
};
// Test that CRLSets are effective in making a certificate appear to be
// revoked.
TEST_F(CertVerifyProcTest, CRLSet) {
- CertificateList certs = CreateCertificateListFromFile(
- GetTestCertsDirectory(),
- "googlenew.chain.pem",
- X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
-
- X509Certificate::OSCertHandles intermediates;
- intermediates.push_back(certs[1]->os_cert_handle());
+ CertificateList ca_cert_list =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "root_ca_cert.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, ca_cert_list.size());
+ ScopedTestRoot test_root(ca_cert_list[0]);
- scoped_refptr<X509Certificate> google_full_chain =
- X509Certificate::CreateFromHandle(certs[0]->os_cert_handle(),
- intermediates);
+ CertificateList cert_list = CreateCertificateListFromFile(
+ GetTestCertsDirectory(), "ok_cert.pem", X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, cert_list.size());
+ scoped_refptr<X509Certificate> cert(cert_list[0]);
+ int flags = 0;
CertVerifyResult verify_result;
- int error = Verify(google_full_chain.get(),
- "www.google.com",
- 0,
- NULL,
- empty_cert_list_,
- &verify_result);
+ int error = Verify(
+ cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, &verify_result);
EXPECT_EQ(OK, error);
+ EXPECT_EQ(0U, verify_result.cert_status);
// First test blocking by SPKI.
base::StringPiece crl_set_bytes(
- reinterpret_cast<const char*>(kCRLSetThawteSPKIBlocked),
- sizeof(kCRLSetThawteSPKIBlocked));
+ reinterpret_cast<const char*>(kCRLSetLeafSPKIBlocked),
+ sizeof(kCRLSetLeafSPKIBlocked));
scoped_refptr<CRLSet> crl_set;
ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
- error = Verify(google_full_chain.get(),
- "www.google.com",
- 0,
+ error = Verify(cert.get(),
+ "127.0.0.1",
+ flags,
crl_set.get(),
empty_cert_list_,
&verify_result);
@@ -1090,29 +1154,66 @@ TEST_F(CertVerifyProcTest, CRLSet) {
// Second, test revocation by serial number of a cert directly under the
// root.
- crl_set_bytes = base::StringPiece(
- reinterpret_cast<const char*>(kCRLSetThawteSerialBlocked),
- sizeof(kCRLSetThawteSerialBlocked));
+ crl_set_bytes =
+ base::StringPiece(reinterpret_cast<const char*>(kCRLSetLeafSerialBlocked),
+ sizeof(kCRLSetLeafSerialBlocked));
ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
- error = Verify(google_full_chain.get(),
- "www.google.com",
- 0,
+ error = Verify(cert.get(),
+ "127.0.0.1",
+ flags,
crl_set.get(),
empty_cert_list_,
&verify_result);
EXPECT_EQ(ERR_CERT_REVOKED, error);
+}
- // Lastly, test revocation by serial number of a certificate not under the
- // root.
- crl_set_bytes = base::StringPiece(
- reinterpret_cast<const char*>(kCRLSetGoogleSerialBlocked),
- sizeof(kCRLSetGoogleSerialBlocked));
+TEST_F(CertVerifyProcTest, CRLSetLeafSerial) {
+ CertificateList ca_cert_list =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "quic_root.crt",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, ca_cert_list.size());
+ ScopedTestRoot test_root(ca_cert_list[0]);
+
+ CertificateList intermediate_cert_list =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "quic_intermediate.crt",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, intermediate_cert_list.size());
+ X509Certificate::OSCertHandles intermediates;
+ intermediates.push_back(intermediate_cert_list[0]->os_cert_handle());
+
+ CertificateList cert_list = CreateCertificateListFromFile(
+ GetTestCertsDirectory(), "quic_test.example.com.crt",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(1U, cert_list.size());
+
+ scoped_refptr<X509Certificate> leaf =
+ X509Certificate::CreateFromHandle(cert_list[0]->os_cert_handle(),
+ intermediates);
+
+ int flags = 0;
+ CertVerifyResult verify_result;
+ int error = Verify(leaf.get(),
+ "test.example.com",
+ flags,
+ NULL,
+ empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(OK, error);
+ EXPECT_EQ(0U, verify_result.cert_status);
+
+ // Test revocation by serial number of a certificate not under the root.
+ scoped_refptr<CRLSet> crl_set;
+ base::StringPiece crl_set_bytes =
+ base::StringPiece(reinterpret_cast<const char*>(kCRLSetQUICSerialBlocked),
+ sizeof(kCRLSetQUICSerialBlocked));
ASSERT_TRUE(CRLSet::Parse(crl_set_bytes, &crl_set));
- error = Verify(google_full_chain.get(),
- "www.google.com",
- 0,
+ error = Verify(leaf.get(),
+ "test.example.com",
+ flags,
crl_set.get(),
empty_cert_list_,
&verify_result);
diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc
index b64797a1d6f..29885eac18f 100644
--- a/chromium/net/cert/cert_verify_proc_win.cc
+++ b/chromium/net/cert/cert_verify_proc_win.cc
@@ -764,8 +764,10 @@ int CertVerifyProcWin::VerifyInternal(
// Perform hostname verification independent of
// CertVerifyCertificateChainPolicy.
- if (!cert->VerifyNameMatch(hostname))
+ if (!cert->VerifyNameMatch(hostname,
+ &verify_result->common_name_fallback_used)) {
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
+ }
if (!rev_checking_enabled) {
// If we didn't do online revocation checking then Windows will report
diff --git a/chromium/net/cert/cert_verify_result.cc b/chromium/net/cert/cert_verify_result.cc
index 68e76a77f7a..82df72cdba5 100644
--- a/chromium/net/cert/cert_verify_result.cc
+++ b/chromium/net/cert/cert_verify_result.cc
@@ -23,6 +23,7 @@ void CertVerifyResult::Reset() {
has_md4 = false;
is_issued_by_known_root = false;
is_issued_by_additional_trust_anchor = false;
+ common_name_fallback_used = false;
public_key_hashes.clear();
}
diff --git a/chromium/net/cert/cert_verify_result.h b/chromium/net/cert/cert_verify_result.h
index a00c03e4a24..09deffa0998 100644
--- a/chromium/net/cert/cert_verify_result.h
+++ b/chromium/net/cert/cert_verify_result.h
@@ -62,6 +62,10 @@ class NET_EXPORT CertVerifyResult {
// is_issued_by_additional_trust_anchor is true if the root CA used for this
// verification came from the list of additional trust anchors.
bool is_issued_by_additional_trust_anchor;
+
+ // True if a fallback to the common name was used when matching the host
+ // name, rather than using the subjectAltName.
+ bool common_name_fallback_used;
};
} // namespace net
diff --git a/chromium/net/cert/ct_known_logs.cc b/chromium/net/cert/ct_known_logs.cc
new file mode 100644
index 00000000000..d6164da7846
--- /dev/null
+++ b/chromium/net/cert/ct_known_logs.cc
@@ -0,0 +1,80 @@
+// 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/cert/ct_known_logs.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/cert/ct_log_verifier.h"
+
+namespace net {
+
+namespace ct {
+
+namespace {
+
+// Oldest log - the "pilot" log.
+const char kGooglePilotLogKey[] =
+ "\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\x7d\xa8\x4b\x12\x29\x80\xa3\x3d\xad"
+ "\xd3\x5a\x77\xb8\xcc\xe2\x88\xb3\xa5\xfd\xf1\xd3\x0c\xcd\x18\x0c\xe8\x41"
+ "\x46\xe8\x81\x01\x1b\x15\xe1\x4b\xf1\x1b\x62\xdd\x36\x0a\x08\x18\xba\xed"
+ "\x0b\x35\x84\xd0\x9e\x40\x3c\x2d\x9e\x9b\x82\x65\xbd\x1f\x04\x10\x41\x4c"
+ "\xa0";
+
+const size_t kGooglePilotLogKeyLength = arraysize(kGooglePilotLogKey) - 1;
+
+const char kGooglePilotLogName[] = "Google US1 CT";
+
+// Newer log - the "aviator" log.
+const char kGoogleAviatorLogKey[] =
+ "\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\xd7\xf4\xcc\x69\xb2\xe4\x0e\x90\xa3"
+ "\x8a\xea\x5a\x70\x09\x4f\xef\x13\x62\xd0\x8d\x49\x60\xff\x1b\x40\x50\x07"
+ "\x0c\x6d\x71\x86\xda\x25\x49\x8d\x65\xe1\x08\x0d\x47\x34\x6b\xbd\x27\xbc"
+ "\x96\x21\x3e\x34\xf5\x87\x76\x31\xb1\x7f\x1d\xc9\x85\x3b\x0d\xf7\x1f\x3f"
+ "\xe9";
+
+const size_t kGoogleAviatorLogKeyLength = arraysize(kGoogleAviatorLogKey) - 1;
+
+const char kGoogleAviatorLogName[] = "Google US2 CT";
+
+// Latest log, not turned up yet, nicknamed "rocketeer"
+const char kGoogleRocketeerLogKey[] =
+ "\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\xf3\x58\x9d\x31\x6e\x2f\xc8\x98\x46"
+ "\x2b\x92\x08\x1f\x46\x98\x80\x55\xa9\x0d\x02\xe1\x39\xba\x9a\x90\xcf\x8b"
+ "\xe0\x8a\x7e\x06\x72\xd6\x53\x48\xb3\x4a\xc3\x4d\x2f\x52\xa6\x21\xfc\xcc"
+ "\x33\xcb\x92\x2b\x57\x95\x76\xf2\x07\xcd\x37\x56\x83\xbb\xfa\xea\xb6\xc4"
+ "\xd8";
+
+const size_t kGoogleRocketeerLogKeyLength =
+ arraysize(kGoogleRocketeerLogKey) - 1;
+
+const char kGoogleRocketeerLogName[] = "Google EU CT";
+
+} // namespace
+
+scoped_ptr<CTLogVerifier> CreateGooglePilotLogVerifier() {
+ base::StringPiece key(kGooglePilotLogKey, kGooglePilotLogKeyLength);
+
+ return CTLogVerifier::Create(key, kGooglePilotLogName);
+}
+
+scoped_ptr<CTLogVerifier> CreateGoogleAviatorLogVerifier() {
+ base::StringPiece key(kGoogleAviatorLogKey, kGoogleAviatorLogKeyLength);
+
+ return CTLogVerifier::Create(key, kGoogleAviatorLogName);
+}
+
+scoped_ptr<CTLogVerifier> CreateGoogleRocketeerLogVerifier() {
+ base::StringPiece key(kGoogleRocketeerLogKey, kGoogleRocketeerLogKeyLength);
+
+ return CTLogVerifier::Create(key, kGoogleRocketeerLogName);
+}
+
+} // namespace ct
+
+} // namespace net
+
diff --git a/chromium/net/cert/ct_known_logs.h b/chromium/net/cert/ct_known_logs.h
new file mode 100644
index 00000000000..d616e9b358c
--- /dev/null
+++ b/chromium/net/cert/ct_known_logs.h
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_CT_KNOWN_LOGS_H_
+#define NET_CERT_CT_KNOWN_LOGS_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class CTLogVerifier;
+
+namespace ct {
+
+// Creates a CTLogVerifier instance for the Google Pilot CT Log
+NET_EXPORT scoped_ptr<CTLogVerifier> CreateGooglePilotLogVerifier();
+
+// Creates a CTLogVerifier instance for the Google "Aviator" Log
+NET_EXPORT scoped_ptr<CTLogVerifier> CreateGoogleAviatorLogVerifier();
+
+// Creates a CTLogVerifier instance for the Google "Rocketeer" Log
+NET_EXPORT scoped_ptr<CTLogVerifier> CreateGoogleRocketeerLogVerifier();
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_KNOWN_LOGS_H_
diff --git a/chromium/net/cert/ct_log_verifier.cc b/chromium/net/cert/ct_log_verifier.cc
new file mode 100644
index 00000000000..1c9374dfd94
--- /dev/null
+++ b/chromium/net/cert/ct_log_verifier.cc
@@ -0,0 +1,56 @@
+// 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/cert/ct_log_verifier.h"
+
+#include "base/logging.h"
+#include "net/cert/ct_serialization.h"
+
+namespace net {
+
+// static
+scoped_ptr<CTLogVerifier> CTLogVerifier::Create(
+ const base::StringPiece& public_key,
+ const base::StringPiece& description) {
+ scoped_ptr<CTLogVerifier> result(new CTLogVerifier());
+ if (!result->Init(public_key, description))
+ result.reset();
+ return result.Pass();
+}
+
+bool CTLogVerifier::Verify(const ct::LogEntry& entry,
+ const ct::SignedCertificateTimestamp& sct) {
+ if (sct.log_id != key_id()) {
+ DVLOG(1) << "SCT is not signed by this log.";
+ return false;
+ }
+
+ if (sct.signature.hash_algorithm != hash_algorithm_) {
+ DVLOG(1) << "Mismatched hash algorithm. Expected " << hash_algorithm_
+ << ", got " << sct.signature.hash_algorithm << ".";
+ return false;
+ }
+
+ if (sct.signature.signature_algorithm != signature_algorithm_) {
+ DVLOG(1) << "Mismatched sig algorithm. Expected " << signature_algorithm_
+ << ", got " << sct.signature.signature_algorithm << ".";
+ return false;
+ }
+
+ std::string serialized_log_entry;
+ if (!ct::EncodeLogEntry(entry, &serialized_log_entry)) {
+ DVLOG(1) << "Unable to serialize entry.";
+ return false;
+ }
+ std::string serialized_data;
+ if (!ct::EncodeV1SCTSignedData(sct.timestamp, serialized_log_entry,
+ sct.extensions, &serialized_data)) {
+ DVLOG(1) << "Unable to create SCT to verify.";
+ return false;
+ }
+
+ return VerifySignature(serialized_data, sct.signature.signature_data);
+}
+
+} // namespace net
diff --git a/chromium/net/cert/ct_log_verifier.h b/chromium/net/cert/ct_log_verifier.h
new file mode 100644
index 00000000000..b4ee5202674
--- /dev/null
+++ b/chromium/net/cert/ct_log_verifier.h
@@ -0,0 +1,78 @@
+// 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_CERT_CT_LOG_VERIFIER_H_
+#define NET_CERT_CT_LOG_VERIFIER_H_
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+// Forward declare the crypto types to avoid having to include the full
+// headers.
+#if defined(USE_OPENSSL)
+typedef struct evp_pkey_st EVP_PKEY;
+#else
+typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
+#endif
+
+namespace net {
+
+// Class for verifying Signed Certificate Timestamps (SCTs) provided by a
+// specific log (whose identity is provided during construction).
+class NET_EXPORT CTLogVerifier {
+ public:
+ // Creates a new CTLogVerifier that will verify SignedCertificateTimestamps
+ // using |public_key|, which is a DER-encoded SubjectPublicKeyInfo.
+ // If |public_key| refers to an unsupported public key, returns NULL.
+ // |description| is a textual description of the log.
+ static scoped_ptr<CTLogVerifier> Create(
+ const base::StringPiece& public_key,
+ const base::StringPiece& description);
+
+ ~CTLogVerifier();
+
+ // Returns the log's key ID (RFC6962, Section 3.2)
+ const std::string& key_id() const { return key_id_; }
+ // Returns the log's human-readable description.
+ const std::string& description() const { return description_; }
+
+ // Verifies that |sct| contains a valid signature for |entry|.
+ bool Verify(const ct::LogEntry& entry,
+ const ct::SignedCertificateTimestamp& sct);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(CTLogVerifierTest, VerifySignature);
+
+ CTLogVerifier();
+
+ // Performs crypto-library specific initialization.
+ bool Init(const base::StringPiece& public_key,
+ const base::StringPiece& description);
+
+ // Performs the underlying verification using the selected public key. Note
+ // that |signature| contains the raw signature data (eg: without any
+ // DigitallySigned struct encoding).
+ bool VerifySignature(const base::StringPiece& data_to_sign,
+ const base::StringPiece& signature);
+
+ std::string key_id_;
+ std::string description_;
+ ct::DigitallySigned::HashAlgorithm hash_algorithm_;
+ ct::DigitallySigned::SignatureAlgorithm signature_algorithm_;
+
+#if defined(USE_OPENSSL)
+ EVP_PKEY* public_key_;
+#else
+ SECKEYPublicKey* public_key_;
+#endif
+};
+
+} // namespace net
+
+#endif // NET_CERT_CT_LOG_VERIFIER_H_
diff --git a/chromium/net/cert/ct_log_verifier_nss.cc b/chromium/net/cert/ct_log_verifier_nss.cc
new file mode 100644
index 00000000000..49b6f7339ba
--- /dev/null
+++ b/chromium/net/cert/ct_log_verifier_nss.cc
@@ -0,0 +1,142 @@
+// 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/cert/ct_log_verifier.h"
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <nss.h>
+#include <pk11pub.h>
+#include <secitem.h>
+#include <secoid.h>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/sha2.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+namespace {
+
+SECOidTag GetNSSSigAlg(ct::DigitallySigned::SignatureAlgorithm alg) {
+ switch (alg) {
+ case ct::DigitallySigned::SIG_ALGO_RSA:
+ return SEC_OID_PKCS1_RSA_ENCRYPTION;
+ case ct::DigitallySigned::SIG_ALGO_DSA:
+ return SEC_OID_ANSIX9_DSA_SIGNATURE;
+ case ct::DigitallySigned::SIG_ALGO_ECDSA:
+ return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
+ case ct::DigitallySigned::SIG_ALGO_ANONYMOUS:
+ default:
+ NOTREACHED();
+ return SEC_OID_UNKNOWN;
+ }
+}
+
+SECOidTag GetNSSHashAlg(ct::DigitallySigned::HashAlgorithm alg) {
+ switch (alg) {
+ case ct::DigitallySigned::HASH_ALGO_MD5:
+ return SEC_OID_MD5;
+ case ct::DigitallySigned::HASH_ALGO_SHA1:
+ return SEC_OID_SHA1;
+ case ct::DigitallySigned::HASH_ALGO_SHA224:
+ return SEC_OID_SHA224;
+ case ct::DigitallySigned::HASH_ALGO_SHA256:
+ return SEC_OID_SHA256;
+ case ct::DigitallySigned::HASH_ALGO_SHA384:
+ return SEC_OID_SHA384;
+ case ct::DigitallySigned::HASH_ALGO_SHA512:
+ return SEC_OID_SHA512;
+ case ct::DigitallySigned::HASH_ALGO_NONE:
+ default:
+ NOTREACHED();
+ return SEC_OID_UNKNOWN;
+ }
+}
+
+} // namespace
+
+CTLogVerifier::~CTLogVerifier() {
+ if (public_key_)
+ SECKEY_DestroyPublicKey(public_key_);
+}
+
+CTLogVerifier::CTLogVerifier()
+ : hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE),
+ signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS),
+ public_key_(NULL) {}
+
+bool CTLogVerifier::Init(const base::StringPiece& public_key,
+ const base::StringPiece& description) {
+ SECItem key_data;
+
+ crypto::EnsureNSSInit();
+
+ key_data.data = reinterpret_cast<unsigned char*>(
+ const_cast<char*>(public_key.data()));
+ key_data.len = public_key.size();
+
+ CERTSubjectPublicKeyInfo* public_key_info =
+ SECKEY_DecodeDERSubjectPublicKeyInfo(&key_data);
+ if (!public_key_info) {
+ DVLOG(1) << "Failed decoding public key.";
+ return false;
+ }
+
+ public_key_ = SECKEY_ExtractPublicKey(public_key_info);
+ SECKEY_DestroySubjectPublicKeyInfo(public_key_info);
+
+ if (!public_key_) {
+ DVLOG(1) << "Failed extracting public key.";
+ return false;
+ }
+
+ key_id_ = crypto::SHA256HashString(public_key);
+ description_ = description.as_string();
+
+ // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are
+ // supported.
+ switch (SECKEY_GetPublicKeyType(public_key_)) {
+ case rsaKey:
+ hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
+ signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA;
+ break;
+ case ecKey:
+ hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
+ signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA;
+ break;
+ default:
+ DVLOG(1) << "Unsupported key type: "
+ << SECKEY_GetPublicKeyType(public_key_);
+ return false;
+ }
+
+ // Extra sanity check: Require RSA keys of at least 2048 bits.
+ if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA &&
+ SECKEY_PublicKeyStrengthInBits(public_key_) < 2048) {
+ DVLOG(1) << "Too small a public key.";
+ return false;
+ }
+
+ return true;
+}
+
+bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign,
+ const base::StringPiece& signature) {
+ SECItem sig_data;
+ sig_data.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
+ signature.data()));
+ sig_data.len = signature.size();
+
+ SECStatus rv = VFY_VerifyDataDirect(
+ reinterpret_cast<const unsigned char*>(data_to_sign.data()),
+ data_to_sign.size(), public_key_, &sig_data,
+ GetNSSSigAlg(signature_algorithm_), GetNSSHashAlg(hash_algorithm_),
+ NULL, NULL);
+ DVLOG(1) << "Signature verification result: " << (rv == SECSuccess);
+ return rv == SECSuccess;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/ct_log_verifier_openssl.cc b/chromium/net/cert/ct_log_verifier_openssl.cc
new file mode 100644
index 00000000000..fca4182e126
--- /dev/null
+++ b/chromium/net/cert/ct_log_verifier_openssl.cc
@@ -0,0 +1,120 @@
+// 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/cert/ct_log_verifier.h"
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include "base/logging.h"
+#include "crypto/openssl_util.h"
+#include "crypto/sha2.h"
+
+namespace net {
+
+namespace {
+
+const EVP_MD* GetEvpAlg(ct::DigitallySigned::HashAlgorithm alg) {
+ switch (alg) {
+ case ct::DigitallySigned::HASH_ALGO_MD5:
+ return EVP_md5();
+ case ct::DigitallySigned::HASH_ALGO_SHA1:
+ return EVP_sha1();
+ case ct::DigitallySigned::HASH_ALGO_SHA224:
+ return EVP_sha224();
+ case ct::DigitallySigned::HASH_ALGO_SHA256:
+ return EVP_sha256();
+ case ct::DigitallySigned::HASH_ALGO_SHA384:
+ return EVP_sha384();
+ case ct::DigitallySigned::HASH_ALGO_SHA512:
+ return EVP_sha512();
+ case ct::DigitallySigned::HASH_ALGO_NONE:
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+} // namespace
+
+CTLogVerifier::~CTLogVerifier() {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ if (public_key_)
+ EVP_PKEY_free(public_key_);
+}
+
+CTLogVerifier::CTLogVerifier()
+ : hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE),
+ signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS),
+ public_key_(NULL) {}
+
+bool CTLogVerifier::Init(const base::StringPiece& public_key,
+ const base::StringPiece& description) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(
+ BIO_new_mem_buf(const_cast<char*>(public_key.data()), public_key.size()));
+ if (!bio.get())
+ return false;
+
+ public_key_ = d2i_PUBKEY_bio(bio.get(), NULL);
+ if (!public_key_)
+ return false;
+
+ key_id_ = crypto::SHA256HashString(public_key);
+ description_ = description.as_string();
+
+ // Right now, only RSASSA-PKCS1v15 with SHA-256 and ECDSA with SHA-256 are
+ // supported.
+ switch (EVP_PKEY_type(public_key_->type)) {
+ case EVP_PKEY_RSA:
+ hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
+ signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_RSA;
+ break;
+ case EVP_PKEY_EC:
+ hash_algorithm_ = ct::DigitallySigned::HASH_ALGO_SHA256;
+ signature_algorithm_ = ct::DigitallySigned::SIG_ALGO_ECDSA;
+ break;
+ default:
+ DVLOG(1) << "Unsupported key type: " << EVP_PKEY_type(public_key_->type);
+ return false;
+ }
+
+ // Extra sanity check: Require RSA keys of at least 2048 bits.
+ // EVP_PKEY_size returns the size in bytes. 256 = 2048-bit RSA key.
+ if (signature_algorithm_ == ct::DigitallySigned::SIG_ALGO_RSA &&
+ EVP_PKEY_size(public_key_) < 256) {
+ DVLOG(1) << "Too small a public key.";
+ return false;
+ }
+
+ return true;
+}
+
+bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign,
+ const base::StringPiece& signature) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_);
+ if (hash_alg == NULL)
+ return false;
+
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+
+ bool ok = (
+ 1 == EVP_DigestVerifyInit(&ctx, NULL, hash_alg, NULL, public_key_) &&
+ 1 == EVP_DigestVerifyUpdate(
+ &ctx, data_to_sign.data(), data_to_sign.size()) &&
+ 1 == EVP_DigestVerifyFinal(
+ &ctx,
+ reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data())),
+ signature.size()));
+
+ EVP_MD_CTX_cleanup(&ctx);
+ return ok;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/ct_log_verifier_unittest.cc b/chromium/net/cert/ct_log_verifier_unittest.cc
new file mode 100644
index 00000000000..b94f14a11c2
--- /dev/null
+++ b/chromium/net/cert/ct_log_verifier_unittest.cc
@@ -0,0 +1,78 @@
+// 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/cert/ct_log_verifier.h"
+
+#include <string>
+
+#include "base/time/time.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/test/ct_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class CTLogVerifierTest : public ::testing::Test {
+ public:
+ CTLogVerifierTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog").Pass();
+
+ ASSERT_TRUE(log_);
+ ASSERT_EQ(log_->key_id(), ct::GetTestPublicKeyId());
+ }
+
+ protected:
+ scoped_ptr<CTLogVerifier> log_;
+};
+
+TEST_F(CTLogVerifierTest, VerifiesCertSCT) {
+ ct::LogEntry cert_entry;
+ ct::GetX509CertLogEntry(&cert_entry);
+
+ scoped_refptr<ct::SignedCertificateTimestamp> cert_sct;
+ ct::GetX509CertSCT(&cert_sct);
+
+ EXPECT_TRUE(log_->Verify(cert_entry, *cert_sct));
+}
+
+TEST_F(CTLogVerifierTest, VerifiesPrecertSCT) {
+ ct::LogEntry precert_entry;
+ ct::GetPrecertLogEntry(&precert_entry);
+
+ scoped_refptr<ct::SignedCertificateTimestamp> precert_sct;
+ ct::GetPrecertSCT(&precert_sct);
+
+ EXPECT_TRUE(log_->Verify(precert_entry, *precert_sct));
+}
+
+TEST_F(CTLogVerifierTest, FailsInvalidTimestamp) {
+ ct::LogEntry cert_entry;
+ ct::GetX509CertLogEntry(&cert_entry);
+
+ scoped_refptr<ct::SignedCertificateTimestamp> cert_sct;
+ ct::GetX509CertSCT(&cert_sct);
+
+ // Mangle the timestamp, so that it should fail signature validation.
+ cert_sct->timestamp = base::Time::Now();
+
+ EXPECT_FALSE(log_->Verify(cert_entry, *cert_sct));
+}
+
+TEST_F(CTLogVerifierTest, FailsInvalidLogID) {
+ ct::LogEntry cert_entry;
+ ct::GetX509CertLogEntry(&cert_entry);
+
+ scoped_refptr<ct::SignedCertificateTimestamp> cert_sct;
+ ct::GetX509CertSCT(&cert_sct);
+
+ // Mangle the log ID, which should cause it to match a different log before
+ // attempting signature validation.
+ cert_sct->log_id.assign(cert_sct->log_id.size(), '\0');
+
+ EXPECT_FALSE(log_->Verify(cert_entry, *cert_sct));
+}
+
+} // namespace net
diff --git a/chromium/net/cert/ct_objects_extractor.h b/chromium/net/cert/ct_objects_extractor.h
new file mode 100644
index 00000000000..d8fc5f95e52
--- /dev/null
+++ b/chromium/net/cert/ct_objects_extractor.h
@@ -0,0 +1,64 @@
+// 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_CERT_CT_OBJECTS_EXTRACTOR_H_
+#define NET_CERT_CT_OBJECTS_EXTRACTOR_H_
+
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+
+namespace ct {
+
+struct LogEntry;
+
+// Extracts a SignedCertificateTimestampList that has been embedded within a
+// leaf cert as an X.509v3 extension with the OID 1.3.6.1.4.1.11129.2.4.2.
+// If the extension is present, returns true, updating |*sct_list| to contain
+// the encoded list, minus the DER encoding necessary for the extension.
+// |*sct_list| can then be further decoded with ct::DecodeSCTList
+NET_EXPORT_PRIVATE bool ExtractEmbeddedSCTList(
+ X509Certificate::OSCertHandle cert,
+ std::string* sct_list);
+
+// Obtains a PrecertChain log entry for |leaf|, an X.509v3 certificate that
+// contains an X.509v3 extension with the OID 1.3.6.1.4.1.11129.2.4.2. On
+// success, fills |*result| with the data for a PrecertChain log entry and
+// returns true.
+// The filled |*result| should be verified using ct::CTLogVerifier::Verify
+// Note: If |leaf| does not contain the required extension, it is treated as
+// a failure.
+NET_EXPORT_PRIVATE bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
+ X509Certificate::OSCertHandle issuer,
+ LogEntry* result);
+
+// Obtains an X509Chain log entry for |leaf|, an X.509v3 certificate that
+// is not expected to contain an X.509v3 extension with the OID
+// 1.3.6.1.4.1.11129.2.4.2 (meaning a certificate without an embedded SCT).
+// On success, fills |result| with the data for an X509Chain log entry and
+// returns true.
+// The filled |*result| should be verified using ct::CTLogVerifier::Verify
+NET_EXPORT_PRIVATE bool GetX509LogEntry(X509Certificate::OSCertHandle leaf,
+ LogEntry* result);
+
+// Extracts a SignedCertificateTimestampList that has been embedded within
+// an OCSP response as an extension with the OID 1.3.6.1.4.1.11129.2.4.5.
+// If the extension is present, and the response matches the issuer and
+// serial number, returns true, updating |*sct_list| to contain
+// the encoded list, minus the DER encoding necessary for the extension.
+// |*sct_list| can then be further decoded with ct::DecodeSCTList.
+NET_EXPORT_PRIVATE bool ExtractSCTListFromOCSPResponse(
+ X509Certificate::OSCertHandle issuer,
+ const std::string& cert_serial_number,
+ const std::string& ocsp_response,
+ std::string* sct_list);
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_OBJECTS_EXTRACTOR_H_
diff --git a/chromium/net/cert/ct_objects_extractor_nss.cc b/chromium/net/cert/ct_objects_extractor_nss.cc
new file mode 100644
index 00000000000..c29b34c10c6
--- /dev/null
+++ b/chromium/net/cert/ct_objects_extractor_nss.cc
@@ -0,0 +1,617 @@
+// 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/cert/ct_objects_extractor.h"
+
+#include <cert.h>
+#include <secasn1.h>
+#include <secitem.h>
+#include <secoid.h>
+
+#include "base/lazy_instance.h"
+#include "base/sha1.h"
+#include "crypto/scoped_nss_types.h"
+#include "crypto/sha2.h"
+#include "net/cert/asn1_util.h"
+#include "net/cert/scoped_nss_types.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+namespace ct {
+
+namespace {
+
+// NSS black magic to get the address of externally defined template at runtime.
+SEC_ASN1_MKSUB(SEC_IntegerTemplate)
+SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
+SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate)
+SEC_ASN1_MKSUB(CERT_SequenceOfCertExtensionTemplate)
+
+// Wrapper class to convert a X509Certificate::OSCertHandle directly
+// into a CERTCertificate* usable with other NSS functions. This is used for
+// platforms where X509Certificate::OSCertHandle refers to a different type
+// than a CERTCertificate*.
+struct NSSCertWrapper {
+ explicit NSSCertWrapper(X509Certificate::OSCertHandle cert_handle);
+ ~NSSCertWrapper() {}
+
+ ScopedCERTCertificate cert;
+};
+
+NSSCertWrapper::NSSCertWrapper(X509Certificate::OSCertHandle cert_handle) {
+#if defined(USE_NSS)
+ cert.reset(CERT_DupCertificate(cert_handle));
+#else
+ SECItem der_cert;
+ std::string der_data;
+ if (!X509Certificate::GetDEREncoded(cert_handle, &der_data))
+ return;
+ der_cert.data =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(der_data.data()));
+ der_cert.len = der_data.size();
+
+ // Note: CERT_NewTempCertificate may return NULL if the certificate
+ // shares a serial number with another cert issued by the same CA,
+ // which is not supposed to happen.
+ cert.reset(CERT_NewTempCertificate(
+ CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE));
+#endif
+ DCHECK(cert.get() != NULL);
+}
+
+// The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of
+// RFC6962.
+const unsigned char kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
+ 0xD6, 0x79, 0x02, 0x04, 0x02};
+const char kEmbeddedSCTDescription[] =
+ "X.509v3 Certificate Transparency Embedded Signed Certificate Timestamp "
+ "List";
+
+// The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for
+// X.509v3 Certificate Transparency Signed Certificate Timestamp List, see
+// Section 3.3 of RFC6962.
+const unsigned char kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01,
+ 0xD6, 0x79, 0x02, 0x04, 0x05};
+
+const SECItem kOCSPExtensionOidItem = {
+ siBuffer, const_cast<unsigned char*>(kOCSPExtensionOid),
+ sizeof(kOCSPExtensionOid)
+};
+
+// id-ad-ocsp: 1.3.6.1.5.5.7.48.1.1
+const unsigned char kBasicOCSPResponseOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x30, 0x01, 0x01};
+
+const SECItem kBasicOCSPResponseOidItem = {
+ siBuffer, const_cast<unsigned char*>(kBasicOCSPResponseOid),
+ sizeof(kBasicOCSPResponseOid)
+};
+
+
+// Initializes the necessary NSS internals for use with Certificate
+// Transparency.
+class CTInitSingleton {
+ public:
+ SECOidTag embedded_oid() const { return embedded_oid_; }
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<CTInitSingleton>;
+
+ CTInitSingleton() : embedded_oid_(SEC_OID_UNKNOWN) {
+ embedded_oid_ = RegisterOid(
+ kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), kEmbeddedSCTDescription);
+ }
+
+ ~CTInitSingleton() {}
+
+ SECOidTag RegisterOid(const unsigned char* oid,
+ unsigned int oid_len,
+ const char* description) {
+ SECOidData oid_data;
+ oid_data.oid.len = oid_len;
+ oid_data.oid.data = const_cast<unsigned char*>(oid);
+ oid_data.offset = SEC_OID_UNKNOWN;
+ oid_data.desc = description;
+ oid_data.mechanism = CKM_INVALID_MECHANISM;
+ // Setting this to SUPPORTED_CERT_EXTENSION ensures that if a certificate
+ // contains this extension with the critical bit set, NSS will not reject
+ // it. However, because verification of this extension happens after NSS,
+ // it is currently left as INVALID_CERT_EXTENSION.
+ oid_data.supportedExtension = INVALID_CERT_EXTENSION;
+
+ SECOidTag result = SECOID_AddEntry(&oid_data);
+ CHECK_NE(SEC_OID_UNKNOWN, result);
+
+ return result;
+ }
+
+ SECOidTag embedded_oid_;
+
+ DISALLOW_COPY_AND_ASSIGN(CTInitSingleton);
+};
+
+base::LazyInstance<CTInitSingleton>::Leaky g_ct_singleton =
+ LAZY_INSTANCE_INITIALIZER;
+
+// Obtains the data for an X.509v3 certificate extension identified by |oid|
+// and encoded as an OCTET STRING. Returns true if the extension was found in
+// the certificate, updating |ext_data| to be the extension data after removing
+// the DER encoding of OCTET STRING.
+bool GetCertOctetStringExtension(CERTCertificate* cert,
+ SECOidTag oid,
+ std::string* extension_data) {
+ SECItem extension;
+ SECStatus rv = CERT_FindCertExtension(cert, oid, &extension);
+ if (rv != SECSuccess)
+ return false;
+
+ base::StringPiece raw_data(reinterpret_cast<char*>(extension.data),
+ extension.len);
+ base::StringPiece parsed_data;
+ if (!asn1::GetElement(&raw_data, asn1::kOCTETSTRING, &parsed_data) ||
+ raw_data.size() > 0) { // Decoding failure or raw data left
+ rv = SECFailure;
+ } else {
+ parsed_data.CopyToString(extension_data);
+ }
+
+ SECITEM_FreeItem(&extension, PR_FALSE);
+ return rv == SECSuccess;
+}
+
+// NSS offers CERT_FindCertExtension for certificates, but that only accepts
+// CERTCertificate* inputs, so the method below extracts the SCT extension
+// directly from the CERTCertExtension** of an OCSP response.
+//
+// Obtains the data for an OCSP extension identified by kOCSPExtensionOidItem
+// and encoded as an OCTET STRING. Returns true if the extension was found in
+// |extensions|, updating |extension_data| to be the extension data after
+// removing the DER encoding of OCTET STRING.
+bool GetSCTListFromOCSPExtension(PLArenaPool* arena,
+ const CERTCertExtension* const* extensions,
+ std::string* extension_data) {
+ if (!extensions)
+ return false;
+
+ const CERTCertExtension* match = NULL;
+
+ for (const CERTCertExtension* const* exts = extensions; *exts; ++exts) {
+ const CERTCertExtension* ext = *exts;
+ if (SECITEM_ItemsAreEqual(&kOCSPExtensionOidItem, &ext->id)) {
+ match = ext;
+ break;
+ }
+ }
+
+ if (!match)
+ return false;
+
+ SECItem contents;
+ // SEC_QuickDERDecodeItem sets |contents| to point to |match|, so it is not
+ // necessary to free the contents of |contents|.
+ SECStatus rv = SEC_QuickDERDecodeItem(arena, &contents,
+ SEC_ASN1_GET(SEC_OctetStringTemplate),
+ &match->value);
+ if (rv != SECSuccess)
+ return false;
+
+ base::StringPiece parsed_data(reinterpret_cast<char*>(contents.data),
+ contents.len);
+ parsed_data.CopyToString(extension_data);
+ return true;
+}
+
+// Given a |cert|, extract the TBSCertificate from this certificate, also
+// removing the X.509 extension with OID 1.3.6.1.4.1.11129.2.4.2 (that is,
+// the embedded SCT)
+bool ExtractTBSCertWithoutSCTs(CERTCertificate* cert,
+ std::string* to_be_signed) {
+ SECOidData* oid = SECOID_FindOIDByTag(g_ct_singleton.Get().embedded_oid());
+ if (!oid)
+ return false;
+
+ // This is a giant hack, due to the fact that NSS does not expose a good API
+ // for simply removing certificate fields from existing certificates.
+ CERTCertificate temp_cert;
+ temp_cert = *cert;
+ temp_cert.extensions = NULL;
+
+ // Strip out the embedded SCT OID from the new certificate by directly
+ // mutating the extensions in place.
+ std::vector<CERTCertExtension*> new_extensions;
+ if (cert->extensions) {
+ for (CERTCertExtension** exts = cert->extensions; *exts; ++exts) {
+ CERTCertExtension* ext = *exts;
+ SECComparison result = SECITEM_CompareItem(&oid->oid, &ext->id);
+ if (result != SECEqual)
+ new_extensions.push_back(ext);
+ }
+ }
+ if (!new_extensions.empty()) {
+ new_extensions.push_back(NULL);
+ temp_cert.extensions = &new_extensions[0];
+ }
+
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+
+ SECItem tbs_data;
+ tbs_data.len = 0;
+ tbs_data.data = NULL;
+ void* result = SEC_ASN1EncodeItem(arena.get(),
+ &tbs_data,
+ &temp_cert,
+ SEC_ASN1_GET(CERT_CertificateTemplate));
+ if (!result)
+ return false;
+
+ to_be_signed->assign(reinterpret_cast<char*>(tbs_data.data), tbs_data.len);
+ return true;
+}
+
+// The following code is adapted from the NSS OCSP module, in order to expose
+// the internal structure of an OCSP response.
+
+// ResponseBytes ::= SEQUENCE {
+// responseType OBJECT IDENTIFIER,
+// response OCTET STRING }
+struct ResponseBytes {
+ SECItem response_type;
+ SECItem der_response;
+};
+
+const SEC_ASN1Template kResponseBytesTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseBytes) },
+ { SEC_ASN1_OBJECT_ID, offsetof(ResponseBytes, response_type) },
+ { SEC_ASN1_OCTET_STRING, offsetof(ResponseBytes, der_response) },
+ { 0 }
+};
+
+// OCSPResponse ::= SEQUENCE {
+// responseStatus OCSPResponseStatus,
+// responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
+struct OCSPResponse {
+ SECItem response_status;
+ // This indirection is needed because |response_bytes| is an optional
+ // component and we need a way to determine if it is missing.
+ ResponseBytes* response_bytes;
+};
+
+const SEC_ASN1Template kPointerToResponseBytesTemplate[] = {
+ { SEC_ASN1_POINTER, 0, kResponseBytesTemplate }
+};
+
+const SEC_ASN1Template kOCSPResponseTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OCSPResponse) },
+ { SEC_ASN1_ENUMERATED, offsetof(OCSPResponse, response_status) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(OCSPResponse, response_bytes),
+ kPointerToResponseBytesTemplate },
+ { 0 }
+};
+
+// CertID ::= SEQUENCE {
+// hashAlgorithm AlgorithmIdentifier,
+// issuerNameHash OCTET STRING, -- Hash of Issuer's DN
+// issuerKeyHash OCTET STRING, -- Hash of Issuers public key
+// serialNumber CertificateSerialNumber }
+struct CertID {
+ SECAlgorithmID hash_algorithm;
+ SECItem issuer_name_hash;
+ SECItem issuer_key_hash;
+ SECItem serial_number;
+};
+
+const SEC_ASN1Template kCertIDTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CertID) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CertID, hash_algorithm),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_name_hash) },
+ { SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_key_hash) },
+ { SEC_ASN1_INTEGER, offsetof(CertID, serial_number) },
+ { 0 }
+};
+
+// SingleResponse ::= SEQUENCE {
+// certID CertID,
+// certStatus CertStatus,
+// thisUpdate GeneralizedTime,
+// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
+// singleExtensions [1] EXPLICIT Extensions OPTIONAL }
+struct SingleResponse {
+ CertID cert_id;
+ // The following three fields are not used.
+ SECItem der_cert_status;
+ SECItem this_update;
+ SECItem next_update;
+ CERTCertExtension** single_extensions;
+};
+
+const SEC_ASN1Template kSingleResponseTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SingleResponse) },
+ { SEC_ASN1_INLINE, offsetof(SingleResponse, cert_id), kCertIDTemplate },
+ // Really a CHOICE but we make it an ANY because we don't care about the
+ // contents of this field.
+ // TODO(ekasper): use SEC_ASN1_CHOICE.
+ { SEC_ASN1_ANY, offsetof(SingleResponse, der_cert_status) },
+ { SEC_ASN1_GENERALIZED_TIME, offsetof(SingleResponse, this_update) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
+ SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
+ offsetof(SingleResponse, next_update),
+ SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
+ offsetof(SingleResponse, single_extensions),
+ SEC_ASN1_SUB(CERT_SequenceOfCertExtensionTemplate) },
+ { 0 }
+};
+
+// ResponseData ::= SEQUENCE {
+// version [0] EXPLICIT Version DEFAULT v1,
+// responderID ResponderID,
+// producedAt GeneralizedTime,
+// responses SEQUENCE OF SingleResponse,
+// responseExtensions [1] EXPLICIT Extensions OPTIONAL }
+struct ResponseData {
+ // The first three fields are not used.
+ SECItem version;
+ SECItem der_responder_id;
+ SECItem produced_at;
+ SingleResponse** single_responses;
+ // Skip extensions.
+};
+
+const SEC_ASN1Template kResponseDataTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseData) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED |
+ SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
+ offsetof(ResponseData, version), SEC_ASN1_SUB(SEC_IntegerTemplate) },
+ // Really a CHOICE but we make it an ANY because we don't care about the
+ // contents of this field.
+ // TODO(ekasper): use SEC_ASN1_CHOICE.
+ { SEC_ASN1_ANY, offsetof(ResponseData, der_responder_id) },
+ { SEC_ASN1_GENERALIZED_TIME, offsetof(ResponseData, produced_at) },
+ { SEC_ASN1_SEQUENCE_OF, offsetof(ResponseData, single_responses),
+ kSingleResponseTemplate },
+ { SEC_ASN1_SKIP_REST },
+ { 0 }
+};
+
+// BasicOCSPResponse ::= SEQUENCE {
+// tbsResponseData ResponseData,
+// signatureAlgorithm AlgorithmIdentifier,
+// signature BIT STRING,
+// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
+struct BasicOCSPResponse {
+ ResponseData tbs_response_data;
+ // We do not care about the rest.
+};
+
+const SEC_ASN1Template kBasicOCSPResponseTemplate[] = {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(BasicOCSPResponse) },
+ { SEC_ASN1_INLINE, offsetof(BasicOCSPResponse, tbs_response_data),
+ kResponseDataTemplate },
+ { SEC_ASN1_SKIP_REST },
+ { 0 }
+};
+
+bool StringEqualToSECItem(const std::string& value1, const SECItem& value2) {
+ if (value1.size() != value2.len)
+ return false;
+ return memcmp(value1.data(), value2.data, value2.len) == 0;
+}
+
+// TODO(ekasper): also use the issuer name hash in matching.
+bool CertIDMatches(const CertID& cert_id,
+ const std::string& serial_number,
+ const std::string& issuer_key_sha1_hash,
+ const std::string& issuer_key_sha256_hash) {
+ if (!StringEqualToSECItem(serial_number, cert_id.serial_number))
+ return false;
+
+ SECOidTag hash_alg = SECOID_FindOIDTag(&cert_id.hash_algorithm.algorithm);
+ switch (hash_alg) {
+ case SEC_OID_SHA1:
+ return StringEqualToSECItem(issuer_key_sha1_hash,
+ cert_id.issuer_key_hash);
+ case SEC_OID_SHA256:
+ return StringEqualToSECItem(issuer_key_sha256_hash,
+ cert_id.issuer_key_hash);
+ default:
+ return false;
+ }
+}
+
+} // namespace
+
+bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert,
+ std::string* sct_list) {
+ DCHECK(cert);
+
+ NSSCertWrapper leaf_cert(cert);
+ if (!leaf_cert.cert)
+ return false;
+
+ return GetCertOctetStringExtension(leaf_cert.cert.get(),
+ g_ct_singleton.Get().embedded_oid(),
+ sct_list);
+}
+
+bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
+ X509Certificate::OSCertHandle issuer,
+ LogEntry* result) {
+ DCHECK(leaf);
+ DCHECK(issuer);
+
+ NSSCertWrapper leaf_cert(leaf);
+ NSSCertWrapper issuer_cert(issuer);
+
+ result->Reset();
+ // XXX(rsleevi): This check may be overkill, since we should be able to
+ // generate precerts for certs without the extension. For now, just a sanity
+ // check to match the reference implementation.
+ SECItem extension;
+ SECStatus rv = CERT_FindCertExtension(
+ leaf_cert.cert.get(), g_ct_singleton.Get().embedded_oid(), &extension);
+ if (rv != SECSuccess)
+ return false;
+ SECITEM_FreeItem(&extension, PR_FALSE);
+
+ std::string to_be_signed;
+ if (!ExtractTBSCertWithoutSCTs(leaf_cert.cert.get(), &to_be_signed))
+ return false;
+
+ if (!issuer_cert.cert) {
+ // This can happen when the issuer and leaf certs share the same serial
+ // number and are from the same CA, which should never be the case
+ // (but happened with bad test certs).
+ VLOG(1) << "Issuer cert is null, cannot generate Precert entry.";
+ return false;
+ }
+
+ SECKEYPublicKey* issuer_pub_key =
+ SECKEY_ExtractPublicKey(&(issuer_cert.cert->subjectPublicKeyInfo));
+ if (!issuer_pub_key) {
+ VLOG(1) << "Could not extract issuer public key, "
+ << "cannot generate Precert entry.";
+ return false;
+ }
+
+ SECItem* encoded_issuer_pubKey =
+ SECKEY_EncodeDERSubjectPublicKeyInfo(issuer_pub_key);
+ if (!encoded_issuer_pubKey) {
+ SECKEY_DestroyPublicKey(issuer_pub_key);
+ return false;
+ }
+
+ result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT;
+ result->tbs_certificate.swap(to_be_signed);
+
+ crypto::SHA256HashString(
+ base::StringPiece(reinterpret_cast<char*>(encoded_issuer_pubKey->data),
+ encoded_issuer_pubKey->len),
+ result->issuer_key_hash.data,
+ sizeof(result->issuer_key_hash.data));
+
+ SECITEM_FreeItem(encoded_issuer_pubKey, PR_TRUE);
+ SECKEY_DestroyPublicKey(issuer_pub_key);
+
+ return true;
+}
+
+bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) {
+ DCHECK(leaf);
+
+ std::string encoded;
+ if (!X509Certificate::GetDEREncoded(leaf, &encoded))
+ return false;
+
+ result->Reset();
+ result->type = ct::LogEntry::LOG_ENTRY_TYPE_X509;
+ result->leaf_certificate.swap(encoded);
+ return true;
+}
+
+bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer,
+ const std::string& cert_serial_number,
+ const std::string& ocsp_response,
+ std::string* sct_list) {
+ DCHECK(issuer);
+
+ // Any OCSP response is unlikely to be even close to 2^24 bytes; further, CT
+ // only uses stapled OCSP responses which have this limit imposed by the TLS
+ // protocol.
+ if (ocsp_response.size() > 0xffffff)
+ return false;
+
+ crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+
+ OCSPResponse response;
+ memset(&response, 0, sizeof(response));
+
+ SECItem src = { siBuffer,
+ reinterpret_cast<unsigned char*>(const_cast<char*>(
+ ocsp_response.data())),
+ static_cast<unsigned int>(ocsp_response.size()) };
+
+ // |response| will point directly into |src|, so it's not necessary to
+ // free the |response| contents, but they may only be used while |src|
+ // is valid (i.e., in this method).
+ SECStatus rv = SEC_QuickDERDecodeItem(arena.get(), &response,
+ kOCSPResponseTemplate, &src);
+ if (rv != SECSuccess)
+ return false;
+
+ if (!response.response_bytes)
+ return false;
+
+ if (!SECITEM_ItemsAreEqual(&kBasicOCSPResponseOidItem,
+ &response.response_bytes->response_type)) {
+ return false;
+ }
+
+ BasicOCSPResponse basic_response;
+ memset(&basic_response, 0, sizeof(basic_response));
+
+ rv = SEC_QuickDERDecodeItem(arena.get(), &basic_response,
+ kBasicOCSPResponseTemplate,
+ &response.response_bytes->der_response);
+ if (rv != SECSuccess)
+ return false;
+
+ SingleResponse** responses =
+ basic_response.tbs_response_data.single_responses;
+ if (!responses)
+ return false;
+
+ std::string issuer_der;
+ if (!X509Certificate::GetDEREncoded(issuer, &issuer_der))
+ return false;
+
+ base::StringPiece issuer_spki;
+ if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_spki))
+ return false;
+
+ // In OCSP, only the key itself is under hash.
+ base::StringPiece issuer_spk;
+ if (!asn1::ExtractSubjectPublicKeyFromSPKI(issuer_spki, &issuer_spk))
+ return false;
+
+ // ExtractSubjectPublicKey... does not remove the initial octet encoding the
+ // number of unused bits in the ASN.1 BIT STRING so we do it here. For public
+ // keys, the bitstring is in practice always byte-aligned.
+ if (issuer_spk.empty() || issuer_spk[0] != 0)
+ return false;
+ issuer_spk.remove_prefix(1);
+
+ // NSS OCSP lib recognizes SHA1, MD5 and MD2; MD5 and MD2 are dead but
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=663315 will add SHA-256
+ // and SHA-384.
+ // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves
+ // necessary.
+ // TODO(ekasper): only compute the hashes on demand.
+ std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk);
+ std::string issuer_key_sha1_hash = base::SHA1HashString(
+ issuer_spk.as_string());
+
+ const SingleResponse* match = NULL;
+ for (const SingleResponse* const* resps = responses; *resps; ++resps) {
+ const SingleResponse* resp = *resps;
+ if (CertIDMatches(resp->cert_id, cert_serial_number,
+ issuer_key_sha1_hash, issuer_key_sha256_hash)) {
+ match = resp;
+ break;
+ }
+ }
+
+ if (!match)
+ return false;
+
+ return GetSCTListFromOCSPExtension(arena.get(), match->single_extensions,
+ sct_list);
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/ct_objects_extractor_openssl.cc b/chromium/net/cert/ct_objects_extractor_openssl.cc
new file mode 100644
index 00000000000..f6bd8b0e867
--- /dev/null
+++ b/chromium/net/cert/ct_objects_extractor_openssl.cc
@@ -0,0 +1,41 @@
+// 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/cert/ct_objects_extractor.h"
+
+#include "base/logging.h"
+
+namespace net {
+
+namespace ct {
+
+bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert,
+ std::string* sct_list) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf,
+ X509Certificate::OSCertHandle issuer,
+ LogEntry* result) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer,
+ const std::string& cert_serial_number,
+ const std::string& ocsp_response,
+ std::string* sct_list) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/ct_objects_extractor_unittest.cc b/chromium/net/cert/ct_objects_extractor_unittest.cc
new file mode 100644
index 00000000000..b229a478ae9
--- /dev/null
+++ b/chromium/net/cert/ct_objects_extractor_unittest.cc
@@ -0,0 +1,181 @@
+// 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/cert/ct_objects_extractor.h"
+
+#include "base/files/file_path.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/ct_log_verifier.h"
+#include "net/cert/ct_serialization.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/ct_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace ct {
+
+class CTObjectsExtractorTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ precert_chain_ =
+ CreateCertificateListFromFile(GetTestCertsDirectory(),
+ "ct-test-embedded-cert.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_EQ(2u, precert_chain_.size());
+
+ std::string der_test_cert(ct::GetDerEncodedX509Cert());
+ test_cert_ = X509Certificate::CreateFromBytes(der_test_cert.data(),
+ der_test_cert.length());
+
+ log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog").Pass();
+ ASSERT_TRUE(log_);
+ }
+
+ void ExtractEmbeddedSCT(scoped_refptr<X509Certificate> cert,
+ scoped_refptr<SignedCertificateTimestamp>* sct) {
+ std::string sct_list;
+ EXPECT_TRUE(ExtractEmbeddedSCTList(cert->os_cert_handle(), &sct_list));
+
+ std::vector<base::StringPiece> parsed_scts;
+ base::StringPiece sct_list_sp(sct_list);
+ // Make sure the SCT list can be decoded properly
+ EXPECT_TRUE(DecodeSCTList(&sct_list_sp, &parsed_scts));
+
+ EXPECT_TRUE(DecodeSignedCertificateTimestamp(&parsed_scts[0], sct));
+ }
+
+ protected:
+ CertificateList precert_chain_;
+ scoped_refptr<X509Certificate> test_cert_;
+ scoped_ptr<CTLogVerifier> log_;
+};
+
+// Test that an SCT can be extracted and the extracted SCT contains the
+// expected data.
+TEST_F(CTObjectsExtractorTest, ExtractEmbeddedSCT) {
+ scoped_refptr<ct::SignedCertificateTimestamp> sct(
+ new ct::SignedCertificateTimestamp());
+ ExtractEmbeddedSCT(precert_chain_[0], &sct);
+
+ EXPECT_EQ(sct->version, SignedCertificateTimestamp::SCT_VERSION_1);
+ EXPECT_EQ(ct::GetTestPublicKeyId(), sct->log_id);
+
+ base::Time expected_timestamp =
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(1365181456275);
+ EXPECT_EQ(expected_timestamp, sct->timestamp);
+}
+
+TEST_F(CTObjectsExtractorTest, ExtractPrecert) {
+ LogEntry entry;
+ ASSERT_TRUE(GetPrecertLogEntry(precert_chain_[0]->os_cert_handle(),
+ precert_chain_[1]->os_cert_handle(),
+ &entry));
+
+ ASSERT_EQ(ct::LogEntry::LOG_ENTRY_TYPE_PRECERT, entry.type);
+ // Should have empty leaf cert for this log entry type.
+ ASSERT_TRUE(entry.leaf_certificate.empty());
+ // Compare hash values of issuer spki.
+ SHA256HashValue expected_issuer_key_hash;
+ memcpy(expected_issuer_key_hash.data, GetDefaultIssuerKeyHash().data(), 32);
+ ASSERT_TRUE(expected_issuer_key_hash.Equals(entry.issuer_key_hash));
+}
+
+TEST_F(CTObjectsExtractorTest, ExtractOrdinaryX509Cert) {
+ LogEntry entry;
+ ASSERT_TRUE(GetX509LogEntry(test_cert_->os_cert_handle(), &entry));
+
+ ASSERT_EQ(ct::LogEntry::LOG_ENTRY_TYPE_X509, entry.type);
+ // Should have empty tbs_certificate for this log entry type.
+ ASSERT_TRUE(entry.tbs_certificate.empty());
+ // Length of leaf_certificate should be 718, see the CT Serialization tests.
+ ASSERT_EQ(718U, entry.leaf_certificate.size());
+}
+
+// Test that the embedded SCT verifies
+TEST_F(CTObjectsExtractorTest, ExtractedSCTVerifies) {
+ scoped_refptr<ct::SignedCertificateTimestamp> sct(
+ new ct::SignedCertificateTimestamp());
+ ExtractEmbeddedSCT(precert_chain_[0], &sct);
+
+ LogEntry entry;
+ ASSERT_TRUE(GetPrecertLogEntry(precert_chain_[0]->os_cert_handle(),
+ precert_chain_[1]->os_cert_handle(),
+ &entry));
+
+ EXPECT_TRUE(log_->Verify(entry, *sct));
+}
+
+// Test that an externally-provided SCT verifies over the LogEntry
+// of a regular X.509 Certificate
+TEST_F(CTObjectsExtractorTest, ComplementarySCTVerifies) {
+ scoped_refptr<ct::SignedCertificateTimestamp> sct(
+ new ct::SignedCertificateTimestamp());
+ GetX509CertSCT(&sct);
+
+ LogEntry entry;
+ ASSERT_TRUE(GetX509LogEntry(test_cert_->os_cert_handle(), &entry));
+
+ EXPECT_TRUE(log_->Verify(entry, *sct));
+}
+
+// Test that the extractor can parse OCSP responses.
+TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponse) {
+ std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
+ scoped_refptr<X509Certificate> subject_cert =
+ X509Certificate::CreateFromBytes(der_subject_cert.data(),
+ der_subject_cert.length());
+ std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
+ scoped_refptr<X509Certificate> issuer_cert =
+ X509Certificate::CreateFromBytes(der_issuer_cert.data(),
+ der_issuer_cert.length());
+
+ std::string fake_sct_list = ct::GetFakeOCSPExtensionValue();
+ ASSERT_FALSE(fake_sct_list.empty());
+ std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
+
+ std::string extracted_sct_list;
+ EXPECT_TRUE(ct::ExtractSCTListFromOCSPResponse(
+ issuer_cert->os_cert_handle(), subject_cert->serial_number(),
+ ocsp_response, &extracted_sct_list));
+ EXPECT_EQ(extracted_sct_list, fake_sct_list);
+}
+
+// Test that the extractor honours serial number.
+TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesSerial) {
+ std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
+ scoped_refptr<X509Certificate> issuer_cert =
+ X509Certificate::CreateFromBytes(der_issuer_cert.data(),
+ der_issuer_cert.length());
+
+ std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
+
+ std::string extracted_sct_list;
+ EXPECT_FALSE(ct::ExtractSCTListFromOCSPResponse(
+ issuer_cert->os_cert_handle(), test_cert_->serial_number(),
+ ocsp_response, &extracted_sct_list));
+}
+
+// Test that the extractor honours issuer ID.
+TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesIssuer) {
+ std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
+ scoped_refptr<X509Certificate> subject_cert =
+ X509Certificate::CreateFromBytes(der_subject_cert.data(),
+ der_subject_cert.length());
+
+ std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
+
+ std::string extracted_sct_list;
+ // Use test_cert_ for issuer - it is not the correct issuer of |subject_cert|.
+ EXPECT_FALSE(ct::ExtractSCTListFromOCSPResponse(
+ test_cert_->os_cert_handle(), subject_cert->serial_number(),
+ ocsp_response, &extracted_sct_list));
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/ct_serialization.cc b/chromium/net/cert/ct_serialization.cc
new file mode 100644
index 00000000000..3de512c8181
--- /dev/null
+++ b/chromium/net/cert/ct_serialization.cc
@@ -0,0 +1,368 @@
+// 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/cert/ct_serialization.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+namespace net {
+
+namespace ct {
+
+namespace {
+
+// Note: length is always specified in bytes.
+// Signed Certificate Timestamp (SCT) Version length
+const size_t kVersionLength = 1;
+
+// Members of a V1 SCT
+const size_t kLogIdLength = 32;
+const size_t kTimestampLength = 8;
+const size_t kExtensionsLengthBytes = 2;
+const size_t kHashAlgorithmLength = 1;
+const size_t kSigAlgorithmLength = 1;
+const size_t kSignatureLengthBytes = 2;
+
+// Members of the digitally-signed struct of a V1 SCT
+const size_t kSignatureTypeLength = 1;
+const size_t kLogEntryTypeLength = 2;
+const size_t kAsn1CertificateLengthBytes = 3;
+const size_t kTbsCertificateLengthBytes = 3;
+
+const size_t kSCTListLengthBytes = 2;
+const size_t kSerializedSCTLengthBytes = 2;
+
+enum SignatureType {
+ SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP = 0,
+ TREE_HASH = 1,
+};
+
+// Reads a TLS-encoded variable length unsigned integer from |in|.
+// The integer is expected to be in big-endian order, which is used by TLS.
+// The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
+// |length| indicates the size (in bytes) of the integer. On success, returns
+// true and stores the result in |*out|.
+template <typename T>
+bool ReadUint(size_t length, base::StringPiece* in, T* out) {
+ if (in->size() < length)
+ return false;
+ 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]);
+ }
+ in->remove_prefix(length);
+ *out = result;
+ return true;
+}
+
+// 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)
+// success, returns true and stores the result in |*out|.
+bool ReadLength(size_t prefix_length, base::StringPiece* in, size_t* out) {
+ size_t length;
+ if (!ReadUint(prefix_length, in, &length))
+ return false;
+ *out = length;
+ return true;
+}
+
+// Reads |length| bytes from |*in|. If |*in| is too small, returns false.
+// The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
+bool ReadFixedBytes(size_t length,
+ base::StringPiece* in,
+ base::StringPiece* out) {
+ if (in->length() < length)
+ return false;
+ out->set(in->data(), length);
+ in->remove_prefix(length);
+ return true;
+}
+
+// Reads a length-prefixed variable amount of bytes from |in|, updating |out|
+// on success. |prefix_length| indicates the number of bytes needed to represent
+// the length.
+// The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
+bool ReadVariableBytes(size_t prefix_length,
+ base::StringPiece* in,
+ base::StringPiece* out) {
+ size_t length;
+ if (!ReadLength(prefix_length, in, &length))
+ return false;
+ return ReadFixedBytes(length, in, out);
+}
+
+// Reads a variable-length list that has been TLS encoded.
+// The bytes read from |in| are discarded (i.e. |in|'s prefix removed)
+// |max_list_length| contains the overall length of the encoded list.
+// |max_item_length| contains the maximum length of a single item.
+// On success, returns true and updates |*out| with the encoded list.
+bool ReadList(size_t max_list_length,
+ size_t max_item_length,
+ base::StringPiece* in,
+ std::vector<base::StringPiece>* out) {
+ std::vector<base::StringPiece> result;
+
+ base::StringPiece list_data;
+ if (!ReadVariableBytes(max_list_length, in, &list_data))
+ return false;
+
+ while (!list_data.empty()) {
+ base::StringPiece list_item;
+ if (!ReadVariableBytes(max_item_length, &list_data, &list_item)) {
+ DVLOG(1) << "Failed to read item in list.";
+ return false;
+ }
+ if (list_item.empty()) {
+ DVLOG(1) << "Empty item in list";
+ return false;
+ }
+ result.push_back(list_item);
+ }
+
+ result.swap(*out);
+ return true;
+}
+
+// Checks and converts a hash algorithm.
+// |in| is the numeric representation of the algorithm.
+// If the hash algorithm value is in a set of known values, fills in |out| and
+// returns true. Otherwise, returns false.
+bool ConvertHashAlgorithm(unsigned in, DigitallySigned::HashAlgorithm* out) {
+ switch (in) {
+ case DigitallySigned::HASH_ALGO_NONE:
+ case DigitallySigned::HASH_ALGO_MD5:
+ case DigitallySigned::HASH_ALGO_SHA1:
+ case DigitallySigned::HASH_ALGO_SHA224:
+ case DigitallySigned::HASH_ALGO_SHA256:
+ case DigitallySigned::HASH_ALGO_SHA384:
+ case DigitallySigned::HASH_ALGO_SHA512:
+ break;
+ default:
+ return false;
+ }
+ *out = static_cast<DigitallySigned::HashAlgorithm>(in);
+ return true;
+}
+
+// Checks and converts a signing algorithm.
+// |in| is the numeric representation of the algorithm.
+// If the signing algorithm value is in a set of known values, fills in |out|
+// and returns true. Otherwise, returns false.
+bool ConvertSignatureAlgorithm(
+ unsigned in,
+ DigitallySigned::SignatureAlgorithm* out) {
+ switch (in) {
+ case DigitallySigned::SIG_ALGO_ANONYMOUS:
+ case DigitallySigned::SIG_ALGO_RSA:
+ case DigitallySigned::SIG_ALGO_DSA:
+ case DigitallySigned::SIG_ALGO_ECDSA:
+ break;
+ default:
+ return false;
+ }
+ *out = static_cast<DigitallySigned::SignatureAlgorithm>(in);
+ return true;
+}
+
+// Writes a TLS-encoded variable length unsigned integer to |output|.
+// |length| indicates the size (in bytes) of the integer.
+// |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);
+
+ for (; length > 0; --length) {
+ output->push_back((value >> ((length - 1)* 8)) & 0xFF);
+ }
+}
+
+// Writes an array to |output| from |input|.
+// Should be used in one of two cases:
+// * The length of |input| has already been encoded into the |output| stream.
+// * The length of |input| is fixed and the reader is expected to specify that
+// 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) {
+ input.AppendToString(output);
+}
+
+// Writes a variable-length array to |output|.
+// |prefix_length| indicates the number of bytes needed to represnt 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.
+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)
+ return false;
+
+ WriteUint(prefix_length, input.size(), output);
+ WriteEncodedBytes(input, output);
+
+ return true;
+}
+
+// Writes a LogEntry of type X.509 cert to |output|.
+// |input| is the LogEntry containing the certificate.
+// Returns true if the leaf_certificate in the LogEntry does not exceed
+// kMaxAsn1CertificateLength and so can be written to |output|.
+bool EncodeAsn1CertLogEntry(const LogEntry& input, std::string* output) {
+ return WriteVariableBytes(kAsn1CertificateLengthBytes,
+ input.leaf_certificate, output);
+}
+
+// Writes a LogEntry of type PreCertificate to |output|.
+// |input| is the LogEntry containing the TBSCertificate and issuer key hash.
+// Returns true if the TBSCertificate component in the LogEntry does not
+// exceed kMaxTbsCertificateLength and so can be written to |output|.
+bool EncodePrecertLogEntry(const LogEntry& input, std::string* output) {
+ WriteEncodedBytes(
+ base::StringPiece(
+ reinterpret_cast<const char*>(input.issuer_key_hash.data),
+ kLogIdLength),
+ output);
+ return WriteVariableBytes(kTbsCertificateLengthBytes,
+ input.tbs_certificate, output);
+}
+
+} // namespace
+
+bool EncodeDigitallySigned(const DigitallySigned& input,
+ std::string* output) {
+ WriteUint(kHashAlgorithmLength, input.hash_algorithm, output);
+ WriteUint(kSigAlgorithmLength, input.signature_algorithm,
+ output);
+ return WriteVariableBytes(kSignatureLengthBytes, input.signature_data,
+ output);
+}
+
+bool DecodeDigitallySigned(base::StringPiece* input,
+ DigitallySigned* output) {
+ unsigned hash_algo;
+ unsigned sig_algo;
+ base::StringPiece sig_data;
+
+ if (!ReadUint(kHashAlgorithmLength, input, &hash_algo) ||
+ !ReadUint(kSigAlgorithmLength, input, &sig_algo) ||
+ !ReadVariableBytes(kSignatureLengthBytes, input, &sig_data)) {
+ return false;
+ }
+
+ DigitallySigned result;
+ if (!ConvertHashAlgorithm(hash_algo, &result.hash_algorithm)) {
+ DVLOG(1) << "Invalid hash algorithm " << hash_algo;
+ return false;
+ }
+ if (!ConvertSignatureAlgorithm(sig_algo, &result.signature_algorithm)) {
+ DVLOG(1) << "Invalid signature algorithm " << sig_algo;
+ return false;
+ }
+ sig_data.CopyToString(&result.signature_data);
+
+ *output = result;
+ return true;
+}
+
+bool EncodeLogEntry(const LogEntry& input, std::string* output) {
+ WriteUint(kLogEntryTypeLength, input.type, output);
+ switch (input.type) {
+ case LogEntry::LOG_ENTRY_TYPE_X509:
+ return EncodeAsn1CertLogEntry(input, output);
+ case LogEntry::LOG_ENTRY_TYPE_PRECERT:
+ return EncodePrecertLogEntry(input, output);
+ }
+ return false;
+}
+
+bool EncodeV1SCTSignedData(const base::Time& timestamp,
+ const std::string& serialized_log_entry,
+ const std::string& extensions,
+ std::string* output) {
+ WriteUint(kVersionLength, SignedCertificateTimestamp::SCT_VERSION_1,
+ output);
+ WriteUint(kSignatureTypeLength, SIGNATURE_TYPE_CERTIFICATE_TIMESTAMP,
+ output);
+ base::TimeDelta time_since_epoch = timestamp - base::Time::UnixEpoch();
+ WriteUint(kTimestampLength, time_since_epoch.InMilliseconds(),
+ output);
+ // NOTE: serialized_log_entry must already be serialized and contain the
+ // length as the prefix.
+ WriteEncodedBytes(serialized_log_entry, output);
+ return WriteVariableBytes(kExtensionsLengthBytes, extensions, output);
+}
+
+bool DecodeSCTList(base::StringPiece* input,
+ std::vector<base::StringPiece>* output) {
+ std::vector<base::StringPiece> result;
+ if (!ReadList(kSCTListLengthBytes, kSerializedSCTLengthBytes,
+ input, &result)) {
+ return false;
+ }
+
+ if (!input->empty() || result.empty())
+ return false;
+ output->swap(result);
+ return true;
+}
+
+bool DecodeSignedCertificateTimestamp(
+ base::StringPiece* input,
+ scoped_refptr<SignedCertificateTimestamp>* output) {
+ scoped_refptr<SignedCertificateTimestamp> result(
+ new SignedCertificateTimestamp());
+ unsigned version;
+ if (!ReadUint(kVersionLength, input, &version))
+ return false;
+ if (version != SignedCertificateTimestamp::SCT_VERSION_1) {
+ DVLOG(1) << "Unsupported/invalid version " << version;
+ return false;
+ }
+
+ result->version = SignedCertificateTimestamp::SCT_VERSION_1;
+ uint64 timestamp;
+ base::StringPiece log_id;
+ base::StringPiece extensions;
+ if (!ReadFixedBytes(kLogIdLength, input, &log_id) ||
+ !ReadUint(kTimestampLength, input, &timestamp) ||
+ !ReadVariableBytes(kExtensionsLengthBytes, input,
+ &extensions) ||
+ !DecodeDigitallySigned(input, &result->signature)) {
+ return false;
+ }
+
+ if (timestamp > static_cast<uint64>(kint64max)) {
+ DVLOG(1) << "Timestamp value too big to cast to int64: " << timestamp;
+ return false;
+ }
+
+ log_id.CopyToString(&result->log_id);
+ extensions.CopyToString(&result->extensions);
+ result->timestamp =
+ base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(static_cast<int64>(timestamp));
+
+ output->swap(result);
+ return true;
+}
+
+bool EncodeSCTListForTesting(const base::StringPiece& sct,
+ std::string* output) {
+ std::string encoded_sct;
+ return WriteVariableBytes(kSerializedSCTLengthBytes, sct, &encoded_sct) &&
+ WriteVariableBytes(kSCTListLengthBytes, encoded_sct, output);
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/ct_serialization.h b/chromium/net/cert/ct_serialization.h
new file mode 100644
index 00000000000..19dc0873f4f
--- /dev/null
+++ b/chromium/net/cert/ct_serialization.h
@@ -0,0 +1,75 @@
+// 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_CERT_CT_SERIALIZATION_H_
+#define NET_CERT_CT_SERIALIZATION_H_
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+// Utility functions for encoding/decoding structures used by Certificate
+// Transparency to/from the TLS wire format encoding.
+namespace ct {
+
+// If |input.signature_data| is less than kMaxSignatureLength, encodes the
+// |input| to |output| and returns true. Otherwise, returns false.
+NET_EXPORT_PRIVATE bool EncodeDigitallySigned(const DigitallySigned& input,
+ std::string* output);
+
+// Reads and decodes a DigitallySigned object from |input|.
+// The bytes read from |input| are discarded (i.e. |input|'s prefix removed)
+// Returns true and fills |output| if all fields can be read, false otherwise.
+NET_EXPORT_PRIVATE bool DecodeDigitallySigned(base::StringPiece* input,
+ DigitallySigned* output);
+
+// Encodes the |input| LogEntry to |output|. Returns true if the entry size
+// does not exceed allowed size in RFC6962, false otherwise.
+NET_EXPORT_PRIVATE bool EncodeLogEntry(const LogEntry& input,
+ std::string* output);
+
+// Encodes the data signed by a Signed Certificate Timestamp (SCT) into
+// |output|. The signature included in the SCT is then verified over these
+// bytes.
+// |timestamp| timestamp from the SCT.
+// |serialized_log_entry| the log entry signed by the SCT.
+// |extensions| CT extensions.
+// Returns true if the extensions' length does not exceed
+// kMaxExtensionsLength, false otherwise.
+NET_EXPORT_PRIVATE bool EncodeV1SCTSignedData(
+ const base::Time& timestamp,
+ const std::string& serialized_log_entry,
+ const std::string& extensions,
+ std::string* output);
+
+// Decode a list of Signed Certificate Timestamps
+// (SignedCertificateTimestampList as defined in RFC6962): from a single
+// string in |input| to a vector of individually-encoded SCTs |output|.
+// This list is typically obtained from the CT extension in a certificate.
+// Returns true if the list could be read and decoded successfully, false
+// otherwise (note that the validity of each individual SCT should be checked
+// separately).
+NET_EXPORT_PRIVATE bool DecodeSCTList(base::StringPiece* input,
+ std::vector<base::StringPiece>* output);
+
+// Decodes a single SCT from |input| to |output|.
+// Returns true if all fields in the SCT could be read and decoded, false
+// otherwise.
+NET_EXPORT_PRIVATE bool DecodeSignedCertificateTimestamp(
+ base::StringPiece* input,
+ scoped_refptr<ct::SignedCertificateTimestamp>* output);
+
+// Writes an SCTList into |output|, containing a single |sct|.
+NET_EXPORT_PRIVATE bool EncodeSCTListForTesting(const base::StringPiece& sct,
+ std::string* output);
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_SERIALIZATION_H_
diff --git a/chromium/net/cert/ct_serialization_unittest.cc b/chromium/net/cert/ct_serialization_unittest.cc
new file mode 100644
index 00000000000..d832c1d8ef1
--- /dev/null
+++ b/chromium/net/cert/ct_serialization_unittest.cc
@@ -0,0 +1,166 @@
+// 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/cert/ct_serialization.h"
+
+#include <string>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "net/base/net_log.h"
+#include "net/base/test_completion_callback.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/ct_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class CtSerializationTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ test_digitally_signed_ = ct::GetTestDigitallySigned();
+ }
+
+ protected:
+ std::string test_digitally_signed_;
+};
+
+TEST_F(CtSerializationTest, DecodesDigitallySigned) {
+ base::StringPiece digitally_signed(test_digitally_signed_);
+ ct::DigitallySigned parsed;
+
+ ASSERT_TRUE(ct::DecodeDigitallySigned(&digitally_signed, &parsed));
+ EXPECT_EQ(
+ ct::DigitallySigned::HASH_ALGO_SHA256,
+ parsed.hash_algorithm);
+
+ EXPECT_EQ(
+ ct::DigitallySigned::SIG_ALGO_ECDSA,
+ parsed.signature_algorithm);
+
+ // The encoded data contains the signature itself from the 4th byte.
+ // The first bytes are:
+ // 1 byte of hash algorithm
+ // 1 byte of signature algorithm
+ // 2 bytes - prefix containing length of the signature data.
+ EXPECT_EQ(
+ test_digitally_signed_.substr(4),
+ parsed.signature_data);
+}
+
+
+TEST_F(CtSerializationTest, FailsToDecodePartialDigitallySigned) {
+ base::StringPiece digitally_signed(test_digitally_signed_);
+ base::StringPiece partial_digitally_signed(
+ digitally_signed.substr(0, test_digitally_signed_.size() - 5));
+ ct::DigitallySigned parsed;
+
+ ASSERT_FALSE(ct::DecodeDigitallySigned(&partial_digitally_signed, &parsed));
+}
+
+
+TEST_F(CtSerializationTest, EncodesDigitallySigned) {
+ ct::DigitallySigned digitally_signed;
+ digitally_signed.hash_algorithm = ct::DigitallySigned::HASH_ALGO_SHA256;
+ digitally_signed.signature_algorithm = ct::DigitallySigned::SIG_ALGO_ECDSA;
+ digitally_signed.signature_data = test_digitally_signed_.substr(4);
+
+ std::string encoded;
+
+ ASSERT_TRUE(ct::EncodeDigitallySigned(digitally_signed, &encoded));
+ EXPECT_EQ(test_digitally_signed_, encoded);
+}
+
+
+TEST_F(CtSerializationTest, EncodesLogEntryForX509Cert) {
+ ct::LogEntry entry;
+ GetX509CertLogEntry(&entry);
+
+ std::string encoded;
+ ASSERT_TRUE(ct::EncodeLogEntry(entry, &encoded));
+ EXPECT_EQ((718U + 5U), encoded.size());
+ // First two bytes are log entry type. Next, length:
+ // Length is 718 which is 512 + 206, which is 0x2ce
+ std::string expected_prefix("\0\0\0\x2\xCE", 5);
+ // Note we use std::string comparison rather than ASSERT_STREQ due
+ // to null characters in the buffer.
+ EXPECT_EQ(expected_prefix, encoded.substr(0, 5));
+}
+
+TEST_F(CtSerializationTest, EncodesV1SCTSignedData) {
+ base::Time timestamp = base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(1348589665525);
+ std::string dummy_entry("abc");
+ std::string empty_extensions("");
+ // For now, no known failure cases.
+ std::string encoded;
+ ASSERT_TRUE(ct::EncodeV1SCTSignedData(
+ timestamp,
+ dummy_entry,
+ empty_extensions,
+ &encoded));
+ EXPECT_EQ((size_t) 15, encoded.size());
+ // Byte 0 is version, byte 1 is signature type
+ // Bytes 2-10 are timestamp
+ // Bytes 11-14 are the log signature
+ // Byte 15 is the empty extension
+ //EXPECT_EQ(0, timestamp.ToTimeT());
+ std::string expected_buffer(
+ "\x0\x0\x0\x0\x1\x39\xFE\x35\x3C\xF5\x61\x62\x63\x0\x0", 15);
+ EXPECT_EQ(expected_buffer, encoded);
+}
+
+TEST_F(CtSerializationTest, DecodesSCTList) {
+ // Two items in the list: "abc", "def"
+ base::StringPiece encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x3\x64\x65\x66", 12);
+ std::vector<base::StringPiece> decoded;
+
+ ASSERT_TRUE(ct::DecodeSCTList(&encoded, &decoded));
+ ASSERT_STREQ("abc", decoded[0].data());
+ ASSERT_STREQ("def", decoded[1].data());
+}
+
+TEST_F(CtSerializationTest, FailsDecodingInvalidSCTList) {
+ // A list with one item that's too short
+ base::StringPiece encoded("\x0\xa\x0\x3\x61\x62\x63\x0\x5\x64\x65\x66", 12);
+ std::vector<base::StringPiece> decoded;
+
+ ASSERT_FALSE(ct::DecodeSCTList(&encoded, &decoded));
+}
+
+TEST_F(CtSerializationTest, DecodesSignedCertificateTimestamp) {
+ std::string encoded_test_sct(ct::GetTestSignedCertificateTimestamp());
+ base::StringPiece encoded_sct(encoded_test_sct);
+
+ scoped_refptr<ct::SignedCertificateTimestamp> sct;
+ ASSERT_TRUE(ct::DecodeSignedCertificateTimestamp(&encoded_sct, &sct));
+ EXPECT_EQ(0, sct->version);
+ EXPECT_EQ(ct::GetTestPublicKeyId(), sct->log_id);
+ base::Time expected_time = base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(1365181456089);
+ EXPECT_EQ(expected_time, sct->timestamp);
+ // Subtracting 4 bytes for signature data (hash & sig algs),
+ // actual signature data should be 71 bytes.
+ EXPECT_EQ((size_t) 71, sct->signature.signature_data.size());
+ EXPECT_EQ(std::string(""), sct->extensions);
+}
+
+TEST_F(CtSerializationTest, FailsDecodingInvalidSignedCertificateTimestamp) {
+ // Invalid version
+ base::StringPiece invalid_version_sct("\x2\x0", 2);
+ scoped_refptr<ct::SignedCertificateTimestamp> sct;
+
+ ASSERT_FALSE(
+ ct::DecodeSignedCertificateTimestamp(&invalid_version_sct, &sct));
+
+ // Valid version, invalid length (missing data)
+ base::StringPiece invalid_length_sct("\x0\xa\xb\xc", 4);
+ ASSERT_FALSE(
+ ct::DecodeSignedCertificateTimestamp(&invalid_length_sct, &sct));
+}
+
+} // namespace net
+
diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc
new file mode 100644
index 00000000000..75190871a55
--- /dev/null
+++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc
@@ -0,0 +1,159 @@
+// 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/cert/ct_signed_certificate_timestamp_log_param.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/base64.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "net/cert/ct_verify_result.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+namespace {
+
+// Converts a numeric |origin| to text describing the SCT's origin
+const char* OriginToString(ct::SignedCertificateTimestamp::Origin origin) {
+ switch (origin) {
+ case ct::SignedCertificateTimestamp::SCT_EMBEDDED:
+ return "embedded_in_certificate";
+ case ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION:
+ return "tls_extension";
+ case ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE:
+ return "ocsp";
+ }
+
+ return "unknown";
+}
+
+// Converts a numeric |hash_algorithm| to its textual representation
+const char* HashAlgorithmToString(
+ ct::DigitallySigned::HashAlgorithm hash_algorithm) {
+ switch (hash_algorithm) {
+ case ct::DigitallySigned::HASH_ALGO_NONE:
+ return "NONE";
+ case ct::DigitallySigned::HASH_ALGO_MD5:
+ return "MD5";
+ case ct::DigitallySigned::HASH_ALGO_SHA1:
+ return "SHA1";
+ case ct::DigitallySigned::HASH_ALGO_SHA224:
+ return "SHA224";
+ case ct::DigitallySigned::HASH_ALGO_SHA256:
+ return "SHA256";
+ case ct::DigitallySigned::HASH_ALGO_SHA384:
+ return "SHA384";
+ case ct::DigitallySigned::HASH_ALGO_SHA512:
+ return "SHA512";
+ }
+
+ return "unknown";
+}
+
+// Converts a numeric |signature_algorithm| to its textual representation
+const char* SignatureAlgorithmToString(
+ ct::DigitallySigned::SignatureAlgorithm signature_algorithm) {
+ switch (signature_algorithm) {
+ case ct::DigitallySigned::SIG_ALGO_ANONYMOUS:
+ return "ANONYMOUS";
+ case ct::DigitallySigned::SIG_ALGO_RSA:
+ return "RSA";
+ case ct::DigitallySigned::SIG_ALGO_DSA:
+ return "DSA";
+ case ct::DigitallySigned::SIG_ALGO_ECDSA:
+ return "ECDSA";
+ }
+
+ return "unknown";
+}
+
+// Base64 encode the given |value| string and put it in |dict| with the
+// description |key|.
+void SetBinaryData(
+ const char* key,
+ const std::string& value,
+ base::DictionaryValue* dict) {
+ std::string b64_value;
+ base::Base64Encode(value, &b64_value);
+
+ dict->SetString(key, b64_value);
+}
+
+// Returns a dictionary where each key is a field of the SCT and its value
+// is this field's value in the SCT. This dictionary is meant to be used for
+// outputting a de-serialized SCT to the NetLog.
+base::DictionaryValue* SCTToDictionary(
+ const ct::SignedCertificateTimestamp& sct) {
+ base::DictionaryValue* out = new base::DictionaryValue();
+
+ out->SetString("origin", OriginToString(sct.origin));
+ out->SetInteger("version", sct.version);
+
+ SetBinaryData("log_id", sct.log_id, out);
+ base::TimeDelta time_since_unix_epoch =
+ sct.timestamp - base::Time::UnixEpoch();
+ out->SetString("timestamp",
+ base::Int64ToString(time_since_unix_epoch.InMilliseconds()));
+ SetBinaryData("extensions", sct.extensions, out);
+
+ out->SetString("hash_algorithm",
+ HashAlgorithmToString(sct.signature.hash_algorithm));
+ out->SetString("signature_algorithm",
+ SignatureAlgorithmToString(sct.signature.signature_algorithm));
+ SetBinaryData(
+ "signature_data", sct.signature.signature_data, out);
+
+ return out;
+}
+
+// Given a list of SCTs, return a ListValue instance where each item in the
+// list is a dictionary created by SCTToDictionary.
+base::ListValue* SCTListToPrintableValues(
+ const ct::SCTList& sct_list) {
+ base::ListValue* output_scts = new base::ListValue();
+ for (ct::SCTList::const_iterator it = sct_list.begin();
+ it != sct_list.end();
+ ++it)
+ output_scts->Append(SCTToDictionary(*(it->get())));
+
+ return output_scts;
+}
+
+} // namespace
+
+base::Value* NetLogSignedCertificateTimestampCallback(
+ const ct::CTVerifyResult* ct_result, NetLog::LogLevel log_level) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+
+ dict->Set("verified_scts",
+ SCTListToPrintableValues(ct_result->verified_scts));
+
+ dict->Set("invalid_scts",
+ SCTListToPrintableValues(ct_result->invalid_scts));
+
+ dict->Set("unknown_logs_scts",
+ SCTListToPrintableValues(ct_result->unknown_logs_scts));
+
+ return dict;
+}
+
+base::Value* NetLogRawSignedCertificateTimestampCallback(
+ const std::string* embedded_scts,
+ const std::string* sct_list_from_ocsp,
+ const std::string* sct_list_from_tls_extension,
+ NetLog::LogLevel log_level) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+
+ SetBinaryData("embedded_scts", *embedded_scts, dict);
+ SetBinaryData("scts_from_ocsp_response", *sct_list_from_ocsp, dict);
+ SetBinaryData("scts_from_tls_extension", *sct_list_from_tls_extension, dict);
+
+ return dict;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h
new file mode 100644
index 00000000000..dde120dcc46
--- /dev/null
+++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h
@@ -0,0 +1,35 @@
+// 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_CERT_CT_SIGNED_CERTIFICATE_TIMESTAMP_LOG_PARAM_H_
+#define NET_CERT_CT_SIGNED_CERTIFICATE_TIMESTAMP_LOG_PARAM_H_
+
+#include "net/base/net_log.h"
+
+namespace net {
+
+namespace ct {
+struct CTVerifyResult;
+}
+
+// Creates a dictionary of processed Signed Certificate Timestamps to be
+// logged in the NetLog.
+// See the documentation for SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED
+// in net/base/net_log_event_type_list.h
+base::Value* NetLogSignedCertificateTimestampCallback(
+ const ct::CTVerifyResult* ct_result, NetLog::LogLevel log_level);
+
+// Creates a dictionary of raw Signed Certificate Timestamps to be logged
+// in the NetLog.
+// See the documentation for SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED
+// in net/base/net_log_event_type_list.h
+base::Value* NetLogRawSignedCertificateTimestampCallback(
+ const std::string* embedded_scts,
+ const std::string* sct_list_from_ocsp,
+ const std::string* sct_list_from_tls_extension,
+ NetLog::LogLevel log_level);
+
+} // namespace net
+
+#endif // NET_CERT_CT_SIGNED_CERTIFICATE_TIMESTAMP_LOG_PARAM_H_
diff --git a/chromium/net/cert/ct_verifier.h b/chromium/net/cert/ct_verifier.h
new file mode 100644
index 00000000000..290a0474a64
--- /dev/null
+++ b/chromium/net/cert/ct_verifier.h
@@ -0,0 +1,43 @@
+// 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_CERT_CT_VERIFIER_H_
+#define NET_CERT_CT_VERIFIER_H_
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+namespace ct {
+struct CTVerifyResult;
+} // namespace ct
+
+class BoundNetLog;
+class X509Certificate;
+
+// Interface for verifying Signed Certificate Timestamps over a certificate.
+class NET_EXPORT CTVerifier {
+ public:
+ virtual ~CTVerifier() {}
+
+ // Verifies SCTs embedded in the certificate itself, SCTs embedded in a
+ // stapled OCSP response, and SCTs obtained via the
+ // signed_certificate_timestamp TLS extension on the given |cert|.
+ // A certificate is permitted but not required to use multiple sources for
+ // SCTs. It is expected that most certificates will use only one source
+ // (embedding, TLS extension or OCSP stapling). If no stapled OCSP response
+ // is available, |stapled_ocsp_response| should be an empty string. If no SCT
+ // TLS extension was negotiated, |sct_list_from_tls_extension| should be an
+ // empty string. |result| will be filled with the SCTs present, divided into
+ // categories based on the verification result.
+ virtual int Verify(X509Certificate* cert,
+ const std::string& stapled_ocsp_response,
+ const std::string& sct_list_from_tls_extension,
+ ct::CTVerifyResult* result,
+ const BoundNetLog& net_log) = 0;
+};
+
+} // namespace net
+
+#endif // NET_CERT_CT_VERIFIER_H_
diff --git a/chromium/net/cert/ct_verify_result.cc b/chromium/net/cert/ct_verify_result.cc
new file mode 100644
index 00000000000..c62a18a7c2d
--- /dev/null
+++ b/chromium/net/cert/ct_verify_result.cc
@@ -0,0 +1,17 @@
+// 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/cert/ct_verify_result.h"
+
+namespace net {
+
+namespace ct {
+
+CTVerifyResult::CTVerifyResult() {}
+
+CTVerifyResult::~CTVerifyResult() {}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/ct_verify_result.h b/chromium/net/cert/ct_verify_result.h
new file mode 100644
index 00000000000..aa90164193b
--- /dev/null
+++ b/chromium/net/cert/ct_verify_result.h
@@ -0,0 +1,37 @@
+// 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_CERT_CT_VERIFY_RESULT_H_
+#define NET_CERT_CT_VERIFY_RESULT_H_
+
+#include <vector>
+
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+namespace ct {
+
+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.
+struct NET_EXPORT CTVerifyResult {
+ CTVerifyResult();
+ ~CTVerifyResult();
+
+ // SCTs from known logs where the signature verified correctly.
+ SCTList verified_scts;
+ // SCTs from known logs where the signature failed to verify.
+ SCTList invalid_scts;
+ // SCTs from unknown logs and as such are unverifiable.
+ SCTList unknown_logs_scts;
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_VERIFY_RESULT_H_
diff --git a/chromium/net/cert/ev_root_ca_metadata.cc b/chromium/net/cert/ev_root_ca_metadata.cc
index 9e611a3093d..04f4bda3c96 100644
--- a/chromium/net/cert/ev_root_ca_metadata.cc
+++ b/chromium/net/cert/ev_root_ca_metadata.cc
@@ -21,6 +21,7 @@
namespace net {
+#if defined(USE_NSS) || defined(OS_IOS) || defined(OS_WIN)
// Raw metadata.
struct EVMetadata {
// kMaxOIDsPerCA is the number of OIDs that we can support per root CA. At
@@ -93,6 +94,18 @@ static const EVMetadata ev_root_ca_metadata[] = {
0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb } },
{"1.3.6.1.4.1.34697.2.4", ""},
},
+ // 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", ""},
+ },
// CertPlus Class 2 Primary CA (KEYNECTIS)
// https://www.keynectis.com/
{ { { 0x74, 0x20, 0x74, 0x41, 0x72, 0x9c, 0xdd, 0x92, 0xec, 0x79,
@@ -105,6 +118,12 @@ static const EVMetadata ev_root_ca_metadata[] = {
0x06, 0x28, 0xa2, 0x59, 0x3a, 0x19, 0xa7, 0x0f, 0x06, 0x9e } },
{"1.2.616.1.113527.2.5.1.1", ""},
},
+ // 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,
@@ -160,6 +179,12 @@ static const EVMetadata ev_root_ca_metadata[] = {
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,
@@ -227,15 +252,15 @@ static const EVMetadata ev_root_ca_metadata[] = {
0x3f, 0xf8, 0xbc, 0xf8, 0x15, 0xb0, 0x82, 0xf9, 0xae, 0xfd} },
{"1.3.6.1.4.1.14777.6.1.1", "1.3.6.1.4.1.14777.6.1.2"},
},
- // Network Solutions Certificate Authority
- // https://www.networksolutions.com/website-packages/index.jsp
+ // 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
+ // 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", ""},
@@ -322,6 +347,12 @@ static const EVMetadata ev_root_ca_metadata[] = {
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,
@@ -389,6 +420,8 @@ static const EVMetadata ev_root_ca_metadata[] = {
}
};
+#endif // defined(USE_NSS) || defined(OS_IOS) || defined(OS_WIN)
+
static base::LazyInstance<EVRootCAMetadata>::Leaky
g_ev_root_ca_metadata = LAZY_INSTANCE_INITIALIZER;
diff --git a/chromium/net/cert/ev_root_ca_metadata_unittest.cc b/chromium/net/cert/ev_root_ca_metadata_unittest.cc
index 2c845dbfcff..1bb547565fd 100644
--- a/chromium/net/cert/ev_root_ca_metadata_unittest.cc
+++ b/chromium/net/cert/ev_root_ca_metadata_unittest.cc
@@ -16,17 +16,17 @@ namespace net {
namespace {
-static const char kVerisignPolicy[] = "2.16.840.1.113733.1.7.23.6";
-static const char kThawtePolicy[] = "2.16.840.1.113733.1.7.48.1";
-static const char kFakePolicy[] = "2.16.840.1.42";
-static const SHA1HashValue kVerisignFingerprint =
+#if defined(USE_NSS) || defined(OS_WIN)
+const char kVerisignPolicy[] = "2.16.840.1.113733.1.7.23.6";
+const char kThawtePolicy[] = "2.16.840.1.113733.1.7.48.1";
+const char kFakePolicy[] = "2.16.840.1.42";
+const SHA1HashValue kVerisignFingerprint =
{ { 0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45,
0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2 } };
-static const SHA1HashValue kFakeFingerprint =
+const SHA1HashValue kFakeFingerprint =
{ { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 } };
-#if defined(USE_NSS) || defined(OS_WIN)
class EVOidData {
public:
EVOidData();
diff --git a/chromium/net/cert/jwk_serializer.h b/chromium/net/cert/jwk_serializer.h
index 7a12a366246..ee8cc8ad098 100644
--- a/chromium/net/cert/jwk_serializer.h
+++ b/chromium/net/cert/jwk_serializer.h
@@ -17,7 +17,7 @@ namespace net {
namespace JwkSerializer {
// Converts a subject public key info from DER to JWK.
-// See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-13 for
+// See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-17 for
// the output format.
NET_EXPORT_PRIVATE bool ConvertSpkiFromDerToJwk(
const base::StringPiece& spki_der,
diff --git a/chromium/net/cert/jwk_serializer_nss.cc b/chromium/net/cert/jwk_serializer_nss.cc
index d8445805f8e..3da0a81f25a 100644
--- a/chromium/net/cert/jwk_serializer_nss.cc
+++ b/chromium/net/cert/jwk_serializer_nss.cc
@@ -30,7 +30,7 @@ bool ConvertEcPrime256v1PublicKeyInfoToJwk(
spki->subjectPublicKey.data[0] != kUncompressedEncodingType)
return false;
- public_key_jwk->SetString("alg", "EC");
+ public_key_jwk->SetString("kty", "EC");
public_key_jwk->SetString("crv", "P-256");
base::StringPiece x(
diff --git a/chromium/net/cert/jwk_serializer_unittest.cc b/chromium/net/cert/jwk_serializer_unittest.cc
index 8059e73a3a6..dbf0e97689c 100644
--- a/chromium/net/cert/jwk_serializer_unittest.cc
+++ b/chromium/net/cert/jwk_serializer_unittest.cc
@@ -10,6 +10,7 @@
namespace net {
+#if !defined(USE_OPENSSL)
// This is the ASN.1 prefix for a P-256 public key. Specifically it's:
// SEQUENCE
// SEQUENCE
@@ -27,6 +28,7 @@ static const unsigned char kP256SpkiPrefix[] = {
0x42, 0x00, 0x04
};
static const unsigned int kEcCoordinateSize = 32U;
+#endif
// This is a valid P-256 public key.
static const unsigned char kSpkiEc[] = {
@@ -44,6 +46,7 @@ static const unsigned char kSpkiEc[] = {
0x05, 0xd3, 0xd2, 0xca, 0xdf, 0x44, 0x2f, 0xf4
};
+#if !defined(USE_OPENSSL)
// This is a P-256 public key with 0 X and Y values.
static const unsigned char kSpkiEcWithZeroXY[] = {
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
@@ -60,8 +63,6 @@ static const unsigned char kSpkiEcWithZeroXY[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-#if !defined(USE_OPENSSL)
-
TEST(JwkSerializerNSSTest, ConvertSpkiFromDerToJwkEc) {
base::StringPiece spki;
base::DictionaryValue public_key_jwk;
@@ -74,7 +75,7 @@ TEST(JwkSerializerNSSTest, ConvertSpkiFromDerToJwkEc) {
EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
std::string string_value;
- EXPECT_TRUE(public_key_jwk.GetString("alg", &string_value));
+ EXPECT_TRUE(public_key_jwk.GetString("kty", &string_value));
EXPECT_STREQ("EC", string_value.c_str());
EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
EXPECT_STREQ("P-256", string_value.c_str());
@@ -102,7 +103,7 @@ TEST(JwkSerializerNSSTest, ConvertSpkiFromDerToJwkEc) {
sizeof(kSpkiEcWithZeroXY));
EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
- EXPECT_TRUE(public_key_jwk.GetString("alg", &string_value));
+ EXPECT_TRUE(public_key_jwk.GetString("kty", &string_value));
EXPECT_STREQ("EC", string_value.c_str());
EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
EXPECT_STREQ("P-256", string_value.c_str());
diff --git a/chromium/net/cert/multi_log_ct_verifier.cc b/chromium/net/cert/multi_log_ct_verifier.cc
new file mode 100644
index 00000000000..05a32da81eb
--- /dev/null
+++ b/chromium/net/cert/multi_log_ct_verifier.cc
@@ -0,0 +1,177 @@
+// 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/cert/multi_log_ct_verifier.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/cert/ct_log_verifier.h"
+#include "net/cert/ct_objects_extractor.h"
+#include "net/cert/ct_serialization.h"
+#include "net/cert/ct_signed_certificate_timestamp_log_param.h"
+#include "net/cert/ct_verify_result.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+
+MultiLogCTVerifier::MultiLogCTVerifier() { }
+
+MultiLogCTVerifier::~MultiLogCTVerifier() { }
+
+void MultiLogCTVerifier::AddLog(scoped_ptr<CTLogVerifier> log_verifier) {
+ DCHECK(log_verifier);
+ if (!log_verifier)
+ return;
+
+ linked_ptr<CTLogVerifier> log(log_verifier.release());
+ logs_[log->key_id()] = log;
+}
+
+int MultiLogCTVerifier::Verify(
+ X509Certificate* cert,
+ const std::string& stapled_ocsp_response,
+ const std::string& sct_list_from_tls_extension,
+ ct::CTVerifyResult* result,
+ const BoundNetLog& net_log) {
+ DCHECK(cert);
+ DCHECK(result);
+
+ result->verified_scts.clear();
+ result->invalid_scts.clear();
+ result->unknown_logs_scts.clear();
+
+ bool has_verified_scts = false;
+
+ std::string embedded_scts;
+ if (!cert->GetIntermediateCertificates().empty() &&
+ ct::ExtractEmbeddedSCTList(
+ cert->os_cert_handle(),
+ &embedded_scts)) {
+ ct::LogEntry precert_entry;
+
+ has_verified_scts =
+ ct::GetPrecertLogEntry(
+ cert->os_cert_handle(),
+ cert->GetIntermediateCertificates().front(),
+ &precert_entry) &&
+ VerifySCTs(
+ embedded_scts,
+ precert_entry,
+ ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ result);
+ }
+
+ std::string sct_list_from_ocsp;
+ if (!stapled_ocsp_response.empty() &&
+ !cert->GetIntermediateCertificates().empty()) {
+ ct::ExtractSCTListFromOCSPResponse(
+ cert->GetIntermediateCertificates().front(), cert->serial_number(),
+ stapled_ocsp_response, &sct_list_from_ocsp);
+ }
+
+ // Log to Net Log, after extracting SCTs but before possibly failing on
+ // X.509 entry creation.
+ NetLog::ParametersCallback net_log_callback =
+ base::Bind(&NetLogRawSignedCertificateTimestampCallback,
+ &embedded_scts, &sct_list_from_ocsp, &sct_list_from_tls_extension);
+
+ net_log.AddEvent(
+ NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_RECEIVED,
+ net_log_callback);
+
+ ct::LogEntry x509_entry;
+ if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) {
+ has_verified_scts |= VerifySCTs(
+ sct_list_from_ocsp,
+ x509_entry,
+ ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE,
+ result);
+
+ has_verified_scts |= VerifySCTs(
+ sct_list_from_tls_extension,
+ x509_entry,
+ ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION,
+ result);
+ }
+
+ NetLog::ParametersCallback net_log_checked_callback =
+ base::Bind(&NetLogSignedCertificateTimestampCallback, result);
+
+ net_log.AddEvent(
+ NetLog::TYPE_SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED,
+ net_log_checked_callback);
+
+ if (has_verified_scts)
+ return OK;
+
+ return ERR_CT_NO_SCTS_VERIFIED_OK;
+}
+
+bool MultiLogCTVerifier::VerifySCTs(
+ const std::string& encoded_sct_list,
+ const ct::LogEntry& expected_entry,
+ ct::SignedCertificateTimestamp::Origin origin,
+ ct::CTVerifyResult* result) {
+ if (logs_.empty())
+ return false;
+
+ base::StringPiece temp(encoded_sct_list);
+ std::vector<base::StringPiece> sct_list;
+
+ if (!ct::DecodeSCTList(&temp, &sct_list))
+ return false;
+
+ bool verified = false;
+ for (std::vector<base::StringPiece>::const_iterator it = sct_list.begin();
+ it != sct_list.end(); ++it) {
+ base::StringPiece encoded_sct(*it);
+
+ scoped_refptr<ct::SignedCertificateTimestamp> decoded_sct;
+ if (!DecodeSignedCertificateTimestamp(&encoded_sct, &decoded_sct)) {
+ // XXX(rsleevi): Should we really just skip over bad SCTs?
+ continue;
+ }
+ decoded_sct->origin = origin;
+
+ verified |= VerifySingleSCT(decoded_sct, expected_entry, result);
+ }
+
+ return verified;
+}
+
+bool MultiLogCTVerifier::VerifySingleSCT(
+ scoped_refptr<ct::SignedCertificateTimestamp> sct,
+ const ct::LogEntry& expected_entry,
+ ct::CTVerifyResult* result) {
+
+ // Assume this SCT is untrusted until proven otherwise.
+ IDToLogMap::iterator it = logs_.find(sct->log_id);
+ if (it == logs_.end()) {
+ DVLOG(1) << "SCT does not match any known log.";
+ result->unknown_logs_scts.push_back(sct);
+ return false;
+ }
+
+ sct->log_description = it->second->description();
+
+ if (!it->second->Verify(expected_entry, *sct)) {
+ DVLOG(1) << "Unable to verify SCT signature.";
+ result->invalid_scts.push_back(sct);
+ return false;
+ }
+
+ // SCT verified ok, just make sure the timestamp is legitimate.
+ if (sct->timestamp > base::Time::Now()) {
+ DVLOG(1) << "SCT is from the future!";
+ result->invalid_scts.push_back(sct);
+ return false;
+ }
+
+ result->verified_scts.push_back(sct);
+ return true;
+}
+
+} // namespace net
diff --git a/chromium/net/cert/multi_log_ct_verifier.h b/chromium/net/cert/multi_log_ct_verifier.h
new file mode 100644
index 00000000000..d70ba4581f5
--- /dev/null
+++ b/chromium/net/cert/multi_log_ct_verifier.h
@@ -0,0 +1,71 @@
+// 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_CERT_MULTI_LOG_CT_VERIFIER_H_
+#define NET_CERT_MULTI_LOG_CT_VERIFIER_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/linked_ptr.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+#include "net/cert/ct_verifier.h"
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+namespace ct {
+struct LogEntry;
+} // namespace ct
+
+class CTLogVerifier;
+
+// A Certificate Transparency verifier that can verify Signed Certificate
+// Timestamps from multiple logs.
+// There should be a global instance of this class and for all known logs,
+// AddLog should be called with a CTLogVerifier (which is created from the
+// log's public key).
+class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
+ public:
+ MultiLogCTVerifier();
+ virtual ~MultiLogCTVerifier();
+
+ void AddLog(scoped_ptr<CTLogVerifier> log_verifier);
+
+ // CTVerifier implementation:
+ virtual 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;
+
+ private:
+ // Mapping from a log's ID to the verifier for this log.
+ // A log's ID is the SHA-256 of the log's key, as defined in section 3.2.
+ // of RFC6962.
+ typedef std::map<std::string, linked_ptr<CTLogVerifier> > IDToLogMap;
+
+ // Verify a list of SCTs from |encoded_sct_list| over |expected_entry|,
+ // placing the verification results in |result|. The SCTs in the list
+ // come from |origin| (as will be indicated in the origin field of each SCT).
+ bool VerifySCTs(const std::string& encoded_sct_list,
+ const ct::LogEntry& expected_entry,
+ ct::SignedCertificateTimestamp::Origin origin,
+ ct::CTVerifyResult* result);
+
+ // Verifies a single, parsed SCT against all logs.
+ bool VerifySingleSCT(
+ scoped_refptr<ct::SignedCertificateTimestamp> sct,
+ const ct::LogEntry& expected_entry,
+ ct::CTVerifyResult* result);
+
+ IDToLogMap logs_;
+
+ DISALLOW_COPY_AND_ASSIGN(MultiLogCTVerifier);
+};
+
+} // namespace net
+
+#endif // NET_CERT_MULTI_LOG_CT_VERIFIER_H_
diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
new file mode 100644
index 00000000000..b1d1aa889e8
--- /dev/null
+++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/multi_log_ct_verifier.h"
+
+#include <string>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "net/base/capturing_net_log.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+#include "net/base/test_data_directory.h"
+#include "net/cert/ct_log_verifier.h"
+#include "net/cert/ct_serialization.h"
+#include "net/cert/ct_verify_result.h"
+#include "net/cert/pem_tokenizer.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/x509_certificate.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/ct_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+const char kLogDescription[] = "somelog";
+
+class MultiLogCTVerifierTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ scoped_ptr<CTLogVerifier> log(
+ CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
+ ASSERT_TRUE(log);
+
+ verifier_.reset(new MultiLogCTVerifier());
+ verifier_->AddLog(log.Pass());
+ std::string der_test_cert(ct::GetDerEncodedX509Cert());
+ chain_ = X509Certificate::CreateFromBytes(
+ der_test_cert.data(),
+ der_test_cert.length());
+ ASSERT_TRUE(chain_);
+ }
+
+ 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(CapturingNetLog& net_log) {
+ CapturingNetLog::CapturedEntryList entries;
+ net_log.GetEntries(&entries);
+ if (entries.size() != 2)
+ return false;
+
+ const CapturingNetLog::CapturedEntry& received(entries[0]);
+ std::string embedded_scts;
+ if (!received.GetStringValue("embedded_scts", &embedded_scts))
+ return false;
+ if (embedded_scts.empty())
+ return false;
+
+ //XXX(eranm): entries[1] is the NetLog message with the checked SCTs.
+ //When CapturedEntry has methods to get a dictionary, rather than just
+ //a string, add more checks here.
+
+ return true;
+ }
+
+ bool CheckPrecertificateVerification(scoped_refptr<X509Certificate> chain) {
+ ct::CTVerifyResult result;
+ CapturingNetLog net_log;
+ BoundNetLog bound_net_log =
+ BoundNetLog::Make(&net_log, NetLog::SOURCE_CONNECT_JOB);
+ return (verifier_->Verify(chain, std::string(), std::string(), &result,
+ bound_net_log) == OK) &&
+ CheckForSingleVerifiedSCTInResult(result) &&
+ CheckForSCTOrigin(
+ result, ct::SignedCertificateTimestamp::SCT_EMBEDDED) &&
+ CheckForEmbeddedSCTInNetLog(net_log);
+ }
+
+ protected:
+ scoped_ptr<MultiLogCTVerifier> verifier_;
+ scoped_refptr<X509Certificate> chain_;
+};
+
+TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT) {
+ scoped_refptr<X509Certificate> chain(
+ CreateCertificateChainFromFile(GetTestCertsDirectory(),
+ "ct-test-embedded-cert.pem",
+ X509Certificate::FORMAT_AUTO));
+ ASSERT_TRUE(chain);
+ ASSERT_TRUE(CheckPrecertificateVerification(chain));
+}
+
+TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithPreCA) {
+ scoped_refptr<X509Certificate> chain(
+ CreateCertificateChainFromFile(GetTestCertsDirectory(),
+ "ct-test-embedded-with-preca-chain.pem",
+ X509Certificate::FORMAT_AUTO));
+ ASSERT_TRUE(chain);
+ ASSERT_TRUE(CheckPrecertificateVerification(chain));
+}
+
+TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCTWithIntermediate) {
+ scoped_refptr<X509Certificate> chain(CreateCertificateChainFromFile(
+ GetTestCertsDirectory(),
+ "ct-test-embedded-with-intermediate-chain.pem",
+ X509Certificate::FORMAT_AUTO));
+ ASSERT_TRUE(chain);
+ ASSERT_TRUE(CheckPrecertificateVerification(chain));
+}
+
+TEST_F(MultiLogCTVerifierTest,
+ VerifiesEmbeddedSCTWithIntermediateAndPreCA) {
+ scoped_refptr<X509Certificate> chain(CreateCertificateChainFromFile(
+ GetTestCertsDirectory(),
+ "ct-test-embedded-with-intermediate-preca-chain.pem",
+ X509Certificate::FORMAT_AUTO));
+ ASSERT_TRUE(chain);
+ ASSERT_TRUE(CheckPrecertificateVerification(chain));
+}
+
+TEST_F(MultiLogCTVerifierTest,
+ VerifiesSCTOverX509Cert) {
+ std::string sct(ct::GetTestSignedCertificateTimestamp());
+
+ std::string sct_list;
+ ASSERT_TRUE(ct::EncodeSCTListForTesting(sct, &sct_list));
+
+ ct::CTVerifyResult result;
+ EXPECT_EQ(OK,
+ verifier_->Verify(chain_, std::string(), sct_list, &result,
+ BoundNetLog()));
+ ASSERT_TRUE(CheckForSingleVerifiedSCTInResult(result));
+ ASSERT_TRUE(CheckForSCTOrigin(
+ result, ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION));
+}
+
+TEST_F(MultiLogCTVerifierTest,
+ IdentifiesSCTFromUnknownLog) {
+ 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;
+ ASSERT_TRUE(ct::EncodeSCTListForTesting(sct, &sct_list));
+
+ ct::CTVerifyResult result;
+ EXPECT_NE(OK,
+ verifier_->Verify(chain_, std::string(), sct_list, &result,
+ BoundNetLog()));
+ EXPECT_EQ(1U, result.unknown_logs_scts.size());
+ EXPECT_EQ("", result.unknown_logs_scts[0]->log_description);
+}
+
+} // namespace
+
+} // namespace net
diff --git a/chromium/net/cert/multi_threaded_cert_verifier.cc b/chromium/net/cert/multi_threaded_cert_verifier.cc
index 821cec1220b..4b2f37fbc55 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier.cc
+++ b/chromium/net/cert/multi_threaded_cert_verifier.cc
@@ -556,7 +556,7 @@ void MultiThreadedCertVerifier::HandleResult(
delete job;
}
-void MultiThreadedCertVerifier::OnCertTrustChanged(
+void MultiThreadedCertVerifier::OnCACertChanged(
const X509Certificate* cert) {
DCHECK(CalledOnValidThread());
diff --git a/chromium/net/cert/multi_threaded_cert_verifier.h b/chromium/net/cert/multi_threaded_cert_verifier.h
index bc9cd4f6ce6..f4e278793f1 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier.h
+++ b/chromium/net/cert/multi_threaded_cert_verifier.h
@@ -137,7 +137,7 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier
const CertVerifyResult& verify_result);
// CertDatabase::Observer methods:
- virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;
// For unit testing.
void ClearCache() { cache_.Clear(); }
diff --git a/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc b/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc
index 17d23d34995..3a0c765d212 100644
--- a/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc
+++ b/chromium/net/cert/multi_threaded_cert_verifier_unittest.cc
@@ -279,7 +279,13 @@ TEST_F(MultiThreadedCertVerifierTest, CancelRequest) {
}
// Tests that a canceled request is not leaked.
-TEST_F(MultiThreadedCertVerifierTest, CancelRequestThenQuit) {
+#if !defined(LEAK_SANITIZER)
+#define MAYBE_CancelRequestThenQuit CancelRequestThenQuit
+#else
+// See PR303886. LeakSanitizer flags a leak here.
+#define MAYBE_CancelRequestThenQuit DISABLED_CancelRequestThenQuit
+#endif
+TEST_F(MultiThreadedCertVerifierTest, MAYBE_CancelRequestThenQuit) {
base::FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> test_cert(
ImportCertFromFile(certs_dir, "ok_cert.pem"));
diff --git a/chromium/net/cert/nss_cert_database.cc b/chromium/net/cert/nss_cert_database.cc
index 8e9ef4e6f01..d4ece105745 100644
--- a/chromium/net/cert/nss_cert_database.cc
+++ b/chromium/net/cert/nss_cert_database.cc
@@ -16,6 +16,7 @@
#include "base/observer_list_threadsafe.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_nss_types.h"
#include "net/base/crypto_module.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_database.h"
@@ -69,49 +70,45 @@ void NSSCertDatabase::ListCerts(CertificateList* certs) {
CERT_DestroyCertList(cert_list);
}
-CryptoModule* NSSCertDatabase::GetPublicModule() const {
- CryptoModule* module =
- CryptoModule::CreateFromHandle(crypto::GetPublicNSSKeySlot());
- // The module is already referenced when returned from
- // GetPublicNSSKeySlot, so we need to deref it once.
- PK11_FreeSlot(module->os_module_handle());
+crypto::ScopedPK11Slot NSSCertDatabase::GetPublicSlot() const {
+ return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot());
+}
- return module;
+crypto::ScopedPK11Slot NSSCertDatabase::GetPrivateSlot() const {
+ return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot());
}
-CryptoModule* NSSCertDatabase::GetPrivateModule() const {
- CryptoModule* module =
- CryptoModule::CreateFromHandle(crypto::GetPrivateNSSKeySlot());
- // The module is already referenced when returned from
- // GetPrivateNSSKeySlot, so we need to deref it once.
- PK11_FreeSlot(module->os_module_handle());
+CryptoModule* NSSCertDatabase::GetPublicModule() const {
+ crypto::ScopedPK11Slot slot(GetPublicSlot());
+ return CryptoModule::CreateFromHandle(slot.get());
+}
- return module;
+CryptoModule* NSSCertDatabase::GetPrivateModule() const {
+ crypto::ScopedPK11Slot slot(GetPrivateSlot());
+ return CryptoModule::CreateFromHandle(slot.get());
}
void NSSCertDatabase::ListModules(CryptoModuleList* modules,
bool need_rw) const {
modules->clear();
- PK11SlotList* slot_list = NULL;
// The wincx arg is unused since we don't call PK11_SetIsLoggedInFunc.
- slot_list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
- need_rw ? PR_TRUE : PR_FALSE, // needRW
- PR_TRUE, // loadCerts (unused)
- NULL); // wincx
+ crypto::ScopedPK11SlotList slot_list(
+ PK11_GetAllTokens(CKM_INVALID_MECHANISM,
+ need_rw ? PR_TRUE : PR_FALSE, // needRW
+ PR_TRUE, // loadCerts (unused)
+ NULL)); // wincx
if (!slot_list) {
LOG(ERROR) << "PK11_GetAllTokens failed: " << PORT_GetError();
return;
}
- PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list);
+ PK11SlotListElement* slot_element = PK11_GetFirstSafe(slot_list.get());
while (slot_element) {
modules->push_back(CryptoModule::CreateFromHandle(slot_element->slot));
- slot_element = PK11_GetNextSafe(slot_list, slot_element,
+ slot_element = PK11_GetNextSafe(slot_list.get(), slot_element,
PR_FALSE); // restart
}
-
- PK11_FreeSlotList(slot_list);
}
int NSSCertDatabase::ImportFromPKCS12(
@@ -164,11 +161,12 @@ X509Certificate* NSSCertDatabase::FindRootInList(
bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates,
TrustBits trust_bits,
ImportCertFailureList* not_imported) {
+ crypto::ScopedPK11Slot slot(GetPublicSlot());
X509Certificate* root = FindRootInList(certificates);
- bool success = psm::ImportCACerts(certificates, root, trust_bits,
- not_imported);
+ bool success = psm::ImportCACerts(
+ slot.get(), certificates, root, trust_bits, not_imported);
if (success)
- NotifyObserversOfCertTrustChanged(NULL);
+ NotifyObserversOfCACertChanged(NULL);
return success;
}
@@ -176,7 +174,9 @@ bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates,
bool NSSCertDatabase::ImportServerCert(const CertificateList& certificates,
TrustBits trust_bits,
ImportCertFailureList* not_imported) {
- return psm::ImportServerCert(certificates, trust_bits, not_imported);
+ crypto::ScopedPK11Slot slot(GetPublicSlot());
+ return psm::ImportServerCert(
+ slot.get(), certificates, trust_bits, not_imported);
}
NSSCertDatabase::TrustBits NSSCertDatabase::GetCertTrust(
@@ -284,7 +284,7 @@ bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert,
TrustBits trust_bits) {
bool success = psm::SetCertTrust(cert, type, trust_bits);
if (success)
- NotifyObserversOfCertTrustChanged(cert);
+ NotifyObserversOfCACertChanged(cert);
return success;
}
@@ -319,6 +319,11 @@ bool NSSCertDatabase::IsReadOnly(const X509Certificate* cert) const {
return slot && PK11_IsReadOnly(slot);
}
+bool NSSCertDatabase::IsHardwareBacked(const X509Certificate* cert) const {
+ PK11SlotInfo* slot = cert->os_cert_handle()->slot;
+ return slot && PK11_IsHW(slot);
+}
+
void NSSCertDatabase::AddObserver(Observer* observer) {
observer_list_->AddObserver(observer);
}
@@ -336,10 +341,10 @@ void NSSCertDatabase::NotifyObserversOfCertRemoved(
observer_list_->Notify(&Observer::OnCertRemoved, make_scoped_refptr(cert));
}
-void NSSCertDatabase::NotifyObserversOfCertTrustChanged(
+void NSSCertDatabase::NotifyObserversOfCACertChanged(
const X509Certificate* cert) {
observer_list_->Notify(
- &Observer::OnCertTrustChanged, make_scoped_refptr(cert));
+ &Observer::OnCACertChanged, make_scoped_refptr(cert));
}
} // namespace net
diff --git a/chromium/net/cert/nss_cert_database.h b/chromium/net/cert/nss_cert_database.h
index 9db1b75d973..28751a46d01 100644
--- a/chromium/net/cert/nss_cert_database.h
+++ b/chromium/net/cert/nss_cert_database.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
+#include "crypto/scoped_nss_types.h"
#include "net/base/net_export.h"
#include "net/cert/cert_type.h"
#include "net/cert/x509_certificate.h"
@@ -39,10 +40,10 @@ class NET_EXPORT NSSCertDatabase {
// Will be called when a certificate is removed.
virtual void OnCertRemoved(const X509Certificate* cert) {}
- // Will be called when a certificate's trust is changed.
+ // Will be called when a CA certificate is changed.
// Called with |cert| == NULL after importing a list of certificates
// in ImportCACerts().
- virtual void OnCertTrustChanged(const X509Certificate* cert) {}
+ virtual void OnCACertChanged(const X509Certificate* cert) {}
protected:
Observer() {}
@@ -94,16 +95,27 @@ class NET_EXPORT NSSCertDatabase {
// instance of all certificates).
void ListCerts(CertificateList* certs);
+ // Get the default slot for public key data.
+ crypto::ScopedPK11Slot GetPublicSlot() const;
+
+ // Get the default slot for private key or mixed private/public key data.
+ crypto::ScopedPK11Slot GetPrivateSlot() const;
+
// Get the default module for public key data.
// The returned pointer must be stored in a scoped_refptr<CryptoModule>.
+ // DEPRECATED: use GetPublicSlot instead.
+ // TODO(mattm): remove usage of this method and remove it.
CryptoModule* GetPublicModule() const;
// Get the default module for private key or mixed private/public key data.
// The returned pointer must be stored in a scoped_refptr<CryptoModule>.
+ // DEPRECATED: use GetPrivateSlot instead.
+ // TODO(mattm): remove usage of this method and remove it.
CryptoModule* GetPrivateModule() const;
// Get all modules.
// If |need_rw| is true, only writable modules will be returned.
+ // TODO(mattm): come up with better alternative to CryptoModuleList.
void ListModules(CryptoModuleList* modules, bool need_rw) const;
// Import certificates and private keys from PKCS #12 blob into the module.
@@ -178,6 +190,9 @@ class NET_EXPORT NSSCertDatabase {
// Check whether cert is stored in a readonly slot.
bool IsReadOnly(const X509Certificate* cert) const;
+ // Check whether cert is stored in a hardware slot.
+ bool IsHardwareBacked(const X509Certificate* cert) const;
+
// Registers |observer| to receive notifications of certificate changes. The
// thread on which this is called is the thread on which |observer| will be
// called back with notifications.
@@ -196,7 +211,7 @@ class NET_EXPORT NSSCertDatabase {
// Broadcasts notifications to all registered observers.
void NotifyObserversOfCertAdded(const X509Certificate* cert);
void NotifyObserversOfCertRemoved(const X509Certificate* cert);
- void NotifyObserversOfCertTrustChanged(const X509Certificate* cert);
+ void NotifyObserversOfCACertChanged(const X509Certificate* cert);
const scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_;
diff --git a/chromium/net/cert/scoped_nss_types.h b/chromium/net/cert/scoped_nss_types.h
new file mode 100644
index 00000000000..3e6d57d998d
--- /dev/null
+++ b/chromium/net/cert/scoped_nss_types.h
@@ -0,0 +1,26 @@
+// 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_CERT_SCOPED_NSS_TYPES_H_
+#define NET_CERT_SCOPED_NSS_TYPES_H_
+
+#include <cert.h>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace net {
+
+struct FreeCERTCertificate {
+ public:
+ void operator()(CERTCertificate* x) const {
+ CERT_DestroyCertificate(x);
+ }
+};
+
+typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate>
+ ScopedCERTCertificate;
+
+} // namespace net
+
+#endif // NET_CERT_SCOPED_NSS_TYPES_H_
diff --git a/chromium/net/cert/sct_status_flags.h b/chromium/net/cert/sct_status_flags.h
new file mode 100644
index 00000000000..1bcb42272b0
--- /dev/null
+++ b/chromium/net/cert/sct_status_flags.h
@@ -0,0 +1,32 @@
+// 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_CERT_SCT_STATUS_FLAGS_H_
+#define NET_CERT_SCT_STATUS_FLAGS_H_
+
+namespace net {
+
+namespace ct {
+
+// The possible verification statuses for a SignedCertificateTimestamp.
+enum SCTVerifyStatus {
+ // Not a real status, this just prevents a default int value from being
+ // mis-interpreseted as a valid status.
+ SCT_STATUS_NONE = 0,
+
+ // The SCT is from an unknown log, so we cannot verify its signature.
+ SCT_STATUS_LOG_UNKNOWN = 1,
+
+ // The SCT is from a known log, but the signature is invalid.
+ SCT_STATUS_INVALID = 2,
+
+ // The SCT is from a known log, and the signature is valid.
+ SCT_STATUS_OK = 3,
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_SCT_STATUS_FLAGS_H_
diff --git a/chromium/net/cert/signed_certificate_timestamp.cc b/chromium/net/cert/signed_certificate_timestamp.cc
new file mode 100644
index 00000000000..0a72cd1f9d2
--- /dev/null
+++ b/chromium/net/cert/signed_certificate_timestamp.cc
@@ -0,0 +1,94 @@
+// 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/cert/signed_certificate_timestamp.h"
+
+#include "base/pickle.h"
+
+namespace net {
+
+namespace ct {
+
+bool SignedCertificateTimestamp::LessThan::operator()(
+ const scoped_refptr<SignedCertificateTimestamp>& lhs,
+ const scoped_refptr<SignedCertificateTimestamp>& rhs) const {
+ if (lhs.get() == rhs.get())
+ return false;
+ if (lhs->signature.signature_data != rhs->signature.signature_data)
+ return lhs->signature.signature_data < rhs->signature.signature_data;
+ if (lhs->log_id != rhs->log_id)
+ return lhs->log_id < rhs->log_id;
+ if (lhs->timestamp != rhs->timestamp)
+ return lhs->timestamp < rhs->timestamp;
+ if (lhs->extensions != rhs->extensions)
+ return lhs->extensions < rhs->extensions;
+ return lhs->version < rhs->version;
+}
+
+SignedCertificateTimestamp::SignedCertificateTimestamp() {}
+
+SignedCertificateTimestamp::~SignedCertificateTimestamp() {}
+
+void SignedCertificateTimestamp::Persist(Pickle* pickle) {
+ CHECK(pickle->WriteInt(version));
+ CHECK(pickle->WriteString(log_id));
+ CHECK(pickle->WriteInt64(timestamp.ToInternalValue()));
+ CHECK(pickle->WriteString(extensions));
+ CHECK(pickle->WriteInt(signature.hash_algorithm));
+ CHECK(pickle->WriteInt(signature.signature_algorithm));
+ CHECK(pickle->WriteString(signature.signature_data));
+ CHECK(pickle->WriteInt(origin));
+ CHECK(pickle->WriteString(log_description));
+}
+
+// static
+scoped_refptr<SignedCertificateTimestamp>
+SignedCertificateTimestamp::CreateFromPickle(PickleIterator* iter) {
+ int version;
+ int64 timestamp;
+ int hash_algorithm;
+ int sig_algorithm;
+ scoped_refptr<SignedCertificateTimestamp> sct(
+ new SignedCertificateTimestamp());
+ int origin;
+ // string values are set directly
+ if (!(iter->ReadInt(&version) &&
+ iter->ReadString(&sct->log_id) &&
+ iter->ReadInt64(&timestamp) &&
+ iter->ReadString(&sct->extensions) &&
+ iter->ReadInt(&hash_algorithm) &&
+ iter->ReadInt(&sig_algorithm) &&
+ iter->ReadString(&sct->signature.signature_data) &&
+ iter->ReadInt(&origin) &&
+ iter->ReadString(&sct->log_description))) {
+ return NULL;
+ }
+ // Now set the rest of the member variables:
+ sct->version = static_cast<Version>(version);
+ sct->timestamp = base::Time::FromInternalValue(timestamp);
+ sct->signature.hash_algorithm =
+ static_cast<DigitallySigned::HashAlgorithm>(hash_algorithm);
+ sct->signature.signature_algorithm =
+ static_cast<DigitallySigned::SignatureAlgorithm>(sig_algorithm);
+ sct->origin = static_cast<Origin>(origin);
+ return sct;
+}
+
+LogEntry::LogEntry() {}
+
+LogEntry::~LogEntry() {}
+
+void LogEntry::Reset() {
+ type = LogEntry::LOG_ENTRY_TYPE_X509;
+ leaf_certificate.clear();
+ tbs_certificate.clear();
+}
+
+DigitallySigned::DigitallySigned() {}
+
+DigitallySigned::~DigitallySigned() {}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/signed_certificate_timestamp.h b/chromium/net/cert/signed_certificate_timestamp.h
new file mode 100644
index 00000000000..f065a9472a1
--- /dev/null
+++ b/chromium/net/cert/signed_certificate_timestamp.h
@@ -0,0 +1,129 @@
+// 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_CERT_SIGNED_CERTIFICATE_TIMESTAMP_H_
+#define NET_CERT_SIGNED_CERTIFICATE_TIMESTAMP_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
+#include "net/base/hash_value.h"
+#include "net/base/net_export.h"
+
+class Pickle;
+class PickleIterator;
+
+namespace net {
+
+// Structures related to Certificate Transparency (RFC6962).
+namespace ct {
+
+// LogEntry struct in RFC 6962, Section 3.1
+struct NET_EXPORT LogEntry {
+ // LogEntryType enum in RFC 6962, Section 3.1
+ enum Type {
+ LOG_ENTRY_TYPE_X509 = 0,
+ LOG_ENTRY_TYPE_PRECERT = 1
+ };
+
+ LogEntry();
+ ~LogEntry();
+ void Reset();
+
+ Type type;
+
+ // Set if type == LOG_ENTRY_TYPE_X509
+ std::string leaf_certificate;
+
+ // Set if type == LOG_ENTRY_TYPE_PRECERT
+ SHA256HashValue issuer_key_hash;
+ std::string tbs_certificate;
+};
+
+// Helper structure to represent Digitally Signed data, as described in
+// Sections 4.7 and 7.4.1.4.1 of RFC 5246.
+struct NET_EXPORT_PRIVATE DigitallySigned {
+ enum HashAlgorithm {
+ HASH_ALGO_NONE = 0,
+ HASH_ALGO_MD5 = 1,
+ HASH_ALGO_SHA1 = 2,
+ HASH_ALGO_SHA224 = 3,
+ HASH_ALGO_SHA256 = 4,
+ HASH_ALGO_SHA384 = 5,
+ HASH_ALGO_SHA512 = 6,
+ };
+
+ enum SignatureAlgorithm {
+ SIG_ALGO_ANONYMOUS = 0,
+ SIG_ALGO_RSA = 1,
+ SIG_ALGO_DSA = 2,
+ SIG_ALGO_ECDSA = 3
+ };
+
+ DigitallySigned();
+ ~DigitallySigned();
+
+ HashAlgorithm hash_algorithm;
+ SignatureAlgorithm signature_algorithm;
+ // 'signature' field.
+ std::string signature_data;
+};
+
+// SignedCertificateTimestamp struct in RFC 6962, Section 3.2.
+struct NET_EXPORT SignedCertificateTimestamp
+ : public base::RefCountedThreadSafe<SignedCertificateTimestamp> {
+ // Predicate functor used in maps when SignedCertificateTimestamp is used as
+ // the key.
+ struct NET_EXPORT LessThan {
+ bool operator()(const scoped_refptr<SignedCertificateTimestamp>& lhs,
+ const scoped_refptr<SignedCertificateTimestamp>& rhs) const;
+ };
+
+ // Version enum in RFC 6962, Section 3.2.
+ enum Version {
+ SCT_VERSION_1 = 0,
+ };
+
+ // Source of the SCT - supplementary, not defined in CT RFC.
+ enum Origin {
+ SCT_EMBEDDED = 0,
+ SCT_FROM_TLS_EXTENSION = 1,
+ SCT_FROM_OCSP_RESPONSE = 2,
+ };
+
+ SignedCertificateTimestamp();
+
+ void Persist(Pickle* pickle);
+ static scoped_refptr<SignedCertificateTimestamp> CreateFromPickle(
+ PickleIterator* iter);
+
+ Version version;
+ std::string log_id;
+ base::Time timestamp;
+ std::string extensions;
+ DigitallySigned signature;
+ // The origin should not participate in equality checks
+ // as the same SCT can be provided from multiple sources.
+ Origin origin;
+ // The log description is not one of the SCT fields, but a user-readable
+ // name defined alongside the log key. It should not participate
+ // in equality checks as the log's description could change while
+ // the SCT would be the same.
+ std::string log_description;
+
+ private:
+ friend class base::RefCountedThreadSafe<SignedCertificateTimestamp>;
+
+ ~SignedCertificateTimestamp();
+
+ DISALLOW_COPY_AND_ASSIGN(SignedCertificateTimestamp);
+};
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_SIGNED_CERTIFICATE_TIMESTAMP_H_
diff --git a/chromium/net/cert/signed_certificate_timestamp_unittest.cc b/chromium/net/cert/signed_certificate_timestamp_unittest.cc
new file mode 100644
index 00000000000..c758d656b1b
--- /dev/null
+++ b/chromium/net/cert/signed_certificate_timestamp_unittest.cc
@@ -0,0 +1,54 @@
+// 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/cert/signed_certificate_timestamp.h"
+
+#include <string>
+
+#include "base/pickle.h"
+#include "net/test/ct_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace ct {
+
+namespace {
+
+const char kLogDescription[] = "somelog";
+
+class SignedCertificateTimestampTest : public ::testing::Test {
+ public:
+ virtual void SetUp() OVERRIDE {
+ GetX509CertSCT(&sample_sct_);
+ sample_sct_->origin = SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE;
+ sample_sct_->log_description = kLogDescription;
+ }
+
+ protected:
+ scoped_refptr<SignedCertificateTimestamp> sample_sct_;
+};
+
+TEST_F(SignedCertificateTimestampTest, PicklesAndUnpickles) {
+ Pickle pickle;
+
+ sample_sct_->Persist(&pickle);
+ PickleIterator iter(pickle);
+
+ scoped_refptr<SignedCertificateTimestamp> unpickled_sct(
+ SignedCertificateTimestamp::CreateFromPickle(&iter));
+
+ SignedCertificateTimestamp::LessThan less_than;
+
+ ASSERT_FALSE(less_than(sample_sct_, unpickled_sct));
+ ASSERT_FALSE(less_than(unpickled_sct, sample_sct_));
+ ASSERT_EQ(sample_sct_->origin, unpickled_sct->origin);
+ ASSERT_EQ(sample_sct_->log_description, unpickled_sct->log_description);
+}
+
+} // namespace
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/cert/x509_certificate.cc b/chromium/net/cert/x509_certificate.cc
index 36e806ebaba..a095fdf83e9 100644
--- a/chromium/net/cert/x509_certificate.cc
+++ b/chromium/net/cert/x509_certificate.cc
@@ -504,7 +504,8 @@ bool X509Certificate::VerifyHostname(
const std::string& hostname,
const std::string& cert_common_name,
const std::vector<std::string>& cert_san_dns_names,
- const std::vector<std::string>& cert_san_ip_addrs) {
+ const std::vector<std::string>& cert_san_ip_addrs,
+ bool* common_name_fallback_used) {
DCHECK(!hostname.empty());
// Perform name verification following http://tools.ietf.org/html/rfc6125.
// The terminology used in this method is as per that RFC:-
@@ -528,6 +529,7 @@ bool X509Certificate::VerifyHostname(
// Allow fallback to Common name matching?
const bool common_name_fallback = cert_san_dns_names.empty() &&
cert_san_ip_addrs.empty();
+ *common_name_fallback_used = common_name_fallback;
// Fully handle all cases where |hostname| contains an IP address.
if (host_info.IsIPAddress()) {
@@ -649,10 +651,12 @@ bool X509Certificate::VerifyHostname(
return false;
}
-bool X509Certificate::VerifyNameMatch(const std::string& hostname) const {
+bool X509Certificate::VerifyNameMatch(const std::string& hostname,
+ bool* common_name_fallback_used) const {
std::vector<std::string> dns_names, ip_addrs;
GetSubjectAltName(&dns_names, &ip_addrs);
- return VerifyHostname(hostname, subject_.common_name, dns_names, ip_addrs);
+ return VerifyHostname(hostname, subject_.common_name, dns_names, ip_addrs,
+ common_name_fallback_used);
}
// static
@@ -661,8 +665,7 @@ bool X509Certificate::GetPEMEncodedFromDER(const std::string& der_encoded,
if (der_encoded.empty())
return false;
std::string b64_encoded;
- if (!base::Base64Encode(der_encoded, &b64_encoded) || b64_encoded.empty())
- return false;
+ base::Base64Encode(der_encoded, &b64_encoded);
*pem_encoded = "-----BEGIN CERTIFICATE-----\n";
// Divide the Base-64 encoded data into 64-character chunks, as per
diff --git a/chromium/net/cert/x509_certificate.h b/chromium/net/cert/x509_certificate.h
index ef552431729..43ed01414e5 100644
--- a/chromium/net/cert/x509_certificate.h
+++ b/chromium/net/cert/x509_certificate.h
@@ -313,8 +313,11 @@ class NET_EXPORT X509Certificate
// Verifies that |hostname| matches this certificate.
// Does not verify that the certificate is valid, only that the certificate
// matches this host.
- // Returns true if it matches.
- bool VerifyNameMatch(const std::string& hostname) const;
+ // Returns true if it matches, and updates |*common_name_fallback_used|,
+ // setting it to true if a fallback to the CN was used, rather than
+ // subjectAltName.
+ bool VerifyNameMatch(const std::string& hostname,
+ bool* common_name_fallback_used) const;
// Obtains the DER encoded certificate data for |cert_handle|. On success,
// returns true and writes the DER encoded certificate to |*der_encoded|.
@@ -425,10 +428,14 @@ class NET_EXPORT X509Certificate
// extension, if present. Note these IP addresses are NOT ascii-encoded:
// they must be 4 or 16 bytes of network-ordered data, for IPv4 and IPv6
// addresses, respectively.
+ // |common_name_fallback_used| will be updated to true if cert_common_name
+ // was used to match the hostname, or false if either of the |cert_san_*|
+ // parameters was used to match the hostname.
static bool VerifyHostname(const std::string& hostname,
const std::string& cert_common_name,
const std::vector<std::string>& cert_san_dns_names,
- const std::vector<std::string>& cert_san_ip_addrs);
+ const std::vector<std::string>& cert_san_ip_addrs,
+ bool* common_name_fallback_used);
// Reads a single certificate from |pickle_iter| and returns a
// platform-specific certificate handle. The format of the certificate
diff --git a/chromium/net/cert/x509_certificate_mac.cc b/chromium/net/cert/x509_certificate_mac.cc
index 96f7b52ab3d..1d874c4b023 100644
--- a/chromium/net/cert/x509_certificate_mac.cc
+++ b/chromium/net/cert/x509_certificate_mac.cc
@@ -206,60 +206,6 @@ struct CSSMOIDString {
typedef std::vector<CSSMOIDString> CSSMOIDStringVector;
-bool CERTNameToCSSMOIDVector(CERTName* name, CSSMOIDStringVector* out_values) {
- struct OIDCSSMMap {
- SECOidTag sec_OID_;
- const CSSM_OID* cssm_OID_;
- };
-
- const OIDCSSMMap kOIDs[] = {
- { SEC_OID_AVA_COMMON_NAME, &CSSMOID_CommonName },
- { SEC_OID_AVA_COUNTRY_NAME, &CSSMOID_CountryName },
- { SEC_OID_AVA_LOCALITY, &CSSMOID_LocalityName },
- { SEC_OID_AVA_STATE_OR_PROVINCE, &CSSMOID_StateProvinceName },
- { SEC_OID_AVA_STREET_ADDRESS, &CSSMOID_StreetAddress },
- { SEC_OID_AVA_ORGANIZATION_NAME, &CSSMOID_OrganizationName },
- { SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, &CSSMOID_OrganizationalUnitName },
- { SEC_OID_AVA_DN_QUALIFIER, &CSSMOID_DNQualifier },
- { SEC_OID_RFC1274_UID, &CSSMOID_UniqueIdentifier },
- { SEC_OID_PKCS9_EMAIL_ADDRESS, &CSSMOID_EmailAddress },
- };
-
- CERTRDN** rdns = name->rdns;
- for (size_t rdn = 0; rdns[rdn]; ++rdn) {
- CERTAVA** avas = rdns[rdn]->avas;
- for (size_t pair = 0; avas[pair] != 0; ++pair) {
- SECOidTag tag = CERT_GetAVATag(avas[pair]);
- if (tag == SEC_OID_UNKNOWN) {
- return false;
- }
- CSSMOIDString oidString;
- bool found_oid = false;
- for (size_t oid = 0; oid < ARRAYSIZE_UNSAFE(kOIDs); ++oid) {
- if (kOIDs[oid].sec_OID_ == tag) {
- SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
- if (!decode_item)
- return false;
-
- // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
- std::string value(reinterpret_cast<char*>(decode_item->data),
- decode_item->len);
- oidString.oid_ = kOIDs[oid].cssm_OID_;
- oidString.string_ = value;
- out_values->push_back(oidString);
- SECITEM_FreeItem(decode_item, PR_TRUE);
- found_oid = true;
- break;
- }
- }
- if (!found_oid) {
- DLOG(ERROR) << "Unrecognized OID: " << tag;
- }
- }
- }
- return true;
-}
-
class ScopedCertName {
public:
explicit ScopedCertName(CERTName* name) : name_(name) { }
diff --git a/chromium/net/cert/x509_certificate_unittest.cc b/chromium/net/cert/x509_certificate_unittest.cc
index 04dbaddf69f..83de91a64bc 100644
--- a/chromium/net/cert/x509_certificate_unittest.cc
+++ b/chromium/net/cert/x509_certificate_unittest.cc
@@ -190,11 +190,12 @@ TEST(X509CertificateTest, WebkitCertParsing) {
EXPECT_EQ("webkit.org", dns_names[1]);
// Test that the wildcard cert matches properly.
- EXPECT_TRUE(webkit_cert->VerifyNameMatch("www.webkit.org"));
- EXPECT_TRUE(webkit_cert->VerifyNameMatch("foo.webkit.org"));
- EXPECT_TRUE(webkit_cert->VerifyNameMatch("webkit.org"));
- EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.webkit.com"));
- EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.foo.webkit.com"));
+ bool unused = false;
+ EXPECT_TRUE(webkit_cert->VerifyNameMatch("www.webkit.org", &unused));
+ EXPECT_TRUE(webkit_cert->VerifyNameMatch("foo.webkit.org", &unused));
+ EXPECT_TRUE(webkit_cert->VerifyNameMatch("webkit.org", &unused));
+ EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.webkit.com", &unused));
+ EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.foo.webkit.com", &unused));
}
TEST(X509CertificateTest, ThawteCertParsing) {
@@ -1139,8 +1140,9 @@ TEST_P(X509CertificateNameVerifyTest, VerifyHostname) {
}
}
+ bool unused = false;
EXPECT_EQ(test_data.expected, X509Certificate::VerifyHostname(
- test_data.hostname, common_name, dns_names, ip_addressses));
+ test_data.hostname, common_name, dns_names, ip_addressses, &unused));
}
INSTANTIATE_TEST_CASE_P(, X509CertificateNameVerifyTest,
diff --git a/chromium/net/cert/x509_util.cc b/chromium/net/cert/x509_util.cc
index 8beb5572b87..cc0a2c583bf 100644
--- a/chromium/net/cert/x509_util.cc
+++ b/chromium/net/cert/x509_util.cc
@@ -4,13 +4,24 @@
#include "net/cert/x509_util.h"
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
+#include "crypto/ec_private_key.h"
+#include "crypto/rsa_private_key.h"
#include "net/cert/x509_certificate.h"
namespace net {
namespace x509_util {
+// RSA keys created by CreateKeyAndSelfSignedCert will be of this length.
+static const uint16 kRSAKeyLength = 1024;
+
+// Certificates made by CreateKeyAndSelfSignedCert and
+// CreateKeyAndDomainBoundCertEC will be signed using this digest algorithm.
+static const DigestAlgorithm kSignatureDigestAlgorithm = DIGEST_SHA256;
+
ClientCertSorter::ClientCertSorter() : now_(base::Time::Now()) {}
bool ClientCertSorter::operator()(
@@ -44,6 +55,53 @@ bool ClientCertSorter::operator()(
return a_intermediates.size() < b_intermediates.size();
}
+bool CreateKeyAndDomainBoundCertEC(const std::string& domain,
+ uint32 serial_number,
+ base::Time not_valid_before,
+ base::Time not_valid_after,
+ scoped_ptr<crypto::ECPrivateKey>* key,
+ std::string* der_cert) {
+ scoped_ptr<crypto::ECPrivateKey> new_key(crypto::ECPrivateKey::Create());
+ if (!new_key.get())
+ return false;
+
+ bool success = CreateDomainBoundCertEC(new_key.get(),
+ kSignatureDigestAlgorithm,
+ domain,
+ serial_number,
+ not_valid_before,
+ not_valid_after,
+ der_cert);
+ if (success)
+ key->reset(new_key.release());
+
+ return success;
+}
+
+bool CreateKeyAndSelfSignedCert(const std::string& subject,
+ uint32 serial_number,
+ base::Time not_valid_before,
+ base::Time not_valid_after,
+ scoped_ptr<crypto::RSAPrivateKey>* key,
+ std::string* der_cert) {
+ scoped_ptr<crypto::RSAPrivateKey> new_key(
+ crypto::RSAPrivateKey::Create(kRSAKeyLength));
+ if (!new_key.get())
+ return false;
+
+ bool success = CreateSelfSignedCert(new_key.get(),
+ kSignatureDigestAlgorithm,
+ subject,
+ serial_number,
+ not_valid_before,
+ not_valid_after,
+ der_cert);
+ if (success)
+ key->reset(new_key.release());
+
+ return success;
+}
+
} // namespace x509_util
} // namespace net
diff --git a/chromium/net/cert/x509_util.h b/chromium/net/cert/x509_util.h
index 8a6bae2c95f..e6b0e448cd4 100644
--- a/chromium/net/cert/x509_util.h
+++ b/chromium/net/cert/x509_util.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
@@ -22,6 +23,12 @@ class X509Certificate;
namespace x509_util {
+// Supported digest algorithms for signing certificates.
+enum DigestAlgorithm {
+ DIGEST_SHA1,
+ DIGEST_SHA256
+};
+
// Returns true if the times can be used to create an X.509 certificate.
// Certificates can accept dates from Jan 1st, 1 to Dec 31, 9999. A bug in NSS
// limited the range to 1950-9999
@@ -30,30 +37,38 @@ namespace x509_util {
NET_EXPORT_PRIVATE bool IsSupportedValidityRange(base::Time not_valid_before,
base::Time not_valid_after);
-// Creates a server bound certificate containing the public key in |key|.
+// Creates a private keypair and server bound certificate.
// Domain, serial number and validity period are given as
// parameters. The certificate is signed by the private key in |key|.
-// The hashing algorithm for the signature is SHA-1.
+// The signature algorithm may be updated periodically to match best practices.
//
// See Internet Draft draft-balfanz-tls-obc-00 for more details:
// http://tools.ietf.org/html/draft-balfanz-tls-obc-00
-NET_EXPORT_PRIVATE bool CreateDomainBoundCertEC(
- crypto::ECPrivateKey* key,
+NET_EXPORT_PRIVATE bool CreateKeyAndDomainBoundCertEC(
const std::string& domain,
uint32 serial_number,
base::Time not_valid_before,
base::Time not_valid_after,
+ scoped_ptr<crypto::ECPrivateKey>* key,
std::string* der_cert);
-// Create a self-signed certificate containing the public key in |key|.
+// Helper function for CreateKeyAndDomainBoundCertEC.
+NET_EXPORT_PRIVATE bool CreateDomainBoundCertEC(crypto::ECPrivateKey* key,
+ DigestAlgorithm alg,
+ const std::string& domain,
+ uint32 serial_number,
+ base::Time not_valid_before,
+ base::Time not_valid_after,
+ std::string* der_cert);
+
+// 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 hashing
-// algorithm for the signature is SHA-1.
+// The certificate is signed by the private key in |key|. The key length and
+// signature algorithm may be updated periodically to match best practices.
//
-// |subject| is a distinguished name defined in RFC4514.
-//
-// An example:
-// CN=Michael Wong,O=FooBar Corporation,DC=foobar,DC=com
+// |subject| is a distinguished name defined in RFC4514 with _only_ a CN
+// component, as in:
+// CN=Michael Wong
//
// SECURITY WARNING
//
@@ -63,7 +78,19 @@ NET_EXPORT_PRIVATE bool CreateDomainBoundCertEC(
// 2. Self-signed certificates cannot be revoked.
//
// Use this certificate only after the above risks are acknowledged.
+NET_EXPORT bool CreateKeyAndSelfSignedCert(
+ const std::string& subject,
+ uint32 serial_number,
+ base::Time not_valid_before,
+ base::Time not_valid_after,
+ scoped_ptr<crypto::RSAPrivateKey>* key,
+ std::string* der_cert);
+
+// Creates a self-signed certificate from a provided key, using the specified
+// hash algorithm. You should not re-use a key for signing data with multiple
+// signature algorithms or parameters.
NET_EXPORT bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
+ DigestAlgorithm alg,
const std::string& subject,
uint32 serial_number,
base::Time not_valid_before,
diff --git a/chromium/net/cert/x509_util_android.cc b/chromium/net/cert/x509_util_android.cc
new file mode 100644
index 00000000000..1f6c3c696d2
--- /dev/null
+++ b/chromium/net/cert/x509_util_android.cc
@@ -0,0 +1,25 @@
+// 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/cert/x509_util_android.h"
+
+#include "base/android/jni_android.h"
+#include "jni/X509Util_jni.h"
+#include "net/cert/cert_database.h"
+
+namespace net {
+
+void NotifyKeyChainChanged(JNIEnv* env, jclass clazz) {
+ CertDatabase::GetInstance()->OnAndroidKeyChainChanged();
+}
+
+jobject GetApplicationContext(JNIEnv* env, jclass clazz) {
+ return base::android::GetApplicationContext();
+}
+
+bool RegisterX509Util(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // net namespace
diff --git a/chromium/net/cert/x509_util_android.h b/chromium/net/cert/x509_util_android.h
new file mode 100644
index 00000000000..205a60ab58b
--- /dev/null
+++ b/chromium/net/cert/x509_util_android.h
@@ -0,0 +1,16 @@
+// 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_CERT_X509_UTIL_ANDROID_H_
+#define NET_CERT_X509_UTIL_ANDROID_H_
+
+#include <jni.h>
+
+namespace net {
+
+bool RegisterX509Util(JNIEnv* env);
+
+} // net namespace
+
+#endif // NET_CERT_X509_UTIL_ANDROID_H_
diff --git a/chromium/net/cert/x509_util_nss.cc b/chromium/net/cert/x509_util_nss.cc
index f8fbd6feda9..67ad467f5c5 100644
--- a/chromium/net/cert/x509_util_nss.cc
+++ b/chromium/net/cert/x509_util_nss.cc
@@ -134,6 +134,16 @@ CERTCertificate* CreateCertificate(
return cert;
}
+SECOidTag ToSECOid(x509_util::DigestAlgorithm alg) {
+ switch (alg) {
+ case x509_util::DIGEST_SHA1:
+ return SEC_OID_SHA1;
+ case x509_util::DIGEST_SHA256:
+ return SEC_OID_SHA256;
+ }
+ return SEC_OID_UNKNOWN;
+}
+
// Signs a certificate object, with |key| generating a new X509Certificate
// and destroying the passed certificate object (even when NULL is returned).
// The logic of this method references SignCert() in NSS utility certutil:
@@ -142,11 +152,12 @@ CERTCertificate* CreateCertificate(
// certificate signing process.
bool SignCertificate(
CERTCertificate* cert,
- SECKEYPrivateKey* key) {
+ SECKEYPrivateKey* key,
+ SECOidTag hash_algorithm) {
// |arena| is used to encode the cert.
PLArenaPool* arena = cert->arena;
SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->keyType,
- SEC_OID_SHA1);
+ hash_algorithm);
if (algo_id == SEC_OID_UNKNOWN)
return false;
@@ -240,12 +251,14 @@ CERTName* CreateCertNameFromEncoded(PLArenaPool* arena,
namespace x509_util {
bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
+ DigestAlgorithm alg,
const std::string& subject,
uint32 serial_number,
base::Time not_valid_before,
base::Time not_valid_after,
std::string* der_cert) {
DCHECK(key);
+ DCHECK(!strncmp(subject.c_str(), "CN=", 3U));
CERTCertificate* cert = CreateCertificate(key->public_key(),
subject,
serial_number,
@@ -254,7 +267,7 @@ bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
if (!cert)
return false;
- if (!SignCertificate(cert, key->key())) {
+ if (!SignCertificate(cert, key->key(), ToSECOid(alg))) {
CERT_DestroyCertificate(cert);
return false;
}
@@ -279,6 +292,7 @@ bool IsSupportedValidityRange(base::Time not_valid_before,
}
bool CreateDomainBoundCertEC(crypto::ECPrivateKey* key,
+ DigestAlgorithm alg,
const std::string& domain,
uint32 serial_number,
base::Time not_valid_before,
@@ -340,7 +354,7 @@ bool CreateDomainBoundCertEC(crypto::ECPrivateKey* key,
return false;
}
- if (!SignCertificate(cert, key->key())) {
+ if (!SignCertificate(cert, key->key(), ToSECOid(alg))) {
CERT_DestroyCertificate(cert);
return false;
}
diff --git a/chromium/net/cert/x509_util_nss_unittest.cc b/chromium/net/cert/x509_util_nss_unittest.cc
index 968cc147ec5..0ad5ecddfaa 100644
--- a/chromium/net/cert/x509_util_nss_unittest.cc
+++ b/chromium/net/cert/x509_util_nss_unittest.cc
@@ -141,21 +141,20 @@ void VerifyDomainBoundCert(const std::string& domain,
} // namespace
-// This test creates a domain-bound cert from an EC private key and
+// This test creates a domain-bound cert and an EC private key and
// then verifies the content of the certificate.
-TEST(X509UtilNSSTest, CreateDomainBoundCertEC) {
+TEST(X509UtilNSSTest, CreateKeyAndDomainBoundCertEC) {
// Create a sample ASCII weborigin.
std::string domain = "weborigin.com";
base::Time now = base::Time::Now();
- scoped_ptr<crypto::ECPrivateKey> private_key(
- crypto::ECPrivateKey::Create());
+ scoped_ptr<crypto::ECPrivateKey> private_key;
std::string der_cert;
- ASSERT_TRUE(x509_util::CreateDomainBoundCertEC(
- private_key.get(),
+ ASSERT_TRUE(x509_util::CreateKeyAndDomainBoundCertEC(
domain, 1,
now,
now + base::TimeDelta::FromDays(1),
+ &private_key,
&der_cert));
VerifyDomainBoundCert(domain, der_cert);
diff --git a/chromium/net/cert/x509_util_openssl.cc b/chromium/net/cert/x509_util_openssl.cc
index e4dec992575..2e52221e704 100644
--- a/chromium/net/cert/x509_util_openssl.cc
+++ b/chromium/net/cert/x509_util_openssl.cc
@@ -2,19 +2,182 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/cert/x509_util.h"
#include "net/cert/x509_util_openssl.h"
#include <algorithm>
+#include <openssl/asn1.h>
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
+#include "crypto/ec_private_key.h"
+#include "crypto/openssl_util.h"
+#include "crypto/rsa_private_key.h"
#include "net/cert/x509_cert_types.h"
+#include "net/cert/x509_util.h"
namespace net {
+namespace {
+
+const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) {
+ switch (alg) {
+ case x509_util::DIGEST_SHA1:
+ return EVP_sha1();
+ case x509_util::DIGEST_SHA256:
+ return EVP_sha256();
+ }
+ return NULL;
+}
+
+} // namespace
+
namespace x509_util {
+namespace {
+
+X509* CreateCertificate(EVP_PKEY* key,
+ DigestAlgorithm alg,
+ const std::string& common_name,
+ uint32_t serial_number,
+ base::Time not_valid_before,
+ base::Time not_valid_after) {
+ // Put the serial number into an OpenSSL-friendly object.
+ crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free> asn1_serial(
+ ASN1_INTEGER_new());
+ if (!asn1_serial.get() ||
+ !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) {
+ LOG(ERROR) << "Invalid serial number " << serial_number;
+ return NULL;
+ }
+
+ // Do the same for the time stamps.
+ crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free> asn1_not_before_time(
+ ASN1_TIME_set(NULL, not_valid_before.ToTimeT()));
+ if (!asn1_not_before_time.get()) {
+ LOG(ERROR) << "Invalid not_valid_before time: "
+ << not_valid_before.ToTimeT();
+ return NULL;
+ }
+
+ crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free> asn1_not_after_time(
+ ASN1_TIME_set(NULL, not_valid_after.ToTimeT()));
+ if (!asn1_not_after_time.get()) {
+ LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT();
+ return NULL;
+ }
+
+ // Because |common_name| only contains a common name and starts with 'CN=',
+ // there is no need for a full RFC 2253 parser here. Do some sanity checks
+ // though.
+ static const char kCommonNamePrefix[] = "CN=";
+ const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1;
+ if (common_name.size() < kCommonNamePrefixLen ||
+ strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) {
+ LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix;
+ return NULL;
+ }
+ if (common_name.size() > INT_MAX) {
+ LOG(ERROR) << "Common name too long";
+ return NULL;
+ }
+ unsigned char* common_name_str =
+ reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) +
+ kCommonNamePrefixLen;
+ int common_name_len =
+ static_cast<int>(common_name.size() - kCommonNamePrefixLen);
+
+ crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free> name(X509_NAME_new());
+ if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(),
+ NID_commonName,
+ MBSTRING_ASC,
+ common_name_str,
+ common_name_len,
+ -1,
+ 0)) {
+ LOG(ERROR) << "Can't parse common name: " << common_name.c_str();
+ return NULL;
+ }
+
+ // Now create certificate and populate it.
+ crypto::ScopedOpenSSL<X509, X509_free> cert(X509_new());
+ if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ ||
+ !X509_set_pubkey(cert.get(), key) ||
+ !X509_set_serialNumber(cert.get(), asn1_serial.get()) ||
+ !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) ||
+ !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) ||
+ !X509_set_subject_name(cert.get(), name.get()) ||
+ !X509_set_issuer_name(cert.get(), name.get())) {
+ LOG(ERROR) << "Could not create certificate";
+ return NULL;
+ }
+
+ return cert.release();
+}
+
+bool SignAndDerEncodeCert(X509* cert,
+ EVP_PKEY* key,
+ DigestAlgorithm alg,
+ std::string* der_encoded) {
+ // Get the message digest algorithm
+ const EVP_MD* md = ToEVP(alg);
+ if (!md) {
+ LOG(ERROR) << "Unrecognized hash algorithm.";
+ return false;
+ }
+
+ // Sign it with the private key.
+ if (!X509_sign(cert, key, md)) {
+ LOG(ERROR) << "Could not sign certificate with key.";
+ return false;
+ }
+
+ // Convert it into a DER-encoded string copied to |der_encoded|.
+ int der_data_length = i2d_X509(cert, NULL);
+ if (der_data_length < 0)
+ return false;
+
+ der_encoded->resize(der_data_length);
+ unsigned char* der_data =
+ reinterpret_cast<unsigned char*>(&(*der_encoded)[0]);
+ if (i2d_X509(cert, &der_data) < 0)
+ return false;
+
+ return true;
+}
+
+// There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
+// so create a global ASN1_OBJECT lazily with the right parameters.
+class DomainBoundOid {
+ public:
+ DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); }
+
+ ~DomainBoundOid() {
+ if (obj_)
+ ASN1_OBJECT_free(obj_);
+ }
+
+ ASN1_OBJECT* obj() const { return obj_; }
+
+ private:
+ static const char kDomainBoundOidText[];
+
+ ASN1_OBJECT* obj_;
+};
+
+// 1.3.6.1.4.1.11129.2.1.6
+// (iso.org.dod.internet.private.enterprises.google.googleSecurity.
+// certificateExtensions.originBoundCertificate)
+const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";
+
+ASN1_OBJECT* GetDomainBoundOid() {
+ static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
+ LAZY_INSTANCE_INITIALIZER;
+ return s_lazy.Get().obj();
+}
+
+} // namespace
+
bool IsSupportedValidityRange(base::Time not_valid_before,
base::Time not_valid_after) {
if (not_valid_before > not_valid_after)
@@ -50,23 +213,79 @@ bool IsSupportedValidityRange(base::Time not_valid_before,
bool CreateDomainBoundCertEC(
crypto::ECPrivateKey* key,
+ DigestAlgorithm alg,
const std::string& domain,
uint32 serial_number,
base::Time not_valid_before,
base::Time not_valid_after,
std::string* der_cert) {
- NOTIMPLEMENTED();
- return false;
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ // Create certificate.
+ crypto::ScopedOpenSSL<X509, X509_free> cert(
+ CreateCertificate(key->key(),
+ alg,
+ "CN=anonymous.invalid",
+ serial_number,
+ not_valid_before,
+ not_valid_after));
+ if (!cert.get())
+ return false;
+
+ // Add TLS-Channel-ID extension to the certificate before signing it.
+ // The value must be stored DER-encoded, as a ASN.1 IA5String.
+ crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free> domain_ia5(
+ ASN1_IA5STRING_new());
+ if (!domain_ia5.get() ||
+ !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size()))
+ return false;
+
+ std::string domain_der;
+ int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL);
+ if (domain_der_len < 0)
+ return false;
+
+ domain_der.resize(domain_der_len);
+ unsigned char* domain_der_data =
+ reinterpret_cast<unsigned char*>(&domain_der[0]);
+ if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0)
+ return false;
+
+ crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free> domain_str(
+ ASN1_OCTET_STRING_new());
+ if (!domain_str.get() ||
+ !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size()))
+ return false;
+
+ crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free> ext(
+ X509_EXTENSION_create_by_OBJ(
+ NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get()));
+ if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) {
+ return false;
+ }
+
+ // Sign and encode it.
+ return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert);
}
bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
+ DigestAlgorithm alg,
const std::string& common_name,
uint32 serial_number,
base::Time not_valid_before,
base::Time not_valid_after,
std::string* der_encoded) {
- NOTIMPLEMENTED();
- return false;
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+ crypto::ScopedOpenSSL<X509, X509_free> cert(
+ CreateCertificate(key->key(),
+ alg,
+ common_name,
+ serial_number,
+ not_valid_before,
+ not_valid_after));
+ if (!cert.get())
+ return false;
+
+ return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded);
}
bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
diff --git a/chromium/net/cert/x509_util_openssl_unittest.cc b/chromium/net/cert/x509_util_openssl_unittest.cc
index f237602ecbd..c99f811705d 100644
--- a/chromium/net/cert/x509_util_openssl_unittest.cc
+++ b/chromium/net/cert/x509_util_openssl_unittest.cc
@@ -4,12 +4,89 @@
#include "base/memory/scoped_ptr.h"
#include "crypto/ec_private_key.h"
+#include "crypto/openssl_util.h"
#include "net/cert/x509_util.h"
#include "net/cert/x509_util_openssl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
+namespace {
+
+// Verify that a given certificate was signed with the private key corresponding
+// to a given public key.
+// |der_cert| is the DER-encoded X.509 certificate.
+// |der_spki| is the DER-encoded public key of the signer.
+void VerifyCertificateSignature(const std::string& der_cert,
+ const std::vector<uint8>& der_spki) {
+ const unsigned char* cert_data =
+ reinterpret_cast<const unsigned char*>(der_cert.data());
+ int cert_data_len = static_cast<int>(der_cert.size());
+ crypto::ScopedOpenSSL<X509, X509_free> cert(
+ d2i_X509(NULL, &cert_data, cert_data_len));
+ ASSERT_TRUE(cert.get());
+
+ // NOTE: SignatureVerifier wants the DER-encoded ASN.1 AlgorithmIdentifier
+ // but there is no OpenSSL API to extract it from an X509 object (!?)
+ // Use X509_verify() directly instead, which takes an EVP_PKEY.
+ const unsigned char* pub_key_data = &der_spki.front();
+ int pub_key_len = static_cast<int>(der_spki.size());
+ crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> pub_key(
+ d2i_PUBKEY(NULL, &pub_key_data, pub_key_len));
+ ASSERT_TRUE(pub_key.get());
+
+ // NOTE: X509_verify() returns 1 in case of succes, 0 or -1 on error.
+ EXPECT_EQ(1, X509_verify(cert.get(), pub_key.get()));
+}
+
+// Verify the attributes of a domain-bound certificate.
+// |domain| is the bound domain name.
+// |der_cert| is the DER-encoded X.509 certificate.
+void VerifyDomainBoundCert(const std::string& domain,
+ const std::string& der_cert) {
+ // Origin Bound Cert OID.
+ static const char oid_string[] = "1.3.6.1.4.1.11129.2.1.6";
+ crypto::ScopedOpenSSL<ASN1_OBJECT, ASN1_OBJECT_free> oid_obj(
+ OBJ_txt2obj(oid_string, 0));
+ ASSERT_TRUE(oid_obj.get());
+
+ const unsigned char* cert_data =
+ reinterpret_cast<const unsigned char*>(der_cert.data());
+ int cert_data_len = static_cast<int>(der_cert.size());
+ crypto::ScopedOpenSSL<X509, X509_free> cert(
+ d2i_X509(NULL, &cert_data, cert_data_len));
+ ASSERT_TRUE(cert.get());
+
+ // Find the extension.
+ int ext_pos = X509_get_ext_by_OBJ(cert.get(), oid_obj.get(), -1);
+ ASSERT_NE(-1, ext_pos);
+ X509_EXTENSION* ext = X509_get_ext(cert.get(), ext_pos);
+ ASSERT_TRUE(ext);
+
+ // Check its value, it must be an ASN.1 IA5STRING
+ // Which means <tag> <length> <domain>, with:
+ // <tag> == 22
+ // <length> is the domain length, a single byte for short forms.
+ // <domain> are the domain characters.
+ // See http://en.wikipedia.org/wiki/X.690
+ ASN1_STRING* value_asn1 = X509_EXTENSION_get_data(ext);
+ ASSERT_TRUE(value_asn1);
+ std::string value_str(reinterpret_cast<const char*>(value_asn1->data),
+ value_asn1->length);
+
+ // Check that the domain size is small enough for short form.
+ ASSERT_LE(domain.size(), 127U) << "Domain is too long!";
+ std::string value_expected;
+ value_expected.resize(2);
+ value_expected[0] = 22;
+ value_expected[1] = static_cast<char>(domain.size());
+ value_expected += domain;
+
+ EXPECT_EQ(value_expected, value_str);
+}
+
+} // namespace
+
TEST(X509UtilOpenSSLTest, IsSupportedValidityRange) {
base::Time now = base::Time::Now();
EXPECT_TRUE(x509_util::IsSupportedValidityRange(now, now));
@@ -35,23 +112,29 @@ TEST(X509UtilOpenSSLTest, IsSupportedValidityRange) {
EXPECT_FALSE(x509_util::IsSupportedValidityRange(too_late, too_late));
}
-// For OpenSSL, x509_util::CreateDomainBoundCertEC() is not yet implemented
-// and should return false. This unit test ensures that a stub implementation
-// is present.
-TEST(X509UtilOpenSSLTest, CreateDomainBoundCertNotImplemented) {
+TEST(X509UtilOpenSSLTest, CreateDomainBoundCertEC) {
+ // Create a sample ASCII weborigin.
std::string domain = "weborigin.com";
base::Time now = base::Time::Now();
+
scoped_ptr<crypto::ECPrivateKey> private_key(
crypto::ECPrivateKey::Create());
std::string der_cert;
- EXPECT_FALSE(x509_util::CreateDomainBoundCertEC(
- private_key.get(),
- domain, 1,
- now,
- now + base::TimeDelta::FromDays(1),
- &der_cert));
- EXPECT_TRUE(der_cert.empty());
+ ASSERT_TRUE(
+ x509_util::CreateDomainBoundCertEC(private_key.get(),
+ x509_util::DIGEST_SHA1,
+ domain,
+ 1,
+ now,
+ now + base::TimeDelta::FromDays(1),
+ &der_cert));
+
+ VerifyDomainBoundCert(domain, der_cert);
+ // signature_verifier_win and signature_verifier_mac can't handle EC certs.
+ std::vector<uint8> spki;
+ ASSERT_TRUE(private_key->ExportPublicKey(&spki));
+ VerifyCertificateSignature(der_cert, spki);
}
} // namespace net
diff --git a/chromium/net/cert/x509_util_unittest.cc b/chromium/net/cert/x509_util_unittest.cc
index cc13d96f1bf..716f61e5912 100644
--- a/chromium/net/cert/x509_util_unittest.cc
+++ b/chromium/net/cert/x509_util_unittest.cc
@@ -52,33 +52,33 @@ TEST(X509UtilTest, SortClientCertificates) {
ASSERT_FALSE(certs[5].get());
}
-#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
-// This test creates a self-signed cert from a private key and then verify the
+// This test creates a self-signed cert and a private key and then verifies the
// content of the certificate.
-TEST(X509UtilTest, CreateSelfSigned) {
- scoped_ptr<crypto::RSAPrivateKey> private_key(
- crypto::RSAPrivateKey::Create(1024));
-
- ASSERT_TRUE(private_key.get());
+TEST(X509UtilTest, CreateKeyAndSelfSigned) {
+ scoped_ptr<crypto::RSAPrivateKey> private_key;
std::string der_cert;
- ASSERT_TRUE(x509_util::CreateSelfSignedCert(
- private_key.get(),
+ ASSERT_TRUE(x509_util::CreateKeyAndSelfSignedCert(
"CN=subject",
1,
base::Time::Now(),
base::Time::Now() + base::TimeDelta::FromDays(1),
+ &private_key,
&der_cert));
+ ASSERT_TRUE(private_key.get());
+
scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes(
der_cert.data(), der_cert.size()));
ASSERT_TRUE(cert.get());
EXPECT_EQ("subject", cert->subject().GetDisplayName());
EXPECT_FALSE(cert->HasExpired());
+}
- cert = NULL;
-
+// This test creates a self-signed cert from a private key and then verifies the
+// content of the certificate.
+TEST(X509UtilTest, CreateSelfSigned) {
const uint8 private_key_info[] = {
0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
@@ -166,24 +166,27 @@ TEST(X509UtilTest, CreateSelfSigned) {
input.resize(sizeof(private_key_info));
memcpy(&input.front(), private_key_info, sizeof(private_key_info));
- private_key.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+ scoped_ptr<crypto::RSAPrivateKey> private_key(
+ crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
ASSERT_TRUE(private_key.get());
+ std::string der_cert;
ASSERT_TRUE(x509_util::CreateSelfSignedCert(
private_key.get(),
+ x509_util::DIGEST_SHA1,
"CN=subject",
1,
base::Time::Now(),
base::Time::Now() + base::TimeDelta::FromDays(1),
&der_cert));
- cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
+ scoped_refptr<X509Certificate> cert =
+ X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
ASSERT_TRUE(cert.get());
EXPECT_EQ("subject", cert->subject().GetDisplayName());
EXPECT_FALSE(cert->HasExpired());
}
-#endif
} // namespace x509_util
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc
index 65723ff20a6..15c7143a608 100644
--- a/chromium/net/cookies/cookie_monster.cc
+++ b/chromium/net/cookies/cookie_monster.cc
@@ -104,9 +104,8 @@ const size_t CookieMonster::kPurgeCookies = 300;
const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
const size_t CookieMonster::kDomainCookiesQuotaMedium = 50;
const size_t CookieMonster::kDomainCookiesQuotaHigh =
- CookieMonster::kDomainMaxCookies - CookieMonster::kDomainPurgeCookies
- - CookieMonster::kDomainCookiesQuotaLow
- - CookieMonster::kDomainCookiesQuotaMedium;
+ kDomainMaxCookies - kDomainPurgeCookies
+ - kDomainCookiesQuotaLow - kDomainCookiesQuotaMedium;
const int CookieMonster::kSafeFromGlobalPurgeDays = 30;
@@ -202,16 +201,6 @@ struct CookieSignature {
std::string path;
};
-// Determine the cookie domain to use for setting the specified cookie.
-bool GetCookieDomain(const GURL& url,
- const ParsedCookie& pc,
- std::string* result) {
- std::string domain_string;
- if (pc.HasDomain())
- domain_string = pc.Domain();
- return cookie_util::GetCookieDomainWithString(url, domain_string, result);
-}
-
// For a CookieItVector iterator range [|it_begin|, |it_end|),
// sorts the first |num_sort| + 1 elements by LastAccessDate().
// The + 1 element exists so for any interval of length <= |num_sort| starting
@@ -331,8 +320,7 @@ CookieMonster::CookieMonster(PersistentCookieStore* store, Delegate* delegate)
delegate_(delegate),
last_statistic_record_time_(Time::Now()),
keep_expired_cookies_(false),
- persist_session_cookies_(false),
- priority_aware_garbage_collection_(false) {
+ persist_session_cookies_(false) {
InitializeHistograms();
SetDefaultCookieableSchemes();
}
@@ -348,8 +336,7 @@ CookieMonster::CookieMonster(PersistentCookieStore* store,
delegate_(delegate),
last_statistic_record_time_(base::Time::Now()),
keep_expired_cookies_(false),
- persist_session_cookies_(false),
- priority_aware_garbage_collection_(false) {
+ persist_session_cookies_(false) {
InitializeHistograms();
SetDefaultCookieableSchemes();
}
@@ -410,13 +397,12 @@ void CookieMonster::CookieMonsterTask::InvokeCallback(base::Closure callback) {
callback.Run();
} else {
thread_->PostTask(FROM_HERE, base::Bind(
- &CookieMonster::CookieMonsterTask::InvokeCallback, this, callback));
+ &CookieMonsterTask::InvokeCallback, this, callback));
}
}
// Task class for SetCookieWithDetails call.
-class CookieMonster::SetCookieWithDetailsTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
public:
SetCookieWithDetailsTask(CookieMonster* cookie_monster,
const GURL& url,
@@ -428,7 +414,7 @@ class CookieMonster::SetCookieWithDetailsTask
bool secure,
bool http_only,
CookiePriority priority,
- const CookieMonster::SetCookiesCallback& callback)
+ const SetCookiesCallback& callback)
: CookieMonsterTask(cookie_monster),
url_(url),
name_(name),
@@ -442,7 +428,7 @@ class CookieMonster::SetCookieWithDetailsTask
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask:
+ // CookieMonsterTask:
virtual void Run() OVERRIDE;
protected:
@@ -458,7 +444,7 @@ class CookieMonster::SetCookieWithDetailsTask
bool secure_;
bool http_only_;
CookiePriority priority_;
- CookieMonster::SetCookiesCallback callback_;
+ SetCookiesCallback callback_;
DISALLOW_COPY_AND_ASSIGN(SetCookieWithDetailsTask);
};
@@ -468,29 +454,28 @@ void CookieMonster::SetCookieWithDetailsTask::Run() {
SetCookieWithDetails(url_, name_, value_, domain_, path_,
expiration_time_, secure_, http_only_, priority_);
if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::SetCookiesCallback::Run,
+ this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
base::Unretained(&callback_), success));
}
}
// Task class for GetAllCookies call.
-class CookieMonster::GetAllCookiesTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::GetAllCookiesTask : public CookieMonsterTask {
public:
GetAllCookiesTask(CookieMonster* cookie_monster,
- const CookieMonster::GetCookieListCallback& callback)
+ const GetCookieListCallback& callback)
: CookieMonsterTask(cookie_monster),
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask
+ // CookieMonsterTask
virtual void Run() OVERRIDE;
protected:
virtual ~GetAllCookiesTask() {}
private:
- CookieMonster::GetCookieListCallback callback_;
+ GetCookieListCallback callback_;
DISALLOW_COPY_AND_ASSIGN(GetAllCookiesTask);
};
@@ -498,27 +483,27 @@ class CookieMonster::GetAllCookiesTask
void CookieMonster::GetAllCookiesTask::Run() {
if (!callback_.is_null()) {
CookieList cookies = this->cookie_monster()->GetAllCookies();
- this->InvokeCallback(base::Bind(&CookieMonster::GetCookieListCallback::Run,
+ this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
base::Unretained(&callback_), cookies));
}
}
// Task class for GetAllCookiesForURLWithOptions call.
class CookieMonster::GetAllCookiesForURLWithOptionsTask
- : public CookieMonster::CookieMonsterTask {
+ : public CookieMonsterTask {
public:
GetAllCookiesForURLWithOptionsTask(
CookieMonster* cookie_monster,
const GURL& url,
const CookieOptions& options,
- const CookieMonster::GetCookieListCallback& callback)
+ const GetCookieListCallback& callback)
: CookieMonsterTask(cookie_monster),
url_(url),
options_(options),
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask:
+ // CookieMonsterTask:
virtual void Run() OVERRIDE;
protected:
@@ -527,7 +512,7 @@ class CookieMonster::GetAllCookiesForURLWithOptionsTask
private:
GURL url_;
CookieOptions options_;
- CookieMonster::GetCookieListCallback callback_;
+ GetCookieListCallback callback_;
DISALLOW_COPY_AND_ASSIGN(GetAllCookiesForURLWithOptionsTask);
};
@@ -536,56 +521,109 @@ void CookieMonster::GetAllCookiesForURLWithOptionsTask::Run() {
if (!callback_.is_null()) {
CookieList cookies = this->cookie_monster()->
GetAllCookiesForURLWithOptions(url_, options_);
- this->InvokeCallback(base::Bind(&CookieMonster::GetCookieListCallback::Run,
+ this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
base::Unretained(&callback_), cookies));
}
}
-// Task class for DeleteAll call.
-class CookieMonster::DeleteAllTask : public CookieMonster::CookieMonsterTask {
+template <typename Result> struct CallbackType {
+ typedef base::Callback<void(Result)> Type;
+};
+
+template <> struct CallbackType<void> {
+ typedef base::Closure Type;
+};
+
+// Base task class for Delete*Task.
+template <typename Result>
+class CookieMonster::DeleteTask : public CookieMonsterTask {
public:
- DeleteAllTask(CookieMonster* cookie_monster,
- const CookieMonster::DeleteCallback& callback)
+ DeleteTask(CookieMonster* cookie_monster,
+ const typename CallbackType<Result>::Type& callback)
: CookieMonsterTask(cookie_monster),
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask:
+ // CookieMonsterTask:
virtual void Run() OVERRIDE;
+ private:
+ // Runs the delete task and returns a result.
+ virtual Result RunDeleteTask() = 0;
+ base::Closure RunDeleteTaskAndBindCallback();
+ void FlushDone(const base::Closure& callback);
+
+ typename CallbackType<Result>::Type callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteTask);
+};
+
+template <typename Result>
+base::Closure CookieMonster::DeleteTask<Result>::
+RunDeleteTaskAndBindCallback() {
+ Result result = RunDeleteTask();
+ if (callback_.is_null())
+ return base::Closure();
+ return base::Bind(callback_, result);
+}
+
+template <>
+base::Closure CookieMonster::DeleteTask<void>::RunDeleteTaskAndBindCallback() {
+ RunDeleteTask();
+ return callback_;
+}
+
+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) {
+ if (!callback.is_null()) {
+ this->InvokeCallback(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:
+ virtual int RunDeleteTask() OVERRIDE;
+
protected:
virtual ~DeleteAllTask() {}
private:
- CookieMonster::DeleteCallback callback_;
-
DISALLOW_COPY_AND_ASSIGN(DeleteAllTask);
};
-void CookieMonster::DeleteAllTask::Run() {
- int num_deleted = this->cookie_monster()->DeleteAll(true);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::DeleteCallback::Run,
- base::Unretained(&callback_), num_deleted));
- }
+int CookieMonster::DeleteAllTask::RunDeleteTask() {
+ return this->cookie_monster()->DeleteAll(true);
}
// Task class for DeleteAllCreatedBetween call.
-class CookieMonster::DeleteAllCreatedBetweenTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::DeleteAllCreatedBetweenTask : public DeleteTask<int> {
public:
DeleteAllCreatedBetweenTask(CookieMonster* cookie_monster,
const Time& delete_begin,
const Time& delete_end,
- const CookieMonster::DeleteCallback& callback)
- : CookieMonsterTask(cookie_monster),
+ const DeleteCallback& callback)
+ : DeleteTask<int>(cookie_monster, callback),
delete_begin_(delete_begin),
- delete_end_(delete_end),
- callback_(callback) {
+ delete_end_(delete_end) {
}
- // CookieMonster::CookieMonsterTask:
- virtual void Run() OVERRIDE;
+ // DeleteTask:
+ virtual int RunDeleteTask() OVERRIDE;
protected:
virtual ~DeleteAllCreatedBetweenTask() {}
@@ -593,72 +631,59 @@ class CookieMonster::DeleteAllCreatedBetweenTask
private:
Time delete_begin_;
Time delete_end_;
- CookieMonster::DeleteCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenTask);
};
-void CookieMonster::DeleteAllCreatedBetweenTask::Run() {
- int num_deleted = this->cookie_monster()->
+int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() {
+ return this->cookie_monster()->
DeleteAllCreatedBetween(delete_begin_, delete_end_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::DeleteCallback::Run,
- base::Unretained(&callback_), num_deleted));
- }
}
// Task class for DeleteAllForHost call.
-class CookieMonster::DeleteAllForHostTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::DeleteAllForHostTask : public DeleteTask<int> {
public:
DeleteAllForHostTask(CookieMonster* cookie_monster,
const GURL& url,
- const CookieMonster::DeleteCallback& callback)
- : CookieMonsterTask(cookie_monster),
- url_(url),
- callback_(callback) {
+ const DeleteCallback& callback)
+ : DeleteTask<int>(cookie_monster, callback),
+ url_(url) {
}
- // CookieMonster::CookieMonsterTask:
- virtual void Run() OVERRIDE;
+ // DeleteTask:
+ virtual int RunDeleteTask() OVERRIDE;
protected:
virtual ~DeleteAllForHostTask() {}
private:
GURL url_;
- CookieMonster::DeleteCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteAllForHostTask);
};
-void CookieMonster::DeleteAllForHostTask::Run() {
- int num_deleted = this->cookie_monster()->DeleteAllForHost(url_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::DeleteCallback::Run,
- base::Unretained(&callback_), num_deleted));
- }
+int CookieMonster::DeleteAllForHostTask::RunDeleteTask() {
+ return this->cookie_monster()->DeleteAllForHost(url_);
}
// Task class for DeleteAllCreatedBetweenForHost call.
class CookieMonster::DeleteAllCreatedBetweenForHostTask
- : public CookieMonster::CookieMonsterTask {
+ : public DeleteTask<int> {
public:
DeleteAllCreatedBetweenForHostTask(
CookieMonster* cookie_monster,
Time delete_begin,
Time delete_end,
const GURL& url,
- const CookieMonster::DeleteCallback& callback)
- : CookieMonsterTask(cookie_monster),
+ const DeleteCallback& callback)
+ : DeleteTask<int>(cookie_monster, callback),
delete_begin_(delete_begin),
delete_end_(delete_end),
- url_(url),
- callback_(callback) {
+ url_(url) {
}
- // CookieMonster::CookieMonsterTask:
- virtual void Run() OVERRIDE;
+ // DeleteTask:
+ virtual int RunDeleteTask() OVERRIDE;
protected:
virtual ~DeleteAllCreatedBetweenForHostTask() {}
@@ -667,62 +692,49 @@ class CookieMonster::DeleteAllCreatedBetweenForHostTask
Time delete_begin_;
Time delete_end_;
GURL url_;
- CookieMonster::DeleteCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenForHostTask);
};
-void CookieMonster::DeleteAllCreatedBetweenForHostTask::Run() {
- int num_deleted = this->cookie_monster()->DeleteAllCreatedBetweenForHost(
+int CookieMonster::DeleteAllCreatedBetweenForHostTask::RunDeleteTask() {
+ return this->cookie_monster()->DeleteAllCreatedBetweenForHost(
delete_begin_, delete_end_, url_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::DeleteCallback::Run,
- base::Unretained(&callback_), num_deleted));
- }
}
// Task class for DeleteCanonicalCookie call.
-class CookieMonster::DeleteCanonicalCookieTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<bool> {
public:
DeleteCanonicalCookieTask(CookieMonster* cookie_monster,
const CanonicalCookie& cookie,
- const CookieMonster::DeleteCookieCallback& callback)
- : CookieMonsterTask(cookie_monster),
- cookie_(cookie),
- callback_(callback) {
+ const DeleteCookieCallback& callback)
+ : DeleteTask<bool>(cookie_monster, callback),
+ cookie_(cookie) {
}
- // CookieMonster::CookieMonsterTask:
- virtual void Run() OVERRIDE;
+ // DeleteTask:
+ virtual bool RunDeleteTask() OVERRIDE;
protected:
virtual ~DeleteCanonicalCookieTask() {}
private:
CanonicalCookie cookie_;
- CookieMonster::DeleteCookieCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask);
};
-void CookieMonster::DeleteCanonicalCookieTask::Run() {
- bool result = this->cookie_monster()->DeleteCanonicalCookie(cookie_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::DeleteCookieCallback::Run,
- base::Unretained(&callback_), result));
- }
+bool CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
+ return this->cookie_monster()->DeleteCanonicalCookie(cookie_);
}
// Task class for SetCookieWithOptions call.
-class CookieMonster::SetCookieWithOptionsTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask {
public:
SetCookieWithOptionsTask(CookieMonster* cookie_monster,
const GURL& url,
const std::string& cookie_line,
const CookieOptions& options,
- const CookieMonster::SetCookiesCallback& callback)
+ const SetCookiesCallback& callback)
: CookieMonsterTask(cookie_monster),
url_(url),
cookie_line_(cookie_line),
@@ -730,7 +742,7 @@ class CookieMonster::SetCookieWithOptionsTask
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask:
+ // CookieMonsterTask:
virtual void Run() OVERRIDE;
protected:
@@ -740,7 +752,7 @@ class CookieMonster::SetCookieWithOptionsTask
GURL url_;
std::string cookie_line_;
CookieOptions options_;
- CookieMonster::SetCookiesCallback callback_;
+ SetCookiesCallback callback_;
DISALLOW_COPY_AND_ASSIGN(SetCookieWithOptionsTask);
};
@@ -749,26 +761,25 @@ void CookieMonster::SetCookieWithOptionsTask::Run() {
bool result = this->cookie_monster()->
SetCookieWithOptions(url_, cookie_line_, options_);
if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::SetCookiesCallback::Run,
+ this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
base::Unretained(&callback_), result));
}
}
// Task class for GetCookiesWithOptions call.
-class CookieMonster::GetCookiesWithOptionsTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::GetCookiesWithOptionsTask : public CookieMonsterTask {
public:
GetCookiesWithOptionsTask(CookieMonster* cookie_monster,
const GURL& url,
const CookieOptions& options,
- const CookieMonster::GetCookiesCallback& callback)
+ const GetCookiesCallback& callback)
: CookieMonsterTask(cookie_monster),
url_(url),
options_(options),
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask:
+ // CookieMonsterTask:
virtual void Run() OVERRIDE;
protected:
@@ -777,7 +788,7 @@ class CookieMonster::GetCookiesWithOptionsTask
private:
GURL url_;
CookieOptions options_;
- CookieMonster::GetCookiesCallback callback_;
+ GetCookiesCallback callback_;
DISALLOW_COPY_AND_ASSIGN(GetCookiesWithOptionsTask);
};
@@ -786,26 +797,25 @@ void CookieMonster::GetCookiesWithOptionsTask::Run() {
std::string cookie = this->cookie_monster()->
GetCookiesWithOptions(url_, options_);
if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::GetCookiesCallback::Run,
+ this->InvokeCallback(base::Bind(&GetCookiesCallback::Run,
base::Unretained(&callback_), cookie));
}
}
// Task class for DeleteCookie call.
-class CookieMonster::DeleteCookieTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::DeleteCookieTask : public DeleteTask<void> {
public:
DeleteCookieTask(CookieMonster* cookie_monster,
const GURL& url,
const std::string& cookie_name,
const base::Closure& callback)
- : CookieMonsterTask(cookie_monster),
+ : DeleteTask<void>(cookie_monster, callback),
url_(url),
- cookie_name_(cookie_name),
- callback_(callback) { }
+ cookie_name_(cookie_name) {
+ }
- // CookieMonster::CookieMonsterTask:
- virtual void Run() OVERRIDE;
+ // DeleteTask:
+ virtual void RunDeleteTask() OVERRIDE;
protected:
virtual ~DeleteCookieTask() {}
@@ -813,61 +823,50 @@ class CookieMonster::DeleteCookieTask
private:
GURL url_;
std::string cookie_name_;
- base::Closure callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteCookieTask);
};
-void CookieMonster::DeleteCookieTask::Run() {
+void CookieMonster::DeleteCookieTask::RunDeleteTask() {
this->cookie_monster()->DeleteCookie(url_, cookie_name_);
- if (!callback_.is_null()) {
- this->InvokeCallback(callback_);
- }
}
// Task class for DeleteSessionCookies call.
-class CookieMonster::DeleteSessionCookiesTask
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::DeleteSessionCookiesTask : public DeleteTask<int> {
public:
DeleteSessionCookiesTask(CookieMonster* cookie_monster,
- const CookieMonster::DeleteCallback& callback)
- : CookieMonsterTask(cookie_monster), callback_(callback) {
+ const DeleteCallback& callback)
+ : DeleteTask<int>(cookie_monster, callback) {
}
- // CookieMonster::CookieMonsterTask:
- virtual void Run() OVERRIDE;
+ // DeleteTask:
+ virtual int RunDeleteTask() OVERRIDE;
protected:
virtual ~DeleteSessionCookiesTask() {}
private:
- CookieMonster::DeleteCallback callback_;
DISALLOW_COPY_AND_ASSIGN(DeleteSessionCookiesTask);
};
-void CookieMonster::DeleteSessionCookiesTask::Run() {
- int num_deleted = this->cookie_monster()->DeleteSessionCookies();
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&CookieMonster::DeleteCallback::Run,
- base::Unretained(&callback_), num_deleted));
- }
+int CookieMonster::DeleteSessionCookiesTask::RunDeleteTask() {
+ return this->cookie_monster()->DeleteSessionCookies();
}
// Task class for HasCookiesForETLDP1Task call.
-class CookieMonster::HasCookiesForETLDP1Task
- : public CookieMonster::CookieMonsterTask {
+class CookieMonster::HasCookiesForETLDP1Task : public CookieMonsterTask {
public:
HasCookiesForETLDP1Task(
CookieMonster* cookie_monster,
const std::string& etldp1,
- const CookieMonster::HasCookiesForETLDP1Callback& callback)
+ const HasCookiesForETLDP1Callback& callback)
: CookieMonsterTask(cookie_monster),
etldp1_(etldp1),
callback_(callback) {
}
- // CookieMonster::CookieMonsterTask:
+ // CookieMonsterTask:
virtual void Run() OVERRIDE;
protected:
@@ -875,7 +874,7 @@ class CookieMonster::HasCookiesForETLDP1Task
private:
std::string etldp1_;
- CookieMonster::HasCookiesForETLDP1Callback callback_;
+ HasCookiesForETLDP1Callback callback_;
DISALLOW_COPY_AND_ASSIGN(HasCookiesForETLDP1Task);
};
@@ -884,7 +883,7 @@ void CookieMonster::HasCookiesForETLDP1Task::Run() {
bool result = this->cookie_monster()->HasCookiesForETLDP1(etldp1_);
if (!callback_.is_null()) {
this->InvokeCallback(
- base::Bind(&CookieMonster::HasCookiesForETLDP1Callback::Run,
+ base::Bind(&HasCookiesForETLDP1Callback::Run,
base::Unretained(&callback_), result));
}
}
@@ -1408,13 +1407,6 @@ void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
persist_session_cookies_ = persist_session_cookies;
}
-// This function must be called before the CookieMonster is used.
-void CookieMonster::SetPriorityAwareGarbageCollection(
- bool priority_aware_garbage_collection) {
- DCHECK(!initialized_);
- priority_aware_garbage_collection_ = priority_aware_garbage_collection;
-}
-
void CookieMonster::SetForceKeepSessionState() {
if (store_.get()) {
store_->SetForceKeepSessionState();
@@ -1463,21 +1455,31 @@ void CookieMonster::OnKeyLoaded(const std::string& key,
StoreLoadedCookies(cookies);
std::deque<scoped_refptr<CookieMonsterTask> > tasks_pending_for_key;
- {
- base::AutoLock autolock(lock_);
- keys_loaded_.insert(key);
- std::map<std::string, std::deque<scoped_refptr<CookieMonsterTask> > >
- ::iterator it = tasks_pending_for_key_.find(key);
- if (it == tasks_pending_for_key_.end())
- return;
- it->second.swap(tasks_pending_for_key);
- tasks_pending_for_key_.erase(it);
- }
- while (!tasks_pending_for_key.empty()) {
- scoped_refptr<CookieMonsterTask> task = tasks_pending_for_key.front();
- task->Run();
- tasks_pending_for_key.pop_front();
+ // 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);
+ }
+
+ while (!tasks_pending_for_key.empty()) {
+ scoped_refptr<CookieMonsterTask> task = tasks_pending_for_key.front();
+ task->Run();
+ tasks_pending_for_key.pop_front();
+ }
}
}
@@ -1666,9 +1668,9 @@ int CookieMonster::TrimDuplicateCookiesForKey(
// Note: file must be the last scheme.
const char* CookieMonster::kDefaultCookieableSchemes[] =
- { "http", "https", "file" };
+ { "http", "https", "ws", "wss", "file" };
const int CookieMonster::kDefaultCookieableSchemesCount =
- arraysize(CookieMonster::kDefaultCookieableSchemes);
+ arraysize(kDefaultCookieableSchemes);
void CookieMonster::SetDefaultCookieableSchemes() {
int num_schemes = default_enable_file_scheme_ ?
@@ -1775,7 +1777,7 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
cookies_.insert(CookieMap::value_type(key, cc));
if (delegate_.get()) {
delegate_->OnCookieChanged(
- *cc, false, CookieMonster::Delegate::CHANGE_COOKIE_EXPLICIT);
+ *cc, false, Delegate::CHANGE_COOKIE_EXPLICIT);
}
return inserted;
@@ -1947,11 +1949,6 @@ int CookieMonster::GarbageCollect(const Time& current,
for (int i = 0; i < 3 && purge_goal > 0; ++i) {
accumulated_quota += quota[i];
- // If we are not using priority, only do Round 3. This reproduces the
- // old way of indiscriminately purging least-recently accessed cookies.
- if (!priority_aware_garbage_collection_ && i < 2)
- continue;
-
size_t num_considered = it_bdd[i + 1] - it_purge_begin;
if (num_considered <= accumulated_quota)
continue;
@@ -2050,8 +2047,8 @@ int CookieMonster::GarbageCollectExpired(
int CookieMonster::GarbageCollectDeleteRange(
const Time& current,
DeletionCause cause,
- CookieMonster::CookieItVector::iterator it_begin,
- CookieMonster::CookieItVector::iterator it_end) {
+ CookieItVector::iterator it_begin,
+ CookieItVector::iterator it_end) {
for (CookieItVector::iterator it = it_begin; it != it_end; it++) {
histogram_evicted_last_access_minutes_->Add(
(current - (*it)->second->LastAccessDate()).InMinutes());
diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h
index 1df616cd6d9..de00319fb4b 100644
--- a/chromium/net/cookies/cookie_monster.h
+++ b/chromium/net/cookies/cookie_monster.h
@@ -288,11 +288,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
// (i.e. as part of the instance initialization process).
void SetPersistSessionCookies(bool persist_session_cookies);
- // Enables the new garbage collection algorithm where domain cookie eviction
- // uses cookie priorities to decide which cookies to purge and which to keep.
- void SetPriorityAwareGarbageCollection(
- bool priority_aware_garbage_collection);
-
// Debugging method to perform various validation checks on the map.
// Currently just checking that there are no null CanonicalCookie pointers
// in the map.
@@ -311,6 +306,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
private:
// For queueing the cookie monster calls.
class CookieMonsterTask;
+ template <typename Result> class DeleteTask;
class DeleteAllCreatedBetweenTask;
class DeleteAllCreatedBetweenForHostTask;
class DeleteAllForHostTask;
@@ -679,7 +675,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
bool keep_expired_cookies_;
bool persist_session_cookies_;
- bool priority_aware_garbage_collection_;
// Static setting for whether or not file scheme cookies are allows when
// a new CookieMonster is created, or the accepted schemes on a CookieMonster
diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc
index 2bfe9ee9978..69d98a1862a 100644
--- a/chromium/net/cookies/cookie_monster_unittest.cc
+++ b/chromium/net/cookies/cookie_monster_unittest.cc
@@ -50,7 +50,10 @@ class NewMockPersistentCookieStore
MOCK_METHOD1(AddCookie, void(const CanonicalCookie& cc));
MOCK_METHOD1(UpdateCookieAccessTime, void(const CanonicalCookie& cc));
MOCK_METHOD1(DeleteCookie, void(const CanonicalCookie& cc));
- MOCK_METHOD1(Flush, void(const base::Closure& callback));
+ virtual void Flush(const base::Closure& callback) {
+ if (!callback.is_null())
+ base::MessageLoop::current()->PostTask(FROM_HERE, callback);
+ }
MOCK_METHOD0(SetForceKeepSessionState, void());
private:
@@ -89,7 +92,6 @@ struct CookieMonsterTestTraits {
static const bool is_cookie_monster = true;
static const bool supports_http_only = true;
- static const bool supports_cookies_with_info = true;
static const bool supports_non_dotted_domains = true;
static const bool supports_trailing_dots = true;
static const bool filters_schemes = true;
@@ -570,7 +572,6 @@ class CookieMonsterTest : public CookieStoreTest<CookieMonsterTestTraits> {
DCHECK_EQ(70U, CookieMonster::kDomainCookiesQuotaHigh);
scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- cm->SetPriorityAwareGarbageCollection(true);
// Each test case adds 181 cookies, so 31 cookies are evicted.
// Cookie same priority, repeated for each priority.
@@ -1097,16 +1098,13 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
MockGetCookiesCallback get_cookies_callback;
MockSetCookiesCallback set_cookies_callback;
- MockClosure delete_cookie_callback;
MockGetCookiesCallback get_cookies_callback_deferred;
EXPECT_CALL(*this, Begin()).WillOnce(testing::DoAll(
GetCookiesAction(
&cookie_monster(), url_google_, &get_cookies_callback),
SetCookieAction(
- &cookie_monster(), url_google_, "A=B", &set_cookies_callback),
- DeleteCookieAction(
- &cookie_monster(), url_google_, "A", &delete_cookie_callback)));
+ &cookie_monster(), url_google_, "A=B", &set_cookies_callback)));
ExpectLoadCall();
ExpectLoadForKeyCall("google.izzle", false);
Begin();
@@ -1115,10 +1113,9 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce(
GetCookiesAction(
&cookie_monster(), url_google_, &get_cookies_callback_deferred));
- EXPECT_CALL(get_cookies_callback_deferred, Invoke("X=1")).WillOnce(
- QuitCurrentMessageLoop());
EXPECT_CALL(set_cookies_callback, Invoke(true));
- EXPECT_CALL(delete_cookie_callback, Invoke());
+ EXPECT_CALL(get_cookies_callback_deferred, Invoke("A=B; X=1")).WillOnce(
+ QuitCurrentMessageLoop());
CompleteLoadingAndWait();
}
diff --git a/chromium/net/data/file_stream_unittest/red.png b/chromium/net/data/file_stream_unittest/red.png
new file mode 100644
index 00000000000..08061414f7a
--- /dev/null
+++ b/chromium/net/data/file_stream_unittest/red.png
Binary files differ
diff --git a/chromium/net/data/ftp/dir-listing-ls-32 b/chromium/net/data/ftp/dir-listing-ls-32
new file mode 100644
index 00000000000..aa21f24570c
--- /dev/null
+++ b/chromium/net/data/ftp/dir-listing-ls-32
@@ -0,0 +1,13 @@
+
+total 1
+drwxrwxr-x 1 500 244 660 Jan 1 00:0 bin
+drwxr-xr-x 1 0 0 0 Jan 1 00:0 dev
+drwxrwxr-x 1 500 244 272 Jan 1 00:0 etc
+drwxrwxr-x 1 500 244 16 Jan 1 00:0 mnt
+drwxrwxr-x 1 500 244 0 Jan 1 00:0 nfs
+dr-xr-xr-x 50 0 0 0 Jan 1 00:0 proc
+drwxrwxrwx 1 0 0 0 Jan 1 00:0 ram
+drwxrwxr-x 1 500 244 296 Jan 1 00:0 sbin
+lrwxrwxrwx 1 500 244 7 Jan 1 00:0 tmp -> ram/tmp
+drwxrwxr-x 1 500 244 16 Jan 1 00:0 usr
+lrwxrwxrwx 1 500 244 7 Jan 1 00:0 var -> ram/var
diff --git a/chromium/net/data/ftp/dir-listing-ls-32.expected b/chromium/net/data/ftp/dir-listing-ls-32.expected
new file mode 100644
index 00000000000..4626652da42
--- /dev/null
+++ b/chromium/net/data/ftp/dir-listing-ls-32.expected
@@ -0,0 +1,98 @@
+d
+bin
+-1
+1994
+1
+1
+0
+0
+
+d
+dev
+-1
+1994
+1
+1
+0
+0
+
+d
+etc
+-1
+1994
+1
+1
+0
+0
+
+d
+mnt
+-1
+1994
+1
+1
+0
+0
+
+d
+nfs
+-1
+1994
+1
+1
+0
+0
+
+d
+proc
+-1
+1994
+1
+1
+0
+0
+
+d
+ram
+-1
+1994
+1
+1
+0
+0
+
+d
+sbin
+-1
+1994
+1
+1
+0
+0
+
+l
+tmp
+-1
+1994
+1
+1
+0
+0
+
+d
+usr
+-1
+1994
+1
+1
+0
+0
+
+l
+var
+-1
+1994
+1
+1
+0
+0
diff --git a/chromium/net/data/ssl/certificates/README b/chromium/net/data/ssl/certificates/README
index 01f6dfd69c8..0ef59fca041 100644
--- a/chromium/net/data/ssl/certificates/README
+++ b/chromium/net/data/ssl/certificates/README
@@ -226,3 +226,12 @@ unit tests.
http://crbug.com/31497. It is generated by running the script
net/data/ssl/scripts/generate-policy-certs.sh
+- ct-test-embedded-cert.pem
+- ct-test-embedded-with-intermediate-chain.pem
+- ct-test-embedded-with-intermediate-preca-chain.pem
+- ct-test-embedded-with-preca-chain.pem
+ Test certificate chains for Certificate Transparency: Each of these
+ files contains a leaf certificate as the first certificate, which has
+ embedded SCTs, followed by the issuer certificates chain.
+ All files are from the src/test/testdada directory in
+ https://code.google.com/p/certificate-transparency/
diff --git a/chromium/net/data/ssl/certificates/ct-test-embedded-cert.pem b/chromium/net/data/ssl/certificates/ct-test-embedded-cert.pem
new file mode 100644
index 00000000000..ff4875d936d
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/ct-test-embedded-cert.pem
@@ -0,0 +1,126 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7 (0x7)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:be:ef:98:e7:c2:68:77:ae:38:5f:75:32:5a:0c:
+ 1d:32:9b:ed:f1:8f:aa:f4:d7:96:bf:04:7e:b7:e1:
+ ce:15:c9:5b:a2:f8:0e:e4:58:bd:7d:b8:6f:8a:4b:
+ 25:21:91:a7:9b:d7:00:c3:8e:9c:03:89:b4:5c:d4:
+ dc:9a:12:0a:b2:1e:0c:b4:1c:d0:e7:28:05:a4:10:
+ cd:9c:5b:db:5d:49:27:72:6d:af:17:10:f6:01:87:
+ 37:7e:a2:5b:1a:1e:39:ee:d0:b8:81:19:dc:15:4d:
+ c6:8f:7d:a8:e3:0c:af:15:8a:33:e6:c9:50:9f:4a:
+ 05:b0:14:09:ff:5d:d8:7e:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 20:31:54:1A:F2:5C:05:FF:D8:65:8B:68:43:79:4F:5E:90:36:F7:B4
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:FALSE
+ 1.3.6.1.4.1.11129.2.4.2:
+ .z.x.v........RG.ah2].\yY..........?t.d...=.'.......G0E. H/gQ.5..T6...d.=..AB...E0(....>..!.....:.r.....jh.S.}.A.}....Q.....
+ Signature Algorithm: sha1WithRSAEncryption
+ 8a:0c:4b:ef:09:9d:47:92:79:af:a0:a2:8e:68:9f:91:e1:c4:
+ 42:1b:e2:d2:69:a2:ea:6c:a4:e8:21:5d:de:dd:ca:15:04:a1:
+ 1e:7c:87:c4:b7:7e:80:f0:e9:79:03:52:68:f2:7c:a2:0e:16:
+ 68:04:ae:55:6f:31:69:81:f9:6a:39:4a:b7:ab:fd:3e:25:5a:
+ c0:04:45:13:fe:76:57:0c:67:95:ab:e4:70:31:33:d3:03:f8:
+ 9f:3a:fa:6b:bc:fc:51:73:19:df:d9:5b:93:42:41:21:1f:63:
+ 40:35:c3:d0:78:30:7a:68:c6:07:5a:2e:20:c8:9f:36:b8:91:
+ 0c:a0
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIBBzANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFIxCzAJBgNVBAYTAkdCMSEwHwYDVQQKExhDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kxDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+75jnwmh3rjhfdTJaDB0ym+3xj6r015a/
+BH634c4VyVui+A7kWL19uG+KSyUhkaeb1wDDjpwDibRc1NyaEgqyHgy0HNDnKAWk
+EM2cW9tdSSdyba8XEPYBhzd+olsaHjnu0LiBGdwVTcaPfajjDK8VijPmyVCfSgWw
+FAn/Xdh+tQIDAQABo4IBOjCCATYwHQYDVR0OBBYEFCAxVBryXAX/2GWLaEN5T16Q
+Nve0MH0GA1UdIwR2MHSAFF+diA3Ic+ZU1PgN2OawwSS0R8NVoVmkVzBVMQswCQYD
+VQQGEwJHQjEkMCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4w
+DAYDVQQIEwVXYWxlczEQMA4GA1UEBxMHRXJ3IFdlboIBADAJBgNVHRMEAjAAMIGK
+BgorBgEEAdZ5AgQCBHwEegB4AHYA3xwuwRUAlFJHqWFoMl3cXHlZ6PfG04j8AC4L
+vT9012QAAAE92yffkwAABAMARzBFAiBIL2dRrzXbplQ2vh/WZA89v5pBQpSVkkUw
+KI+j5eI+BgIhAOTtwNs6xXKx4vXoq2poBlOYfc9BAn3+/6EFUZ2J7b8IMA0GCSqG
+SIb3DQEBBQUAA4GBAIoMS+8JnUeSea+goo5on5HhxEIb4tJpoupspOghXd7dyhUE
+oR58h8S3foDw6XkDUmjyfKIOFmgErlVvMWmB+Wo5Srer/T4lWsAERRP+dlcMZ5Wr
+5HAxM9MD+J86+mu8/FFzGd/ZW5NCQSEfY0A1w9B4MHpoxgdaLiDInza4kQyg
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d5:8a:68:53:62:10:a2:71:19:93:6e:77:83:21:
+ 18:1c:2a:40:13:c6:d0:7b:8c:76:eb:91:57:d3:d0:
+ fb:4b:3b:51:6e:ce:cb:d1:c9:8d:91:c5:2f:74:3f:
+ ab:63:5d:55:09:9c:d1:3a:ba:f3:1a:e5:41:44:24:
+ 51:a7:4c:78:16:f2:24:3c:f8:48:cf:28:31:cc:e6:
+ 7b:a0:4a:5a:23:81:9f:3c:ba:37:e6:24:d9:c3:bd:
+ b2:99:b8:39:dd:fe:26:31:d2:cb:3a:84:fc:7b:b2:
+ b5:c5:2f:cf:c1:4f:ff:40:6f:5c:d4:46:69:cb:b2:
+ f7:cf:df:86:fb:6a:b9:d1:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:08:cc:4a:6d:64:f2:20:5e:14:6c:04:b2:76:f9:2b:0e:fa:
+ 94:a5:da:f2:3a:fc:38:06:60:6d:39:90:d0:a1:ea:23:3d:40:
+ 29:57:69:46:3b:04:66:61:e7:fa:1d:17:99:15:20:9a:ea:2e:
+ 0a:77:51:76:41:12:27:d7:c0:03:07:c7:47:0e:61:58:4f:d7:
+ 33:42:24:72:7f:51:d6:90:bc:47:a9:df:35:4d:b0:f6:eb:25:
+ 95:5d:e1:89:3c:4d:d5:20:2b:24:a2:f3:e4:40:d2:74:b5:4e:
+ 1b:d3:76:26:9c:a9:62:89:b7:6e:ca:a4:10:90:e1:4f:3b:0a:
+ 94:2e
+-----BEGIN CERTIFICATE-----
+MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7
+jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP
+KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL
+svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk
+tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG
+A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO
+MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt
+OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy
+f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP
+OwqULg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-chain.pem b/chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-chain.pem
new file mode 100644
index 00000000000..22244617bcc
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-chain.pem
@@ -0,0 +1,188 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency Intermediate CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:bb:27:2b:26:e5:de:b5:45:9d:4a:cc:a0:27:e8:
+ f1:2a:4d:83:9a:c3:73:0a:6a:10:9f:f7:e2:54:98:
+ dd:bd:3f:18:95:d0:8b:a4:1f:8d:e3:49:67:a3:a0:
+ 86:ce:13:a9:0d:d5:ad:bb:54:18:4b:dc:08:e1:ac:
+ 78:26:ad:b8:dc:9c:71:7b:fd:7d:a5:b4:1b:4d:b1:
+ 73:6e:00:f1:da:c3:ce:c9:81:9c:cb:1a:28:ba:12:
+ 0b:02:0a:82:0e:94:0d:d6:1f:95:b5:43:2a:4b:c0:
+ 5d:08:18:f1:8c:e2:15:4e:b3:8d:2f:a7:d2:2d:72:
+ b9:76:e5:60:db:0c:7f:c7:7f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ B1:B1:48:E6:58:E7:03:F5:F7:F3:10:5F:20:B3:C3:84:D7:EF:F1:BF
+ X509v3 Authority Key Identifier:
+ keyid:96:55:08:05:02:78:47:9E:87:73:76:41:31:BC:14:3A:47:E2:29:AB
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:09
+
+ X509v3 Basic Constraints:
+ CA:FALSE
+ 1.3.6.1.4.1.11129.2.4.2:
+ .z.x.v........RG.ah2].\yY..........?t.d...=.'.......G0E.!...E..9-...W.....E.L..8V.......u.. ^&...."...)....4...O.......f...?
+ Signature Algorithm: sha1WithRSAEncryption
+ 0f:95:a5:b4:e1:28:a9:14:b1:e8:8b:e8:b3:29:64:22:1b:58:
+ f4:55:84:33:d0:20:a8:e2:46:cc:a6:5a:40:bc:bf:5f:2d:48:
+ 93:3e:bc:99:be:69:27:ca:75:64:72:fb:0b:dc:7f:50:5f:41:
+ f4:62:f2:bc:19:d0:b2:99:c9:90:91:8d:f8:82:0f:3d:31:db:
+ 37:97:9e:8b:ad:56:3b:17:f0:0a:e6:7b:0f:87:31:c1:06:c9:
+ 43:a7:3b:f5:36:af:16:8a:fe:21:ef:4a:df:ca:e1:9a:3c:c0:
+ 74:89:99:92:bf:50:6b:c5:ce:1d:ec:aa:f0:7f:fe:eb:c8:05:
+ c0:39
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAs+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJHQjEx
+MC8GA1UEChMoQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IEludGVybWVkaWF0ZSBD
+QTEOMAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW4wHhcNMTIwNjAxMDAw
+MDAwWhcNMjIwNjAxMDAwMDAwWjBSMQswCQYDVQQGEwJHQjEhMB8GA1UEChMYQ2Vy
+dGlmaWNhdGUgVHJhbnNwYXJlbmN5MQ4wDAYDVQQIEwVXYWxlczEQMA4GA1UEBxMH
+RXJ3IFdlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuycrJuXetUWdSsyg
+J+jxKk2DmsNzCmoQn/fiVJjdvT8YldCLpB+N40lno6CGzhOpDdWtu1QYS9wI4ax4
+Jq243Jxxe/19pbQbTbFzbgDx2sPOyYGcyxoouhILAgqCDpQN1h+VtUMqS8BdCBjx
+jOIVTrONL6fSLXK5duVg2wx/x38CAwEAAaOCATowggE2MB0GA1UdDgQWBBSxsUjm
+WOcD9ffzEF8gs8OE1+/xvzB9BgNVHSMEdjB0gBSWVQgFAnhHnodzdkExvBQ6R+Ip
+q6FZpFcwVTELMAkGA1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5z
+cGFyZW5jeSBDQTEOMAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQkw
+CQYDVR0TBAIwADCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN8cLsEVAJRSR6lhaDJd
+3Fx5Wej3xtOI/AAuC70/dNdkAAABPdsn4qQAAAQDAEcwRQIhAKbTRRfzOS2exdJX
+rfHFl9xFvUzTtzhWxhap+5nlrnWoAiBeJsjRx+Ii/ozaKbrrBKg07pfTT9gXGPGq
+4M1m9LipPzANBgkqhkiG9w0BAQUFAAOBgQAPlaW04SipFLHoi+izKWQiG1j0VYQz
+0CCo4kbMplpAvL9fLUiTPryZvmknynVkcvsL3H9QX0H0YvK8GdCymcmQkY34gg89
+Mds3l56LrVY7F/AK5nsPhzHBBslDpzv1Nq8Wiv4h70rfyuGaPMB0iZmSv1Brxc4d
+7Krwf/7ryAXAOQ==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9 (0x9)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency Intermediate CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d7:6a:67:8d:11:6f:52:2e:55:ff:82:1c:90:64:
+ 25:08:b7:07:4b:14:d7:71:15:90:64:f7:92:7e:fd:
+ ed:b8:71:35:a1:36:5e:e7:de:18:cb:d5:ce:86:5f:
+ 86:0c:78:f4:33:b4:d0:d3:d3:40:77:02:e7:a3:ef:
+ 54:2b:1d:fe:9b:ba:a7:cd:f9:4d:c5:97:5f:c7:29:
+ f8:6f:10:5f:38:1b:24:35:35:cf:9c:80:0f:5c:a7:
+ 80:c1:d3:c8:44:00:ee:65:d1:6e:e9:cf:52:db:8a:
+ df:fe:50:f5:c4:93:35:0b:21:90:bf:50:d5:bc:36:
+ f3:ca:c5:a8:da:ae:92:cd:8b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 96:55:08:05:02:78:47:9E:87:73:76:41:31:BC:14:3A:47:E2:29:AB
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 22:06:da:b1:c6:6b:71:dc:e0:95:c3:f6:aa:2e:f7:2c:f7:76:
+ 1b:e7:ab:d7:fc:39:c3:1a:4c:fe:1b:d9:6d:67:34:ca:82:f2:
+ 2d:de:5a:0c:8b:bb:dd:82:5d:7b:6f:3e:76:12:ad:8d:b3:00:
+ a7:e2:11:69:88:60:23:26:22:84:c3:aa:5d:21:91:ef:da:10:
+ bf:92:35:d3:7b:3a:2a:34:0d:59:41:9b:94:a4:85:66:f3:fa:
+ c3:cd:8b:53:d5:a4:e9:82:70:ea:d2:97:b0:72:10:f9:ce:4a:
+ 21:38:b1:88:11:14:3b:93:fa:4e:7a:87:dd:37:e1:38:5f:2c:
+ 29:08
+-----BEGIN CERTIFICATE-----
+MIIC3TCCAkagAwIBAgIBCTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMGIxCzAJBgNVBAYTAkdCMTEwLwYDVQQKEyhDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgSW50ZXJtZWRpYXRlIENBMQ4wDAYDVQQIEwVXYWxlczEQMA4GA1UE
+BxMHRXJ3IFdlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA12pnjRFvUi5V
+/4IckGQlCLcHSxTXcRWQZPeSfv3tuHE1oTZe594Yy9XOhl+GDHj0M7TQ09NAdwLn
+o+9UKx3+m7qnzflNxZdfxyn4bxBfOBskNTXPnIAPXKeAwdPIRADuZdFu6c9S24rf
+/lD1xJM1CyGQv1DVvDbzysWo2q6SzYsCAwEAAaOBrzCBrDAdBgNVHQ4EFgQUllUI
+BQJ4R56Hc3ZBMbwUOkfiKaswfQYDVR0jBHYwdIAUX52IDchz5lTU+A3Y5rDBJLRH
+w1WhWaRXMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuggEA
+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAIgbascZrcdzglcP2qi73
+LPd2G+er1/w5wxpM/hvZbWc0yoLyLd5aDIu73YJde28+dhKtjbMAp+IRaYhgIyYi
+hMOqXSGR79oQv5I103s6KjQNWUGblKSFZvP6w82LU9Wk6YJw6tKXsHIQ+c5KITix
+iBEUO5P6TnqH3TfhOF8sKQg=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d5:8a:68:53:62:10:a2:71:19:93:6e:77:83:21:
+ 18:1c:2a:40:13:c6:d0:7b:8c:76:eb:91:57:d3:d0:
+ fb:4b:3b:51:6e:ce:cb:d1:c9:8d:91:c5:2f:74:3f:
+ ab:63:5d:55:09:9c:d1:3a:ba:f3:1a:e5:41:44:24:
+ 51:a7:4c:78:16:f2:24:3c:f8:48:cf:28:31:cc:e6:
+ 7b:a0:4a:5a:23:81:9f:3c:ba:37:e6:24:d9:c3:bd:
+ b2:99:b8:39:dd:fe:26:31:d2:cb:3a:84:fc:7b:b2:
+ b5:c5:2f:cf:c1:4f:ff:40:6f:5c:d4:46:69:cb:b2:
+ f7:cf:df:86:fb:6a:b9:d1:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:08:cc:4a:6d:64:f2:20:5e:14:6c:04:b2:76:f9:2b:0e:fa:
+ 94:a5:da:f2:3a:fc:38:06:60:6d:39:90:d0:a1:ea:23:3d:40:
+ 29:57:69:46:3b:04:66:61:e7:fa:1d:17:99:15:20:9a:ea:2e:
+ 0a:77:51:76:41:12:27:d7:c0:03:07:c7:47:0e:61:58:4f:d7:
+ 33:42:24:72:7f:51:d6:90:bc:47:a9:df:35:4d:b0:f6:eb:25:
+ 95:5d:e1:89:3c:4d:d5:20:2b:24:a2:f3:e4:40:d2:74:b5:4e:
+ 1b:d3:76:26:9c:a9:62:89:b7:6e:ca:a4:10:90:e1:4f:3b:0a:
+ 94:2e
+-----BEGIN CERTIFICATE-----
+MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7
+jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP
+KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL
+svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk
+tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG
+A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO
+MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt
+OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy
+f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP
+OwqULg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-preca-chain.pem b/chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-preca-chain.pem
new file mode 100644
index 00000000000..597cebc294f
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/ct-test-embedded-with-intermediate-preca-chain.pem
@@ -0,0 +1,188 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3 (0x3)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency Intermediate CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d4:49:70:56:cd:fc:65:e1:34:2c:c3:df:6e:65:
+ 4b:8a:f0:10:47:02:ac:d2:27:5c:7d:3f:b1:fc:43:
+ 8a:89:b2:12:11:0d:64:19:bc:c1:3a:e4:7d:64:bb:
+ a2:41:e6:70:6b:9e:d6:27:f8:b3:4a:0d:7d:ff:1c:
+ 44:b9:62:87:c5:4b:ea:9d:10:dc:01:7b:ce:b6:4f:
+ 7b:6a:ff:3c:35:a4:74:af:ec:40:38:ab:36:40:b0:
+ cd:1f:b0:58:2e:c0:3b:17:9a:27:76:c8:c4:35:d1:
+ 4a:b4:88:2d:59:d7:b7:24:fa:37:7c:a6:db:08:39:
+ 21:73:f9:c6:05:6b:3a:ba:df
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 32:DA:55:18:D8:7F:1D:26:EA:27:67:97:3C:0B:EF:28:6E:78:6A:4A
+ X509v3 Authority Key Identifier:
+ keyid:96:55:08:05:02:78:47:9E:87:73:76:41:31:BC:14:3A:47:E2:29:AB
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:09
+
+ X509v3 Basic Constraints:
+ CA:FALSE
+ 1.3.6.1.4.1.11129.2.4.2:
+ .z.x.v........RG.ah2].\yY..........?t.d...=.'.......G0E.!.......!...<..p.3..7K ...e.^..C.0. .v.GQ8..v.810M..C....n..O..|....
+ Signature Algorithm: sha1WithRSAEncryption
+ 88:ee:4e:9e:5e:ed:6b:11:2c:c7:64:b1:51:ed:92:94:00:e9:
+ 40:67:89:c1:5f:bb:cf:cd:ab:2f:10:b4:00:23:41:39:e6:ce:
+ 65:c1:e5:1b:47:bf:7c:89:50:f8:0b:cc:d5:71:68:56:79:54:
+ ed:35:b0:ce:93:46:06:5a:5e:ae:5b:f9:5d:41:da:8e:27:ce:
+ e9:ee:ac:68:8f:4b:d3:43:f9:c2:88:83:27:ab:d8:b9:f6:8d:
+ cb:1e:30:50:04:1d:31:bd:a8:e2:dd:6d:39:b3:66:4d:e5:ce:
+ 08:70:f5:fc:7e:6a:00:d6:ed:00:52:84:58:d9:53:d2:37:58:
+ 6d:73
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAs+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJHQjEx
+MC8GA1UEChMoQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IEludGVybWVkaWF0ZSBD
+QTEOMAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW4wHhcNMTIwNjAxMDAw
+MDAwWhcNMjIwNjAxMDAwMDAwWjBSMQswCQYDVQQGEwJHQjEhMB8GA1UEChMYQ2Vy
+dGlmaWNhdGUgVHJhbnNwYXJlbmN5MQ4wDAYDVQQIEwVXYWxlczEQMA4GA1UEBxMH
+RXJ3IFdlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1ElwVs38ZeE0LMPf
+bmVLivAQRwKs0idcfT+x/EOKibISEQ1kGbzBOuR9ZLuiQeZwa57WJ/izSg19/xxE
+uWKHxUvqnRDcAXvOtk97av88NaR0r+xAOKs2QLDNH7BYLsA7F5ondsjENdFKtIgt
+Wde3JPo3fKbbCDkhc/nGBWs6ut8CAwEAAaOCATowggE2MB0GA1UdDgQWBBQy2lUY
+2H8dJuonZ5c8C+8obnhqSjB9BgNVHSMEdjB0gBSWVQgFAnhHnodzdkExvBQ6R+Ip
+q6FZpFcwVTELMAkGA1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5z
+cGFyZW5jeSBDQTEOMAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQkw
+CQYDVR0TBAIwADCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN8cLsEVAJRSR6lhaDJd
+3Fx5Wej3xtOI/AAuC70/dNdkAAABPdsn474AAAQDAEcwRQIhANn2Ggf+4CHjFZ88
+ovVw2DP/ATdLIJbLpWWMXhb7Q+swAiALdv5HUTjYz3aDODEwTavwQ+sSE8luE/9P
+o39808jcHzANBgkqhkiG9w0BAQUFAAOBgQCI7k6eXu1rESzHZLFR7ZKUAOlAZ4nB
+X7vPzasvELQAI0E55s5lweUbR798iVD4C8zVcWhWeVTtNbDOk0YGWl6uW/ldQdqO
+J87p7qxoj0vTQ/nCiIMnq9i59o3LHjBQBB0xvaji3W05s2ZN5c4IcPX8fmoA1u0A
+UoRY2VPSN1htcw==
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9 (0x9)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency Intermediate CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d7:6a:67:8d:11:6f:52:2e:55:ff:82:1c:90:64:
+ 25:08:b7:07:4b:14:d7:71:15:90:64:f7:92:7e:fd:
+ ed:b8:71:35:a1:36:5e:e7:de:18:cb:d5:ce:86:5f:
+ 86:0c:78:f4:33:b4:d0:d3:d3:40:77:02:e7:a3:ef:
+ 54:2b:1d:fe:9b:ba:a7:cd:f9:4d:c5:97:5f:c7:29:
+ f8:6f:10:5f:38:1b:24:35:35:cf:9c:80:0f:5c:a7:
+ 80:c1:d3:c8:44:00:ee:65:d1:6e:e9:cf:52:db:8a:
+ df:fe:50:f5:c4:93:35:0b:21:90:bf:50:d5:bc:36:
+ f3:ca:c5:a8:da:ae:92:cd:8b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 96:55:08:05:02:78:47:9E:87:73:76:41:31:BC:14:3A:47:E2:29:AB
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 22:06:da:b1:c6:6b:71:dc:e0:95:c3:f6:aa:2e:f7:2c:f7:76:
+ 1b:e7:ab:d7:fc:39:c3:1a:4c:fe:1b:d9:6d:67:34:ca:82:f2:
+ 2d:de:5a:0c:8b:bb:dd:82:5d:7b:6f:3e:76:12:ad:8d:b3:00:
+ a7:e2:11:69:88:60:23:26:22:84:c3:aa:5d:21:91:ef:da:10:
+ bf:92:35:d3:7b:3a:2a:34:0d:59:41:9b:94:a4:85:66:f3:fa:
+ c3:cd:8b:53:d5:a4:e9:82:70:ea:d2:97:b0:72:10:f9:ce:4a:
+ 21:38:b1:88:11:14:3b:93:fa:4e:7a:87:dd:37:e1:38:5f:2c:
+ 29:08
+-----BEGIN CERTIFICATE-----
+MIIC3TCCAkagAwIBAgIBCTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMGIxCzAJBgNVBAYTAkdCMTEwLwYDVQQKEyhDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgSW50ZXJtZWRpYXRlIENBMQ4wDAYDVQQIEwVXYWxlczEQMA4GA1UE
+BxMHRXJ3IFdlbjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA12pnjRFvUi5V
+/4IckGQlCLcHSxTXcRWQZPeSfv3tuHE1oTZe594Yy9XOhl+GDHj0M7TQ09NAdwLn
+o+9UKx3+m7qnzflNxZdfxyn4bxBfOBskNTXPnIAPXKeAwdPIRADuZdFu6c9S24rf
+/lD1xJM1CyGQv1DVvDbzysWo2q6SzYsCAwEAAaOBrzCBrDAdBgNVHQ4EFgQUllUI
+BQJ4R56Hc3ZBMbwUOkfiKaswfQYDVR0jBHYwdIAUX52IDchz5lTU+A3Y5rDBJLRH
+w1WhWaRXMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuggEA
+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAIgbascZrcdzglcP2qi73
+LPd2G+er1/w5wxpM/hvZbWc0yoLyLd5aDIu73YJde28+dhKtjbMAp+IRaYhgIyYi
+hMOqXSGR79oQv5I103s6KjQNWUGblKSFZvP6w82LU9Wk6YJw6tKXsHIQ+c5KITix
+iBEUO5P6TnqH3TfhOF8sKQg=
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d5:8a:68:53:62:10:a2:71:19:93:6e:77:83:21:
+ 18:1c:2a:40:13:c6:d0:7b:8c:76:eb:91:57:d3:d0:
+ fb:4b:3b:51:6e:ce:cb:d1:c9:8d:91:c5:2f:74:3f:
+ ab:63:5d:55:09:9c:d1:3a:ba:f3:1a:e5:41:44:24:
+ 51:a7:4c:78:16:f2:24:3c:f8:48:cf:28:31:cc:e6:
+ 7b:a0:4a:5a:23:81:9f:3c:ba:37:e6:24:d9:c3:bd:
+ b2:99:b8:39:dd:fe:26:31:d2:cb:3a:84:fc:7b:b2:
+ b5:c5:2f:cf:c1:4f:ff:40:6f:5c:d4:46:69:cb:b2:
+ f7:cf:df:86:fb:6a:b9:d1:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:08:cc:4a:6d:64:f2:20:5e:14:6c:04:b2:76:f9:2b:0e:fa:
+ 94:a5:da:f2:3a:fc:38:06:60:6d:39:90:d0:a1:ea:23:3d:40:
+ 29:57:69:46:3b:04:66:61:e7:fa:1d:17:99:15:20:9a:ea:2e:
+ 0a:77:51:76:41:12:27:d7:c0:03:07:c7:47:0e:61:58:4f:d7:
+ 33:42:24:72:7f:51:d6:90:bc:47:a9:df:35:4d:b0:f6:eb:25:
+ 95:5d:e1:89:3c:4d:d5:20:2b:24:a2:f3:e4:40:d2:74:b5:4e:
+ 1b:d3:76:26:9c:a9:62:89:b7:6e:ca:a4:10:90:e1:4f:3b:0a:
+ 94:2e
+-----BEGIN CERTIFICATE-----
+MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7
+jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP
+KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL
+svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk
+tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG
+A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO
+MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt
+OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy
+f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP
+OwqULg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/ct-test-embedded-with-preca-chain.pem b/chromium/net/data/ssl/certificates/ct-test-embedded-with-preca-chain.pem
new file mode 100644
index 00000000000..7c9a8cf8b9f
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/ct-test-embedded-with-preca-chain.pem
@@ -0,0 +1,126 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8 (0x8)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:af:ae:ea:ca:c5:1a:b7:ce:bd:f9:ea:ca:e7:dd:
+ 17:52:95:e1:93:95:5a:17:98:9a:ef:8d:97:ab:7c:
+ df:f7:76:10:93:c0:b8:23:d2:a4:e3:a5:1a:17:b8:
+ 6f:28:16:2b:66:a2:53:89:35:eb:ec:dc:10:36:23:
+ 3d:a2:dd:65:31:b0:c6:3b:cc:68:76:1e:bd:c8:54:
+ 03:7b:77:39:92:46:b8:70:a7:b7:2b:14:c9:b1:66:
+ 7d:e0:9a:96:40:ed:9f:3f:3c:72:5d:95:0b:4d:26:
+ 55:98:69:fe:7f:1e:91:9a:66:eb:76:d3:5c:01:17:
+ c6:bc:d0:d8:cf:d2:10:28:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 61:2C:64:EF:AC:79:B7:28:39:7C:9D:93:E6:DF:86:46:5F:A7:6A:88
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:FALSE
+ 1.3.6.1.4.1.11129.2.4.2:
+ .z.x.v........RG.ah2].\yY..........?t.d...=.'.[.....G0E. z....t..r{.O....y......C.*)|.:5\.!...... dL..Ri..c..5l.P"O.......#.
+ Signature Algorithm: sha1WithRSAEncryption
+ a3:a8:6c:41:ad:00:88:a2:5a:ed:c4:e7:b5:29:a2:dd:bf:9e:
+ 18:7f:fb:36:21:57:e9:30:2d:96:1b:73:b4:3c:ba:0a:e1:e2:
+ 30:d9:e4:50:49:b7:e8:c9:24:79:2e:bb:e7:d1:75:ba:a8:7b:
+ 17:0d:fa:d8:ee:78:89:84:59:9d:05:25:79:94:08:4e:2e:0e:
+ 79:6f:ca:58:36:88:1c:3e:05:35:53:e0:6a:b2:30:f9:19:08:
+ 9b:91:4e:4a:8e:2d:a4:5f:8a:87:f2:c8:1a:25:a6:1f:04:fe:
+ 1c:ac:e6:01:55:65:38:27:d4:1f:ad:9f:06:58:f2:87:d0:58:
+ 19:2c
+-----BEGIN CERTIFICATE-----
+MIIDWTCCAsKgAwIBAgIBCDANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFIxCzAJBgNVBAYTAkdCMSEwHwYDVQQKExhDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kxDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGfMA0G
+CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvrurKxRq3zr356srn3RdSleGTlVoXmJrv
+jZerfN/3dhCTwLgj0qTjpRoXuG8oFitmolOJNevs3BA2Iz2i3WUxsMY7zGh2Hr3I
+VAN7dzmSRrhwp7crFMmxZn3gmpZA7Z8/PHJdlQtNJlWYaf5/HpGaZut201wBF8a8
+0NjP0hAosQIDAQABo4IBOjCCATYwHQYDVR0OBBYEFGEsZO+sebcoOXydk+bfhkZf
+p2qIMH0GA1UdIwR2MHSAFF+diA3Ic+ZU1PgN2OawwSS0R8NVoVmkVzBVMQswCQYD
+VQQGEwJHQjEkMCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4w
+DAYDVQQIEwVXYWxlczEQMA4GA1UEBxMHRXJ3IFdlboIBADAJBgNVHRMEAjAAMIGK
+BgorBgEEAdZ5AgQCBHwEegB4AHYA3xwuwRUAlFJHqWFoMl3cXHlZ6PfG04j8AC4L
+vT9012QAAAE92yfgWwAABAMARzBFAiB6p5YExHSA83J7CE+Qs5ifeQkYheAEhEMa
+Kil8vzo1XAIhALSf2BILDWRM1+dSabTaYxepNWy5UCJPwRzClrLjmyOGMA0GCSqG
+SIb3DQEBBQUAA4GBAKOobEGtAIiiWu3E57Upot2/nhh/+zYhV+kwLZYbc7Q8ugrh
+4jDZ5FBJt+jJJHkuu+fRdbqoexcN+tjueImEWZ0FJXmUCE4uDnlvylg2iBw+BTVT
+4GqyMPkZCJuRTkqOLaRfiofyyBolph8E/hys5gFVZTgn1B+tnwZY8ofQWBks
+-----END CERTIFICATE-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Validity
+ Not Before: Jun 1 00:00:00 2012 GMT
+ Not After : Jun 1 00:00:00 2022 GMT
+ Subject: C=GB, O=Certificate Transparency CA, ST=Wales, L=Erw Wen
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:d5:8a:68:53:62:10:a2:71:19:93:6e:77:83:21:
+ 18:1c:2a:40:13:c6:d0:7b:8c:76:eb:91:57:d3:d0:
+ fb:4b:3b:51:6e:ce:cb:d1:c9:8d:91:c5:2f:74:3f:
+ ab:63:5d:55:09:9c:d1:3a:ba:f3:1a:e5:41:44:24:
+ 51:a7:4c:78:16:f2:24:3c:f8:48:cf:28:31:cc:e6:
+ 7b:a0:4a:5a:23:81:9f:3c:ba:37:e6:24:d9:c3:bd:
+ b2:99:b8:39:dd:fe:26:31:d2:cb:3a:84:fc:7b:b2:
+ b5:c5:2f:cf:c1:4f:ff:40:6f:5c:d4:46:69:cb:b2:
+ f7:cf:df:86:fb:6a:b9:d1:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ X509v3 Authority Key Identifier:
+ keyid:5F:9D:88:0D:C8:73:E6:54:D4:F8:0D:D8:E6:B0:C1:24:B4:47:C3:55
+ DirName:/C=GB/O=Certificate Transparency CA/ST=Wales/L=Erw Wen
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 06:08:cc:4a:6d:64:f2:20:5e:14:6c:04:b2:76:f9:2b:0e:fa:
+ 94:a5:da:f2:3a:fc:38:06:60:6d:39:90:d0:a1:ea:23:3d:40:
+ 29:57:69:46:3b:04:66:61:e7:fa:1d:17:99:15:20:9a:ea:2e:
+ 0a:77:51:76:41:12:27:d7:c0:03:07:c7:47:0e:61:58:4f:d7:
+ 33:42:24:72:7f:51:d6:90:bc:47:a9:df:35:4d:b0:f6:eb:25:
+ 95:5d:e1:89:3c:4d:d5:20:2b:24:a2:f3:e4:40:d2:74:b5:4e:
+ 1b:d3:76:26:9c:a9:62:89:b7:6e:ca:a4:10:90:e1:4f:3b:0a:
+ 94:2e
+-----BEGIN CERTIFICATE-----
+MIIC0DCCAjmgAwIBAgIBADANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJHQjEk
+MCIGA1UEChMbQ2VydGlmaWNhdGUgVHJhbnNwYXJlbmN5IENBMQ4wDAYDVQQIEwVX
+YWxlczEQMA4GA1UEBxMHRXJ3IFdlbjAeFw0xMjA2MDEwMDAwMDBaFw0yMjA2MDEw
+MDAwMDBaMFUxCzAJBgNVBAYTAkdCMSQwIgYDVQQKExtDZXJ0aWZpY2F0ZSBUcmFu
+c3BhcmVuY3kgQ0ExDjAMBgNVBAgTBVdhbGVzMRAwDgYDVQQHEwdFcncgV2VuMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVimhTYhCicRmTbneDIRgcKkATxtB7
+jHbrkVfT0PtLO1FuzsvRyY2RxS90P6tjXVUJnNE6uvMa5UFEJFGnTHgW8iQ8+EjP
+KDHM5nugSlojgZ88ujfmJNnDvbKZuDnd/iYx0ss6hPx7srXFL8/BT/9Ab1zURmnL
+svfP34b7arnRsQIDAQABo4GvMIGsMB0GA1UdDgQWBBRfnYgNyHPmVNT4DdjmsMEk
+tEfDVTB9BgNVHSMEdjB0gBRfnYgNyHPmVNT4DdjmsMEktEfDVaFZpFcwVTELMAkG
+A1UEBhMCR0IxJDAiBgNVBAoTG0NlcnRpZmljYXRlIFRyYW5zcGFyZW5jeSBDQTEO
+MAwGA1UECBMFV2FsZXMxEDAOBgNVBAcTB0VydyBXZW6CAQAwDAYDVR0TBAUwAwEB
+/zANBgkqhkiG9w0BAQUFAAOBgQAGCMxKbWTyIF4UbASydvkrDvqUpdryOvw4BmBt
+OZDQoeojPUApV2lGOwRmYef6HReZFSCa6i4Kd1F2QRIn18ADB8dHDmFYT9czQiRy
+f1HWkLxHqd81TbD26yWVXeGJPE3VICskovPkQNJ0tU4b03YmnKliibduyqQQkOFP
+OwqULg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/name_constraint_bad.crt b/chromium/net/data/ssl/certificates/name_constraint_bad.crt
new file mode 100644
index 00000000000..d73312b6616
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/name_constraint_bad.crt
@@ -0,0 +1,109 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAzNtr+fM1JtFhOTaJsZVJr/UYpLxylg28jY/V3SLItFrnYQOs
+XrwjoWI3osQjBe34PrhI7XmHIEACprY5q/bKTOz+PgBiX2tp9oieXtLi9O3qDrlC
+Z0HentNomdR0yojK5nPAloSCgdgX2sA+c6oyzKAmReKlReXEgh0hI43YVILKLLnO
+I4O1jowGVg/QATR12OQGYswUJuApW8KQeT7bI9ZCewacZD1UiiAlQ57w2rZ41fJh
+4W4nKKjkuH43wSNW7BH7VWECt1RrxkeSdFh6GPYwMrkT+KDs8aqzMXdlRN1CXCpv
+4CbrLM2j5B4dLkhuU9KZAiOXBSew9TJrZ9ga9wIDAQABAoIBAEw8V/mDpcMVZm4J
+OsLIgMynlI0xyB7Ja+LupTMPT8u2jKbQ3CPBNi1HxNag0TvSrHCC2jjt4fiBebsa
+02mIhQ6Nn6vpLrK94YgqnW1CY82sgE8MaIbOv48xs5qTswbwUznh18jr9Tlm9rGk
+m1kl/JOkAbo+Ny1E7ZVSS9PUZK5F94oYbq8H/IT9Vh5doyMG66fwhGfZaXSv7+tF
+R8dEkfkyfVBhwcR8H738MkcGVjPRkGGUgaUTHktr3l642YXYYSRbZ1lNIpXM2oHH
+qCRqWy/tg6p2AIMSqRXy+jEn1YSlGI+hndMXDvPJoH8rqbuTIxzNKLneZiSDNVqq
+K9+XalkCgYEA6FhwTyc/4QEyFP2HWArpkcxvws6OVIrJG76K+j/c+G1pUfmhIICY
+Rx/xEAXA7iT7B4S0DWqYMG2eYos6bd2Qj1nK8x/ishM2awlyN4mYjn1fr/AI7fbD
+omtFlUDwQLD0KB630I+KyNLBoHgV70559MHk93uYCq/2cRl+KvDuLL0CgYEA4baP
+qu32Ln9JmThVD9GotlEUJMHkfkSLeXFe+tPjQLuFoeijvMFai60sZ1J/OXf7yMiR
+u6j4QIlepqK1TlvCfIjQeg620az4v1kap3JL9XNWOXjdOzsBeJPPE/dp0akeG5uB
+XXvTSwRWLcxzkfzaEPuy8HWPdphrQ+PleZQiE8MCgYAjQ8EQEnn8kazjSLOxJj7b
+NTdFTwqFRGdPwbTgVK8aOakBmyzcfQgfy3ZQIz9sJcrAEmEtpB8jQpAGjvE4Waem
+Sk+mZRGIS6g3yMBAM68m+Vp7nqgMTibVUQjHpYqRlwoHyNnHWvIKlwpya6eQoc2a
+248ADQ8/mAOEmQTwSY8s1QKBgQC27lnz45aBSsJgfspZ3sdIs9+KhuZj+7O6gkrD
+KRVmclS0yzJhGagDyh9RwgfAkOCscvnByQkibPMcRISC9FVkzxF/ywsaVoDnvBSh
+Hz42uPpp6+4JQiJIEitjeEL4HIN9RoQLOv8dLm+WALyt1er6lrQItI7IRHGy/TIP
+XiJcNwKBgDc4CCqWTS1D3mB8L9Dwom3lrFQRitUbeNmI/787x8Mh2x5kYJZWLXj5
+r8ZCugcUO2N7hW4sZSBXH7N8Udbyud1fLk2pVJmJ4QCk4wvNpITM3ZMSJp7LAKhs
+cmxcrrVKAk47W9EOnTb50THDlsWfO/vO7XhE82N27cnEPPCi+umS
+-----END RSA PRIVATE KEY-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 24598234 (0x17756da)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Jan 1 10:00:00 2013 GMT
+ Not After : Dec 31 10:00:00 2023 GMT
+ Subject: O=Acme Co, CN=Leaf certificate
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:cc:db:6b:f9:f3:35:26:d1:61:39:36:89:b1:95:
+ 49:af:f5:18:a4:bc:72:96:0d:bc:8d:8f:d5:dd:22:
+ c8:b4:5a:e7:61:03:ac:5e:bc:23:a1:62:37:a2:c4:
+ 23:05:ed:f8:3e:b8:48:ed:79:87:20:40:02:a6:b6:
+ 39:ab:f6:ca:4c:ec:fe:3e:00:62:5f:6b:69:f6:88:
+ 9e:5e:d2:e2:f4:ed:ea:0e:b9:42:67:41:de:9e:d3:
+ 68:99:d4:74:ca:88:ca:e6:73:c0:96:84:82:81:d8:
+ 17:da:c0:3e:73:aa:32:cc:a0:26:45:e2:a5:45:e5:
+ c4:82:1d:21:23:8d:d8:54:82:ca:2c:b9:ce:23:83:
+ b5:8e:8c:06:56:0f:d0:01:34:75:d8:e4:06:62:cc:
+ 14:26:e0:29:5b:c2:90:79:3e:db:23:d6:42:7b:06:
+ 9c:64:3d:54:8a:20:25:43:9e:f0:da:b6:78:d5:f2:
+ 61:e1:6e:27:28:a8:e4:b8:7e:37:c1:23:56:ec:11:
+ fb:55:61:02:b7:54:6b:c6:47:92:74:58:7a:18:f6:
+ 30:32:b9:13:f8:a0:ec:f1:aa:b3:31:77:65:44:dd:
+ 42:5c:2a:6f:e0:26:eb:2c:cd:a3:e4:1e:1d:2e:48:
+ 6e:53:d2:99:02:23:97:05:27:b0:f5:32:6b:67:d8:
+ 1a:f7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Authority Key Identifier:
+ keyid:2B:88:93:E1:D2:54:50:F4:B8:A4:20:BD:B1:79:E6:0B:AA:EB:EC:1A
+
+ X509v3 Subject Alternative Name:
+ DNS:test.ExAmPlE.CoM, DNS:test.ExAmPlE.OrG
+ Signature Algorithm: sha1WithRSAEncryption
+ 08:2e:7b:ca:45:c2:2d:d8:4b:52:ca:af:b0:86:60:58:71:6f:
+ e8:40:2d:fd:e6:44:10:b5:75:d0:81:19:47:05:34:97:0c:6b:
+ 4e:c2:67:7d:7f:72:fe:c7:28:12:a3:b7:a9:9f:11:ef:66:f7:
+ 8f:00:0b:e2:8f:18:9b:1e:06:ee:2a:e0:fa:bd:f7:79:3a:63:
+ 7f:0e:94:b7:56:02:62:a6:65:17:e1:5e:10:13:3a:56:db:b3:
+ 50:54:44:60:d3:36:9e:f3:e9:74:89:35:4a:d6:2b:a5:ba:03:
+ 82:ba:53:9a:21:9e:78:eb:4b:fb:dc:f1:1e:eb:8c:29:57:ab:
+ da:a6:0b:b6:a8:b8:07:d6:92:f3:40:fd:b8:52:8b:eb:53:5e:
+ 4a:d2:9e:cc:aa:85:52:a4:09:02:05:ce:3f:65:82:4e:ec:a9:
+ fa:44:87:bf:35:3c:c2:b8:ba:7d:92:c1:41:45:1d:de:d9:a0:
+ fd:b8:99:6c:c4:75:a6:3e:9d:c9:d0:a4:3b:47:96:97:f8:78:
+ f3:cb:b5:93:19:79:8c:38:70:1c:6f:27:f1:13:d8:a6:4e:6a:
+ 85:b4:df:2f:23:1d:47:5a:76:8c:2a:ea:ac:21:91:16:4c:f3:
+ 74:86:68:57:f1:93:7b:3d:3d:f3:8b:f4:5b:97:d4:13:4a:80:
+ 35:65:78:c7
+-----BEGIN CERTIFICATE-----
+MIIDRTCCAi+gAwIBAgIEAXdW2jALBgkqhkiG9w0BAQUwFzEVMBMGA1UEAwwMVGVz
+dCBSb290IENBMB4XDTEzMDEwMTEwMDAwMFoXDTIzMTIzMTEwMDAwMFowLTEQMA4G
+A1UEChMHQWNtZSBDbzEZMBcGA1UEAxMQTGVhZiBjZXJ0aWZpY2F0ZTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMzba/nzNSbRYTk2ibGVSa/1GKS8cpYN
+vI2P1d0iyLRa52EDrF68I6FiN6LEIwXt+D64SO15hyBAAqa2Oav2ykzs/j4AYl9r
+afaInl7S4vTt6g65QmdB3p7TaJnUdMqIyuZzwJaEgoHYF9rAPnOqMsygJkXipUXl
+xIIdISON2FSCyiy5ziODtY6MBlYP0AE0ddjkBmLMFCbgKVvCkHk+2yPWQnsGnGQ9
+VIogJUOe8Nq2eNXyYeFuJyio5Lh+N8EjVuwR+1VhArdUa8ZHknRYehj2MDK5E/ig
+7PGqszF3ZUTdQlwqb+Am6yzNo+QeHS5IblPSmQIjlwUnsPUya2fYGvcCAwEAAaOB
+hjCBgzAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0T
+AQH/BAIwADAfBgNVHSMEGDAWgBQriJPh0lRQ9LikIL2xeeYLquvsGjAtBgNVHREE
+JjAkghB0ZXN0LkV4QW1QbEUuQ29NghB0ZXN0LkV4QW1QbEUuT3JHMAsGCSqGSIb3
+DQEBBQOCAQEACC57ykXCLdhLUsqvsIZgWHFv6EAt/eZEELV10IEZRwU0lwxrTsJn
+fX9y/scoEqO3qZ8R72b3jwAL4o8Ymx4G7irg+r33eTpjfw6Ut1YCYqZlF+FeEBM6
+VtuzUFREYNM2nvPpdIk1StYrpboDgrpTmiGeeOtL+9zxHuuMKVer2qYLtqi4B9aS
+80D9uFKL61NeStKezKqFUqQJAgXOP2WCTuyp+kSHvzU8wri6fZLBQUUd3tmg/biZ
+bMR1pj6dydCkO0eWl/h488u1kxl5jDhwHG8n8RPYpk5qhbTfLyMdR1p2jCrqrCGR
+FkzzdIZoV/GTez0984v0W5fUE0qANWV4xw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/name_constraint_ok.crt b/chromium/net/data/ssl/certificates/name_constraint_ok.crt
new file mode 100644
index 00000000000..d4293238f47
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/name_constraint_ok.crt
@@ -0,0 +1,109 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAzNtr+fM1JtFhOTaJsZVJr/UYpLxylg28jY/V3SLItFrnYQOs
+XrwjoWI3osQjBe34PrhI7XmHIEACprY5q/bKTOz+PgBiX2tp9oieXtLi9O3qDrlC
+Z0HentNomdR0yojK5nPAloSCgdgX2sA+c6oyzKAmReKlReXEgh0hI43YVILKLLnO
+I4O1jowGVg/QATR12OQGYswUJuApW8KQeT7bI9ZCewacZD1UiiAlQ57w2rZ41fJh
+4W4nKKjkuH43wSNW7BH7VWECt1RrxkeSdFh6GPYwMrkT+KDs8aqzMXdlRN1CXCpv
+4CbrLM2j5B4dLkhuU9KZAiOXBSew9TJrZ9ga9wIDAQABAoIBAEw8V/mDpcMVZm4J
+OsLIgMynlI0xyB7Ja+LupTMPT8u2jKbQ3CPBNi1HxNag0TvSrHCC2jjt4fiBebsa
+02mIhQ6Nn6vpLrK94YgqnW1CY82sgE8MaIbOv48xs5qTswbwUznh18jr9Tlm9rGk
+m1kl/JOkAbo+Ny1E7ZVSS9PUZK5F94oYbq8H/IT9Vh5doyMG66fwhGfZaXSv7+tF
+R8dEkfkyfVBhwcR8H738MkcGVjPRkGGUgaUTHktr3l642YXYYSRbZ1lNIpXM2oHH
+qCRqWy/tg6p2AIMSqRXy+jEn1YSlGI+hndMXDvPJoH8rqbuTIxzNKLneZiSDNVqq
+K9+XalkCgYEA6FhwTyc/4QEyFP2HWArpkcxvws6OVIrJG76K+j/c+G1pUfmhIICY
+Rx/xEAXA7iT7B4S0DWqYMG2eYos6bd2Qj1nK8x/ishM2awlyN4mYjn1fr/AI7fbD
+omtFlUDwQLD0KB630I+KyNLBoHgV70559MHk93uYCq/2cRl+KvDuLL0CgYEA4baP
+qu32Ln9JmThVD9GotlEUJMHkfkSLeXFe+tPjQLuFoeijvMFai60sZ1J/OXf7yMiR
+u6j4QIlepqK1TlvCfIjQeg620az4v1kap3JL9XNWOXjdOzsBeJPPE/dp0akeG5uB
+XXvTSwRWLcxzkfzaEPuy8HWPdphrQ+PleZQiE8MCgYAjQ8EQEnn8kazjSLOxJj7b
+NTdFTwqFRGdPwbTgVK8aOakBmyzcfQgfy3ZQIz9sJcrAEmEtpB8jQpAGjvE4Waem
+Sk+mZRGIS6g3yMBAM68m+Vp7nqgMTibVUQjHpYqRlwoHyNnHWvIKlwpya6eQoc2a
+248ADQ8/mAOEmQTwSY8s1QKBgQC27lnz45aBSsJgfspZ3sdIs9+KhuZj+7O6gkrD
+KRVmclS0yzJhGagDyh9RwgfAkOCscvnByQkibPMcRISC9FVkzxF/ywsaVoDnvBSh
+Hz42uPpp6+4JQiJIEitjeEL4HIN9RoQLOv8dLm+WALyt1er6lrQItI7IRHGy/TIP
+XiJcNwKBgDc4CCqWTS1D3mB8L9Dwom3lrFQRitUbeNmI/787x8Mh2x5kYJZWLXj5
+r8ZCugcUO2N7hW4sZSBXH7N8Udbyud1fLk2pVJmJ4QCk4wvNpITM3ZMSJp7LAKhs
+cmxcrrVKAk47W9EOnTb50THDlsWfO/vO7XhE82N27cnEPPCi+umS
+-----END RSA PRIVATE KEY-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 54358835 (0x33d7333)
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Jan 1 10:00:00 2013 GMT
+ Not After : Dec 31 10:00:00 2023 GMT
+ Subject: O=Acme Co, CN=Leaf certificate
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:cc:db:6b:f9:f3:35:26:d1:61:39:36:89:b1:95:
+ 49:af:f5:18:a4:bc:72:96:0d:bc:8d:8f:d5:dd:22:
+ c8:b4:5a:e7:61:03:ac:5e:bc:23:a1:62:37:a2:c4:
+ 23:05:ed:f8:3e:b8:48:ed:79:87:20:40:02:a6:b6:
+ 39:ab:f6:ca:4c:ec:fe:3e:00:62:5f:6b:69:f6:88:
+ 9e:5e:d2:e2:f4:ed:ea:0e:b9:42:67:41:de:9e:d3:
+ 68:99:d4:74:ca:88:ca:e6:73:c0:96:84:82:81:d8:
+ 17:da:c0:3e:73:aa:32:cc:a0:26:45:e2:a5:45:e5:
+ c4:82:1d:21:23:8d:d8:54:82:ca:2c:b9:ce:23:83:
+ b5:8e:8c:06:56:0f:d0:01:34:75:d8:e4:06:62:cc:
+ 14:26:e0:29:5b:c2:90:79:3e:db:23:d6:42:7b:06:
+ 9c:64:3d:54:8a:20:25:43:9e:f0:da:b6:78:d5:f2:
+ 61:e1:6e:27:28:a8:e4:b8:7e:37:c1:23:56:ec:11:
+ fb:55:61:02:b7:54:6b:c6:47:92:74:58:7a:18:f6:
+ 30:32:b9:13:f8:a0:ec:f1:aa:b3:31:77:65:44:dd:
+ 42:5c:2a:6f:e0:26:eb:2c:cd:a3:e4:1e:1d:2e:48:
+ 6e:53:d2:99:02:23:97:05:27:b0:f5:32:6b:67:d8:
+ 1a:f7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Authority Key Identifier:
+ keyid:2B:88:93:E1:D2:54:50:F4:B8:A4:20:BD:B1:79:E6:0B:AA:EB:EC:1A
+
+ X509v3 Subject Alternative Name:
+ DNS:test.ExAmPlE.CoM, DNS:example.notarealtld
+ Signature Algorithm: sha512WithRSAEncryption
+ 4f:71:b7:f3:77:b7:66:31:6b:7d:9b:8d:32:fa:18:02:3c:1f:
+ 54:2e:7d:3c:8d:f9:e7:65:f3:18:64:00:3a:6f:c7:ef:3b:69:
+ 0d:d6:3d:d6:dd:79:1d:e7:ca:fb:8c:36:32:98:38:7b:3c:de:
+ 52:b9:0e:a5:dd:c5:12:eb:aa:e8:e9:1b:64:df:25:a7:72:3b:
+ 87:4d:bd:69:a2:56:dc:1e:38:29:62:0a:18:c2:43:19:df:7e:
+ 1d:31:db:b6:5c:cb:aa:70:13:58:c0:ca:8a:66:2a:17:49:d7:
+ 2b:45:5b:bb:f3:2e:4e:53:85:80:7d:47:69:4f:cf:f4:ef:6b:
+ 39:8c:1d:5c:70:d4:5d:29:6b:79:14:2d:41:4d:da:49:8e:c1:
+ b0:65:3e:c8:0b:97:72:b4:21:10:f2:bb:a1:55:cb:43:57:6d:
+ c8:fe:6e:3f:19:57:52:f0:47:e6:04:89:71:28:31:7a:b5:a3:
+ b1:10:7d:ef:c4:a5:f2:80:c0:0a:71:e6:0d:bd:9c:59:a1:32:
+ 94:83:65:2f:f7:e1:47:19:e4:cc:c8:66:2a:fa:f4:ad:c3:c9:
+ 4d:28:d8:37:91:60:1b:b6:24:16:e5:9d:16:36:ca:fd:5e:4e:
+ 0f:4e:18:10:12:34:0a:a4:66:84:ee:6e:df:84:01:5a:ac:34:
+ 0e:68:df:c6
+-----BEGIN CERTIFICATE-----
+MIIDSDCCAjKgAwIBAgIEAz1zMzALBgkqhkiG9w0BAQ0wFzEVMBMGA1UEAwwMVGVz
+dCBSb290IENBMB4XDTEzMDEwMTEwMDAwMFoXDTIzMTIzMTEwMDAwMFowLTEQMA4G
+A1UEChMHQWNtZSBDbzEZMBcGA1UEAxMQTGVhZiBjZXJ0aWZpY2F0ZTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMzba/nzNSbRYTk2ibGVSa/1GKS8cpYN
+vI2P1d0iyLRa52EDrF68I6FiN6LEIwXt+D64SO15hyBAAqa2Oav2ykzs/j4AYl9r
+afaInl7S4vTt6g65QmdB3p7TaJnUdMqIyuZzwJaEgoHYF9rAPnOqMsygJkXipUXl
+xIIdISON2FSCyiy5ziODtY6MBlYP0AE0ddjkBmLMFCbgKVvCkHk+2yPWQnsGnGQ9
+VIogJUOe8Nq2eNXyYeFuJyio5Lh+N8EjVuwR+1VhArdUa8ZHknRYehj2MDK5E/ig
+7PGqszF3ZUTdQlwqb+Am6yzNo+QeHS5IblPSmQIjlwUnsPUya2fYGvcCAwEAAaOB
+iTCBhjAOBgNVHQ8BAf8EBAMCAKAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0T
+AQH/BAIwADAfBgNVHSMEGDAWgBQriJPh0lRQ9LikIL2xeeYLquvsGjAwBgNVHREE
+KTAnghB0ZXN0LkV4QW1QbEUuQ29NghNleGFtcGxlLm5vdGFyZWFsdGxkMAsGCSqG
+SIb3DQEBDQOCAQEAT3G383e3ZjFrfZuNMvoYAjwfVC59PI3552XzGGQAOm/H7ztp
+DdY91t15HefK+4w2Mpg4ezzeUrkOpd3FEuuq6OkbZN8lp3I7h029aaJW3B44KWIK
+GMJDGd9+HTHbtlzLqnATWMDKimYqF0nXK0Vbu/MuTlOFgH1HaU/P9O9rOYwdXHDU
+XSlreRQtQU3aSY7BsGU+yAuXcrQhEPK7oVXLQ1dtyP5uPxlXUvBH5gSJcSgxerWj
+sRB978Sl8oDACnHmDb2cWaEylINlL/fhRxnkzMhmKvr0rcPJTSjYN5FgG7YkFuWd
+FjbK/V5OD04YEBI0CqRmhO5u34QBWqw0Dmjfxg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/quic_intermediate.crt b/chromium/net/data/ssl/certificates/quic_intermediate.crt
index ca1e6f6f13e..29e3a66fd37 100644
--- a/chromium/net/data/ssl/certificates/quic_intermediate.crt
+++ b/chromium/net/data/ssl/certificates/quic_intermediate.crt
@@ -10,17 +10,26 @@ Certificate:
Subject: O=Acme Co, CN=Intermediate CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:af:95:dd:a0:eb:d7:c3:ba:a6:ae:db:6e:05:68:
- a0:00:15:a1:85:d1:89:ba:be:3a:7a:3b:8c:3b:41:
- 07:76:63:71:28:f7:bf:a5:fb:b3:28:94:f9:9a:de:
- 1d:03:00:ce:5e:25:06:6a:e6:c7:0a:6b:6d:d3:76:
- 95:57:f5:16:f8:f0:43:de:b7:c7:1b:0b:83:f4:70:
- e6:29:a1:8d:22:12:9a:df:4b:31:e8:9b:86:7d:95:
- 29:97:18:c1:34:2f:b6:a7:c1:c7:46:d6:9c:c6:a6:
- ae:6e:dd:8f:be:c2:ec:02:00:d2:54:f6:0f:a0:cc:
- af:04:85:65:98:a1:ea:73:f1
+ 00:cd:35:50:e7:0a:68:80:e5:2b:f0:01:2b:93:11:
+ 0c:50:f7:23:e1:d8:d2:ed:48:9a:ea:3b:64:9f:82:
+ fa:e4:ad:23:96:a8:a1:9b:31:d1:d6:4a:b2:79:f1:
+ c1:80:03:18:41:54:a5:30:3a:82:bd:57:10:9c:fd:
+ 5d:34:fd:19:d3:21:1b:cb:06:e7:66:40:e1:27:89:
+ 98:82:2d:d7:2e:0d:5c:05:9a:74:0d:45:de:32:5e:
+ 78:4e:81:b4:c8:60:97:f0:8b:2a:8c:e0:57:f6:b9:
+ db:5a:53:64:1d:27:e0:93:47:d9:93:ee:ac:f6:7b:
+ e7:d2:97:b1:a6:85:37:75:ff:aa:f7:8f:ae:92:4e:
+ 30:0b:56:54:fd:32:f9:9d:3c:d8:2e:95:f5:64:17:
+ ff:26:d2:65:e2:b1:78:6c:83:5d:67:a4:d8:ae:89:
+ 6b:6e:b3:4b:35:a5:b1:03:3c:20:97:79:ed:0b:f8:
+ de:25:a1:3a:50:70:40:ae:9e:04:75:a2:6a:2f:15:
+ 84:5b:08:c3:e0:55:4e:47:db:bc:79:25:b0:2e:58:
+ 0d:bc:aa:a6:f2:ee:cd:e6:b8:02:8c:5b:00:b3:3d:
+ 44:d0:a6:bf:b3:e7:2e:9d:46:70:de:45:d1:bd:79:
+ bd:c0:f2:47:0b:71:28:60:91:c2:98:73:15:2d:b4:
+ b1:f3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
@@ -30,24 +39,37 @@ Certificate:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
- 9a:68:79:17:6c:13:20:b3:5f:01:ca:ae:c0:bf:d2:7b:98:bf:
- dd:4d:d1:c3:a5:ab:01:47:2e:c8:61:b4:f5:1d:55:04:f0:eb:
- 5d:84:5a:78:09:b0:f1:42:64:14:e8:9e:ba:c3:38:32:d3:16:
- fe:e1:65:1f:76:da:e4:c0:83:62:4a:ae:d0:4e:00:2e:38:52:
- 91:81:62:94:b0:3d:69:b3:87:72:39:55:94:9e:ca:2c:ca:51:
- 3c:d3:3f:d2:1c:92:d3:de:df:ba:bc:45:9b:30:99:b4:39:f8:
- 17:55:94:7d:3a:ba:0e:e9:3f:2d:bc:f0:ea:6d:17:85:23:e4:
- ca:94
+ b5:66:2c:a1:f8:76:8a:3b:6c:06:2d:d5:1e:4b:25:5c:b8:6d:
+ ee:0e:7e:09:a4:43:58:65:93:e9:da:6c:42:2e:5d:74:3f:79:
+ 61:4d:e5:72:45:d7:2d:fd:73:8e:e2:98:fe:8e:4a:e4:11:6e:
+ 94:5c:d9:84:c9:cb:a1:1c:fa:95:d9:15:c1:87:72:98:2e:63:
+ df:67:4d:04:1f:da:d7:29:66:ec:20:ea:b6:5d:71:dd:bc:5a:
+ 16:55:87:8f:51:9f:40:05:00:3b:21:ee:74:bc:3b:11:9a:10:
+ ba:b4:e8:5e:6e:90:c3:22:ca:da:92:f8:fb:8e:73:fd:69:91:
+ 13:48:11:01:58:ae:f4:b2:8c:38:56:f0:a5:3b:2a:64:5c:25:
+ 9a:bb:fd:94:27:34:af:b4:21:4c:08:23:3c:fb:3f:08:6f:07:
+ b8:05:9d:85:1d:73:0e:f0:83:f4:3c:9b:cc:aa:fd:3d:fa:82:
+ a4:dd:01:10:9d:10:2c:c4:47:64:ca:b4:b5:6e:be:59:d1:d2:
+ a1:6a:b5:d3:08:23:49:fc:4f:d4:f3:a5:63:b5:e1:34:19:9d:
+ 8c:33:0f:8e:47:01:9a:eb:2a:eb:cb:f4:1a:0c:ee:8e:68:d3:
+ c1:8e:fd:4b:93:ff:40:8c:3a:11:2b:62:a3:c1:a7:13:bd:26:
+ 37:c5:85:c5
-----BEGIN CERTIFICATE-----
-MIIB+DCCAWOgAwIBAgIBAjALBgkqhkiG9w0BAQUwJDEQMA4GA1UEChMHQWNtZSBD
+MIIC/zCCAemgAwIBAgIBAjALBgkqhkiG9w0BAQUwJDEQMA4GA1UEChMHQWNtZSBD
bzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xMzAxMDExMDAwMDBaFw0yMzEyMzExMDAw
MDBaMCwxEDAOBgNVBAoTB0FjbWUgQ28xGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBD
-QTCBnTALBgkqhkiG9w0BAQEDgY0AMIGJAoGBAK+V3aDr18O6pq7bbgVooAAVoYXR
-ibq+Ono7jDtBB3ZjcSj3v6X7syiU+ZreHQMAzl4lBmrmxwprbdN2lVf1FvjwQ963
-xxsLg/Rw5imhjSISmt9LMeibhn2VKZcYwTQvtqfBx0bWnMamrm7dj77C7AIA0lT2
-D6DMrwSFZZih6nPxAgMBAAGjODA2MA4GA1UdDwEB/wQEAwIABDATBgNVHSUEDDAK
-BggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MAsGCSqGSIb3DQEBBQOBgQCaaHkX
-bBMgs18Byq7Av9J7mL/dTdHDpasBRy7IYbT1HVUE8OtdhFp4CbDxQmQU6J66wzgy
-0xb+4WUfdtrkwINiSq7QTgAuOFKRgWKUsD1ps4dyOVWUnsosylE80z/SHJLT3t+6
-vEWbMJm0OfgXVZR9OroO6T8tvPDqbReFI+TKlA==
+QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM01UOcKaIDlK/ABK5MR
+DFD3I+HY0u1Imuo7ZJ+C+uStI5aooZsx0dZKsnnxwYADGEFUpTA6gr1XEJz9XTT9
+GdMhG8sG52ZA4SeJmIIt1y4NXAWadA1F3jJeeE6BtMhgl/CLKozgV/a521pTZB0n
+4JNH2ZPurPZ759KXsaaFN3X/qvePrpJOMAtWVP0y+Z082C6V9WQX/ybSZeKxeGyD
+XWek2K6Ja26zSzWlsQM8IJd57Qv43iWhOlBwQK6eBHWiai8VhFsIw+BVTkfbvHkl
+sC5YDbyqpvLuzea4AoxbALM9RNCmv7PnLp1GcN5F0b15vcDyRwtxKGCRwphzFS20
+sfMCAwEAAaM4MDYwDgYDVR0PAQH/BAQDAgAEMBMGA1UdJQQMMAoGCCsGAQUFBwMB
+MA8GA1UdEwEB/wQFMAMBAf8wCwYJKoZIhvcNAQEFA4IBAQC1Ziyh+HaKO2wGLdUe
+SyVcuG3uDn4JpENYZZPp2mxCLl10P3lhTeVyRdct/XOO4pj+jkrkEW6UXNmEycuh
+HPqV2RXBh3KYLmPfZ00EH9rXKWbsIOq2XXHdvFoWVYePUZ9ABQA7Ie50vDsRmhC6
+tOhebpDDIsrakvj7jnP9aZETSBEBWK70sow4VvClOypkXCWau/2UJzSvtCFMCCM8
++z8Ibwe4BZ2FHXMO8IP0PJvMqv09+oKk3QEQnRAsxEdkyrS1br5Z0dKharXTCCNJ
+/E/U86VjteE0GZ2MMw+ORwGa6yrry/QaDO6OaNPBjv1Lk/9AjDoRK2KjwacTvSY3
+xYXF
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/quic_intermediate.key b/chromium/net/data/ssl/certificates/quic_intermediate.key
new file mode 100644
index 00000000000..a8d1b8cfaa9
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/quic_intermediate.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAzTVQ5wpogOUr8AErkxEMUPcj4djS7Uia6jtkn4L65K0jlqih
+mzHR1kqyefHBgAMYQVSlMDqCvVcQnP1dNP0Z0yEbywbnZkDhJ4mYgi3XLg1cBZp0
+DUXeMl54ToG0yGCX8IsqjOBX9rnbWlNkHSfgk0fZk+6s9nvn0pexpoU3df+q94+u
+kk4wC1ZU/TL5nTzYLpX1ZBf/JtJl4rF4bINdZ6TYrolrbrNLNaWxAzwgl3ntC/je
+JaE6UHBArp4EdaJqLxWEWwjD4FVOR9u8eSWwLlgNvKqm8u7N5rgCjFsAsz1E0Ka/
+s+cunUZw3kXRvXm9wPJHC3EoYJHCmHMVLbSx8wIDAQABAoIBAQCSQevVoA93vt8g
+AlWCTmZO1raWY6mCQXtYcth28C3OCrEQ0kPMjyeV6ktmqq5VhN8mwSOzSiCgvosy
+uUpTWAmt9y0N+W+364oOWf1+2xlA03jA7aLFSwThNX/dxIiLQH1KjoXXPpazXShA
+KqtyNFfV4SHsU/KnAwzphgCyRMSQrk/5YZfdfkbnhKhXGtdBmja+4wB7khOcv5Vb
++S2FAxftWdyTo3AOSwSED5Evq8gML4RWl46bZ5r2Gu6W+eBxDyRT+iftNLOMO6PL
+7ivn3mbZSBUxOZPvKNh6sxrUsSnxUrcZ5d819yiRolKywY5lM+BrqP9CFMfEKFP9
+R9zooJdhAoGBAOLXZviVGzOgLB418GKkw5NReeiKNPPX+w7vX+VYTiw60yRf87iS
+RhgqTXQDYKExgOO/giEJ0M3VJ6RU8MqqeHtDoKPjzZmGXs/zB0WSPIYa1A4QjQHO
+UNE1OvTwxHQCKZg0u46AZMnZWHpt005iVQ4LG8uHpUYdYxLn0LfPTvWpAoGBAOeW
+Cecnv/1GU5ft4Y8LDlFzwFzgRjRBMuX8erQz6lJUlnWLq/ZwSbag0qK+9iVfrvUT
+F9zNpfgFFsyMI8OPeJsEJkvQEZA4XDEZyvZCstjxWvI81T1bnc1/JU+YeaFcqSDq
+X7+ARNquoH9ntbXRRW4ACafQdY3KNqeBCpKBlfQ7AoGAVK/cNoPcMuribajvhLRE
+e7RYUfN/D2YbyZiecY4FKUgQ2ayk3cxmNNFeNyino6ZKmzw9Bb6XYLDqatR3TQJV
+lpdJ2sXKVT2wGex+U3/j7qEHd/S/3+O5klFQIG/et/yysKtHNk1C04S8HoDv+XyG
+ioalKtgKYOHJwh4fcvAHZ3kCgYAen25rzIvMl/IR0vjSi2m3R5EWNunRmxV55+rp
+zTuc62aB4Jg6nBqDNbzknE+8HWzrJz0ui1r48uNS5O0NvPj7to7B05+e7HT0YS6/
+ZY50tWWLRpQD6wtw0vFCFy1uMuyCV7uVfQadzB2Y+0PB6Qw/QW4FbME+oJCdkaiu
+OshzZQKBgQCXKYjh2fwBozDn7u8OQZ6sJt74EOZqAMfv7NQ2xbD5Jg5ABnOcFrXu
+FWvE9KoiJYmDD26lFIbmQ9KlAsQjKrOiRit50IALrlfATRYpEGnlO8M+c209+5wx
+FVncGUcoKbzLIrIJz7Cfd3MLbB8wSO8RBpeTa0IU5XhkTnk130Ue7A==
+-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/quic_root.crt b/chromium/net/data/ssl/certificates/quic_root.crt
index 55502e6b94e..730bfcd6816 100644
--- a/chromium/net/data/ssl/certificates/quic_root.crt
+++ b/chromium/net/data/ssl/certificates/quic_root.crt
@@ -10,17 +10,26 @@ Certificate:
Subject: O=Acme Co, CN=Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:f3:8f:b5:01:f7:8f:bf:0e:c3:bc:2e:43:f9:63:
- 32:ae:e2:70:2d:77:70:bf:32:57:77:dd:00:f4:16:
- 08:e2:f4:b8:b4:c9:bc:41:be:54:ba:44:3f:6f:77:
- f9:d1:1b:52:25:16:7d:df:f9:29:79:3c:7c:8f:16:
- e3:85:d5:7c:96:5e:2e:60:b3:80:e1:fc:09:b9:04:
- 4d:ff:bc:05:25:55:96:b8:e7:7e:03:ed:f4:a1:93:
- 54:66:b6:d5:e4:1f:92:94:52:7d:c3:60:89:5f:79:
- f9:63:d1:f4:bb:4d:fa:da:4d:2e:d2:1d:ac:dc:7a:
- 4f:52:67:3f:ad:eb:ed:ba:cd
+ 00:e4:2b:91:c7:7d:ab:32:b7:38:e1:38:ae:c8:b9:
+ 0b:15:1c:64:76:47:84:5d:cb:e7:e7:0c:30:77:84:
+ 6a:8e:75:95:42:b2:78:c8:88:10:ac:98:47:97:38:
+ d1:3a:7f:86:0d:20:f1:1d:70:84:a2:9d:ed:1a:28:
+ af:5e:43:dd:31:a3:bb:b8:5c:c4:83:79:b8:83:9a:
+ e7:a9:63:04:59:93:b6:26:67:2d:dd:e6:2d:bb:e4:
+ 13:eb:d5:17:0b:de:63:46:76:6f:10:05:40:b0:16:
+ fc:ea:f4:97:1c:d6:dc:fe:37:72:d5:40:df:e3:b4:
+ d5:ac:cf:c9:ae:7c:21:49:01:1e:7e:d4:c1:e1:2a:
+ 11:01:b4:70:3a:31:3d:9a:33:b7:7f:20:f2:8b:e7:
+ 54:8e:06:f2:4b:5f:f0:e2:b9:8f:64:1f:50:bd:b3:
+ a5:ac:69:44:42:6c:12:e9:11:9d:74:b4:49:77:e3:
+ 0f:8b:9c:94:53:17:0c:23:ba:61:fa:70:3d:93:8d:
+ ad:5f:dd:4f:32:84:5b:07:50:e4:58:c7:00:45:82:
+ 1f:21:14:4c:bf:43:92:76:fb:24:09:33:df:58:8d:
+ be:87:ee:b5:54:e4:d3:32:f6:b1:2d:69:74:86:ad:
+ 1f:57:7e:9b:05:11:74:b5:c4:68:ac:9a:80:74:7a:
+ 34:89
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
@@ -30,77 +39,36 @@ Certificate:
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
- 7c:0f:20:54:85:ea:e9:68:c5:15:fc:10:8a:09:98:0e:51:53:
- 7a:a3:37:c3:ec:8d:61:2c:49:66:d0:34:0b:8b:68:50:58:75:
- 1f:fb:76:87:89:16:7d:56:d1:be:2f:bb:ef:95:26:92:55:37:
- 6f:ca:82:e2:d4:93:33:80:1f:9c:b9:2d:1e:ee:3b:90:7d:13:
- 2e:28:9b:17:8c:15:5f:12:eb:ed:f2:86:2f:a5:f5:59:e4:f3:
- 07:a9:99:2d:32:70:d4:2a:d0:43:f2:1c:92:6d:75:f8:60:fa:
- b5:8f:4f:07:6b:f6:c0:80:b3:4f:c8:9f:ed:11:bd:4d:d9:d7:
- 4a:2c
+ 96:cd:db:46:6e:5b:de:fa:f1:d3:1c:e0:fe:47:67:2a:59:d5:
+ f8:c4:0b:25:14:0b:06:8d:82:67:f4:a9:36:e8:53:bc:eb:40:
+ 51:05:8a:42:09:e7:48:a3:7c:42:6d:c1:37:06:49:cf:58:87:
+ d0:0e:c7:9e:4b:0e:34:72:f8:65:65:b2:c4:68:ca:a3:14:e9:
+ 11:5c:da:78:4e:74:80:43:dc:b8:b6:ce:a8:0c:a2:8f:52:59:
+ 89:e0:5a:01:e5:e9:b8:4b:31:91:25:bf:7d:e1:7c:86:e9:36:
+ c1:5b:10:e5:2c:cc:6f:99:c4:66:79:30:41:1f:0b:f9:4b:ea:
+ 1e:8a:45:73:3c:79:21:20:c8:80:c4:f4:e9:4f:85:69:7c:2e:
+ 61:80:3a:4f:5b:92:be:97:12:75:9e:43:09:01:b6:b3:a1:c1:
+ 5f:2d:86:be:d1:6c:55:ee:27:f8:bf:3a:bc:fb:b2:42:8a:6f:
+ 51:a0:d3:46:54:f6:1e:73:42:2a:95:5e:eb:bc:40:6b:71:bf:
+ 90:94:62:f4:90:17:82:e5:1e:33:db:f4:50:11:e5:55:10:09:
+ 6a:11:a9:1e:d4:07:60:58:f7:16:b1:bd:8b:29:f6:3d:61:ad:
+ 73:da:ae:e3:e4:6e:59:46:7f:c0:fb:fa:be:6d:7c:31:94:86:
+ 2e:b3:29:7b
-----BEGIN CERTIFICATE-----
-MIIB8DCCAVugAwIBAgIBATALBgkqhkiG9w0BAQUwJDEQMA4GA1UEChMHQWNtZSBD
+MIIC9zCCAeGgAwIBAgIBATALBgkqhkiG9w0BAQUwJDEQMA4GA1UEChMHQWNtZSBD
bzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xMzAxMDExMDAwMDBaFw0yMzEyMzExMDAw
-MDBaMCQxEDAOBgNVBAoTB0FjbWUgQ28xEDAOBgNVBAMTB1Jvb3QgQ0EwgZ0wCwYJ
-KoZIhvcNAQEBA4GNADCBiQKBgQDzj7UB94+/DsO8LkP5YzKu4nAtd3C/Mld33QD0
-Fgji9Li0ybxBvlS6RD9vd/nRG1IlFn3f+Sl5PHyPFuOF1XyWXi5gs4Dh/Am5BE3/
-vAUlVZa4534D7fShk1RmttXkH5KUUn3DYIlfeflj0fS7TfraTS7SHazcek9SZz+t
-6+26zQIDAQABozgwNjAOBgNVHQ8BAf8EBAMCAAQwEwYDVR0lBAwwCgYIKwYBBQUH
-AwEwDwYDVR0TAQH/BAUwAwEB/zALBgkqhkiG9w0BAQUDgYEAfA8gVIXq6WjFFfwQ
-igmYDlFTeqM3w+yNYSxJZtA0C4toUFh1H/t2h4kWfVbRvi+775UmklU3b8qC4tST
-M4AfnLktHu47kH0TLiibF4wVXxLr7fKGL6X1WeTzB6mZLTJw1CrQQ/Ickm11+GD6
-tY9PB2v2wICzT8if7RG9TdnXSiw=
------END CERTIFICATE-----
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha1WithRSAEncryption
- Issuer: O=Acme Co, CN=Root CA
- Validity
- Not Before: Jan 1 10:00:00 2013 GMT
- Not After : Dec 31 10:00:00 2023 GMT
- Subject: O=Acme Co, CN=Root CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
- Modulus:
- 00:f3:8f:b5:01:f7:8f:bf:0e:c3:bc:2e:43:f9:63:
- 32:ae:e2:70:2d:77:70:bf:32:57:77:dd:00:f4:16:
- 08:e2:f4:b8:b4:c9:bc:41:be:54:ba:44:3f:6f:77:
- f9:d1:1b:52:25:16:7d:df:f9:29:79:3c:7c:8f:16:
- e3:85:d5:7c:96:5e:2e:60:b3:80:e1:fc:09:b9:04:
- 4d:ff:bc:05:25:55:96:b8:e7:7e:03:ed:f4:a1:93:
- 54:66:b6:d5:e4:1f:92:94:52:7d:c3:60:89:5f:79:
- f9:63:d1:f4:bb:4d:fa:da:4d:2e:d2:1d:ac:dc:7a:
- 4f:52:67:3f:ad:eb:ed:ba:cd
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Key Usage: critical
- Certificate Sign
- X509v3 Extended Key Usage:
- TLS Web Server Authentication
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: sha1WithRSAEncryption
- 7c:0f:20:54:85:ea:e9:68:c5:15:fc:10:8a:09:98:0e:51:53:
- 7a:a3:37:c3:ec:8d:61:2c:49:66:d0:34:0b:8b:68:50:58:75:
- 1f:fb:76:87:89:16:7d:56:d1:be:2f:bb:ef:95:26:92:55:37:
- 6f:ca:82:e2:d4:93:33:80:1f:9c:b9:2d:1e:ee:3b:90:7d:13:
- 2e:28:9b:17:8c:15:5f:12:eb:ed:f2:86:2f:a5:f5:59:e4:f3:
- 07:a9:99:2d:32:70:d4:2a:d0:43:f2:1c:92:6d:75:f8:60:fa:
- b5:8f:4f:07:6b:f6:c0:80:b3:4f:c8:9f:ed:11:bd:4d:d9:d7:
- 4a:2c
------BEGIN CERTIFICATE-----
-MIIB8DCCAVugAwIBAgIBATALBgkqhkiG9w0BAQUwJDEQMA4GA1UEChMHQWNtZSBD
-bzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xMzAxMDExMDAwMDBaFw0yMzEyMzExMDAw
-MDBaMCQxEDAOBgNVBAoTB0FjbWUgQ28xEDAOBgNVBAMTB1Jvb3QgQ0EwgZ0wCwYJ
-KoZIhvcNAQEBA4GNADCBiQKBgQDzj7UB94+/DsO8LkP5YzKu4nAtd3C/Mld33QD0
-Fgji9Li0ybxBvlS6RD9vd/nRG1IlFn3f+Sl5PHyPFuOF1XyWXi5gs4Dh/Am5BE3/
-vAUlVZa4534D7fShk1RmttXkH5KUUn3DYIlfeflj0fS7TfraTS7SHazcek9SZz+t
-6+26zQIDAQABozgwNjAOBgNVHQ8BAf8EBAMCAAQwEwYDVR0lBAwwCgYIKwYBBQUH
-AwEwDwYDVR0TAQH/BAUwAwEB/zALBgkqhkiG9w0BAQUDgYEAfA8gVIXq6WjFFfwQ
-igmYDlFTeqM3w+yNYSxJZtA0C4toUFh1H/t2h4kWfVbRvi+775UmklU3b8qC4tST
-M4AfnLktHu47kH0TLiibF4wVXxLr7fKGL6X1WeTzB6mZLTJw1CrQQ/Ickm11+GD6
-tY9PB2v2wICzT8if7RG9TdnXSiw=
+MDBaMCQxEDAOBgNVBAoTB0FjbWUgQ28xEDAOBgNVBAMTB1Jvb3QgQ0EwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkK5HHfasytzjhOK7IuQsVHGR2R4Rd
+y+fnDDB3hGqOdZVCsnjIiBCsmEeXONE6f4YNIPEdcISine0aKK9eQ90xo7u4XMSD
+ebiDmuepYwRZk7YmZy3d5i275BPr1RcL3mNGdm8QBUCwFvzq9Jcc1tz+N3LVQN/j
+tNWsz8mufCFJAR5+1MHhKhEBtHA6MT2aM7d/IPKL51SOBvJLX/DiuY9kH1C9s6Ws
+aURCbBLpEZ10tEl34w+LnJRTFwwjumH6cD2Tja1f3U8yhFsHUORYxwBFgh8hFEy/
+Q5J2+yQJM99Yjb6H7rVU5NMy9rEtaXSGrR9XfpsFEXS1xGismoB0ejSJAgMBAAGj
+ODA2MA4GA1UdDwEB/wQEAwIABDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMB
+Af8EBTADAQH/MAsGCSqGSIb3DQEBBQOCAQEAls3bRm5b3vrx0xzg/kdnKlnV+MQL
+JRQLBo2CZ/SpNuhTvOtAUQWKQgnnSKN8Qm3BNwZJz1iH0A7HnksONHL4ZWWyxGjK
+oxTpEVzaeE50gEPcuLbOqAyij1JZieBaAeXpuEsxkSW/feF8huk2wVsQ5SzMb5nE
+ZnkwQR8L+UvqHopFczx5ISDIgMT06U+FaXwuYYA6T1uSvpcSdZ5DCQG2s6HBXy2G
+vtFsVe4n+L86vPuyQopvUaDTRlT2HnNCKpVe67xAa3G/kJRi9JAXguUeM9v0UBHl
+VRAJahGpHtQHYFj3FrG9iyn2PWGtc9qu4+RuWUZ/wPv6vm18MZSGLrMpew==
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/quic_root.key b/chromium/net/data/ssl/certificates/quic_root.key
new file mode 100644
index 00000000000..9791d1fdb48
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/quic_root.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA5CuRx32rMrc44TiuyLkLFRxkdkeEXcvn5wwwd4RqjnWVQrJ4
+yIgQrJhHlzjROn+GDSDxHXCEop3tGiivXkPdMaO7uFzEg3m4g5rnqWMEWZO2Jmct
+3eYtu+QT69UXC95jRnZvEAVAsBb86vSXHNbc/jdy1UDf47TVrM/JrnwhSQEeftTB
+4SoRAbRwOjE9mjO3fyDyi+dUjgbyS1/w4rmPZB9QvbOlrGlEQmwS6RGddLRJd+MP
+i5yUUxcMI7ph+nA9k42tX91PMoRbB1DkWMcARYIfIRRMv0OSdvskCTPfWI2+h+61
+VOTTMvaxLWl0hq0fV36bBRF0tcRorJqAdHo0iQIDAQABAoIBAC9L/Mb+fMthgY/m
+IQ0IloyEuyptfrm2t9aEB1PvBeuL4inWNwVSdypf0o89PtnCb3YvOuvgVA4lcG24
+u0luBd7xUstPp4idZasaJCVPmio7XUmun6pcuWQ2Tg7XuBREwA1uJW2LuTIHQdwu
+YVigDWVA9zPPY9metaBB3kul/XxVM7+fXheCHzXTzJEaAw+7Gexe8QYuq4ftcocD
+f7O/j/ts3IrKa1Xrl5RFC/tCNwpZ3yrp/Scdit32wbvCQwcdZ6/dDu6BWY4GJm8q
+z7kaDZkXQa50EzT9g+DPTLC3qA2USh8M+NfqVjdHYkAqj64StCjvXHboTbDdZXoz
+HvsONNUCgYEA/THRfqRpRPHW9ONSyRma6+XtzrCepVn/ceguO9bfD0e2+l1/6uXQ
+hctuwelRD89Z6Ir5kW2I8fRT0mPhCcuv5TW1hOiwK6WKasYxRu3ox+bZiAoRsEBd
+Xm4bvr814E/QO5DsDd5KMdEPb6ulStI1y94atCjX50r+vZWMGG82dK8CgYEA5rLF
+FPBt+049Wq8bIXXVbInwPD0hHeIrhfTqsDeuLwYsmf7o29dU7sjDFS5x1cCfVsqO
+UpXM5J4C3lhDC9ZTX0vVgT/TROq7etRZeBHVN+CJS0jgeMjUqWQTZYPMzE0Bu8/P
++9mqSZzkwipesG4JpdSkt/1IOIoDrbK8mYpDqEcCgYEA5wfGOOCcjaR+mAW1THpo
+ukebrrXKjOaKB83sIf32m2K8u8cFKbl5hBwUfCwBI4P4bhAhmWlxRBXFRnyMovuR
+DHztnNEVrz3mB3fBDw+XEJC8fT1y1nhkuf2Oo4amCn/JahDa0+y5lqtEgokE0jjt
+jZCknS+Hki0ENMl4g/M2pVECgYB8oF6vbSM8+4tRjf8OGGXveKT7JdraFfCFMUYH
+ZE0IwkEeAAMzoCQVywb4TlrYqnJppIs2Og6yAlpyWyP9JQ9tD76LUDuFo3kcZdLf
+dmLFCNuifAAnv/aCe7muwYDFbWReXWlyGKhRlBxQeCsnDIrRtwo1CvMU+Bn8n+4a
+1AKwyQKBgGpBZwN28VjqYkM5fO6RDNBvgQ1ApfSh/Kfwg0MrO8uhmvlWDuWCoei4
+v08pchPRO75ktIv4r9bR7ylTpB9JhCe2kNABWma4mnlUg4+nmiWMTZo6Pyabstkt
+yzGIGZYdMDzOBjph7JxQZhGijz3uVc9CiFg+2AElbpCYDRHn5N3s
+-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/quic_test.example.com.crt b/chromium/net/data/ssl/certificates/quic_test.example.com.crt
index 375cedd0339..b8123386fa9 100644
--- a/chromium/net/data/ssl/certificates/quic_test.example.com.crt
+++ b/chromium/net/data/ssl/certificates/quic_test.example.com.crt
@@ -10,17 +10,26 @@ Certificate:
Subject: O=Acme Co, CN=Leaf certificate
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
- Public-Key: (1024 bit)
+ Public-Key: (2048 bit)
Modulus:
- 00:c1:31:32:b2:28:dc:0d:a4:e0:4b:54:d6:fa:b7:
- d2:0c:45:29:bf:67:c7:d1:b8:a9:90:63:51:c4:96:
- 9f:86:a9:47:d7:67:f6:f9:1d:37:29:c2:0a:55:a7:
- 8c:29:97:dc:f2:7f:f4:97:d0:d5:44:c9:04:1c:48:
- ea:cc:a9:48:5c:eb:69:11:75:6e:db:7d:1a:5a:c0:
- 9f:ad:a7:b8:0e:3b:a1:61:24:24:6f:64:84:ad:bb:
- 28:06:c2:4a:c8:07:7b:46:33:8a:c7:81:77:92:4f:
- 9d:88:1c:52:04:23:61:12:97:c7:e4:af:90:67:7e:
- fb:ac:3d:23:92:f0:c9:39:6d
+ 00:d5:ca:19:79:8e:a9:ab:46:f0:4e:b7:58:6d:b3:
+ a3:9a:68:10:52:af:f0:00:94:ae:34:bd:b4:50:1f:
+ a3:26:a4:9e:1c:90:37:5b:3d:e8:d7:3b:bc:93:fb:
+ 00:fb:c7:49:54:9b:f1:d0:9a:f2:51:84:7b:59:8b:
+ bd:66:f3:ae:92:5a:b9:63:8c:64:a7:d0:9e:e3:0c:
+ 50:d2:cf:93:9d:e9:4a:11:57:93:c1:de:af:7b:5a:
+ 44:1d:0a:8c:22:a6:1d:c6:ad:e9:8f:16:8d:4e:91:
+ f1:d3:f1:f3:82:fe:f6:55:dc:72:f1:11:07:75:ec:
+ bb:e9:3a:35:87:43:81:5e:dc:43:4a:b7:7c:a1:1a:
+ d5:d2:c1:40:39:69:7d:89:ad:64:1b:31:34:a8:ea:
+ 9e:5e:26:fc:71:d2:c6:6b:e5:c2:73:30:3f:59:a7:
+ 35:8d:a9:a5:e9:3d:43:41:bd:54:f2:2a:e1:15:0c:
+ 35:30:6b:8b:f2:77:ca:5c:07:8f:58:f4:54:77:5e:
+ af:ce:b1:c1:2b:a7:bb:c0:e9:7d:ef:1a:d7:03:ee:
+ 8f:67:ad:c6:e6:1d:a9:e7:91:3f:41:e7:d6:86:20:
+ 8c:53:b3:d8:79:09:e2:4b:15:5a:d8:92:3b:62:4f:
+ 68:e4:cb:d0:a4:4e:b6:7d:3e:5f:b0:24:ea:62:61:
+ cf:7b
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
@@ -32,25 +41,37 @@ Certificate:
X509v3 Subject Alternative Name:
DNS:test.example.com
Signature Algorithm: sha1WithRSAEncryption
- ad:33:55:2a:80:4c:ab:bc:b3:34:f7:b3:7e:fb:05:a8:11:3f:
- a1:35:56:4c:46:2f:8d:24:70:35:3a:66:8d:14:c4:fb:7f:d9:
- 76:de:c4:52:a7:42:8f:70:1d:fd:d5:33:04:69:5d:3c:18:03:
- 8f:db:19:d0:14:d8:1c:0b:b6:74:9c:cf:41:ba:24:d9:c4:c3:
- cf:86:fb:15:3d:c4:99:ea:af:6a:29:34:ed:97:03:38:ed:38:
- b3:21:39:a0:f0:16:ac:81:d3:88:52:d8:5e:a3:6d:e6:ec:3f:
- e9:20:ac:d3:78:7b:ae:59:9e:5d:3b:5e:61:bb:43:88:cd:8e:
- d0:0d
+ 58:c3:dc:e3:4d:ec:76:c6:62:99:ba:ba:6d:da:e4:2f:ec:00:
+ f8:fb:2a:e3:f6:a4:bc:37:c9:53:0f:73:2e:a6:79:8f:6b:ef:
+ 87:16:56:7b:9e:6d:ac:1a:ec:8b:49:71:7d:f2:11:11:a4:0d:
+ 5e:6e:be:93:6b:fe:cb:44:1b:4e:99:2a:d2:eb:d8:91:80:d7:
+ c8:87:fd:c8:fa:cf:c2:68:06:07:2d:60:ae:56:c4:3c:49:4d:
+ e3:05:3f:1b:15:a8:a9:ea:85:d8:af:d3:f5:be:b5:71:28:23:
+ 8d:04:f1:c6:e1:fb:0c:1b:ac:5a:2d:e0:7f:fb:4e:79:47:29:
+ b3:9c:27:09:7d:3c:84:0b:59:0a:03:c5:86:a9:aa:90:49:89:
+ 0b:bc:8e:0e:2e:b1:67:ed:99:be:37:ee:75:7f:a9:fa:62:95:
+ 44:02:1c:99:26:fa:a7:17:61:d2:ec:e1:ca:42:2b:69:97:8f:
+ 71:dc:1b:41:7b:91:a8:d6:b2:82:05:ef:d0:0b:3c:46:a3:9d:
+ 7c:06:81:da:de:b6:54:ad:97:bd:c2:03:02:ff:1b:64:17:25:
+ 4a:4c:9b:85:c1:bb:6f:26:3a:b5:ba:9b:2d:17:b9:bd:36:b1:
+ 43:48:29:f7:da:88:8d:ce:f0:ac:7f:03:a7:93:e1:e9:c1:58:
+ 15:b3:30:22
-----BEGIN CERTIFICATE-----
-MIICGzCCAYagAwIBAgIBAzALBgkqhkiG9w0BAQUwLDEQMA4GA1UEChMHQWNtZSBD
+MIIDIjCCAgygAwIBAgIBAzALBgkqhkiG9w0BAQUwLDEQMA4GA1UEChMHQWNtZSBD
bzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMB4XDTEzMDEwMTEwMDAwMFoXDTIz
MTIzMTEwMDAwMFowLTEQMA4GA1UEChMHQWNtZSBDbzEZMBcGA1UEAxMQTGVhZiBj
-ZXJ0aWZpY2F0ZTCBnTALBgkqhkiG9w0BAQEDgY0AMIGJAoGBAMExMrIo3A2k4EtU
-1vq30gxFKb9nx9G4qZBjUcSWn4apR9dn9vkdNynCClWnjCmX3PJ/9JfQ1UTJBBxI
-6sypSFzraRF1btt9GlrAn62nuA47oWEkJG9khK27KAbCSsgHe0YziseBd5JPnYgc
-UgQjYRKXx+SvkGd++6w9I5LwyTltAgMBAAGjUjBQMA4GA1UdDwEB/wQEAwIAoDAT
-BgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBsGA1UdEQQUMBKCEHRl
-c3QuZXhhbXBsZS5jb20wCwYJKoZIhvcNAQEFA4GBAK0zVSqATKu8szT3s377BagR
-P6E1VkxGL40kcDU6Zo0UxPt/2XbexFKnQo9wHf3VMwRpXTwYA4/bGdAU2BwLtnSc
-z0G6JNnEw8+G+xU9xJnqr2opNO2XAzjtOLMhOaDwFqyB04hS2F6jbebsP+kgrNN4
-e65Znl07XmG7Q4jNjtAN
+ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANXKGXmO
+qatG8E63WG2zo5poEFKv8ACUrjS9tFAfoyaknhyQN1s96Nc7vJP7APvHSVSb8dCa
+8lGEe1mLvWbzrpJauWOMZKfQnuMMUNLPk53pShFXk8Her3taRB0KjCKmHcat6Y8W
+jU6R8dPx84L+9lXccvERB3Xsu+k6NYdDgV7cQ0q3fKEa1dLBQDlpfYmtZBsxNKjq
+nl4m/HHSxmvlwnMwP1mnNY2ppek9Q0G9VPIq4RUMNTBri/J3ylwHj1j0VHder86x
+wSunu8Dpfe8a1wPuj2etxuYdqeeRP0Hn1oYgjFOz2HkJ4ksVWtiSO2JPaOTL0KRO
+tn0+X7Ak6mJhz3sCAwEAAaNSMFAwDgYDVR0PAQH/BAQDAgCgMBMGA1UdJQQMMAoG
+CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwGwYDVR0RBBQwEoIQdGVzdC5leGFtcGxl
+LmNvbTALBgkqhkiG9w0BAQUDggEBAFjD3ONN7HbGYpm6um3a5C/sAPj7KuP2pLw3
+yVMPcy6meY9r74cWVnuebawa7ItJcX3yERGkDV5uvpNr/stEG06ZKtLr2JGA18iH
+/cj6z8JoBgctYK5WxDxJTeMFPxsVqKnqhdiv0/W+tXEoI40E8cbh+wwbrFot4H/7
+TnlHKbOcJwl9PIQLWQoDxYapqpBJiQu8jg4usWftmb437nV/qfpilUQCHJkm+qcX
+YdLs4cpCK2mXj3HcG0F7kajWsoIF79ALPEajnXwGgdretlStl73CAwL/G2QXJUpM
+m4XBu28mOrW6my0Xub02sUNIKffaiI3O8Kx/A6eT4enBWBWzMCI=
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/quic_test.example.com.key b/chromium/net/data/ssl/certificates/quic_test.example.com.key
new file mode 100644
index 00000000000..9449ec673d7
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/quic_test.example.com.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA1coZeY6pq0bwTrdYbbOjmmgQUq/wAJSuNL20UB+jJqSeHJA3
+Wz3o1zu8k/sA+8dJVJvx0JryUYR7WYu9ZvOuklq5Y4xkp9Ce4wxQ0s+TnelKEVeT
+wd6ve1pEHQqMIqYdxq3pjxaNTpHx0/Hzgv72Vdxy8REHdey76To1h0OBXtxDSrd8
+oRrV0sFAOWl9ia1kGzE0qOqeXib8cdLGa+XCczA/Wac1jaml6T1DQb1U8irhFQw1
+MGuL8nfKXAePWPRUd16vzrHBK6e7wOl97xrXA+6PZ63G5h2p55E/QefWhiCMU7PY
+eQniSxVa2JI7Yk9o5MvQpE62fT5fsCTqYmHPewIDAQABAoIBABIwh8pX4Qe5mWiZ
+IOT0i87vW7QtU/Y4sDm8ikLm7jKzfuBfRNZ2hgEKDBlrGcJSSmLwgbqF9GgLJZOQ
+2CSSRyAcp/lYUJgWn+4hdh75mk2tM6gWE3RDRhrwqyrtYs7v40isM1sBSDSPJkwq
+IdXba4oSn5TzJfdalQJa+YLws2kmnKL2cHvHJudazeV3JScfqOkjjYT1HZVFiech
+KQOJo1d3guvyLzzqDJq/BkUvaAQepJu8oXGhq0lApXPit5aRRft4Fw+ewAbU9t7r
+KzRp7YusZ1EQ2A5vn1F9o/JGRERL42BqwjRqfhHnK084Y4GhbpMrMkV0ae5i7xhK
+npKHXIECgYEA5tW5imZhPtBWSSA1w+MTIoqXPrK3eirmgmHSeYtMbfcUwuSiQOXk
+pqEJ9PoVmvNOuQPdbR4kfLuPUJecT+qEMPJAN3aWZYmSUi/6O1fml6DDvf0dx/LW
+4mZ9Mu3DGGmK+zxplwv4IkkOWIu6hPsioyoMd+QxhIk2o7eBViev7IkCgYEA7Rip
+T8k/5PFxs99OasNlu3fJxRbEeJEiZaW21gcK36LosNITgEQs3r2Q6us0hsfUCvEr
++QAjNOk6zsUlTbJYymshStBPh3OTf2zYwg8SXfuAoFDYTNk2uML2alvBRkIKYSVV
+J2Lv2GoYxE1oTIgBDj3Jv4+xPZPx0AYmYsa6AuMCgYAd8wbirQva8X7wd+xh4Plf
+lumuqdNiV2SW8Ag12tvsvI0GCFIA55L2B5jaHwRkmULSgGzfNnT3dgJPK4yNVdkW
+3Kd2Sr2SqPnCDhWCU5JIhARBhzCw+5Hjx/ZggDa62R6+IAV3IodsM1xYIrDthgPl
+dZQujf3au07KiQmP2xBZOQKBgQDACJ5xwgXfT/ORBYgFDxgh2+bvm/4rzRl4DN1m
+wrN66P7g4HXtCMry6cUrkK+tjsJeznGYLxVU8Kax/Jm3MYGbCWQgrVIM2n6X0bhK
+jVyKBH9s2a4nqDMbOMXO5VxIpIq1nkA3M3oh5eUDcdLNUcbRGxiB8EdVIbPUknaa
+wGy+kwKBgQDE90KVnTzZQ6D20pAAvYaFCGkWUvKzf/C7NZcGH+UcWok3BCrkNiGK
+YTEbEs6h26Q8S7Vm7FiRnfVQEW4HPFuQ8wpnYrYFJbfRbGsG8agxju25Kg+EBJGU
+uu83oQ8zNiK/LMtNEGcQotXSVxAUdg1AoS5p1UX9cgmM9MZhkkbJIw==
+-----END RSA PRIVATE KEY-----
diff --git a/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.crt b/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.crt
index 0e6bfbaa8c2..ff8a18def0a 100644
--- a/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.crt
+++ b/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.crt
@@ -12,11 +12,11 @@ Certificate:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
- 04:6d:48:d0:30:76:bb:bf:91:b1:d7:03:c2:fc:95:
- 9b:e0:ea:42:ed:43:2c:a6:b2:23:c4:52:33:93:95:
- 25:fc:16:75:83:9e:0f:0f:91:a5:47:b1:21:91:d4:
- 94:94:30:b8:00:dc:1c:79:2c:fa:72:99:62:b2:fa:
- af:b0:ca:f2:42
+ 04:05:26:22:0e:77:27:83:00:d0:6b:c0:86:af:f4:
+ f9:99:a8:28:a2:ed:5c:c7:5a:dc:29:72:79:4b:ef:
+ e8:85:aa:3a:9b:84:3d:e3:21:b3:6b:0a:79:52:89:
+ ce:bf:f1:a5:42:8b:ad:5e:34:66:5c:e5:e3:6d:aa:
+ d0:8f:b3:ff:d8
ASN1 OID: prime256v1
X509v3 extensions:
X509v3 Key Usage: critical
@@ -28,23 +28,33 @@ Certificate:
X509v3 Subject Alternative Name:
DNS:test.example.com
Signature Algorithm: sha1WithRSAEncryption
- 5d:23:47:b4:b5:0f:38:18:cd:63:90:24:37:f1:da:67:66:a4:
- fe:8d:53:3f:c5:a7:10:e6:21:a3:1d:b7:42:b0:1a:e7:d7:83:
- 3d:ea:7b:6b:89:85:bb:13:77:4d:45:ab:b2:e7:1e:ac:6e:74:
- b6:9f:c4:e0:76:1c:e4:13:e9:6c:b1:20:a3:34:e8:1e:8a:71:
- 51:cb:00:44:71:64:f6:4b:9e:9a:2d:d9:9a:44:62:f5:8c:3c:
- c5:ec:c1:1c:d5:bb:05:53:33:af:70:44:1d:5b:aa:23:67:30:
- 3e:d3:a9:5e:a2:57:84:86:aa:be:bd:7b:4f:74:d9:3b:cd:2e:
- 7e:d1
+ 40:cb:4b:4f:63:13:8a:4e:b9:76:f6:01:82:f1:29:6d:64:d5:
+ ab:87:2f:5f:4f:e9:97:f7:0d:1c:95:f1:c1:7e:9e:26:c1:f8:
+ b5:6c:5c:7d:7a:54:95:96:0c:ad:72:27:e5:47:2d:13:11:0e:
+ 56:d7:37:0e:9b:ea:1e:93:dc:78:e4:12:3b:bd:d5:21:44:92:
+ cb:bf:f1:36:f5:67:3a:85:92:78:da:1b:c6:01:04:4e:6d:a7:
+ 1b:0e:3b:96:59:a2:da:96:db:8e:97:be:dc:f0:7e:54:3b:12:
+ 3a:e9:44:a0:56:e4:a5:9f:f4:58:7a:22:b9:85:be:b7:ad:51:
+ 05:95:70:ba:d0:69:11:f1:2d:47:32:98:bf:e8:1c:9d:f9:19:
+ 29:f8:17:72:30:bb:3d:4a:d7:f5:cc:50:55:14:a9:6b:37:e7:
+ 08:f2:b6:87:4d:d8:3d:fb:eb:0d:45:3b:bc:3c:c1:92:2d:69:
+ 17:39:4b:b4:ff:04:21:ec:cc:74:ff:37:b4:6d:6f:b1:5d:89:
+ 9c:32:ee:99:60:52:87:15:8f:b7:50:ba:2d:f5:fd:11:f1:f8:
+ 38:94:b6:db:7f:cb:fa:2f:d1:41:26:cc:fa:ec:4d:49:ed:d8:
+ a8:8a:13:e7:14:32:6a:c6:6a:66:c9:5b:81:92:ca:cf:b4:7c:
+ c8:91:cc:a8
-----BEGIN CERTIFICATE-----
-MIIB3DCCAUegAwIBAgIBBDALBgkqhkiG9w0BAQUwLDEQMA4GA1UEChMHQWNtZSBD
+MIICXTCCAUegAwIBAgIBBDALBgkqhkiG9w0BAQUwLDEQMA4GA1UEChMHQWNtZSBD
bzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMB4XDTEzMDEwMTEwMDAwMFoXDTIz
MTIzMTEwMDAwMFowMzEQMA4GA1UEChMHQWNtZSBDbzEfMB0GA1UEAxMWRUNEU0Eg
-TGVhZiBjZXJ0aWZpY2F0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABG1I0DB2
-u7+RsdcDwvyVm+DqQu1DLKayI8RSM5OVJfwWdYOeDw+RpUexIZHUlJQwuADcHHks
-+nKZYrL6r7DK8kKjUjBQMA4GA1UdDwEB/wQEAwIAgDATBgNVHSUEDDAKBggrBgEF
+TGVhZiBjZXJ0aWZpY2F0ZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAUmIg53
+J4MA0GvAhq/0+ZmoKKLtXMda3ClyeUvv6IWqOpuEPeMhs2sKeVKJzr/xpUKLrV40
+Zlzl422q0I+z/9ijUjBQMA4GA1UdDwEB/wQEAwIAgDATBgNVHSUEDDAKBggrBgEF
BQcDATAMBgNVHRMBAf8EAjAAMBsGA1UdEQQUMBKCEHRlc3QuZXhhbXBsZS5jb20w
-CwYJKoZIhvcNAQEFA4GBAF0jR7S1DzgYzWOQJDfx2mdmpP6NUz/FpxDmIaMdt0Kw
-GufXgz3qe2uJhbsTd01Fq7LnHqxudLafxOB2HOQT6WyxIKM06B6KcVHLAERxZPZL
-npot2ZpEYvWMPMXswRzVuwVTM69wRB1bqiNnMD7TqV6iV4SGqr69e0902TvNLn7R
+CwYJKoZIhvcNAQEFA4IBAQBAy0tPYxOKTrl29gGC8SltZNWrhy9fT+mX9w0clfHB
+fp4mwfi1bFx9elSVlgytciflRy0TEQ5W1zcOm+oek9x45BI7vdUhRJLLv/E29Wc6
+hZJ42hvGAQRObacbDjuWWaLaltuOl77c8H5UOxI66USgVuSln/RYeiK5hb63rVEF
+lXC60GkR8S1HMpi/6Byd+Rkp+BdyMLs9Stf1zFBVFKlrN+cI8raHTdg9++sNRTu8
+PMGSLWkXOUu0/wQh7Mx0/ze0bW+xXYmcMu6ZYFKHFY+3ULot9f0R8fg4lLbbf8v6
+L9FBJsz67E1J7dioihPnFDJqxmpmyVuBksrPtHzIkcyo
-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.key b/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.key
new file mode 100644
index 00000000000..0e2f2763b2b
--- /dev/null
+++ b/chromium/net/data/ssl/certificates/quic_test_ecc.example.com.key
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIPqnEQNfDLijySw1wwD3RNPQvgPyAPvaZarw327ZM2lwoAoGCCqGSM49
+AwEHoUQDQgAEBSYiDncngwDQa8CGr/T5magoou1cx1rcKXJ5S+/ohao6m4Q94yGz
+awp5UonOv/GlQoutXjRmXOXjbarQj7P/2A==
+-----END EC PRIVATE KEY-----
diff --git a/chromium/net/data/url_request_unittest/filedir-sentinel b/chromium/net/data/url_request_unittest/filedir-sentinel
new file mode 100644
index 00000000000..408adeacd0e
--- /dev/null
+++ b/chromium/net/data/url_request_unittest/filedir-sentinel
@@ -0,0 +1 @@
+This is the file that the URLRequestTest.FileDirOutputSanity test looks for.
diff --git a/chromium/net/disk_cache/backend_impl.cc b/chromium/net/disk_cache/backend_impl.cc
index 0f8c3fdd195..9e2131715db 100644
--- a/chromium/net/disk_cache/backend_impl.cc
+++ b/chromium/net/disk_cache/backend_impl.cc
@@ -45,7 +45,6 @@ const char* kIndexName = "index";
// for most users.
const int k64kEntriesStore = 240 * 1000 * 1000;
const int kBaseTableLen = 64 * 1024;
-const int kDefaultCacheSize = 80 * 1024 * 1024;
// Avoid trimming the cache for the first 5 minutes (10 timer ticks).
const int kTrimDelay = 10;
@@ -108,37 +107,6 @@ void FinalCleanupCallback(disk_cache::BackendImpl* backend) {
namespace disk_cache {
-// Returns the preferred maximum number of bytes for the cache given the
-// number of available bytes.
-int PreferedCacheSize(int64 available) {
- // Return 80% of the available space if there is not enough space to use
- // kDefaultCacheSize.
- if (available < kDefaultCacheSize * 10 / 8)
- return static_cast<int32>(available * 8 / 10);
-
- // Return kDefaultCacheSize if it uses 80% to 10% of the available space.
- if (available < kDefaultCacheSize * 10)
- return kDefaultCacheSize;
-
- // Return 10% of the available space if the target size
- // (2.5 * kDefaultCacheSize) is more than 10%.
- if (available < static_cast<int64>(kDefaultCacheSize) * 25)
- return static_cast<int32>(available / 10);
-
- // Return the target size (2.5 * kDefaultCacheSize) if it uses 10% to 1%
- // of the available space.
- if (available < static_cast<int64>(kDefaultCacheSize) * 250)
- return kDefaultCacheSize * 5 / 2;
-
- // Return 1% of the available space if it does not exceed kint32max.
- if (available < static_cast<int64>(kint32max) * 100)
- return static_cast<int32>(available / 100);
-
- return kint32max;
-}
-
-// ------------------------------------------------------------------------
-
BackendImpl::BackendImpl(const base::FilePath& path,
base::MessageLoopProxy* cache_thread,
net::NetLog* net_log)
@@ -337,6 +305,8 @@ void BackendImpl::CleanupCache() {
// This is a net_unittest, verify that we are not 'leaking' entries.
File::WaitForPendingIO(&num_pending_io_);
DCHECK(!num_refs_);
+ } else {
+ File::DropPendingIO();
}
}
block_files_.CloseFiles();
@@ -1279,7 +1249,7 @@ bool BackendImpl::CreateBackingStore(disk_cache::File* file) {
}
bool BackendImpl::InitBackingStore(bool* file_created) {
- if (!file_util::CreateDirectory(path_))
+ if (!base::CreateDirectory(path_))
return false;
base::FilePath index_name = path_.AppendASCII(kIndexName);
@@ -1338,12 +1308,7 @@ void BackendImpl::AdjustMaxCacheSize(int table_len) {
if (table_len)
available += data_->header.num_bytes;
- max_size_ = PreferedCacheSize(available);
-
- // Let's not use more than the default size while we tune-up the performance
- // of bigger caches. TODO(rvargas): remove this limit.
- if (max_size_ > kDefaultCacheSize * 4)
- max_size_ = kDefaultCacheSize * 4;
+ max_size_ = PreferredCacheSize(available);
if (!table_len)
return;
@@ -1896,6 +1861,11 @@ void BackendImpl::ReportStats() {
stats_.SetCounter(Stats::DOOM_CACHE, 0);
stats_.SetCounter(Stats::DOOM_RECENT, 0);
+ int age = (Time::Now() -
+ Time::FromInternalValue(data_->header.create_time)).InHours();
+ if (age)
+ CACHE_UMA(HOURS, "FilesAge", 0, age);
+
int64 total_hours = stats_.GetCounter(Stats::TIMER) / 120;
if (!data_->header.create_time || !data_->header.lru.filled) {
int cause = data_->header.create_time ? 0 : 1;
diff --git a/chromium/net/disk_cache/backend_impl.h b/chromium/net/disk_cache/backend_impl.h
index 982bee64818..61b95b3ab0b 100644
--- a/chromium/net/disk_cache/backend_impl.h
+++ b/chromium/net/disk_cache/backend_impl.h
@@ -392,9 +392,6 @@ class NET_EXPORT_PRIVATE BackendImpl : public Backend {
DISALLOW_COPY_AND_ASSIGN(BackendImpl);
};
-// Returns the preferred max cache size given the available disk space.
-NET_EXPORT_PRIVATE int PreferedCacheSize(int64 available);
-
} // namespace disk_cache
#endif // NET_DISK_CACHE_BACKEND_IMPL_H_
diff --git a/chromium/net/disk_cache/backend_unittest.cc b/chromium/net/disk_cache/backend_unittest.cc
index 6ccd1e0224a..f3c02fdf09f 100644
--- a/chromium/net/disk_cache/backend_unittest.cc
+++ b/chromium/net/disk_cache/backend_unittest.cc
@@ -489,7 +489,7 @@ TEST_F(DiskCacheBackendTest, ExternalFiles) {
// And verify that the first file is still there.
scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
- ASSERT_EQ(kSize, file_util::ReadFile(filename, buffer2->data(), kSize));
+ ASSERT_EQ(kSize, base::ReadFile(filename, buffer2->data(), kSize));
EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kSize));
}
@@ -518,9 +518,13 @@ void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) {
base::MessageLoop::current()->RunUntilIdle();
+#if !defined(OS_IOS)
// Wait for the actual operation to complete, or we'll keep a file handle that
- // may cause issues later.
+ // may cause issues later. Note that on iOS systems even though this test
+ // uses a single thread, the actual IO is posted to a worker thread and the
+ // cache destructor breaks the link to reach cb when the operation completes.
rv = cb.GetResult(rv);
+#endif
}
TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) {
@@ -543,6 +547,8 @@ TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) {
}
#endif
+// See crbug.com/330074
+#if !defined(OS_IOS)
// Tests that one cache instance is not affected by another one going away.
TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) {
base::ScopedTempDir store;
@@ -576,6 +582,7 @@ TEST_F(DiskCacheBackendTest, MultipleInstancesWithPendingFileIO) {
// may cause issues later.
rv = cb.GetResult(rv);
}
+#endif
// Tests that we deal with background-thread pending operations.
void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) {
@@ -2898,51 +2905,51 @@ TEST_F(DiskCacheTest, MultipleInstances) {
// Test the six regions of the curve that determines the max cache size.
TEST_F(DiskCacheTest, AutomaticMaxSize) {
- const int kDefaultSize = 80 * 1024 * 1024;
- int64 large_size = kDefaultSize;
- int64 largest_size = kint32max;
+ using disk_cache::kDefaultCacheSize;
+ int64 large_size = kDefaultCacheSize;
// Region 1: expected = available * 0.8
- EXPECT_EQ((kDefaultSize - 1) * 8 / 10,
- disk_cache::PreferedCacheSize(large_size - 1));
- EXPECT_EQ(kDefaultSize * 8 / 10,
- disk_cache::PreferedCacheSize(large_size));
- EXPECT_EQ(kDefaultSize - 1,
- disk_cache::PreferedCacheSize(large_size * 10 / 8 - 1));
+ EXPECT_EQ((kDefaultCacheSize - 1) * 8 / 10,
+ disk_cache::PreferredCacheSize(large_size - 1));
+ EXPECT_EQ(kDefaultCacheSize * 8 / 10,
+ disk_cache::PreferredCacheSize(large_size));
+ EXPECT_EQ(kDefaultCacheSize - 1,
+ disk_cache::PreferredCacheSize(large_size * 10 / 8 - 1));
// Region 2: expected = default_size
- EXPECT_EQ(kDefaultSize,
- disk_cache::PreferedCacheSize(large_size * 10 / 8));
- EXPECT_EQ(kDefaultSize,
- disk_cache::PreferedCacheSize(large_size * 10 - 1));
+ EXPECT_EQ(kDefaultCacheSize,
+ disk_cache::PreferredCacheSize(large_size * 10 / 8));
+ EXPECT_EQ(kDefaultCacheSize,
+ disk_cache::PreferredCacheSize(large_size * 10 - 1));
// Region 3: expected = available * 0.1
- EXPECT_EQ(kDefaultSize,
- disk_cache::PreferedCacheSize(large_size * 10));
- EXPECT_EQ((kDefaultSize * 25 - 1) / 10,
- disk_cache::PreferedCacheSize(large_size * 25 - 1));
+ EXPECT_EQ(kDefaultCacheSize,
+ disk_cache::PreferredCacheSize(large_size * 10));
+ EXPECT_EQ((kDefaultCacheSize * 25 - 1) / 10,
+ disk_cache::PreferredCacheSize(large_size * 25 - 1));
// Region 4: expected = default_size * 2.5
- EXPECT_EQ(kDefaultSize * 25 / 10,
- disk_cache::PreferedCacheSize(large_size * 25));
- EXPECT_EQ(kDefaultSize * 25 / 10,
- disk_cache::PreferedCacheSize(large_size * 100 - 1));
- EXPECT_EQ(kDefaultSize * 25 / 10,
- disk_cache::PreferedCacheSize(large_size * 100));
- EXPECT_EQ(kDefaultSize * 25 / 10,
- disk_cache::PreferedCacheSize(large_size * 250 - 1));
+ EXPECT_EQ(kDefaultCacheSize * 25 / 10,
+ disk_cache::PreferredCacheSize(large_size * 25));
+ EXPECT_EQ(kDefaultCacheSize * 25 / 10,
+ disk_cache::PreferredCacheSize(large_size * 100 - 1));
+ EXPECT_EQ(kDefaultCacheSize * 25 / 10,
+ disk_cache::PreferredCacheSize(large_size * 100));
+ EXPECT_EQ(kDefaultCacheSize * 25 / 10,
+ disk_cache::PreferredCacheSize(large_size * 250 - 1));
// Region 5: expected = available * 0.1
- EXPECT_EQ(kDefaultSize * 25 / 10,
- disk_cache::PreferedCacheSize(large_size * 250));
- EXPECT_EQ(kint32max - 1,
- disk_cache::PreferedCacheSize(largest_size * 100 - 1));
+ int64 largest_size = kDefaultCacheSize * 4;
+ EXPECT_EQ(kDefaultCacheSize * 25 / 10,
+ disk_cache::PreferredCacheSize(large_size * 250));
+ EXPECT_EQ(largest_size - 1,
+ disk_cache::PreferredCacheSize(largest_size * 100 - 1));
- // Region 6: expected = kint32max
- EXPECT_EQ(kint32max,
- disk_cache::PreferedCacheSize(largest_size * 100));
- EXPECT_EQ(kint32max,
- disk_cache::PreferedCacheSize(largest_size * 10000));
+ // Region 6: expected = largest possible size
+ EXPECT_EQ(largest_size,
+ disk_cache::PreferredCacheSize(largest_size * 100));
+ EXPECT_EQ(largest_size,
+ disk_cache::PreferredCacheSize(largest_size * 10000));
}
// Tests that we can "migrate" a running instance from one experiment group to
@@ -3470,8 +3477,4 @@ TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationCorruption) {
EXPECT_TRUE(keys_to_match.empty());
}
-// TODO(pasko): Add a Simple Cache test that would simulate upgrade from the
-// version with the index file in the cache directory to the version with the
-// index file in subdirectory.
-
#endif // defined(OS_POSIX)
diff --git a/chromium/net/disk_cache/block_files.cc b/chromium/net/disk_cache/block_files.cc
index 896cdb16328..d8d13e8f2bf 100644
--- a/chromium/net/disk_cache/block_files.cc
+++ b/chromium/net/disk_cache/block_files.cc
@@ -83,7 +83,7 @@ bool BlockHeader::CreateMapBlock(int size, int* index) {
disk_cache::FileLock lock(header_);
int index_offset = j * 4 + 4 - target;
*index = current * 32 + index_offset;
- DCHECK_EQ(*index / 4, (*index + size - 1) / 4);
+ DLOG_IF(ERROR, *index / 4 != (*index + size - 1) / 4) << "Bit mismatch";
uint32 to_add = ((1 << size) - 1) << index_offset;
header_->num_entries++;
diff --git a/chromium/net/disk_cache/block_files_unittest.cc b/chromium/net/disk_cache/block_files_unittest.cc
index fa7c5dbb742..4a095c992ec 100644
--- a/chromium/net/disk_cache/block_files_unittest.cc
+++ b/chromium/net/disk_cache/block_files_unittest.cc
@@ -31,7 +31,7 @@ namespace disk_cache {
TEST_F(DiskCacheTest, BlockFiles_Grow) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -57,7 +57,7 @@ TEST_F(DiskCacheTest, BlockFiles_Grow) {
// We should be able to delete empty block files.
TEST_F(DiskCacheTest, BlockFiles_Shrink) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -80,7 +80,7 @@ TEST_F(DiskCacheTest, BlockFiles_Shrink) {
// Handling of block files not properly closed.
TEST_F(DiskCacheTest, BlockFiles_Recover) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -157,7 +157,7 @@ TEST_F(DiskCacheTest, BlockFiles_Recover) {
// Handling of truncated files.
TEST_F(DiskCacheTest, BlockFiles_ZeroSizeFile) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -178,7 +178,7 @@ TEST_F(DiskCacheTest, BlockFiles_ZeroSizeFile) {
// Handling of truncated files (non empty).
TEST_F(DiskCacheTest, BlockFiles_TruncatedFile) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -201,7 +201,7 @@ TEST_F(DiskCacheTest, BlockFiles_TruncatedFile) {
// Tests detection of out of sync counters.
TEST_F(DiskCacheTest, BlockFiles_Counters) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -256,7 +256,7 @@ TEST_F(DiskCacheTest, BlockFiles_Counters) {
// An invalid file can be detected after init.
TEST_F(DiskCacheTest, BlockFiles_InvalidFile) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
@@ -302,7 +302,7 @@ TEST_F(DiskCacheTest, BlockFiles_Stats) {
// Tests that we add and remove blocks correctly.
TEST_F(DiskCacheTest, AllocationMap) {
ASSERT_TRUE(CleanupCacheDir());
- ASSERT_TRUE(file_util::CreateDirectory(cache_path_));
+ ASSERT_TRUE(base::CreateDirectory(cache_path_));
BlockFiles files(cache_path_);
ASSERT_TRUE(files.Init(true));
diff --git a/chromium/net/disk_cache/cache_creator.cc b/chromium/net/disk_cache/cache_creator.cc
index 857d1714f7c..1fee41f2738 100644
--- a/chromium/net/disk_cache/cache_creator.cc
+++ b/chromium/net/disk_cache/cache_creator.cc
@@ -82,7 +82,8 @@ int CacheCreator::Run() {
// TODO(gavinp,pasko): Turn Simple Cache on for more cache types as
// appropriate.
if (backend_type_ == net::CACHE_BACKEND_SIMPLE &&
- (type_ == net::DISK_CACHE || type_ == net::APP_CACHE)) {
+ (type_ == net::DISK_CACHE || type_ == net::APP_CACHE ||
+ type_ == net::MEDIA_CACHE)) {
disk_cache::SimpleBackendImpl* simple_cache =
new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_,
thread_.get(), net_log_);
@@ -113,6 +114,7 @@ void CacheCreator::DoCallback(int result) {
#endif
} else {
LOG(ERROR) << "Unable to create cache";
+ created_cache_.reset();
}
callback_.Run(result);
delete this;
diff --git a/chromium/net/disk_cache/cache_util.cc b/chromium/net/disk_cache/cache_util.cc
index 7389960a16a..4452e7b0aa9 100644
--- a/chromium/net/disk_cache/cache_util.cc
+++ b/chromium/net/disk_cache/cache_util.cc
@@ -48,10 +48,37 @@ base::FilePath GetTempCacheName(const base::FilePath& path,
return base::FilePath();
}
+int64 PreferredCacheSizeInternal(int64 available) {
+ using disk_cache::kDefaultCacheSize;
+ // Return 80% of the available space if there is not enough space to use
+ // kDefaultCacheSize.
+ if (available < kDefaultCacheSize * 10 / 8)
+ return available * 8 / 10;
+
+ // Return kDefaultCacheSize if it uses 10% to 80% of the available space.
+ if (available < kDefaultCacheSize * 10)
+ return kDefaultCacheSize;
+
+ // Return 10% of the available space if the target size
+ // (2.5 * kDefaultCacheSize) is more than 10%.
+ if (available < static_cast<int64>(kDefaultCacheSize) * 25)
+ return available / 10;
+
+ // Return the target size (2.5 * kDefaultCacheSize) if it uses 10% to 1%
+ // of the available space.
+ if (available < static_cast<int64>(kDefaultCacheSize) * 250)
+ return kDefaultCacheSize * 5 / 2;
+
+ // Return 1% of the available space.
+ return available / 100;
+}
+
} // namespace
namespace disk_cache {
+const int kDefaultCacheSize = 80 * 1024 * 1024;
+
void DeleteCache(const base::FilePath& path, bool remove_folder) {
if (remove_folder) {
if (!base::DeleteFile(path, /* recursive */ true))
@@ -111,4 +138,21 @@ bool DelayedCacheCleanup(const base::FilePath& full_path) {
return true;
}
+// Returns the preferred maximum number of bytes for the cache given the
+// number of available bytes.
+int PreferredCacheSize(int64 available) {
+ if (available < 0)
+ return kDefaultCacheSize;
+
+ int64 max_size = PreferredCacheSizeInternal(available);
+
+ // Limit cache size to somewhat less than kint32max to avoid potential
+ // integer overflows in cache backend implementations.
+ DCHECK(kDefaultCacheSize * 4 < kint32max);
+ if (max_size > kDefaultCacheSize * 4)
+ max_size = kDefaultCacheSize * 4;
+
+ return implicit_cast<int32>(max_size);
+}
+
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/cache_util.h b/chromium/net/disk_cache/cache_util.h
index 2005ba5e240..c4baa2d6110 100644
--- a/chromium/net/disk_cache/cache_util.h
+++ b/chromium/net/disk_cache/cache_util.h
@@ -36,6 +36,13 @@ NET_EXPORT_PRIVATE bool DeleteCacheFile(const base::FilePath& name);
// task. Used by cache creator itself or by backends for self-restart on error.
bool DelayedCacheCleanup(const base::FilePath& full_path);
+// Returns the preferred max cache size given the available disk space.
+NET_EXPORT_PRIVATE int PreferredCacheSize(int64 available);
+
+// The default cache size should not ideally be exposed, but the blockfile
+// backend uses it for reasons that include testing.
+NET_EXPORT_PRIVATE extern const int kDefaultCacheSize;
+
} // namespace disk_cache
#endif // NET_DISK_CACHE_CACHE_UTIL_H_
diff --git a/chromium/net/disk_cache/cache_util_posix.cc b/chromium/net/disk_cache/cache_util_posix.cc
index b33c560a000..59e1c505d49 100644
--- a/chromium/net/disk_cache/cache_util_posix.cc
+++ b/chromium/net/disk_cache/cache_util_posix.cc
@@ -19,7 +19,7 @@ bool MoveCache(const base::FilePath& from_path, const base::FilePath& to_path) {
// to see these directories anymore in an unmounted encrypted
// filesystem, so we just move each item in the cache to a new
// directory.
- if (!file_util::CreateDirectory(to_path)) {
+ if (!base::CreateDirectory(to_path)) {
LOG(ERROR) << "Unable to create destination cache directory.";
return false;
}
diff --git a/chromium/net/disk_cache/cache_util_unittest.cc b/chromium/net/disk_cache/cache_util_unittest.cc
index d2e76054f7f..3a05196828e 100644
--- a/chromium/net/disk_cache/cache_util_unittest.cc
+++ b/chromium/net/disk_cache/cache_util_unittest.cc
@@ -20,17 +20,17 @@ class CacheUtilTest : public PlatformTest {
file2_ = base::FilePath(cache_dir_.Append(FILE_PATH_LITERAL(".file02")));
dir1_ = base::FilePath(cache_dir_.Append(FILE_PATH_LITERAL("dir01")));
file3_ = base::FilePath(dir1_.Append(FILE_PATH_LITERAL("file03")));
- ASSERT_TRUE(file_util::CreateDirectory(cache_dir_));
- FILE *fp = file_util::OpenFile(file1_, "w");
+ ASSERT_TRUE(base::CreateDirectory(cache_dir_));
+ FILE *fp = base::OpenFile(file1_, "w");
ASSERT_TRUE(fp != NULL);
- file_util::CloseFile(fp);
- fp = file_util::OpenFile(file2_, "w");
+ base::CloseFile(fp);
+ fp = base::OpenFile(file2_, "w");
ASSERT_TRUE(fp != NULL);
- file_util::CloseFile(fp);
- ASSERT_TRUE(file_util::CreateDirectory(dir1_));
- fp = file_util::OpenFile(file3_, "w");
+ base::CloseFile(fp);
+ ASSERT_TRUE(base::CreateDirectory(dir1_));
+ fp = base::OpenFile(file3_, "w");
ASSERT_TRUE(fp != NULL);
- file_util::CloseFile(fp);
+ base::CloseFile(fp);
dest_dir_ = tmp_dir_.path().Append(FILE_PATH_LITERAL("old_Cache_001"));
dest_file1_ = base::FilePath(dest_dir_.Append(FILE_PATH_LITERAL("file01")));
dest_file2_ =
diff --git a/chromium/net/disk_cache/entry_unittest.cc b/chromium/net/disk_cache/entry_unittest.cc
index b8c9e668198..291dedfb433 100644
--- a/chromium/net/disk_cache/entry_unittest.cc
+++ b/chromium/net/disk_cache/entry_unittest.cc
@@ -1931,7 +1931,7 @@ void DiskCacheEntryTest::UpdateSparseEntry() {
entry1->Close();
entry2->Close();
FlushQueueForTest();
- if (memory_only_)
+ if (memory_only_ || simple_cache_mode_)
EXPECT_EQ(2, cache_->GetEntryCount());
else
EXPECT_EQ(3, cache_->GetEntryCount());
@@ -1964,20 +1964,15 @@ void DiskCacheEntryTest::DoomSparseEntry() {
int64 offset = 1024;
// Write to a bunch of ranges.
for (int i = 0; i < 12; i++) {
- EXPECT_EQ(kSize,
- entry1->WriteSparseData(
- offset, buf.get(), kSize, net::CompletionCallback()));
+ EXPECT_EQ(kSize, WriteSparseData(entry1, offset, buf.get(), kSize));
// Keep the second map under the default size.
- if (i < 9) {
- EXPECT_EQ(kSize,
- entry2->WriteSparseData(
- offset, buf.get(), kSize, net::CompletionCallback()));
- }
+ if (i < 9)
+ EXPECT_EQ(kSize, WriteSparseData(entry2, offset, buf.get(), kSize));
offset *= 4;
}
- if (memory_only_)
+ if (memory_only_ || simple_cache_mode_)
EXPECT_EQ(2, cache_->GetEntryCount());
else
EXPECT_EQ(15, cache_->GetEntryCount());
@@ -2110,7 +2105,7 @@ void DiskCacheEntryTest::PartialSparseEntry() {
int rv;
int64 start;
net::TestCompletionCallback cb;
- if (memory_only_) {
+ if (memory_only_ || simple_cache_mode_) {
rv = entry->GetAvailableRange(0, 600, &start, cb.callback());
EXPECT_EQ(100, cb.GetResult(rv));
EXPECT_EQ(500, start);
@@ -2129,7 +2124,7 @@ void DiskCacheEntryTest::PartialSparseEntry() {
// 1. Query before a filled 1KB block.
// 2. Query within a filled 1KB block.
// 3. Query beyond a filled 1KB block.
- if (memory_only_) {
+ if (memory_only_ || simple_cache_mode_) {
rv = entry->GetAvailableRange(19400, kSize, &start, cb.callback());
EXPECT_EQ(3496, cb.GetResult(rv));
EXPECT_EQ(20000, start);
@@ -3019,7 +3014,7 @@ TEST_F(DiskCacheEntryTest, SimpleCacheCreateDoomRace) {
base::FilePath entry_file_path = cache_path_.AppendASCII(
disk_cache::simple_util::GetFilenameFromKeyAndFileIndex(key, i));
base::PlatformFileInfo info;
- EXPECT_FALSE(file_util::GetFileInfo(entry_file_path, &info));
+ EXPECT_FALSE(base::GetFileInfo(entry_file_path, &info));
}
}
@@ -3527,8 +3522,9 @@ TEST_F(DiskCacheEntryTest, SimpleCacheStream1SizeChanges) {
ASSERT_TRUE(entry_file0 != base::kInvalidPlatformFileValue);
int data_size[disk_cache::kSimpleEntryStreamCount] = {kSize, stream1_size, 0};
+ int sparse_data_size = 0;
disk_cache::SimpleEntryStat entry_stat(
- base::Time::Now(), base::Time::Now(), data_size);
+ base::Time::Now(), base::Time::Now(), data_size, sparse_data_size);
int eof_offset = entry_stat.GetEOFOffsetInFile(key, 0);
disk_cache::SimpleFileEOF eof_record;
ASSERT_EQ(static_cast<int>(sizeof(eof_record)), base::ReadPlatformFile(
@@ -3629,12 +3625,7 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream1) {
SetSimpleCacheMode();
InitCache();
- const int kHalfSize = 8;
- const int kSize = kHalfSize * 2;
const char key[] = "key";
- scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
- scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
- CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
disk_cache::Entry* entry;
@@ -3657,19 +3648,16 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream2) {
const int kHalfSize = 8;
const int kSize = kHalfSize * 2;
const char key[] = "key";
- scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
- scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
- CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ CacheTestFillBuffer(buffer->data(), kHalfSize, false);
disk_cache::Entry* entry;
- int buf_len;
// Create entry, write empty buffer to third stream, and close: third stream
// should still be omitted, since the entry ignores writes that don't modify
// data or change the length.
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
- buf_len = WriteData(entry, 2, 0, buffer1, 0, true);
- ASSERT_EQ(0, buf_len);
+ EXPECT_EQ(0, WriteData(entry, 2, 0, buffer, 0, true));
entry->Close();
EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
@@ -3690,21 +3678,18 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream3) {
CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
disk_cache::Entry* entry;
- int buf_len;
// Create entry, write data to third stream, and close: third stream should
// not be omitted, since it contains data. Re-open entry and ensure there
// are that many bytes in the third stream.
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
- buf_len = WriteData(entry, 2, 0, buffer1, kHalfSize, true);
- ASSERT_EQ(kHalfSize, buf_len);
+ EXPECT_EQ(kHalfSize, WriteData(entry, 2, 0, buffer1, kHalfSize, true));
entry->Close();
EXPECT_TRUE(SimpleCacheThirdStreamFileExists(key));
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
- buf_len = ReadData(entry, 2, 0, buffer2, kSize);
- ASSERT_EQ(buf_len, kHalfSize);
- // TODO: Compare data?
+ EXPECT_EQ(kHalfSize, ReadData(entry, 2, 0, buffer2, kSize));
+ EXPECT_EQ(0, memcmp(buffer1->data(), buffer2->data(), kHalfSize));
entry->Close();
EXPECT_TRUE(SimpleCacheThirdStreamFileExists(key));
@@ -3727,7 +3712,6 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream4) {
CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
disk_cache::Entry* entry;
- int buf_len;
// Create entry, write data to third stream, truncate third stream back to
// empty, and close: third stream will not initially be omitted, since entry
@@ -3735,17 +3719,14 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream4) {
// removes it on open if it is empty. Reopen, ensure that the file is
// deleted, and that there's no data in the third stream.
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
- buf_len = WriteData(entry, 2, 0, buffer1, kHalfSize, true);
- ASSERT_EQ(kHalfSize, buf_len);
- buf_len = WriteData(entry, 2, 0, buffer1, 0, true);
- ASSERT_EQ(0, buf_len);
+ EXPECT_EQ(kHalfSize, WriteData(entry, 2, 0, buffer1, kHalfSize, true));
+ EXPECT_EQ(0, WriteData(entry, 2, 0, buffer1, 0, true));
entry->Close();
EXPECT_TRUE(SimpleCacheThirdStreamFileExists(key));
ASSERT_EQ(net::OK, OpenEntry(key, &entry));
EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
- buf_len = ReadData(entry, 2, 0, buffer2, kSize);
- ASSERT_EQ(0, buf_len);
+ EXPECT_EQ(0, ReadData(entry, 2, 0, buffer2, kSize));
entry->Close();
EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
@@ -3762,9 +3743,8 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream5) {
const int kHalfSize = 8;
const int kSize = kHalfSize * 2;
const char key[] = "key";
- scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
- scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
- CacheTestFillBuffer(buffer1->data(), kHalfSize, false);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ CacheTestFillBuffer(buffer->data(), kHalfSize, false);
disk_cache::Entry* entry;
@@ -3773,9 +3753,149 @@ TEST_F(DiskCacheEntryTest, SimpleCacheOmittedThirdStream5) {
// that it doesn't cause the file to be created on disk.)
ASSERT_EQ(net::OK, CreateEntry(key, &entry));
entry->Doom();
- WriteData(entry, 2, 0, buffer1, kHalfSize, true);
+ WriteData(entry, 2, 0, buffer, kHalfSize, true);
entry->Close();
EXPECT_FALSE(SimpleCacheThirdStreamFileExists(key));
}
+// There could be a race between Doom and an optimistic write.
+TEST_F(DiskCacheEntryTest, SimpleCacheDoomOptimisticWritesRace) {
+ // Test sequence:
+ // Create, first Write, second Write, Close.
+ // Open, Close.
+ SetSimpleCacheMode();
+ InitCache();
+ disk_cache::Entry* null = NULL;
+ const char key[] = "the first key";
+
+ const int kSize = 200;
+ scoped_refptr<net::IOBuffer> buffer1(new net::IOBuffer(kSize));
+ scoped_refptr<net::IOBuffer> buffer2(new net::IOBuffer(kSize));
+ CacheTestFillBuffer(buffer1->data(), kSize, false);
+ CacheTestFillBuffer(buffer2->data(), kSize, false);
+
+ // The race only happens on stream 1 and stream 2.
+ for (int i = 0; i < disk_cache::kSimpleEntryStreamCount; ++i) {
+ ASSERT_EQ(net::OK, DoomAllEntries());
+ disk_cache::Entry* entry = NULL;
+
+ ASSERT_EQ(net::OK, CreateEntry(key, &entry));
+ EXPECT_NE(null, entry);
+ entry->Close();
+ entry = NULL;
+
+ ASSERT_EQ(net::OK, DoomAllEntries());
+ ASSERT_EQ(net::OK, CreateEntry(key, &entry));
+ EXPECT_NE(null, entry);
+
+ int offset = 0;
+ int buf_len = kSize;
+ // This write should not be optimistic (since create is).
+ EXPECT_EQ(buf_len,
+ WriteData(entry, i, offset, buffer1.get(), buf_len, false));
+
+ offset = kSize;
+ // This write should be optimistic.
+ EXPECT_EQ(buf_len,
+ WriteData(entry, i, offset, buffer2.get(), buf_len, false));
+ entry->Close();
+
+ ASSERT_EQ(net::OK, OpenEntry(key, &entry));
+ EXPECT_NE(null, entry);
+
+ entry->Close();
+ entry = NULL;
+ }
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheBasicSparseIO) {
+ SetSimpleCacheMode();
+ InitCache();
+ BasicSparseIO();
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheHugeSparseIO) {
+ SetSimpleCacheMode();
+ InitCache();
+ HugeSparseIO();
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheGetAvailableRange) {
+ SetSimpleCacheMode();
+ InitCache();
+ GetAvailableRange();
+}
+
+TEST_F(DiskCacheEntryTest, DISABLED_SimpleCacheCouldBeSparse) {
+ SetSimpleCacheMode();
+ InitCache();
+ CouldBeSparse();
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheUpdateSparseEntry) {
+ SetSimpleCacheMode();
+ InitCache();
+ UpdateSparseEntry();
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheDoomSparseEntry) {
+ SetSimpleCacheMode();
+ InitCache();
+ DoomSparseEntry();
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCachePartialSparseEntry) {
+ SetSimpleCacheMode();
+ InitCache();
+ PartialSparseEntry();
+}
+
+TEST_F(DiskCacheEntryTest, SimpleCacheTruncateLargeSparseFile) {
+ const int kSize = 1024;
+
+ SetSimpleCacheMode();
+ // An entry is allowed sparse data 1/10 the size of the cache, so this size
+ // allows for one |kSize|-sized range plus overhead, but not two ranges.
+ SetMaxSize(kSize * 15);
+ InitCache();
+
+ const char key[] = "key";
+ disk_cache::Entry* null = NULL;
+ disk_cache::Entry* entry;
+ ASSERT_EQ(net::OK, CreateEntry(key, &entry));
+ EXPECT_NE(null, entry);
+
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kSize));
+ CacheTestFillBuffer(buffer->data(), kSize, false);
+ net::TestCompletionCallback callback;
+ int ret;
+
+ // Verify initial conditions.
+ ret = entry->ReadSparseData(0, buffer, kSize, callback.callback());
+ EXPECT_EQ(0, callback.GetResult(ret));
+
+ ret = entry->ReadSparseData(kSize, buffer, kSize, callback.callback());
+ EXPECT_EQ(0, callback.GetResult(ret));
+
+ // Write a range and make sure it reads back.
+ ret = entry->WriteSparseData(0, buffer, kSize, callback.callback());
+ EXPECT_EQ(kSize, callback.GetResult(ret));
+
+ ret = entry->ReadSparseData(0, buffer, kSize, callback.callback());
+ EXPECT_EQ(kSize, callback.GetResult(ret));
+
+ // Write another range and make sure it reads back.
+ ret = entry->WriteSparseData(kSize, buffer, kSize, callback.callback());
+ EXPECT_EQ(kSize, callback.GetResult(ret));
+
+ ret = entry->ReadSparseData(kSize, buffer, kSize, callback.callback());
+ EXPECT_EQ(kSize, callback.GetResult(ret));
+
+ // Make sure the first range was removed when the second was written.
+ ret = entry->ReadSparseData(0, buffer, kSize, callback.callback());
+ EXPECT_EQ(0, callback.GetResult(ret));
+
+ entry->Close();
+}
+
#endif // defined(OS_POSIX)
diff --git a/chromium/net/disk_cache/file.h b/chromium/net/disk_cache/file.h
index eb9a9ecc1e1..190f7cb9f82 100644
--- a/chromium/net/disk_cache/file.h
+++ b/chromium/net/disk_cache/file.h
@@ -70,6 +70,9 @@ class NET_EXPORT_PRIVATE File : public base::RefCounted<File> {
// Blocks until |num_pending_io| IO operations complete.
static void WaitForPendingIO(int* num_pending_io);
+ // Drops current pending operations without waiting for them to complete.
+ static void DropPendingIO();
+
protected:
virtual ~File();
diff --git a/chromium/net/disk_cache/file_ios.cc b/chromium/net/disk_cache/file_ios.cc
new file mode 100644
index 00000000000..9cad1551f15
--- /dev/null
+++ b/chromium/net/disk_cache/file_ios.cc
@@ -0,0 +1,312 @@
+// 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/disk_cache/file.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/threading/worker_pool.h"
+#include "net/base/net_errors.h"
+#include "net/disk_cache/disk_cache.h"
+#include "net/disk_cache/in_flight_io.h"
+
+namespace {
+
+// This class represents a single asynchronous IO operation while it is being
+// bounced between threads.
+class FileBackgroundIO : public disk_cache::BackgroundIO {
+ public:
+ // Other than the actual parameters for the IO operation (including the
+ // |callback| that must be notified at the end), we need the controller that
+ // is keeping track of all operations. When done, we notify the controller
+ // (we do NOT invoke the callback), in the worker thead that completed the
+ // operation.
+ FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len,
+ size_t offset, disk_cache::FileIOCallback* callback,
+ disk_cache::InFlightIO* controller)
+ : disk_cache::BackgroundIO(controller), callback_(callback), file_(file),
+ buf_(buf), buf_len_(buf_len), offset_(offset) {
+ }
+
+ disk_cache::FileIOCallback* callback() {
+ return callback_;
+ }
+
+ disk_cache::File* file() {
+ return file_;
+ }
+
+ // Read and Write are the operations that can be performed asynchronously.
+ // The actual parameters for the operation are setup in the constructor of
+ // the object. Both methods should be called from a worker thread, by posting
+ // a task to the WorkerPool (they are RunnableMethods). When finished,
+ // controller->OnIOComplete() is called.
+ void Read();
+ void Write();
+
+ private:
+ virtual ~FileBackgroundIO() {}
+
+ disk_cache::FileIOCallback* callback_;
+
+ disk_cache::File* file_;
+ const void* buf_;
+ size_t buf_len_;
+ size_t offset_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO);
+};
+
+
+// The specialized controller that keeps track of current operations.
+class FileInFlightIO : public disk_cache::InFlightIO {
+ public:
+ FileInFlightIO() {}
+ virtual ~FileInFlightIO() {}
+
+ // These methods start an asynchronous operation. The arguments have the same
+ // semantics of the File asynchronous operations, with the exception that the
+ // operation never finishes synchronously.
+ void PostRead(disk_cache::File* file, void* buf, size_t buf_len,
+ size_t offset, disk_cache::FileIOCallback* callback);
+ void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len,
+ size_t offset, disk_cache::FileIOCallback* callback);
+
+ protected:
+ // Invokes the users' completion callback at the end of the IO operation.
+ // |cancel| is true if the actual task posted to the thread is still
+ // queued (because we are inside WaitForPendingIO), and false if said task is
+ // the one performing the call.
+ virtual void OnOperationComplete(disk_cache::BackgroundIO* operation,
+ bool cancel) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FileInFlightIO);
+};
+
+// ---------------------------------------------------------------------------
+
+// Runs on a worker thread.
+void FileBackgroundIO::Read() {
+ if (file_->Read(const_cast<void*>(buf_), buf_len_, offset_)) {
+ result_ = static_cast<int>(buf_len_);
+ } else {
+ result_ = net::ERR_CACHE_READ_FAILURE;
+ }
+ NotifyController();
+}
+
+// Runs on a worker thread.
+void FileBackgroundIO::Write() {
+ bool rv = file_->Write(buf_, buf_len_, offset_);
+
+ result_ = rv ? static_cast<int>(buf_len_) : net::ERR_CACHE_WRITE_FAILURE;
+ NotifyController();
+}
+
+// ---------------------------------------------------------------------------
+
+void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
+ size_t offset, disk_cache::FileIOCallback *callback) {
+ scoped_refptr<FileBackgroundIO> operation(
+ new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
+ file->AddRef(); // Balanced on OnOperationComplete()
+
+ base::WorkerPool::PostTask(FROM_HERE,
+ base::Bind(&FileBackgroundIO::Read, operation.get()), true);
+ OnOperationPosted(operation.get());
+}
+
+void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf,
+ size_t buf_len, size_t offset,
+ disk_cache::FileIOCallback* callback) {
+ scoped_refptr<FileBackgroundIO> operation(
+ new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
+ file->AddRef(); // Balanced on OnOperationComplete()
+
+ base::WorkerPool::PostTask(FROM_HERE,
+ base::Bind(&FileBackgroundIO::Write, operation.get()), true);
+ OnOperationPosted(operation.get());
+}
+
+// Runs on the IO thread.
+void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation,
+ bool cancel) {
+ FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation);
+
+ disk_cache::FileIOCallback* callback = op->callback();
+ int bytes = operation->result();
+
+ // Release the references acquired in PostRead / PostWrite.
+ op->file()->Release();
+ callback->OnFileIOComplete(bytes);
+}
+
+// A static object tha will broker all async operations.
+FileInFlightIO* s_file_operations = NULL;
+
+// Returns the current FileInFlightIO.
+FileInFlightIO* GetFileInFlightIO() {
+ if (!s_file_operations) {
+ s_file_operations = new FileInFlightIO;
+ }
+ return s_file_operations;
+}
+
+// Deletes the current FileInFlightIO.
+void DeleteFileInFlightIO() {
+ DCHECK(s_file_operations);
+ delete s_file_operations;
+ s_file_operations = NULL;
+}
+
+} // namespace
+
+namespace disk_cache {
+
+File::File(base::PlatformFile file)
+ : init_(true),
+ mixed_(true),
+ platform_file_(file),
+ sync_platform_file_(base::kInvalidPlatformFileValue) {
+}
+
+bool File::Init(const base::FilePath& name) {
+ if (init_)
+ return false;
+
+ int flags = base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE;
+ platform_file_ = base::CreatePlatformFile(name, flags, NULL, NULL);
+ if (platform_file_ < 0) {
+ platform_file_ = 0;
+ return false;
+ }
+
+ init_ = true;
+ return true;
+}
+
+base::PlatformFile File::platform_file() const {
+ return platform_file_;
+}
+
+bool File::IsValid() const {
+ if (!init_)
+ return false;
+ return (base::kInvalidPlatformFileValue != platform_file_);
+}
+
+bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
+ DCHECK(init_);
+ if (buffer_len > static_cast<size_t>(kint32max) ||
+ offset > static_cast<size_t>(kint32max)) {
+ return false;
+ }
+
+ int ret = base::ReadPlatformFile(platform_file_, offset,
+ static_cast<char*>(buffer), buffer_len);
+ return (static_cast<size_t>(ret) == buffer_len);
+}
+
+bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
+ DCHECK(init_);
+ if (buffer_len > static_cast<size_t>(kint32max) ||
+ offset > static_cast<size_t>(kint32max)) {
+ return false;
+ }
+
+ int ret = base::WritePlatformFile(platform_file_, offset,
+ static_cast<const char*>(buffer),
+ buffer_len);
+ return (static_cast<size_t>(ret) == buffer_len);
+}
+
+// We have to increase the ref counter of the file before performing the IO to
+// prevent the completion to happen with an invalid handle (if the file is
+// closed while the IO is in flight).
+bool File::Read(void* buffer, size_t buffer_len, size_t offset,
+ FileIOCallback* callback, bool* completed) {
+ DCHECK(init_);
+ if (!callback) {
+ if (completed)
+ *completed = true;
+ return Read(buffer, buffer_len, offset);
+ }
+
+ if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
+ return false;
+
+ GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback);
+
+ *completed = false;
+ return true;
+}
+
+bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
+ FileIOCallback* callback, bool* completed) {
+ DCHECK(init_);
+ if (!callback) {
+ if (completed)
+ *completed = true;
+ return Write(buffer, buffer_len, offset);
+ }
+
+ return AsyncWrite(buffer, buffer_len, offset, callback, completed);
+}
+
+bool File::SetLength(size_t length) {
+ DCHECK(init_);
+ if (length > kuint32max)
+ return false;
+
+ return base::TruncatePlatformFile(platform_file_, length);
+}
+
+size_t File::GetLength() {
+ DCHECK(init_);
+ int64 len = base::SeekPlatformFile(platform_file_,
+ base::PLATFORM_FILE_FROM_END, 0);
+
+ if (len > static_cast<int64>(kuint32max))
+ return kuint32max;
+
+ return static_cast<size_t>(len);
+}
+
+// Static.
+void File::WaitForPendingIO(int* num_pending_io) {
+ // We may be running unit tests so we should allow be able to reset the
+ // message loop.
+ GetFileInFlightIO()->WaitForPendingIO();
+ DeleteFileInFlightIO();
+}
+
+// Static.
+void File::DropPendingIO() {
+ GetFileInFlightIO()->DropPendingIO();
+ DeleteFileInFlightIO();
+}
+
+File::~File() {
+ if (IsValid())
+ base::ClosePlatformFile(platform_file_);
+}
+
+bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
+ FileIOCallback* callback, bool* completed) {
+ DCHECK(init_);
+ if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
+ return false;
+
+ GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback);
+
+ if (completed)
+ *completed = false;
+ return true;
+}
+
+} // namespace disk_cache
diff --git a/chromium/net/disk_cache/file_posix.cc b/chromium/net/disk_cache/file_posix.cc
index 30c4a660b13..e1ff6fc4198 100644
--- a/chromium/net/disk_cache/file_posix.cc
+++ b/chromium/net/disk_cache/file_posix.cc
@@ -17,7 +17,7 @@
namespace {
// The maximum number of threads for this pool.
-const int kMaxThreads = 5;
+const int kMaxThreads = 20;
class FileWorkerPool : public base::SequencedWorkerPool {
public:
@@ -167,6 +167,11 @@ void File::WaitForPendingIO(int* num_pending_io) {
base::RunLoop().RunUntilIdle();
}
+// Static.
+void File::DropPendingIO() {
+}
+
+
File::~File() {
if (IsValid())
base::ClosePlatformFile(platform_file_);
diff --git a/chromium/net/disk_cache/file_win.cc b/chromium/net/disk_cache/file_win.cc
index dbb34f38341..1492c42c6e4 100644
--- a/chromium/net/disk_cache/file_win.cc
+++ b/chromium/net/disk_cache/file_win.cc
@@ -267,4 +267,8 @@ void File::WaitForPendingIO(int* num_pending_io) {
}
}
+// Static.
+void File::DropPendingIO() {
+}
+
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/mem_backend_impl.cc b/chromium/net/disk_cache/mem_backend_impl.cc
index a6f1bf13bed..ccd868b6530 100644
--- a/chromium/net/disk_cache/mem_backend_impl.cc
+++ b/chromium/net/disk_cache/mem_backend_impl.cc
@@ -14,7 +14,7 @@ using base::Time;
namespace {
-const int kDefaultCacheSize = 10 * 1024 * 1024;
+const int kDefaultInMemoryCacheSize = 10 * 1024 * 1024;
const int kCleanUpMargin = 1024 * 1024;
int LowWaterAdjust(int high_water) {
@@ -59,15 +59,15 @@ bool MemBackendImpl::Init() {
int64 total_memory = base::SysInfo::AmountOfPhysicalMemory();
if (total_memory <= 0) {
- max_size_ = kDefaultCacheSize;
+ max_size_ = kDefaultInMemoryCacheSize;
return true;
}
// 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.
total_memory = total_memory * 2 / 100;
- if (total_memory > kDefaultCacheSize * 5)
- max_size_ = kDefaultCacheSize * 5;
+ if (total_memory > kDefaultInMemoryCacheSize * 5)
+ max_size_ = kDefaultInMemoryCacheSize * 5;
else
max_size_ = static_cast<int32>(total_memory);
diff --git a/chromium/net/disk_cache/simple/simple_backend_impl.cc b/chromium/net/disk_cache/simple/simple_backend_impl.cc
index 8856a2d7194..7260857e0f1 100644
--- a/chromium/net/disk_cache/simple/simple_backend_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_backend_impl.cc
@@ -26,7 +26,7 @@
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "net/base/net_errors.h"
-#include "net/disk_cache/backend_impl.h"
+#include "net/disk_cache/cache_util.h"
#include "net/disk_cache/simple/simple_entry_format.h"
#include "net/disk_cache/simple/simple_entry_impl.h"
#include "net/disk_cache/simple/simple_histogram_macros.h"
@@ -44,7 +44,7 @@ using base::SequencedWorkerPool;
using base::SingleThreadTaskRunner;
using base::Time;
using base::DirectoryExists;
-using file_util::CreateDirectory;
+using base::CreateDirectory;
namespace disk_cache {
@@ -56,9 +56,6 @@ const int kDefaultMaxWorkerThreads = 50;
const char kThreadNamePrefix[] = "SimpleCache";
-// Cache size when all other size heuristics failed.
-const uint64 kDefaultCacheSize = 80 * 1024 * 1024;
-
// Maximum fraction of the cache that one entry can consume.
const int kMaxFileRatio = 8;
@@ -123,21 +120,11 @@ void MaybeHistogramFdLimit(net::CacheType cache_type) {
g_fd_limit_histogram_has_been_populated = true;
}
-// Must run on IO Thread.
-void DeleteBackendImpl(disk_cache::Backend** backend,
- const net::CompletionCallback& callback,
- int result) {
- DCHECK(*backend);
- delete *backend;
- *backend = NULL;
- callback.Run(result);
-}
-
// Detects if the files in the cache directory match the current disk cache
// backend type and version. If the directory contains no cache, occupies it
// with the fresh structure.
bool FileStructureConsistent(const base::FilePath& path) {
- if (!base::PathExists(path) && !file_util::CreateDirectory(path)) {
+ if (!base::PathExists(path) && !base::CreateDirectory(path)) {
LOG(ERROR) << "Failed to create directory: " << path.LossyDisplayName();
return false;
}
@@ -195,23 +182,6 @@ void RunOperationAndCallback(
operation_callback.Run(operation_result);
}
-// A short bindable thunk that Dooms an entry if it successfully opens.
-void DoomOpenedEntry(scoped_ptr<Entry*> in_entry,
- const net::CompletionCallback& doom_callback,
- int open_result) {
- DCHECK_NE(open_result, net::ERR_IO_PENDING);
- if (open_result == net::OK) {
- DCHECK(in_entry);
- SimpleEntryImpl* simple_entry = static_cast<SimpleEntryImpl*>(*in_entry);
- const int doom_result = simple_entry->DoomEntry(doom_callback);
- simple_entry->Close();
- if (doom_result != net::ERR_IO_PENDING)
- doom_callback.Run(doom_result);
- } else {
- doom_callback.Run(open_result);
- }
-}
-
void RecordIndexLoad(net::CacheType cache_type,
base::TimeTicks constructed_since,
int result) {
@@ -285,13 +255,15 @@ void SimpleBackendImpl::OnDeactivated(const SimpleEntryImpl* entry) {
}
void SimpleBackendImpl::OnDoomStart(uint64 entry_hash) {
- DCHECK_EQ(0u, entries_pending_doom_.count(entry_hash));
+ // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed.
+ CHECK_EQ(0u, entries_pending_doom_.count(entry_hash));
entries_pending_doom_.insert(
std::make_pair(entry_hash, std::vector<Closure>()));
}
void SimpleBackendImpl::OnDoomComplete(uint64 entry_hash) {
- DCHECK_EQ(1u, entries_pending_doom_.count(entry_hash));
+ // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed.
+ CHECK_EQ(1u, entries_pending_doom_.count(entry_hash));
base::hash_map<uint64, std::vector<Closure> >::iterator it =
entries_pending_doom_.find(entry_hash);
std::vector<Closure> to_run_closures;
@@ -317,8 +289,9 @@ void SimpleBackendImpl::DoomEntries(std::vector<uint64>* entry_hashes,
// SimpleSynchronousEntry::DoomEntrySet and delete the files en masse.
for (int i = mass_doom_entry_hashes->size() - 1; i >= 0; --i) {
const uint64 entry_hash = (*mass_doom_entry_hashes)[i];
- DCHECK(active_entries_.count(entry_hash) == 0 ||
- entries_pending_doom_.count(entry_hash) == 0)
+ // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed.
+ CHECK(active_entries_.count(entry_hash) == 0 ||
+ entries_pending_doom_.count(entry_hash) == 0)
<< "The entry 0x" << std::hex << entry_hash
<< " is both active and pending doom.";
if (!active_entries_.count(entry_hash) &&
@@ -339,7 +312,8 @@ void SimpleBackendImpl::DoomEntries(std::vector<uint64>* entry_hashes,
it = to_doom_individually_hashes.begin(),
end = to_doom_individually_hashes.end(); it != end; ++it) {
const int doom_result = DoomEntryFromHash(*it, barrier_callback);
- DCHECK_EQ(net::ERR_IO_PENDING, doom_result);
+ // TODO(ttuttle): Revert to DCHECK once http://crbug.com/317138 is fixed.
+ CHECK_EQ(net::ERR_IO_PENDING, doom_result);
index_->Remove(*it);
}
@@ -525,12 +499,7 @@ SimpleBackendImpl::DiskStatResult SimpleBackendImpl::InitCacheStructureOnDisk(
DCHECK(mtime_result);
if (!result.max_size) {
int64 available = base::SysInfo::AmountOfFreeDiskSpace(path);
- if (available < 0)
- result.max_size = kDefaultCacheSize;
- else
- // TODO(pasko): Move PreferedCacheSize() to cache_util.h. Also fix the
- // spelling.
- result.max_size = disk_cache::PreferedCacheSize(available);
+ result.max_size = disk_cache::PreferredCacheSize(available);
}
DCHECK(result.max_size);
}
diff --git a/chromium/net/disk_cache/simple/simple_entry_format.cc b/chromium/net/disk_cache/simple/simple_entry_format.cc
index d35174a9a7f..41cab2d36f2 100644
--- a/chromium/net/disk_cache/simple/simple_entry_format.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_format.cc
@@ -18,4 +18,9 @@ SimpleFileEOF::SimpleFileEOF() {
std::memset(this, 0, sizeof(*this));
}
+SimpleFileSparseRangeHeader::SimpleFileSparseRangeHeader() {
+ // Make hashing repeatable: leave no padding bytes untouched.
+ std::memset(this, 0, sizeof(*this));
+}
+
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/simple/simple_entry_format.h b/chromium/net/disk_cache/simple/simple_entry_format.h
index 8224b858dcc..abd985c9fee 100644
--- a/chromium/net/disk_cache/simple/simple_entry_format.h
+++ b/chromium/net/disk_cache/simple/simple_entry_format.h
@@ -18,6 +18,7 @@ namespace disk_cache {
const uint64 kSimpleInitialMagicNumber = GG_UINT64_C(0xfcfb6d1ba7725c30);
const uint64 kSimpleFinalMagicNumber = GG_UINT64_C(0xf4fa6f45970d41d8);
+const uint64 kSimpleSparseRangeMagicNumber = GG_UINT64_C(0xeb97bf016553676b);
// A file containing stream 0 and stream 1 in the Simple cache consists of:
// - a SimpleFileHeader.
@@ -58,6 +59,15 @@ struct NET_EXPORT_PRIVATE SimpleFileEOF {
uint32 stream_size;
};
+struct SimpleFileSparseRangeHeader {
+ SimpleFileSparseRangeHeader();
+
+ uint64 sparse_range_magic_number;
+ int64 offset;
+ int64 length;
+ uint32 data_crc32;
+};
+
} // namespace disk_cache
#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_ENTRY_FORMAT_H_
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.cc b/chromium/net/disk_cache/simple/simple_entry_impl.cc
index 3d2bc22cc36..45ec1f9fd1e 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.cc
@@ -31,6 +31,10 @@
namespace disk_cache {
namespace {
+// An entry can store sparse data taking up to 1 / kMaxSparseDataSizeDivisor of
+// the cache.
+const int64 kMaxSparseDataSizeDivisor = 10;
+
// Used in histograms, please only add entries at the end.
enum ReadResult {
READ_RESULT_SUCCESS = 0,
@@ -170,6 +174,7 @@ SimpleEntryImpl::SimpleEntryImpl(net::CacheType cache_type,
use_optimistic_operations_(operations_mode == OPTIMISTIC_OPERATIONS),
last_used_(Time::Now()),
last_modified_(last_used_),
+ sparse_data_size_(0),
open_count_(0),
doomed_(false),
state_(STATE_UNINITIALIZED),
@@ -463,9 +468,11 @@ int SimpleEntryImpl::ReadSparseData(int64 offset,
int buf_len,
const CompletionCallback& callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Determine if the simple backend should support sparse data.
- NOTIMPLEMENTED();
- return net::ERR_FAILED;
+
+ ScopedOperationRunner operation_runner(this);
+ pending_operations_.push(SimpleEntryOperation::ReadSparseOperation(
+ this, offset, buf_len, buf, callback));
+ return net::ERR_IO_PENDING;
}
int SimpleEntryImpl::WriteSparseData(int64 offset,
@@ -473,9 +480,11 @@ int SimpleEntryImpl::WriteSparseData(int64 offset,
int buf_len,
const CompletionCallback& callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Determine if the simple backend should support sparse data.
- NOTIMPLEMENTED();
- return net::ERR_FAILED;
+
+ ScopedOperationRunner operation_runner(this);
+ pending_operations_.push(SimpleEntryOperation::WriteSparseOperation(
+ this, offset, buf_len, buf, callback));
+ return net::ERR_IO_PENDING;
}
int SimpleEntryImpl::GetAvailableRange(int64 offset,
@@ -483,28 +492,32 @@ int SimpleEntryImpl::GetAvailableRange(int64 offset,
int64* start,
const CompletionCallback& callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Determine if the simple backend should support sparse data.
- NOTIMPLEMENTED();
- return net::ERR_FAILED;
+
+ ScopedOperationRunner operation_runner(this);
+ pending_operations_.push(SimpleEntryOperation::GetAvailableRangeOperation(
+ this, offset, len, start, callback));
+ return net::ERR_IO_PENDING;
}
bool SimpleEntryImpl::CouldBeSparse() const {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Determine if the simple backend should support sparse data.
- return false;
+ // TODO(ttuttle): Actually check.
+ return true;
}
void SimpleEntryImpl::CancelSparseIO() {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Determine if the simple backend should support sparse data.
- NOTIMPLEMENTED();
+ // The Simple Cache does not return distinct objects for the same non-doomed
+ // entry, so there's no need to coordinate which object is performing sparse
+ // I/O. Therefore, CancelSparseIO and ReadyForSparseIO succeed instantly.
}
int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) {
DCHECK(io_thread_checker_.CalledOnValidThread());
- // TODO(gavinp): Determine if the simple backend should support sparse data.
- NOTIMPLEMENTED();
- return net::ERR_NOT_IMPLEMENTED;
+ // The simple Cache does not return distinct objects for the same non-doomed
+ // entry, so there's no need to coordinate which object is performing sparse
+ // I/O. Therefore, CancelSparseIO and ReadyForSparseIO succeed instantly.
+ return net::OK;
}
SimpleEntryImpl::~SimpleEntryImpl() {
@@ -608,6 +621,24 @@ void SimpleEntryImpl::RunNextOperationIfNeeded() {
operation->callback(),
operation->truncate());
break;
+ case SimpleEntryOperation::TYPE_READ_SPARSE:
+ ReadSparseDataInternal(operation->sparse_offset(),
+ operation->buf(),
+ operation->length(),
+ operation->callback());
+ break;
+ case SimpleEntryOperation::TYPE_WRITE_SPARSE:
+ WriteSparseDataInternal(operation->sparse_offset(),
+ operation->buf(),
+ operation->length(),
+ operation->callback());
+ break;
+ case SimpleEntryOperation::TYPE_GET_AVAILABLE_RANGE:
+ GetAvailableRangeInternal(operation->sparse_offset(),
+ operation->length(),
+ operation->out_start(),
+ operation->callback());
+ break;
case SimpleEntryOperation::TYPE_DOOM:
DoomEntryInternal(operation->callback());
break;
@@ -651,7 +682,8 @@ void SimpleEntryImpl::OpenEntryInternal(bool have_index,
const base::TimeTicks start_time = base::TimeTicks::Now();
scoped_ptr<SimpleEntryCreationResults> results(
new SimpleEntryCreationResults(
- SimpleEntryStat(last_used_, last_modified_, data_size_)));
+ SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_)));
Closure task = base::Bind(&SimpleSynchronousEntry::OpenEntry,
cache_type_,
path_,
@@ -699,7 +731,8 @@ void SimpleEntryImpl::CreateEntryInternal(bool have_index,
const base::TimeTicks start_time = base::TimeTicks::Now();
scoped_ptr<SimpleEntryCreationResults> results(
new SimpleEntryCreationResults(
- SimpleEntryStat(last_used_, last_modified_, data_size_)));
+ SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_)));
Closure task = base::Bind(&SimpleSynchronousEntry::CreateEntry,
cache_type_,
path_,
@@ -746,7 +779,8 @@ void SimpleEntryImpl::CloseInternal() {
Closure task =
base::Bind(&SimpleSynchronousEntry::Close,
base::Unretained(synchronous_entry_),
- SimpleEntryStat(last_used_, last_modified_, data_size_),
+ SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_),
base::Passed(&crc32s_to_write),
stream_0_data_);
Closure reply = base::Bind(&SimpleEntryImpl::CloseOperationComplete, this);
@@ -825,7 +859,8 @@ void SimpleEntryImpl::ReadDataInternal(int stream_index,
scoped_ptr<uint32> read_crc32(new uint32());
scoped_ptr<int> result(new int());
scoped_ptr<SimpleEntryStat> entry_stat(
- new SimpleEntryStat(last_used_, last_modified_, data_size_));
+ new SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_));
Closure task = base::Bind(
&SimpleSynchronousEntry::ReadData,
base::Unretained(synchronous_entry_),
@@ -908,7 +943,8 @@ void SimpleEntryImpl::WriteDataInternal(int stream_index,
// |entry_stat| needs to be initialized before modifying |data_size_|.
scoped_ptr<SimpleEntryStat> entry_stat(
- new SimpleEntryStat(last_used_, last_modified_, data_size_));
+ new SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_));
if (truncate) {
data_size_[stream_index] = offset + buf_len;
} else {
@@ -944,6 +980,100 @@ void SimpleEntryImpl::WriteDataInternal(int stream_index,
worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
}
+void SimpleEntryImpl::ReadSparseDataInternal(
+ int64 sparse_offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ ScopedOperationRunner operation_runner(this);
+
+ DCHECK_EQ(STATE_READY, state_);
+ state_ = STATE_IO_PENDING;
+
+ 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 reply = base::Bind(&SimpleEntryImpl::ReadSparseOperationComplete,
+ this,
+ callback,
+ base::Passed(&last_used),
+ base::Passed(&result));
+ worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
+}
+
+void SimpleEntryImpl::WriteSparseDataInternal(
+ int64 sparse_offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ ScopedOperationRunner operation_runner(this);
+
+ DCHECK_EQ(STATE_READY, state_);
+ state_ = STATE_IO_PENDING;
+
+ int64 max_sparse_data_size = kint64max;
+ if (backend_.get()) {
+ int64 max_cache_size = backend_->index()->max_size();
+ max_sparse_data_size = max_cache_size / kMaxSparseDataSizeDivisor;
+ }
+
+ scoped_ptr<SimpleEntryStat> entry_stat(
+ new SimpleEntryStat(last_used_, last_modified_, data_size_,
+ sparse_data_size_));
+
+ 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 reply = base::Bind(&SimpleEntryImpl::WriteSparseOperationComplete,
+ this,
+ callback,
+ base::Passed(&entry_stat),
+ base::Passed(&result));
+ worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
+}
+
+void SimpleEntryImpl::GetAvailableRangeInternal(
+ int64 sparse_offset,
+ int len,
+ int64* out_start,
+ const CompletionCallback& callback) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ ScopedOperationRunner operation_runner(this);
+
+ DCHECK_EQ(STATE_READY, state_);
+ state_ = STATE_IO_PENDING;
+
+ scoped_ptr<int> result(new int());
+ Closure task = base::Bind(&SimpleSynchronousEntry::GetAvailableRange,
+ base::Unretained(synchronous_entry_),
+ SimpleSynchronousEntry::EntryOperationData(
+ sparse_offset, len),
+ out_start,
+ result.get());
+ Closure reply = base::Bind(
+ &SimpleEntryImpl::GetAvailableRangeOperationComplete,
+ this,
+ callback,
+ base::Passed(&result));
+ worker_pool_->PostTaskAndReply(FROM_HERE, task, reply);
+}
+
void SimpleEntryImpl::DoomEntryInternal(const CompletionCallback& callback) {
PostTaskAndReplyWithResult(
worker_pool_, FROM_HERE,
@@ -1007,7 +1137,6 @@ void SimpleEntryImpl::CreationOperationComplete(
}
void SimpleEntryImpl::EntryOperationComplete(
- int stream_index,
const CompletionCallback& completion_callback,
const SimpleEntryStat& entry_stat,
scoped_ptr<int> result) {
@@ -1015,12 +1144,11 @@ void SimpleEntryImpl::EntryOperationComplete(
DCHECK(synchronous_entry_);
DCHECK_EQ(STATE_IO_PENDING, state_);
DCHECK(result);
- state_ = STATE_READY;
if (*result < 0) {
- MarkAsDoomed();
state_ = STATE_FAILURE;
- crc32s_end_offset_[stream_index] = 0;
+ MarkAsDoomed();
} else {
+ state_ = STATE_READY;
UpdateDataFromEntryStat(entry_stat);
}
@@ -1086,6 +1214,10 @@ void SimpleEntryImpl::ReadOperationComplete(
}
if (*result < 0) {
+ crc32s_end_offset_[stream_index] = 0;
+ }
+
+ if (*result < 0) {
RecordReadResult(cache_type_, READ_RESULT_SYNC_READ_FAILURE);
} else {
RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
@@ -1100,8 +1232,7 @@ void SimpleEntryImpl::ReadOperationComplete(
CreateNetLogReadWriteCompleteCallback(*result));
}
- EntryOperationComplete(
- stream_index, completion_callback, *entry_stat, result.Pass());
+ EntryOperationComplete(completion_callback, *entry_stat, result.Pass());
}
void SimpleEntryImpl::WriteOperationComplete(
@@ -1118,8 +1249,47 @@ void SimpleEntryImpl::WriteOperationComplete(
CreateNetLogReadWriteCompleteCallback(*result));
}
- EntryOperationComplete(
- stream_index, completion_callback, *entry_stat, result.Pass());
+ if (*result < 0) {
+ crc32s_end_offset_[stream_index] = 0;
+ }
+
+ EntryOperationComplete(completion_callback, *entry_stat, result.Pass());
+}
+
+void SimpleEntryImpl::ReadSparseOperationComplete(
+ const CompletionCallback& completion_callback,
+ scoped_ptr<base::Time> last_used,
+ scoped_ptr<int> result) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(synchronous_entry_);
+ DCHECK(result);
+
+ SimpleEntryStat entry_stat(*last_used, last_modified_, data_size_,
+ sparse_data_size_);
+ EntryOperationComplete(completion_callback, entry_stat, result.Pass());
+}
+
+void SimpleEntryImpl::WriteSparseOperationComplete(
+ const CompletionCallback& completion_callback,
+ scoped_ptr<SimpleEntryStat> entry_stat,
+ scoped_ptr<int> result) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(synchronous_entry_);
+ DCHECK(result);
+
+ EntryOperationComplete(completion_callback, *entry_stat, result.Pass());
+}
+
+void SimpleEntryImpl::GetAvailableRangeOperationComplete(
+ const CompletionCallback& completion_callback,
+ scoped_ptr<int> result) {
+ DCHECK(io_thread_checker_.CalledOnValidThread());
+ DCHECK(synchronous_entry_);
+ DCHECK(result);
+
+ SimpleEntryStat entry_stat(last_used_, last_modified_, data_size_,
+ sparse_data_size_);
+ EntryOperationComplete(completion_callback, entry_stat, result.Pass());
}
void SimpleEntryImpl::DoomOperationComplete(
@@ -1164,11 +1334,9 @@ void SimpleEntryImpl::ChecksumOperationComplete(
CreateNetLogReadWriteCompleteCallback(*result));
}
- EntryOperationComplete(
- stream_index,
- completion_callback,
- SimpleEntryStat(last_used_, last_modified_, data_size_),
- result.Pass());
+ SimpleEntryStat entry_stat(last_used_, last_modified_, data_size_,
+ sparse_data_size_);
+ EntryOperationComplete(completion_callback, entry_stat, result.Pass());
}
void SimpleEntryImpl::CloseOperationComplete() {
@@ -1193,6 +1361,7 @@ void SimpleEntryImpl::UpdateDataFromEntryStat(
for (int i = 0; i < kSimpleEntryStreamCount; ++i) {
data_size_[i] = entry_stat.data_size(i);
}
+ sparse_data_size_ = entry_stat.sparse_data_size();
if (!doomed_ && backend_.get())
backend_->index()->UpdateEntrySize(entry_hash_, GetDiskUsage());
}
@@ -1203,6 +1372,7 @@ int64 SimpleEntryImpl::GetDiskUsage() const {
file_size +=
simple_util::GetFileSizeFromKeyAndDataSize(key_, data_size_[i]);
}
+ file_size += sparse_data_size_;
return file_size;
}
@@ -1286,7 +1456,8 @@ int SimpleEntryImpl::ReadStream0Data(net::IOBuffer* buf,
}
memcpy(buf->data(), stream_0_data_->data() + offset, buf_len);
UpdateDataFromEntryStat(
- SimpleEntryStat(base::Time::Now(), last_modified_, data_size_));
+ SimpleEntryStat(base::Time::Now(), last_modified_, data_size_,
+ sparse_data_size_));
RecordReadResult(cache_type_, READ_RESULT_SUCCESS);
return buf_len;
}
@@ -1296,8 +1467,8 @@ int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf,
int buf_len,
bool truncate) {
// Currently, stream 0 is only used for HTTP headers, and always writes them
- // with a single, truncating write. Detect these writes and record the size
- // changes of the headers. Also, support writes to stream 0 that have
+ // with a single, truncating write. Detect these writes and record the size
+ // changes of the headers. Also, support writes to stream 0 that have
// different access patterns, as required by the API contract.
// All other clients of the Simple Cache are encouraged to use stream 1.
have_written_[0] = true;
@@ -1324,7 +1495,8 @@ int SimpleEntryImpl::SetStream0Data(net::IOBuffer* buf,
base::Time modification_time = base::Time::Now();
AdvanceCrc(buf, offset, buf_len, 0);
UpdateDataFromEntryStat(
- SimpleEntryStat(modification_time, modification_time, data_size_));
+ SimpleEntryStat(modification_time, modification_time, data_size_,
+ sparse_data_size_));
RecordWriteResult(cache_type_, WRITE_RESULT_SUCCESS);
return buf_len;
}
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.h b/chromium/net/disk_cache/simple/simple_entry_impl.h
index e2f0c63b39e..2d78d8bfe0a 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.h
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.h
@@ -188,6 +188,21 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
const CompletionCallback& callback,
bool truncate);
+ void ReadSparseDataInternal(int64 sparse_offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback);
+
+ void WriteSparseDataInternal(int64 sparse_offset,
+ net::IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback);
+
+ void GetAvailableRangeInternal(int64 sparse_offset,
+ int len,
+ int64* out_start,
+ const CompletionCallback& callback);
+
void DoomEntryInternal(const CompletionCallback& callback);
// Called after a SimpleSynchronousEntry has completed CreateEntry() or
@@ -208,8 +223,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
// Internal utility method used by other completion methods. Calls
// |completion_callback| after updating state and dooming on errors.
- void EntryOperationComplete(int stream_index,
- const CompletionCallback& completion_callback,
+ void EntryOperationComplete(const CompletionCallback& completion_callback,
const SimpleEntryStat& entry_stat,
scoped_ptr<int> result);
@@ -227,6 +241,20 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
scoped_ptr<SimpleEntryStat> entry_stat,
scoped_ptr<int> result);
+ void ReadSparseOperationComplete(
+ const CompletionCallback& completion_callback,
+ scoped_ptr<base::Time> last_used,
+ scoped_ptr<int> result);
+
+ void WriteSparseOperationComplete(
+ const CompletionCallback& completion_callback,
+ scoped_ptr<SimpleEntryStat> entry_stat,
+ scoped_ptr<int> result);
+
+ void GetAvailableRangeOperationComplete(
+ const CompletionCallback& completion_callback,
+ scoped_ptr<int> result);
+
// Called after an asynchronous doom completes.
void DoomOperationComplete(const CompletionCallback& callback,
State state_to_restore,
@@ -287,6 +315,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
base::Time last_used_;
base::Time last_modified_;
int32 data_size_[kSimpleEntryStreamCount];
+ int32 sparse_data_size_;
// Number of times this object has been returned from Backend::OpenEntry() and
// Backend::CreateEntry() without subsequent Entry::Close() calls. Used to
diff --git a/chromium/net/disk_cache/simple/simple_entry_operation.cc b/chromium/net/disk_cache/simple/simple_entry_operation.cc
index d4e76082084..7dfe0d2111f 100644
--- a/chromium/net/disk_cache/simple/simple_entry_operation.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_operation.cc
@@ -11,13 +11,36 @@
namespace disk_cache {
+namespace {
+
+bool IsReadWriteType(unsigned int type) {
+ return type == SimpleEntryOperation::TYPE_READ ||
+ type == SimpleEntryOperation::TYPE_WRITE ||
+ type == SimpleEntryOperation::TYPE_READ_SPARSE ||
+ type == SimpleEntryOperation::TYPE_WRITE_SPARSE;
+}
+
+bool IsReadType(unsigned type) {
+ return type == SimpleEntryOperation::TYPE_READ ||
+ type == SimpleEntryOperation::TYPE_READ_SPARSE;
+}
+
+bool IsSparseType(unsigned type) {
+ return type == SimpleEntryOperation::TYPE_READ_SPARSE ||
+ type == SimpleEntryOperation::TYPE_WRITE_SPARSE;
+}
+
+}
+
SimpleEntryOperation::SimpleEntryOperation(const SimpleEntryOperation& other)
: entry_(other.entry_.get()),
buf_(other.buf_),
callback_(other.callback_),
out_entry_(other.out_entry_),
offset_(other.offset_),
+ sparse_offset_(other.sparse_offset_),
length_(other.length_),
+ out_start_(other.out_start_),
type_(other.type_),
have_index_(other.have_index_),
index_(other.index_),
@@ -40,6 +63,8 @@ SimpleEntryOperation SimpleEntryOperation::OpenOperation(
out_entry,
0,
0,
+ 0,
+ NULL,
TYPE_OPEN,
have_index,
0,
@@ -60,6 +85,8 @@ SimpleEntryOperation SimpleEntryOperation::CreateOperation(
out_entry,
0,
0,
+ 0,
+ NULL,
TYPE_CREATE,
have_index,
0,
@@ -77,6 +104,8 @@ SimpleEntryOperation SimpleEntryOperation::CloseOperation(
NULL,
0,
0,
+ 0,
+ NULL,
TYPE_CLOSE,
false,
0,
@@ -99,7 +128,9 @@ SimpleEntryOperation SimpleEntryOperation::ReadOperation(
callback,
NULL,
offset,
+ 0,
length,
+ NULL,
TYPE_READ,
false,
index,
@@ -123,7 +154,9 @@ SimpleEntryOperation SimpleEntryOperation::WriteOperation(
callback,
NULL,
offset,
+ 0,
length,
+ NULL,
TYPE_WRITE,
false,
index,
@@ -133,13 +166,84 @@ SimpleEntryOperation SimpleEntryOperation::WriteOperation(
}
// static
+SimpleEntryOperation SimpleEntryOperation::ReadSparseOperation(
+ SimpleEntryImpl* entry,
+ int64 sparse_offset,
+ int length,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback) {
+ return SimpleEntryOperation(entry,
+ buf,
+ callback,
+ NULL,
+ 0,
+ sparse_offset,
+ length,
+ NULL,
+ TYPE_READ_SPARSE,
+ false,
+ 0,
+ false,
+ false,
+ false);
+}
+
+// static
+SimpleEntryOperation SimpleEntryOperation::WriteSparseOperation(
+ SimpleEntryImpl* entry,
+ int64 sparse_offset,
+ int length,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback) {
+ return SimpleEntryOperation(entry,
+ buf,
+ callback,
+ NULL,
+ 0,
+ sparse_offset,
+ length,
+ NULL,
+ TYPE_WRITE_SPARSE,
+ false,
+ 0,
+ false,
+ false,
+ false);
+}
+
+// static
+SimpleEntryOperation SimpleEntryOperation::GetAvailableRangeOperation(
+ SimpleEntryImpl* entry,
+ int64 sparse_offset,
+ int length,
+ int64* out_start,
+ const CompletionCallback& callback) {
+ return SimpleEntryOperation(entry,
+ NULL,
+ callback,
+ NULL,
+ 0,
+ sparse_offset,
+ length,
+ out_start,
+ TYPE_GET_AVAILABLE_RANGE,
+ false,
+ 0,
+ false,
+ false,
+ false);
+}
+
+// static
SimpleEntryOperation SimpleEntryOperation::DoomOperation(
SimpleEntryImpl* entry,
const CompletionCallback& callback) {
net::IOBuffer* const buf = NULL;
Entry** const out_entry = NULL;
const int offset = 0;
+ const int64 sparse_offset = 0;
const int length = 0;
+ int64* const out_start = NULL;
const bool have_index = false;
const int index = 0;
const bool truncate = false;
@@ -150,7 +254,9 @@ SimpleEntryOperation SimpleEntryOperation::DoomOperation(
callback,
out_entry,
offset,
+ sparse_offset,
length,
+ out_start,
TYPE_DOOM,
have_index,
index,
@@ -161,19 +267,38 @@ SimpleEntryOperation SimpleEntryOperation::DoomOperation(
bool SimpleEntryOperation::ConflictsWith(
const SimpleEntryOperation& other_op) const {
- if (type_ != TYPE_READ && type_ != TYPE_WRITE)
- return true;
- if (other_op.type() != TYPE_READ && other_op.type() != TYPE_WRITE)
+ EntryOperationType other_type = other_op.type();
+
+ // Non-read/write operations conflict with everything.
+ if (!IsReadWriteType(type_) || !IsReadWriteType(other_type))
return true;
- if (type() == TYPE_READ && other_op.type() == TYPE_READ)
+
+ // Reads (sparse or otherwise) conflict with nothing.
+ if (IsReadType(type_) && IsReadType(other_type))
return false;
+
+ // Sparse and non-sparse operations do not conflict with each other.
+ if (IsSparseType(type_) != IsSparseType(other_type)) {
+ return false;
+ }
+
+ // There must be two read/write operations, at least one must be a write, and
+ // they must be either both non-sparse or both sparse. Compare the streams
+ // and offsets to see whether they overlap.
+
+ if (IsSparseType(type_)) {
+ int64 end = sparse_offset_ + length_;
+ int64 other_op_end = other_op.sparse_offset() + other_op.length();
+ return sparse_offset_ < other_op_end && other_op.sparse_offset() < end;
+ }
+
if (index_ != other_op.index_)
return false;
int end = (type_ == TYPE_WRITE && truncate_) ? INT_MAX : offset_ + length_;
int other_op_end = (other_op.type() == TYPE_WRITE && other_op.truncate())
? INT_MAX
: other_op.offset() + other_op.length();
- return (offset_ < other_op_end && other_op.offset() < end);
+ return offset_ < other_op_end && other_op.offset() < end;
}
void SimpleEntryOperation::ReleaseReferences() {
@@ -187,7 +312,9 @@ SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry,
const CompletionCallback& callback,
Entry** out_entry,
int offset,
+ int64 sparse_offset,
int length,
+ int64* out_start,
EntryOperationType type,
bool have_index,
int index,
@@ -199,7 +326,9 @@ SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry,
callback_(callback),
out_entry_(out_entry),
offset_(offset),
+ sparse_offset_(sparse_offset),
length_(length),
+ out_start_(out_start),
type_(type),
have_index_(have_index),
index_(index),
diff --git a/chromium/net/disk_cache/simple/simple_entry_operation.h b/chromium/net/disk_cache/simple/simple_entry_operation.h
index 1c787017229..08863124cfc 100644
--- a/chromium/net/disk_cache/simple/simple_entry_operation.h
+++ b/chromium/net/disk_cache/simple/simple_entry_operation.h
@@ -31,7 +31,10 @@ class SimpleEntryOperation {
TYPE_CLOSE = 2,
TYPE_READ = 3,
TYPE_WRITE = 4,
- TYPE_DOOM = 5,
+ TYPE_READ_SPARSE = 5,
+ TYPE_WRITE_SPARSE = 6,
+ TYPE_GET_AVAILABLE_RANGE = 7,
+ TYPE_DOOM = 8,
};
SimpleEntryOperation(const SimpleEntryOperation& other);
@@ -63,7 +66,24 @@ class SimpleEntryOperation {
bool truncate,
bool optimistic,
const CompletionCallback& callback);
-
+ static SimpleEntryOperation ReadSparseOperation(
+ SimpleEntryImpl* entry,
+ int64 sparse_offset,
+ int length,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback);
+ static SimpleEntryOperation WriteSparseOperation(
+ SimpleEntryImpl* entry,
+ int64 sparse_offset,
+ int length,
+ net::IOBuffer* buf,
+ const CompletionCallback& callback);
+ static SimpleEntryOperation GetAvailableRangeOperation(
+ SimpleEntryImpl* entry,
+ int64 sparse_offset,
+ int length,
+ int64* out_start,
+ const CompletionCallback& callback);
static SimpleEntryOperation DoomOperation(
SimpleEntryImpl* entry,
const CompletionCallback& callback);
@@ -81,7 +101,9 @@ class SimpleEntryOperation {
bool have_index() const { return have_index_; }
int index() const { return index_; }
int offset() const { return offset_; }
+ int64 sparse_offset() const { return sparse_offset_; }
int length() const { return length_; }
+ int64* out_start() { return out_start_; }
net::IOBuffer* buf() { return buf_.get(); }
bool truncate() const { return truncate_; }
bool optimistic() const { return optimistic_; }
@@ -93,7 +115,9 @@ class SimpleEntryOperation {
const CompletionCallback& callback,
Entry** out_entry,
int offset,
+ int64 sparse_offset,
int length,
+ int64* out_start,
EntryOperationType type,
bool have_index,
int index,
@@ -111,18 +135,22 @@ class SimpleEntryOperation {
// Used in write and read operations.
const int offset_;
+ const int64 sparse_offset_;
const int length_;
- const unsigned int type_ : 3; /* 3 */
+ // Used in get available range operations.
+ int64* const out_start_;
+
+ const EntryOperationType type_;
// Used in open and create operations.
- const unsigned int have_index_ : 1; /* 4 */
+ const bool have_index_;
// Used in write and read operations.
- const unsigned int index_ : 2; /* 6 */
+ const unsigned int index_;
// Used only in write operations.
- const unsigned int truncate_ : 1; /* 7 */
- const unsigned int optimistic_ : 1; /* 8 */
+ const bool truncate_;
+ const bool optimistic_;
// Used only in SimpleCache.ReadIsParallelizable histogram.
- const unsigned int alone_in_queue_ : 1; /* 9 */
+ const bool alone_in_queue_;
};
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/simple/simple_histogram_macros.h b/chromium/net/disk_cache/simple/simple_histogram_macros.h
index 2107ad466a7..f800a6f40a3 100644
--- a/chromium/net/disk_cache/simple/simple_histogram_macros.h
+++ b/chromium/net/disk_cache/simple/simple_histogram_macros.h
@@ -10,26 +10,31 @@
#include "net/base/cache_type.h"
// This file contains macros used to report histograms. The main issue is that
-// we want to have separate histograms for each type of cache (http vs app),
-// while making it easy to report histograms and have all names precomputed.
+// we want to have separate histograms for each type of cache (app, http, and
+// media), while making it easy to report histograms and have all names
+// precomputed.
#define SIMPLE_CACHE_THUNK(uma_type, args) UMA_HISTOGRAM_##uma_type args
-#define SIMPLE_CACHE_UMA(uma_type, uma_name, cache_type, ...) \
- do { \
- switch (cache_type) { \
- case net::DISK_CACHE: \
- SIMPLE_CACHE_THUNK( \
- uma_type, ("SimpleCache.Http." uma_name, ##__VA_ARGS__)); \
- break; \
- case net::APP_CACHE: \
- SIMPLE_CACHE_THUNK( \
- uma_type, ("SimpleCache.App." uma_name, ##__VA_ARGS__)); \
- break; \
- default: \
- NOTREACHED(); \
- break; \
- } \
+#define SIMPLE_CACHE_UMA(uma_type, uma_name, cache_type, ...) \
+ do { \
+ switch (cache_type) { \
+ case net::DISK_CACHE: \
+ SIMPLE_CACHE_THUNK( \
+ uma_type, ("SimpleCache.Http." uma_name, ##__VA_ARGS__)); \
+ break; \
+ case net::APP_CACHE: \
+ SIMPLE_CACHE_THUNK( \
+ uma_type, ("SimpleCache.App." uma_name, ##__VA_ARGS__)); \
+ break; \
+ case net::MEDIA_CACHE: \
+ SIMPLE_CACHE_THUNK( \
+ uma_type, ("SimpleCache.Media." uma_name, ##__VA_ARGS__)); \
+ break; \
+ default: \
+ NOTREACHED(); \
+ break; \
+ } \
} while (0)
#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_HISTOGRAM_MACROS_H_
diff --git a/chromium/net/disk_cache/simple/simple_index_file.cc b/chromium/net/disk_cache/simple/simple_index_file.cc
index c350cddb39f..abd9f7a7ae0 100644
--- a/chromium/net/disk_cache/simple/simple_index_file.cc
+++ b/chromium/net/disk_cache/simple/simple_index_file.cc
@@ -30,9 +30,6 @@ const int kEntryFilesSuffixLength = 2;
const uint64 kMaxEntiresInIndex = 100000000;
-const char kIndexFileName[] = "the-real-index";
-const char kTempIndexFileName[] = "temp-index";
-
uint32 CalculatePickleCRC(const Pickle& pickle) {
return crc32(crc32(0, Z_NULL, 0),
reinterpret_cast<const Bytef*>(pickle.payload()),
@@ -99,7 +96,7 @@ void ProcessEntryFile(SimpleIndex::EntrySet* entries,
}
base::PlatformFileInfo file_info;
- if (!file_util::GetFileInfo(file_path, &file_info)) {
+ if (!base::GetFileInfo(file_path, &file_info)) {
LOG(ERROR) << "Could not get file info for " << file_path.value();
return;
}
@@ -206,7 +203,7 @@ void SimpleIndexFile::SyncWriteToDisk(net::CacheType cache_type,
}
SerializeFinalData(cache_dir_mtime, pickle.get());
if (!WritePickleFile(pickle.get(), temp_index_filename)) {
- if (!file_util::CreateDirectory(temp_index_filename.DirName())) {
+ if (!base::CreateDirectory(temp_index_filename.DirName())) {
LOG(ERROR) << "Could not create a directory to hold the index file";
return;
}
diff --git a/chromium/net/disk_cache/simple/simple_index_file.h b/chromium/net/disk_cache/simple/simple_index_file.h
index ce19e2bb56f..756294121c9 100644
--- a/chromium/net/disk_cache/simple/simple_index_file.h
+++ b/chromium/net/disk_cache/simple/simple_index_file.h
@@ -40,15 +40,15 @@ struct NET_EXPORT_PRIVATE SimpleIndexLoadResult {
};
// Simple Index File format is a pickle serialized data of IndexMetadata and
-// EntryMetadata objects. The file format is as follows: one instance of
+// EntryMetadata objects. The file format is as follows: one instance of
// serialized |IndexMetadata| followed serialized |EntryMetadata| entries
-// repeated |number_of_entries| amount of times. To know more about the format,
+// repeated |number_of_entries| amount of times. To know more about the format,
// see SimpleIndexFile::Serialize() and SeeSimpleIndexFile::LoadFromDisk()
// methods.
//
-// The non-static methods must run on the IO thread. All the real
+// The non-static methods must run on the IO thread. All the real
// work is done in the static methods, which are run on the cache thread
-// or in worker threads. Synchronization between methods is the
+// or in worker threads. Synchronization between methods is the
// responsibility of the caller.
class NET_EXPORT_PRIVATE SimpleIndexFile {
public:
diff --git a/chromium/net/disk_cache/simple/simple_index_file_unittest.cc b/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
index 0e9c2e8155b..17aa595bba9 100644
--- a/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
+++ b/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
@@ -11,13 +11,18 @@
#include "base/pickle.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/threading/thread.h"
#include "base/time/time.h"
#include "net/base/cache_type.h"
+#include "net/base/test_completion_callback.h"
+#include "net/disk_cache/disk_cache_test_util.h"
+#include "net/disk_cache/simple/simple_backend_impl.h"
#include "net/disk_cache/simple/simple_backend_version.h"
#include "net/disk_cache/simple/simple_entry_format.h"
#include "net/disk_cache/simple/simple_index.h"
#include "net/disk_cache/simple/simple_index_file.h"
#include "net/disk_cache/simple/simple_util.h"
+#include "net/disk_cache/simple/simple_version_upgrade.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
@@ -81,7 +86,7 @@ class WrappedSimpleIndexFile : public SimpleIndexFile {
}
bool CreateIndexFileDirectory() const {
- return file_util::CreateDirectory(index_file_.DirName());
+ return base::CreateDirectory(index_file_.DirName());
}
};
@@ -173,13 +178,13 @@ TEST_F(SimpleIndexFileTest, LegacyIsIndexFileStale) {
const base::Time past_time = base::Time::Now() -
base::TimeDelta::FromSeconds(10);
- EXPECT_TRUE(file_util::TouchFile(index_path, past_time, past_time));
- EXPECT_TRUE(file_util::TouchFile(cache_path, past_time, past_time));
+ EXPECT_TRUE(base::TouchFile(index_path, past_time, past_time));
+ EXPECT_TRUE(base::TouchFile(cache_path, past_time, past_time));
ASSERT_TRUE(simple_util::GetMTime(cache_path, &cache_mtime));
EXPECT_FALSE(
WrappedSimpleIndexFile::LegacyIsIndexFileStale(cache_mtime, index_path));
const base::Time even_older = past_time - base::TimeDelta::FromSeconds(10);
- EXPECT_TRUE(file_util::TouchFile(index_path, even_older, even_older));
+ EXPECT_TRUE(base::TouchFile(index_path, even_older, even_older));
EXPECT_TRUE(
WrappedSimpleIndexFile::LegacyIsIndexFileStale(cache_mtime, index_path));
}
@@ -257,6 +262,84 @@ TEST_F(SimpleIndexFileTest, LoadCorruptIndex) {
EXPECT_TRUE(load_index_result.flush_required);
}
+// Tests that after an upgrade the backend has the index file put in place.
+TEST_F(SimpleIndexFileTest, SimpleCacheUpgrade) {
+ base::ScopedTempDir cache_dir;
+ ASSERT_TRUE(cache_dir.CreateUniqueTempDir());
+ const base::FilePath cache_path = cache_dir.path();
+
+ // Write an old fake index file.
+ base::PlatformFileError error;
+ base::PlatformFile file = base::CreatePlatformFile(
+ cache_path.AppendASCII("index"),
+ base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE,
+ NULL,
+ &error);
+ disk_cache::FakeIndexData file_contents;
+ file_contents.initial_magic_number = disk_cache::kSimpleInitialMagicNumber;
+ file_contents.version = 5;
+ int bytes_written = base::WritePlatformFile(
+ file, 0, reinterpret_cast<char*>(&file_contents), sizeof(file_contents));
+ ASSERT_TRUE(base::ClosePlatformFile(file));
+ ASSERT_EQ((int)sizeof(file_contents), bytes_written);
+
+ // Write the index file. The format is incorrect, but for transitioning from
+ // v5 it does not matter.
+ const std::string index_file_contents("incorrectly serialized data");
+ const base::FilePath old_index_file =
+ cache_path.AppendASCII("the-real-index");
+ ASSERT_EQ(implicit_cast<int>(index_file_contents.size()),
+ file_util::WriteFile(old_index_file,
+ index_file_contents.data(),
+ index_file_contents.size()));
+
+ // Upgrade the cache.
+ ASSERT_TRUE(disk_cache::UpgradeSimpleCacheOnDisk(cache_path));
+
+ // Create the backend and initiate index flush by destroying the backend.
+ base::Thread cache_thread("CacheThread");
+ ASSERT_TRUE(cache_thread.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0)));
+ disk_cache::SimpleBackendImpl* simple_cache =
+ new disk_cache::SimpleBackendImpl(cache_path,
+ 0,
+ net::DISK_CACHE,
+ cache_thread.message_loop_proxy().get(),
+ NULL);
+ net::TestCompletionCallback cb;
+ int rv = simple_cache->Init(cb.callback());
+ EXPECT_EQ(net::OK, cb.GetResult(rv));
+ rv = simple_cache->index()->ExecuteWhenReady(cb.callback());
+ EXPECT_EQ(net::OK, cb.GetResult(rv));
+ delete simple_cache;
+
+ // The backend flushes the index on destruction and does so on the cache
+ // thread, wait for the flushing to finish by posting a callback to the cache
+ // thread after that.
+ MessageLoopHelper helper;
+ CallbackTest cb_shutdown(&helper, false);
+ cache_thread.message_loop_proxy()->PostTask(
+ FROM_HERE,
+ base::Bind(&CallbackTest::Run, base::Unretained(&cb_shutdown), net::OK));
+ helper.WaitUntilCacheIoFinished(1);
+
+ // Verify that the index file exists.
+ const base::FilePath& index_file_path =
+ cache_path.AppendASCII("index-dir").AppendASCII("the-real-index");
+ EXPECT_TRUE(base::PathExists(index_file_path));
+
+ // Verify that the version of the index file is correct.
+ std::string contents;
+ EXPECT_TRUE(base::ReadFileToString(index_file_path, &contents));
+ base::Time when_index_last_saw_cache;
+ SimpleIndexLoadResult deserialize_result;
+ WrappedSimpleIndexFile::Deserialize(contents.data(),
+ contents.size(),
+ &when_index_last_saw_cache,
+ &deserialize_result);
+ EXPECT_TRUE(deserialize_result.did_load);
+}
+
#endif // defined(OS_POSIX)
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/simple/simple_index_unittest.cc b/chromium/net/disk_cache/simple/simple_index_unittest.cc
index 47ae24f62fe..cee7bf33c4d 100644
--- a/chromium/net/disk_cache/simple/simple_index_unittest.cc
+++ b/chromium/net/disk_cache/simple/simple_index_unittest.cc
@@ -538,7 +538,7 @@ TEST_F(SimpleIndexTest, BasicEviction) {
// Trigger an eviction, and make sure the right things are tossed.
// TODO(rdsmith): This is dependent on the innards of the implementation
- // as to at exactly what point we trigger eviction. Not sure how to fix
+ // as to at exactly what point we trigger eviction. Not sure how to fix
// that.
index()->UpdateEntrySize(hashes_.at<3>(), 475);
EXPECT_EQ(1, doom_entries_calls());
diff --git a/chromium/net/disk_cache/simple/simple_net_log_parameters.h b/chromium/net/disk_cache/simple/simple_net_log_parameters.h
index b6f386f4a99..41ea9a2af91 100644
--- a/chromium/net/disk_cache/simple/simple_net_log_parameters.h
+++ b/chromium/net/disk_cache/simple/simple_net_log_parameters.h
@@ -14,14 +14,14 @@ namespace disk_cache {
class SimpleEntryImpl;
// Creates a NetLog callback that returns parameters for the construction of a
-// SimpleEntryImpl. Contains the entry's hash. |entry| can't be NULL and must
+// SimpleEntryImpl. Contains the entry's hash. |entry| can't be NULL and must
// outlive the returned callback.
net::NetLog::ParametersCallback CreateNetLogSimpleEntryConstructionCallback(
const SimpleEntryImpl* entry);
// Creates a NetLog callback that returns parameters for the result of calling
-// |CreateEntry| or |OpenEntry| on a SimpleEntryImpl. Contains the |net_error|
-// and, if successful, the entry's key. |entry| can't be NULL and must outlive
+// |CreateEntry| or |OpenEntry| on a SimpleEntryImpl. Contains the |net_error|
+// and, if successful, the entry's key. |entry| can't be NULL and must outlive
// the returned callback.
net::NetLog::ParametersCallback CreateNetLogSimpleEntryCreationCallback(
const SimpleEntryImpl* entry,
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
index 38e8a3cae99..81f52e15b7d 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -34,6 +34,7 @@ using base::PLATFORM_FILE_ERROR_EXISTS;
using base::PLATFORM_FILE_ERROR_NOT_FOUND;
using base::PLATFORM_FILE_OK;
using base::PLATFORM_FILE_OPEN;
+using base::PLATFORM_FILE_OPEN_ALWAYS;
using base::PLATFORM_FILE_READ;
using base::PLATFORM_FILE_WRITE;
using base::ReadPlatformFile;
@@ -53,7 +54,8 @@ enum OpenEntryResult {
OPEN_ENTRY_CANT_READ_KEY = 5,
// OPEN_ENTRY_KEY_MISMATCH = 6, Deprecated.
OPEN_ENTRY_KEY_HASH_MISMATCH = 7,
- OPEN_ENTRY_MAX = 8,
+ OPEN_ENTRY_SPARSE_OPEN_FAILED = 8,
+ OPEN_ENTRY_MAX = 9,
};
// Used in histograms, please only add entries at the end.
@@ -128,15 +130,18 @@ namespace disk_cache {
using simple_util::GetEntryHashKey;
using simple_util::GetFilenameFromEntryHashAndFileIndex;
+using simple_util::GetSparseFilenameFromEntryHash;
using simple_util::GetDataSizeFromKeyAndFileSize;
using simple_util::GetFileSizeFromKeyAndDataSize;
using simple_util::GetFileIndexFromStreamIndex;
SimpleEntryStat::SimpleEntryStat(base::Time last_used,
base::Time last_modified,
- const int32 data_size[])
+ const int32 data_size[],
+ const int32 sparse_data_size)
: last_used_(last_used),
- last_modified_(last_modified) {
+ last_modified_(last_modified),
+ sparse_data_size_(sparse_data_size) {
memcpy(data_size_, data_size, sizeof(data_size_));
}
@@ -211,6 +216,12 @@ SimpleSynchronousEntry::EntryOperationData::EntryOperationData(int index_p,
truncate(truncate_p),
doomed(doomed_p) {}
+SimpleSynchronousEntry::EntryOperationData::EntryOperationData(
+ int64 sparse_offset_p,
+ int buf_len_p)
+ : sparse_offset(sparse_offset_p),
+ buf_len(buf_len_p) {}
+
// static
void SimpleSynchronousEntry::OpenEntry(
net::CacheType cache_type,
@@ -391,6 +402,213 @@ void SimpleSynchronousEntry::WriteData(const EntryOperationData& in_entry_op,
*out_result = buf_len;
}
+void SimpleSynchronousEntry::ReadSparseData(
+ const EntryOperationData& in_entry_op,
+ net::IOBuffer* out_buf,
+ base::Time* out_last_used,
+ int* out_result) {
+ DCHECK(initialized_);
+ int64 offset = in_entry_op.sparse_offset;
+ int buf_len = in_entry_op.buf_len;
+
+ char* buf = out_buf->data();
+ int read_so_far = 0;
+
+ // Find the first sparse range at or after the requested offset.
+ SparseRangeIterator it = sparse_ranges_.lower_bound(offset);
+
+ if (it != sparse_ranges_.begin()) {
+ // Hop back one range and read the one overlapping with the start.
+ --it;
+ SparseRange* found_range = &it->second;
+ DCHECK_EQ(it->first, found_range->offset);
+ if (found_range->offset + found_range->length > offset) {
+ DCHECK_LE(0, found_range->length);
+ DCHECK_GE(kint32max, found_range->length);
+ DCHECK_LE(0, offset - found_range->offset);
+ DCHECK_GE(kint32max, offset - found_range->offset);
+ int range_len_after_offset = found_range->length -
+ (offset - found_range->offset);
+ DCHECK_LE(0, range_len_after_offset);
+
+ int len_to_read = std::min(buf_len, range_len_after_offset);
+ if (!ReadSparseRange(found_range,
+ offset - found_range->offset,
+ len_to_read,
+ buf)) {
+ *out_result = net::ERR_CACHE_READ_FAILURE;
+ return;
+ }
+ read_so_far += len_to_read;
+ }
+ ++it;
+ }
+
+ // Keep reading until the buffer is full or there is not another contiguous
+ // range.
+ while (read_so_far < buf_len &&
+ it != sparse_ranges_.end() &&
+ it->second.offset == offset + read_so_far) {
+ SparseRange* found_range = &it->second;
+ DCHECK_EQ(it->first, found_range->offset);
+ int range_len = (found_range->length > kint32max) ?
+ kint32max : found_range->length;
+ int len_to_read = std::min(buf_len - read_so_far, range_len);
+ if (!ReadSparseRange(found_range, 0, len_to_read, buf + read_so_far)) {
+ *out_result = net::ERR_CACHE_READ_FAILURE;
+ return;
+ }
+ read_so_far += len_to_read;
+ ++it;
+ }
+
+ *out_result = read_so_far;
+}
+
+void SimpleSynchronousEntry::WriteSparseData(
+ const EntryOperationData& in_entry_op,
+ net::IOBuffer* in_buf,
+ int64 max_sparse_data_size,
+ SimpleEntryStat* out_entry_stat,
+ int* out_result) {
+ DCHECK(initialized_);
+ int64 offset = in_entry_op.sparse_offset;
+ int buf_len = in_entry_op.buf_len;
+
+ const char* buf = in_buf->data();
+ int written_so_far = 0;
+ int appended_so_far = 0;
+
+ if (!sparse_file_open() && !CreateSparseFile()) {
+ *out_result = net::ERR_CACHE_WRITE_FAILURE;
+ return;
+ }
+
+ int64 sparse_data_size = out_entry_stat->sparse_data_size();
+ // This is a pessimistic estimate; it assumes the entire buffer is going to
+ // be appended as a new range, not written over existing ranges.
+ if (sparse_data_size + buf_len > max_sparse_data_size) {
+ DLOG(INFO) << "Truncating sparse data file (" << sparse_data_size << " + "
+ << buf_len << " > " << max_sparse_data_size << ")";
+ TruncateSparseFile();
+ }
+
+ SparseRangeIterator it = sparse_ranges_.lower_bound(offset);
+
+ if (it != sparse_ranges_.begin()) {
+ --it;
+ SparseRange* found_range = &it->second;
+ if (found_range->offset + found_range->length > offset) {
+ DCHECK_LE(0, found_range->length);
+ DCHECK_GE(kint32max, found_range->length);
+ DCHECK_LE(0, offset - found_range->offset);
+ DCHECK_GE(kint32max, offset - found_range->offset);
+ int range_len_after_offset = found_range->length -
+ (offset - found_range->offset);
+ DCHECK_LE(0, range_len_after_offset);
+
+ int len_to_write = std::min(buf_len, range_len_after_offset);
+ if (!WriteSparseRange(found_range,
+ offset - found_range->offset,
+ len_to_write,
+ buf)) {
+ *out_result = net::ERR_CACHE_WRITE_FAILURE;
+ return;
+ }
+ written_so_far += len_to_write;
+ }
+ ++it;
+ }
+
+ while (written_so_far < buf_len &&
+ it != sparse_ranges_.end() &&
+ it->second.offset < offset + buf_len) {
+ SparseRange* found_range = &it->second;
+ if (offset + written_so_far < found_range->offset) {
+ int len_to_append = found_range->offset - (offset + written_so_far);
+ if (!AppendSparseRange(offset + written_so_far,
+ len_to_append,
+ buf + written_so_far)) {
+ *out_result = net::ERR_CACHE_WRITE_FAILURE;
+ return;
+ }
+ written_so_far += len_to_append;
+ appended_so_far += len_to_append;
+ }
+ int range_len = (found_range->length > kint32max) ?
+ kint32max : found_range->length;
+ int len_to_write = std::min(buf_len - written_so_far, range_len);
+ if (!WriteSparseRange(found_range,
+ 0,
+ len_to_write,
+ buf + written_so_far)) {
+ *out_result = net::ERR_CACHE_WRITE_FAILURE;
+ return;
+ }
+ written_so_far += len_to_write;
+ ++it;
+ }
+
+ if (written_so_far < buf_len) {
+ int len_to_append = buf_len - written_so_far;
+ if (!AppendSparseRange(offset + written_so_far,
+ len_to_append,
+ buf + written_so_far)) {
+ *out_result = net::ERR_CACHE_WRITE_FAILURE;
+ return;
+ }
+ written_so_far += len_to_append;
+ appended_so_far += len_to_append;
+ }
+
+ DCHECK_EQ(buf_len, written_so_far);
+
+ base::Time modification_time = Time::Now();
+ out_entry_stat->set_last_used(modification_time);
+ out_entry_stat->set_last_modified(modification_time);
+ int32 old_sparse_data_size = out_entry_stat->sparse_data_size();
+ out_entry_stat->set_sparse_data_size(old_sparse_data_size + appended_so_far);
+ *out_result = written_so_far;
+}
+
+void SimpleSynchronousEntry::GetAvailableRange(
+ const EntryOperationData& in_entry_op,
+ int64* out_start,
+ int* out_result) {
+ DCHECK(initialized_);
+ int64 offset = in_entry_op.sparse_offset;
+ int len = in_entry_op.buf_len;
+
+ SparseRangeIterator it = sparse_ranges_.lower_bound(offset);
+
+ int64 start = offset;
+ int avail_so_far = 0;
+
+ if (it != sparse_ranges_.end() && it->second.offset < offset + len)
+ start = it->second.offset;
+
+ if ((it == sparse_ranges_.end() || it->second.offset > offset) &&
+ it != sparse_ranges_.begin()) {
+ --it;
+ if (it->second.offset + it->second.length > offset) {
+ start = offset;
+ avail_so_far = (it->second.offset + it->second.length) - offset;
+ }
+ ++it;
+ }
+
+ while (start + avail_so_far < offset + len &&
+ it != sparse_ranges_.end() &&
+ it->second.offset == start + avail_so_far) {
+ avail_so_far += it->second.length;
+ ++it;
+ }
+
+ int len_from_start = len - (start - offset);
+ *out_start = start;
+ *out_result = std::min(avail_so_far, len_from_start);
+}
+
void SimpleSynchronousEntry::CheckEOFRecord(int index,
const SimpleEntryStat& entry_stat,
uint32 expected_crc32,
@@ -482,6 +700,16 @@ void SimpleSynchronousEntry::Close(
cluster_loss * 100 / (cluster_loss + file_size));
}
+ if (sparse_file_open()) {
+ bool did_close_file = ClosePlatformFile(sparse_file_);
+ CHECK(did_close_file);
+ }
+
+ if (files_created_) {
+ const int stream2_file_index = GetFileIndexFromStreamIndex(2);
+ SIMPLE_CACHE_UMA(BOOLEAN, "EntryCreatedAndStream2Omitted", cache_type_,
+ empty_file_omitted_[stream2_file_index]);
+ }
RecordCloseResult(cache_type_, CLOSE_RESULT_SUCCESS);
have_open_files_ = false;
delete this;
@@ -496,7 +724,8 @@ SimpleSynchronousEntry::SimpleSynchronousEntry(net::CacheType cache_type,
entry_hash_(entry_hash),
key_(key),
have_open_files_(false),
- initialized_(false) {
+ initialized_(false),
+ sparse_file_(kInvalidPlatformFileValue) {
for (int i = 0; i < kSimpleEntryFileCount; ++i) {
files_[i] = kInvalidPlatformFileValue;
empty_file_omitted_[i] = false;
@@ -622,6 +851,8 @@ bool SimpleSynchronousEntry::OpenFiles(
"SyncOpenEntryAge", cache_type_,
entry_age.InHours(), 1, 1000, 50);
+ files_created_ = false;
+
return true;
}
@@ -661,6 +892,8 @@ bool SimpleSynchronousEntry::CreateFiles(
for (int i = 0; i < kSimpleEntryStreamCount; ++i)
out_entry_stat->set_data_size(i, 0);
+ files_created_ = true;
+
return true;
}
@@ -673,6 +906,11 @@ void SimpleSynchronousEntry::CloseFile(int index) {
DCHECK(did_close);
files_[index] = kInvalidPlatformFileValue;
}
+
+ if (sparse_file_open()) {
+ bool did_close = CloseSparseFile();
+ DCHECK(did_close);
+ }
}
void SimpleSynchronousEntry::CloseFiles() {
@@ -754,16 +992,29 @@ int SimpleSynchronousEntry::InitializeForOpen(
}
}
- const int third_stream_file_index = GetFileIndexFromStreamIndex(2);
- DCHECK(CanOmitEmptyFile(third_stream_file_index));
- if (!empty_file_omitted_[third_stream_file_index] &&
+ int32 sparse_data_size = 0;
+ if (!OpenSparseFileIfExists(&sparse_data_size)) {
+ RecordSyncOpenResult(
+ cache_type_, OPEN_ENTRY_SPARSE_OPEN_FAILED, had_index);
+ return net::ERR_FAILED;
+ }
+ out_entry_stat->set_sparse_data_size(sparse_data_size);
+
+ bool removed_stream2 = false;
+ const int stream2_file_index = GetFileIndexFromStreamIndex(2);
+ DCHECK(CanOmitEmptyFile(stream2_file_index));
+ if (!empty_file_omitted_[stream2_file_index] &&
out_entry_stat->data_size(2) == 0) {
- DLOG(INFO) << "Removing empty third stream file.";
- CloseFile(third_stream_file_index);
- DeleteFileForEntryHash(path_, entry_hash_, third_stream_file_index);
- empty_file_omitted_[third_stream_file_index] = true;
+ DLOG(INFO) << "Removing empty stream 2 file.";
+ CloseFile(stream2_file_index);
+ DeleteFileForEntryHash(path_, entry_hash_, stream2_file_index);
+ empty_file_omitted_[stream2_file_index] = true;
+ removed_stream2 = true;
}
+ SIMPLE_CACHE_UMA(BOOLEAN, "EntryOpenedAndStream2Removed", cache_type_,
+ removed_stream2);
+
RecordSyncOpenResult(cache_type_, OPEN_ENTRY_SUCCESS, had_index);
initialized_ = true;
return net::OK;
@@ -905,6 +1156,7 @@ void SimpleSynchronousEntry::Doom() const {
DeleteFilesForEntryHash(path_, entry_hash_);
}
+// static
bool SimpleSynchronousEntry::DeleteFileForEntryHash(
const FilePath& path,
const uint64 entry_hash,
@@ -914,6 +1166,7 @@ bool SimpleSynchronousEntry::DeleteFileForEntryHash(
return base::DeleteFile(to_delete, false);
}
+// static
bool SimpleSynchronousEntry::DeleteFilesForEntryHash(
const FilePath& path,
const uint64 entry_hash) {
@@ -922,6 +1175,9 @@ bool SimpleSynchronousEntry::DeleteFilesForEntryHash(
if (!DeleteFileForEntryHash(path, entry_hash, i) && !CanOmitEmptyFile(i))
result = false;
}
+ FilePath to_delete = path.AppendASCII(
+ GetSparseFilenameFromEntryHash(entry_hash));
+ base::DeleteFile(to_delete, false);
return result;
}
@@ -946,4 +1202,277 @@ FilePath SimpleSynchronousEntry::GetFilenameFromFileIndex(int file_index) {
GetFilenameFromEntryHashAndFileIndex(entry_hash_, file_index));
}
+bool SimpleSynchronousEntry::OpenSparseFileIfExists(
+ int32* out_sparse_data_size) {
+ DCHECK(!sparse_file_open());
+
+ FilePath filename = path_.AppendASCII(
+ GetSparseFilenameFromEntryHash(entry_hash_));
+ int flags = PLATFORM_FILE_OPEN | PLATFORM_FILE_READ | PLATFORM_FILE_WRITE;
+ bool created;
+ PlatformFileError error;
+ sparse_file_ = CreatePlatformFile(filename, flags, &created, &error);
+ if (error == PLATFORM_FILE_ERROR_NOT_FOUND)
+ return true;
+
+ return ScanSparseFile(out_sparse_data_size);
+}
+
+bool SimpleSynchronousEntry::CreateSparseFile() {
+ DCHECK(!sparse_file_open());
+
+ FilePath filename = path_.AppendASCII(
+ GetSparseFilenameFromEntryHash(entry_hash_));
+ int flags = PLATFORM_FILE_CREATE | PLATFORM_FILE_READ | PLATFORM_FILE_WRITE;
+ bool created;
+ PlatformFileError error;
+ sparse_file_ = CreatePlatformFile(filename, flags, &created, &error);
+ if (error != PLATFORM_FILE_OK)
+ return false;
+
+ return InitializeSparseFile();
+}
+
+bool SimpleSynchronousEntry::CloseSparseFile() {
+ DCHECK(sparse_file_open());
+
+ bool did_close = ClosePlatformFile(sparse_file_);
+ if (did_close)
+ sparse_file_ = kInvalidPlatformFileValue;
+ return did_close;
+}
+
+bool SimpleSynchronousEntry::TruncateSparseFile() {
+ DCHECK(sparse_file_open());
+
+ int64 header_and_key_length = sizeof(SimpleFileHeader) + key_.size();
+ if (!TruncatePlatformFile(sparse_file_, header_and_key_length)) {
+ DLOG(WARNING) << "Could not truncate sparse file";
+ return false;
+ }
+
+ sparse_ranges_.clear();
+
+ return true;
+}
+
+bool SimpleSynchronousEntry::InitializeSparseFile() {
+ DCHECK(sparse_file_open());
+
+ SimpleFileHeader header;
+ header.initial_magic_number = kSimpleInitialMagicNumber;
+ header.version = kSimpleVersion;
+ header.key_length = key_.size();
+ header.key_hash = base::Hash(key_);
+
+ int header_write_result =
+ WritePlatformFile(sparse_file_, 0, reinterpret_cast<char*>(&header),
+ sizeof(header));
+ if (header_write_result != sizeof(header)) {
+ DLOG(WARNING) << "Could not write sparse file header";
+ return false;
+ }
+
+ int key_write_result = WritePlatformFile(sparse_file_, sizeof(header),
+ key_.data(), key_.size());
+ if (key_write_result != implicit_cast<int>(key_.size())) {
+ DLOG(WARNING) << "Could not write sparse file key";
+ return false;
+ }
+
+ sparse_ranges_.clear();
+ sparse_tail_offset_ = sizeof(header) + key_.size();
+
+ return true;
+}
+
+bool SimpleSynchronousEntry::ScanSparseFile(int32* out_sparse_data_size) {
+ DCHECK(sparse_file_open());
+
+ int32 sparse_data_size = 0;
+
+ SimpleFileHeader header;
+ int header_read_result =
+ ReadPlatformFile(sparse_file_, 0, reinterpret_cast<char*>(&header),
+ sizeof(header));
+ if (header_read_result != sizeof(header)) {
+ DLOG(WARNING) << "Could not read header from sparse file.";
+ return false;
+ }
+
+ if (header.initial_magic_number != kSimpleInitialMagicNumber) {
+ DLOG(WARNING) << "Sparse file magic number did not match.";
+ return false;
+ }
+
+ if (header.version != kSimpleVersion) {
+ DLOG(WARNING) << "Sparse file unreadable version.";
+ return false;
+ }
+
+ sparse_ranges_.clear();
+
+ int64 range_header_offset = sizeof(header) + key_.size();
+ while (1) {
+ SimpleFileSparseRangeHeader range_header;
+ int range_header_read_result =
+ ReadPlatformFile(sparse_file_,
+ range_header_offset,
+ reinterpret_cast<char*>(&range_header),
+ sizeof(range_header));
+ if (range_header_read_result == 0)
+ break;
+ if (range_header_read_result != sizeof(range_header)) {
+ DLOG(WARNING) << "Could not read sparse range header.";
+ return false;
+ }
+
+ if (range_header.sparse_range_magic_number !=
+ kSimpleSparseRangeMagicNumber) {
+ DLOG(WARNING) << "Invalid sparse range header magic number.";
+ return false;
+ }
+
+ SparseRange range;
+ range.offset = range_header.offset;
+ range.length = range_header.length;
+ range.data_crc32 = range_header.data_crc32;
+ range.file_offset = range_header_offset + sizeof(range_header);
+ sparse_ranges_.insert(std::make_pair(range.offset, range));
+
+ range_header_offset += sizeof(range_header) + range.length;
+
+ DCHECK_LE(sparse_data_size, sparse_data_size + range.length);
+ sparse_data_size += range.length;
+ }
+
+ *out_sparse_data_size = sparse_data_size;
+ sparse_tail_offset_ = range_header_offset;
+
+ return true;
+}
+
+bool SimpleSynchronousEntry::ReadSparseRange(const SparseRange* range,
+ int offset, int len, char* buf) {
+ DCHECK(range);
+ DCHECK(buf);
+ DCHECK_GE(range->length, offset);
+ DCHECK_GE(range->length, offset + len);
+
+ int bytes_read = ReadPlatformFile(sparse_file_,
+ range->file_offset + offset,
+ buf, len);
+ if (bytes_read < len) {
+ DLOG(WARNING) << "Could not read sparse range.";
+ return false;
+ }
+
+ // If we read the whole range and we have a crc32, check it.
+ if (offset == 0 && len == range->length && range->data_crc32 != 0) {
+ uint32 actual_crc32 = crc32(crc32(0L, Z_NULL, 0),
+ reinterpret_cast<const Bytef*>(buf),
+ len);
+ if (actual_crc32 != range->data_crc32) {
+ DLOG(WARNING) << "Sparse range crc32 mismatch.";
+ return false;
+ }
+ }
+ // TODO(ttuttle): Incremental crc32 calculation?
+
+ return true;
+}
+
+bool SimpleSynchronousEntry::WriteSparseRange(SparseRange* range,
+ int offset, int len,
+ const char* buf) {
+ DCHECK(range);
+ DCHECK(buf);
+ DCHECK_GE(range->length, offset);
+ DCHECK_GE(range->length, offset + len);
+
+ uint32 new_crc32 = 0;
+ if (offset == 0 && len == range->length) {
+ new_crc32 = crc32(crc32(0L, Z_NULL, 0),
+ reinterpret_cast<const Bytef*>(buf),
+ len);
+ }
+
+ if (new_crc32 != range->data_crc32) {
+ range->data_crc32 = new_crc32;
+
+ SimpleFileSparseRangeHeader header;
+ header.sparse_range_magic_number = kSimpleSparseRangeMagicNumber;
+ header.offset = range->offset;
+ header.length = range->length;
+ header.data_crc32 = range->data_crc32;
+
+ int bytes_written = WritePlatformFile(sparse_file_,
+ range->file_offset - sizeof(header),
+ reinterpret_cast<char*>(&header),
+ sizeof(header));
+ if (bytes_written != implicit_cast<int>(sizeof(header))) {
+ DLOG(WARNING) << "Could not rewrite sparse range header.";
+ return false;
+ }
+ }
+
+ int bytes_written = WritePlatformFile(sparse_file_,
+ range->file_offset + offset,
+ buf, len);
+ if (bytes_written < len) {
+ DLOG(WARNING) << "Could not write sparse range.";
+ return false;
+ }
+
+ return true;
+}
+
+bool SimpleSynchronousEntry::AppendSparseRange(int64 offset,
+ int len,
+ const char* buf) {
+ DCHECK_LE(0, offset);
+ DCHECK_LT(0, len);
+ DCHECK(buf);
+
+ uint32 data_crc32 = crc32(crc32(0L, Z_NULL, 0),
+ reinterpret_cast<const Bytef*>(buf),
+ len);
+
+ SimpleFileSparseRangeHeader header;
+ header.sparse_range_magic_number = kSimpleSparseRangeMagicNumber;
+ header.offset = offset;
+ header.length = len;
+ header.data_crc32 = data_crc32;
+
+ int bytes_written = WritePlatformFile(sparse_file_,
+ sparse_tail_offset_,
+ reinterpret_cast<char*>(&header),
+ sizeof(header));
+ if (bytes_written != implicit_cast<int>(sizeof(header))) {
+ DLOG(WARNING) << "Could not append sparse range header.";
+ return false;
+ }
+ sparse_tail_offset_ += bytes_written;
+
+ bytes_written = WritePlatformFile(sparse_file_,
+ sparse_tail_offset_,
+ buf,
+ len);
+ if (bytes_written < len) {
+ DLOG(WARNING) << "Could not append sparse range data.";
+ return false;
+ }
+ int64 data_file_offset = sparse_tail_offset_;
+ sparse_tail_offset_ += bytes_written;
+
+ SparseRange range;
+ range.offset = offset;
+ range.length = len;
+ range.data_crc32 = data_crc32;
+ range.file_offset = data_file_offset;
+ sparse_ranges_.insert(std::make_pair(offset, range));
+
+ return true;
+}
+
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.h b/chromium/net/disk_cache/simple/simple_synchronous_entry.h
index 470e8e20bd8..2ae4c0d87b6 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.h
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.h
@@ -6,6 +6,7 @@
#define NET_DISK_CACHE_SIMPLE_SIMPLE_SYNCHRONOUS_ENTRY_H_
#include <algorithm>
+#include <map>
#include <string>
#include <utility>
#include <vector>
@@ -35,7 +36,8 @@ class NET_EXPORT_PRIVATE SimpleEntryStat {
public:
SimpleEntryStat(base::Time last_used,
base::Time last_modified,
- const int32 data_size[]);
+ const int32 data_size[],
+ const int32 sparse_data_size);
int GetOffsetInFile(const std::string& key,
int offset,
@@ -56,10 +58,16 @@ class NET_EXPORT_PRIVATE SimpleEntryStat {
data_size_[stream_index] = data_size;
}
+ int32 sparse_data_size() const { return sparse_data_size_; }
+ void set_sparse_data_size(int32 sparse_data_size) {
+ sparse_data_size_ = sparse_data_size;
+ }
+
private:
base::Time last_used_;
base::Time last_modified_;
int32 data_size_[kSimpleEntryStreamCount];
+ int32 sparse_data_size_;
};
struct SimpleEntryCreationResults {
@@ -94,9 +102,11 @@ class SimpleSynchronousEntry {
int buf_len_p,
bool truncate_p,
bool doomed_p);
+ EntryOperationData(int64 sparse_offset_p, int buf_len_p);
int index;
int offset;
+ int64 sparse_offset;
int buf_len;
bool truncate;
bool doomed;
@@ -142,6 +152,19 @@ class SimpleSynchronousEntry {
uint32 expected_crc32,
int* out_result) const;
+ void ReadSparseData(const EntryOperationData& in_entry_op,
+ net::IOBuffer* out_buf,
+ base::Time* out_last_used,
+ int* out_result);
+ void WriteSparseData(const EntryOperationData& in_entry_op,
+ net::IOBuffer* in_buf,
+ int64 max_sparse_data_size,
+ SimpleEntryStat* out_entry_stat,
+ int* out_result);
+ void GetAvailableRange(const EntryOperationData& in_entry_op,
+ int64* out_start,
+ int* out_result);
+
// Close all streams, and add write EOF records to streams indicated by the
// CRCRecord entries in |crc32s_to_write|.
void Close(const SimpleEntryStat& entry_stat,
@@ -165,6 +188,17 @@ class SimpleSynchronousEntry {
FILE_REQUIRED
};
+ struct SparseRange {
+ int64 offset;
+ int64 length;
+ uint32 data_crc32;
+ int64 file_offset;
+
+ bool operator<(const SparseRange& other) const {
+ return offset < other.offset;
+ }
+ };
+
SimpleSynchronousEntry(
net::CacheType cache_type,
const base::FilePath& path,
@@ -175,12 +209,12 @@ class SimpleSynchronousEntry {
// called.
~SimpleSynchronousEntry();
- // Tries to open one of the cache entry files. Succeeds if the open succeeds
+ // Tries to open one of the cache entry files. Succeeds if the open succeeds
// or if the file was not found and is allowed to be omitted if the
// corresponding stream is empty.
bool MaybeOpenFile(int file_index,
base::PlatformFileError* out_error);
- // Creates one of the cache entry files if necessary. If the file is allowed
+ // Creates one of the cache entry files if necessary. If the file is allowed
// to be omitted if the corresponding stream is empty, and if |file_required|
// is FILE_NOT_REQUIRED, then the file is not created; otherwise, it is.
bool MaybeCreateFile(int file_index,
@@ -193,7 +227,7 @@ class SimpleSynchronousEntry {
void CloseFile(int index);
void CloseFiles();
- // Returns a net error, i.e. net::OK on success. |had_index| is passed
+ // Returns a net error, i.e. net::OK on success. |had_index| is passed
// from the main entry for metrics purposes, and is true if the index was
// initialized when the open operation began.
int InitializeForOpen(bool had_index,
@@ -201,13 +235,13 @@ class SimpleSynchronousEntry {
scoped_refptr<net::GrowableIOBuffer>* stream_0_data,
uint32* out_stream_0_crc32);
- // Writes the header and key to a newly-created stream file. |index| is the
- // index of the stream. Returns true on success; returns false and sets
+ // Writes the header and key to a newly-created stream file. |index| is the
+ // index of the stream. Returns true on success; returns false and sets
// |*out_result| on failure.
bool InitializeCreatedFile(int index, CreateEntryResult* out_result);
// Returns a net error, including net::OK on success and net::FILE_EXISTS
- // when the entry already exists. |had_index| is passed from the main entry
+ // when the entry already exists. |had_index| is passed from the main entry
// for metrics purposes, and is true if the index was initialized when the
// create operation began.
int InitializeForCreate(bool had_index, SimpleEntryStat* out_entry_stat);
@@ -227,6 +261,39 @@ class SimpleSynchronousEntry {
int* out_data_size) const;
void Doom() const;
+ // Opens the sparse data file and scans it if it exists.
+ bool OpenSparseFileIfExists(int32* out_sparse_data_size);
+
+ // Creates and initializes the sparse data file.
+ bool CreateSparseFile();
+
+ // Closes the sparse data file.
+ bool CloseSparseFile();
+
+ // Writes the header to the (newly-created) sparse file.
+ bool InitializeSparseFile();
+
+ // Removes all but the header of the sparse file.
+ bool TruncateSparseFile();
+
+ // Scans the existing ranges in the sparse file. Populates |sparse_ranges_|
+ // and sets |*out_sparse_data_size| to the total size of all the ranges (not
+ // including headers).
+ bool ScanSparseFile(int32* out_sparse_data_size);
+
+ // Reads from a single sparse range. If asked to read the entire range, also
+ // verifies the CRC32.
+ bool ReadSparseRange(const SparseRange* range,
+ int offset, int len, char* buf);
+
+ // Writes to a single (existing) sparse range. If asked to write the entire
+ // range, also updates the CRC32; otherwise, invalidates it.
+ bool WriteSparseRange(SparseRange* range,
+ int offset, int len, const char* buf);
+
+ // Appends a new sparse range to the sparse data file.
+ bool AppendSparseRange(int64 offset, int len, const char* buf);
+
static bool DeleteFileForEntryHash(const base::FilePath& path,
uint64 entry_hash,
int file_index);
@@ -237,6 +304,10 @@ class SimpleSynchronousEntry {
base::FilePath GetFilenameFromFileIndex(int file_index);
+ bool sparse_file_open() const {
+ return sparse_file_ != base::kInvalidPlatformFileValue;
+ }
+
const net::CacheType cache_type_;
const base::FilePath path_;
const uint64 entry_hash_;
@@ -250,6 +321,18 @@ class SimpleSynchronousEntry {
// True if the corresponding stream is empty and therefore no on-disk file
// was created to store it.
bool empty_file_omitted_[kSimpleEntryFileCount];
+
+ typedef std::map<int64, SparseRange> SparseRangeOffsetMap;
+ typedef SparseRangeOffsetMap::iterator SparseRangeIterator;
+ SparseRangeOffsetMap sparse_ranges_;
+ base::PlatformFile sparse_file_;
+ // Offset of the end of the sparse file (where the next sparse range will be
+ // written).
+ int64 sparse_tail_offset_;
+
+ // True if the entry was created, or false if it was opened. Used to log
+ // SimpleCache.*.EntryCreatedWithStream2Omitted only for created entries.
+ bool files_created_;
};
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/simple/simple_util.cc b/chromium/net/disk_cache/simple/simple_util.cc
index 4291b1f7773..0ad2a05d5a3 100644
--- a/chromium/net/disk_cache/simple/simple_util.cc
+++ b/chromium/net/disk_cache/simple/simple_util.cc
@@ -82,6 +82,10 @@ std::string GetFilenameFromEntryHashAndFileIndex(uint64 entry_hash,
return base::StringPrintf("%016" PRIx64 "_%1d", entry_hash, file_index);
}
+std::string GetSparseFilenameFromEntryHash(uint64 entry_hash) {
+ return base::StringPrintf("%016" PRIx64 "_s", entry_hash);
+}
+
std::string GetFilenameFromKeyAndFileIndex(const std::string& key,
int file_index) {
return GetEntryHashKeyAsHexString(key) +
@@ -122,7 +126,7 @@ bool GetMTime(const base::FilePath& path, base::Time* out_mtime) {
}
#endif
base::PlatformFileInfo file_info;
- if (!file_util::GetFileInfo(path, &file_info))
+ if (!base::GetFileInfo(path, &file_info))
return false;
*out_mtime = file_info.last_modified;
return true;
diff --git a/chromium/net/disk_cache/simple/simple_util.h b/chromium/net/disk_cache/simple/simple_util.h
index 60a237ecd86..f76215121a4 100644
--- a/chromium/net/disk_cache/simple/simple_util.h
+++ b/chromium/net/disk_cache/simple/simple_util.h
@@ -48,6 +48,9 @@ NET_EXPORT_PRIVATE std::string GetFilenameFromKeyAndFileIndex(
std::string GetFilenameFromEntryHashAndFileIndex(uint64 entry_hash,
int file_index);
+// Given a |key| for an entry, returns the name of the sparse data file.
+std::string GetSparseFilenameFromEntryHash(uint64 entry_hash);
+
// Given the size of a file holding a stream in the simple backend and the key
// to an entry, returns the number of bytes in the stream.
NET_EXPORT_PRIVATE int32 GetDataSizeFromKeyAndFileSize(const std::string& key,
diff --git a/chromium/net/disk_cache/simple/simple_version_upgrade_unittest.cc b/chromium/net/disk_cache/simple/simple_version_upgrade_unittest.cc
index c9d42f10660..a5493f7c6eb 100644
--- a/chromium/net/disk_cache/simple/simple_version_upgrade_unittest.cc
+++ b/chromium/net/disk_cache/simple/simple_version_upgrade_unittest.cc
@@ -31,12 +31,6 @@ const char kFakeIndexFileName[] = "index";
// Same as |SimpleIndexFile::kIndexFileName|.
const char kIndexFileName[] = "the-real-index";
-// Same as |SimpleIndexFile::kIndexDirectory|.
-const char kIndexDirectory[] = "index-dir";
-
-// Same as |SimpleIndexFile::kTempIndexFileName|.
-const char kTempIndexFileName[] = "temp-index";
-
bool WriteFakeIndexFileV5(const base::FilePath& cache_path) {
disk_cache::FakeIndexData data;
data.version = 5;
diff --git a/chromium/net/disk_cache/v3/backend_worker.cc b/chromium/net/disk_cache/v3/backend_worker.cc
index cbccfddb5c6..be12a96eebe 100644
--- a/chromium/net/disk_cache/v3/backend_worker.cc
+++ b/chromium/net/disk_cache/v3/backend_worker.cc
@@ -331,7 +331,7 @@ bool BackendImpl::CreateBackingStore(disk_cache::File* file) {
}
bool BackendImpl::InitBackingStore(bool* file_created) {
- if (!file_util::CreateDirectory(path_))
+ if (!base::CreateDirectory(path_))
return false;
base::FilePath index_name = path_.AppendASCII(kIndexName);
diff --git a/chromium/net/dns/address_sorter_posix.cc b/chromium/net/dns/address_sorter_posix.cc
index 8d87774587d..5e2fe943264 100644
--- a/chromium/net/dns/address_sorter_posix.cc
+++ b/chromium/net/dns/address_sorter_posix.cc
@@ -19,7 +19,6 @@
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
-#include "base/posix/eintr_wrapper.h"
#include "net/socket/client_socket_factory.h"
#include "net/udp/datagram_client_socket.h"
@@ -175,30 +174,6 @@ AddressSorterPosix::PolicyEntry kDefaultIPv4ScopeTable[] = {
{ { }, 0, AddressSorterPosix::SCOPE_GLOBAL },
};
-// Returns number of matching initial bits between the addresses |a1| and |a2|.
-unsigned CommonPrefixLength(const IPAddressNumber& a1,
- const IPAddressNumber& a2) {
- DCHECK_EQ(a1.size(), a2.size());
- for (size_t i = 0; i < a1.size(); ++i) {
- unsigned diff = a1[i] ^ a2[i];
- if (!diff)
- continue;
- for (unsigned j = 0; j < CHAR_BIT; ++j) {
- if (diff & (1 << (CHAR_BIT - 1)))
- return i * CHAR_BIT + j;
- diff <<= 1;
- }
- NOTREACHED();
- }
- return a1.size() * CHAR_BIT;
-}
-
-// Computes the number of leading 1-bits in |mask|.
-unsigned MaskPrefixLength(const IPAddressNumber& mask) {
- IPAddressNumber all_ones(mask.size(), 0xFF);
- return CommonPrefixLength(mask, all_ones);
-}
-
struct DestinationInfo {
IPAddressNumber address;
AddressSorterPosix::AddressScope scope;
@@ -302,8 +277,8 @@ void AddressSorterPosix::Sort(const AddressList& list,
IPEndPoint dest(info->address, 80 /* port */);
int rv = socket->Connect(dest);
if (rv != OK) {
- LOG(WARNING) << "Could not connect to " << dest.ToStringWithoutPort()
- << " reason " << rv;
+ VLOG(1) << "Could not connect to " << dest.ToStringWithoutPort()
+ << " reason " << rv;
continue;
}
// Filter out unusable destinations.
@@ -311,7 +286,7 @@ void AddressSorterPosix::Sort(const AddressList& list,
rv = socket->GetLocalAddress(&src);
if (rv != OK) {
LOG(WARNING) << "Could not get local address for "
- << src.ToStringWithoutPort() << " reason " << rv;
+ << dest.ToStringWithoutPort() << " reason " << rv;
continue;
}
diff --git a/chromium/net/dns/dns_config_service_posix.cc b/chromium/net/dns/dns_config_service_posix.cc
index baf917284c7..b352d3269c0 100644
--- a/chromium/net/dns/dns_config_service_posix.cc
+++ b/chromium/net/dns/dns_config_service_posix.cc
@@ -21,68 +21,9 @@
#include "net/dns/notify_watcher_mac.h"
#include "net/dns/serial_worker.h"
-#if defined(OS_MACOSX)
-#include <dlfcn.h>
-
-#include "third_party/apple_apsl/dnsinfo.h"
-
-namespace {
-
-// dnsinfo symbols are available via libSystem.dylib, but can also be present in
-// SystemConfiguration.framework. To avoid confusion, load them explicitly from
-// libSystem.dylib.
-class DnsInfoApi {
- public:
- typedef const char* (*dns_configuration_notify_key_t)();
- typedef dns_config_t* (*dns_configuration_copy_t)();
- typedef void (*dns_configuration_free_t)(dns_config_t*);
-
- DnsInfoApi()
- : dns_configuration_notify_key(NULL),
- dns_configuration_copy(NULL),
- dns_configuration_free(NULL) {
- handle_ = dlopen("/usr/lib/libSystem.dylib",
- RTLD_LAZY | RTLD_NOLOAD);
- if (!handle_)
- return;
- dns_configuration_notify_key =
- reinterpret_cast<dns_configuration_notify_key_t>(
- dlsym(handle_, "dns_configuration_notify_key"));
- dns_configuration_copy =
- reinterpret_cast<dns_configuration_copy_t>(
- dlsym(handle_, "dns_configuration_copy"));
- dns_configuration_free =
- reinterpret_cast<dns_configuration_free_t>(
- dlsym(handle_, "dns_configuration_free"));
- }
-
- ~DnsInfoApi() {
- if (handle_)
- dlclose(handle_);
- }
-
- dns_configuration_notify_key_t dns_configuration_notify_key;
- dns_configuration_copy_t dns_configuration_copy;
- dns_configuration_free_t dns_configuration_free;
-
- private:
- void* handle_;
-};
-
-const DnsInfoApi& GetDnsInfoApi() {
- static base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER;
- return api.Get();
-}
-
-struct DnsConfigTDeleter {
- inline void operator()(dns_config_t* ptr) const {
- if (GetDnsInfoApi().dns_configuration_free)
- GetDnsInfoApi().dns_configuration_free(ptr);
- }
-};
-
-} // namespace
-#endif // defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include "net/dns/dns_config_watcher_mac.h"
+#endif
namespace net {
@@ -94,20 +35,20 @@ namespace {
const base::FilePath::CharType* kFilePathHosts =
FILE_PATH_LITERAL("/etc/hosts");
-#if defined(OS_MACOSX)
-class ConfigWatcher {
+#if defined(OS_IOS)
+
+// There is no plublic API to watch the DNS configuration on iOS.
+class DnsConfigWatcher {
public:
- bool Watch(const base::Callback<void(bool succeeded)>& callback) {
- if (!GetDnsInfoApi().dns_configuration_notify_key)
- return false;
- return watcher_.Watch(GetDnsInfoApi().dns_configuration_notify_key(),
- callback);
- }
+ typedef base::Callback<void(bool succeeded)> CallbackType;
- private:
- NotifyWatcherMac watcher_;
+ bool Watch(const CallbackType& callback) {
+ return false;
+ }
};
-#else
+
+#elif !defined(OS_MACOSX)
+// DnsConfigWatcher for OS_MACOSX is in dns_config_watcher_mac.{hh,cc}.
#ifndef _PATH_RESCONF // Normally defined in <resolv.h>
#define _PATH_RESCONF "/etc/resolv.conf"
@@ -116,14 +57,14 @@ class ConfigWatcher {
static const base::FilePath::CharType* kFilePathConfig =
FILE_PATH_LITERAL(_PATH_RESCONF);
-class ConfigWatcher {
+class DnsConfigWatcher {
public:
typedef base::Callback<void(bool succeeded)> CallbackType;
bool Watch(const CallbackType& callback) {
callback_ = callback;
return watcher_.Watch(base::FilePath(kFilePathConfig), false,
- base::Bind(&ConfigWatcher::OnCallback,
+ base::Bind(&DnsConfigWatcher::OnCallback,
base::Unretained(this)));
}
@@ -165,31 +106,18 @@ ConfigParsePosixResult ReadDnsConfig(DnsConfig* config) {
#endif
#endif
-#if defined(OS_MACOSX)
- if (!GetDnsInfoApi().dns_configuration_copy)
- return CONFIG_PARSE_POSIX_NO_DNSINFO;
- scoped_ptr<dns_config_t, DnsConfigTDeleter> dns_config(
- GetDnsInfoApi().dns_configuration_copy());
- if (!dns_config)
- return CONFIG_PARSE_POSIX_NO_DNSINFO;
-
- // TODO(szym): Parse dns_config_t for resolvers rather than res_state.
- // DnsClient can't handle domain-specific unscoped resolvers.
- unsigned num_resolvers = 0;
- for (int i = 0; i < dns_config->n_resolver; ++i) {
- dns_resolver_t* resolver = dns_config->resolver[i];
- if (!resolver->n_nameserver)
- continue;
- if (resolver->options && !strcmp(resolver->options, "mdns"))
- continue;
- ++num_resolvers;
- }
- if (num_resolvers > 1) {
- LOG(WARNING) << "dns_config has unhandled options!";
- config->unhandled_options = true;
- return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS;
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ ConfigParsePosixResult error = DnsConfigWatcher::CheckDnsConfig();
+ switch (error) {
+ case CONFIG_PARSE_POSIX_OK:
+ break;
+ case CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS:
+ LOG(WARNING) << "dns_config has unhandled options!";
+ config->unhandled_options = true;
+ default:
+ return error;
}
-#endif // defined(OS_MACOSX)
+#endif // defined(OS_MACOSX) && !defined(OS_IOS)
// Override timeout value to match default setting on Windows.
config->timeout = base::TimeDelta::FromSeconds(kDnsTimeoutSeconds);
return result;
@@ -246,7 +174,7 @@ class DnsConfigServicePosix::Watcher {
base::WeakPtrFactory<Watcher> weak_factory_;
DnsConfigServicePosix* service_;
- ConfigWatcher config_watcher_;
+ DnsConfigWatcher config_watcher_;
base::FilePathWatcher hosts_watcher_;
DISALLOW_COPY_AND_ASSIGN(Watcher);
diff --git a/chromium/net/dns/dns_config_watcher_mac.cc b/chromium/net/dns/dns_config_watcher_mac.cc
new file mode 100644
index 00000000000..a92db0cf179
--- /dev/null
+++ b/chromium/net/dns/dns_config_watcher_mac.cc
@@ -0,0 +1,106 @@
+// 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/dns/dns_config_watcher_mac.h"
+
+#include <dlfcn.h>
+
+#include "base/lazy_instance.h"
+#include "third_party/apple_apsl/dnsinfo.h"
+
+namespace {
+
+// dnsinfo symbols are available via libSystem.dylib, but can also be present in
+// SystemConfiguration.framework. To avoid confusion, load them explicitly from
+// libSystem.dylib.
+class DnsInfoApi {
+ public:
+ typedef const char* (*dns_configuration_notify_key_t)();
+ typedef dns_config_t* (*dns_configuration_copy_t)();
+ typedef void (*dns_configuration_free_t)(dns_config_t*);
+
+ DnsInfoApi()
+ : dns_configuration_notify_key(NULL),
+ dns_configuration_copy(NULL),
+ dns_configuration_free(NULL) {
+ handle_ = dlopen("/usr/lib/libSystem.dylib",
+ RTLD_LAZY | RTLD_NOLOAD);
+ if (!handle_)
+ return;
+ dns_configuration_notify_key =
+ reinterpret_cast<dns_configuration_notify_key_t>(
+ dlsym(handle_, "dns_configuration_notify_key"));
+ dns_configuration_copy =
+ reinterpret_cast<dns_configuration_copy_t>(
+ dlsym(handle_, "dns_configuration_copy"));
+ dns_configuration_free =
+ reinterpret_cast<dns_configuration_free_t>(
+ dlsym(handle_, "dns_configuration_free"));
+ }
+
+ ~DnsInfoApi() {
+ if (handle_)
+ dlclose(handle_);
+ }
+
+ dns_configuration_notify_key_t dns_configuration_notify_key;
+ dns_configuration_copy_t dns_configuration_copy;
+ dns_configuration_free_t dns_configuration_free;
+
+ private:
+ void* handle_;
+};
+
+const DnsInfoApi& GetDnsInfoApi() {
+ static base::LazyInstance<DnsInfoApi>::Leaky api = LAZY_INSTANCE_INITIALIZER;
+ return api.Get();
+}
+
+struct DnsConfigTDeleter {
+ inline void operator()(dns_config_t* ptr) const {
+ if (GetDnsInfoApi().dns_configuration_free)
+ GetDnsInfoApi().dns_configuration_free(ptr);
+ }
+};
+
+} // namespace
+
+namespace net {
+namespace internal {
+
+bool DnsConfigWatcher::Watch(
+ const base::Callback<void(bool succeeded)>& callback) {
+ if (!GetDnsInfoApi().dns_configuration_notify_key)
+ return false;
+ return watcher_.Watch(GetDnsInfoApi().dns_configuration_notify_key(),
+ callback);
+}
+
+// static
+ConfigParsePosixResult DnsConfigWatcher::CheckDnsConfig() {
+ if (!GetDnsInfoApi().dns_configuration_copy)
+ return CONFIG_PARSE_POSIX_NO_DNSINFO;
+ scoped_ptr<dns_config_t, DnsConfigTDeleter> dns_config(
+ GetDnsInfoApi().dns_configuration_copy());
+ if (!dns_config)
+ return CONFIG_PARSE_POSIX_NO_DNSINFO;
+
+ // TODO(szym): Parse dns_config_t for resolvers rather than res_state.
+ // DnsClient can't handle domain-specific unscoped resolvers.
+ unsigned num_resolvers = 0;
+ for (int i = 0; i < dns_config->n_resolver; ++i) {
+ dns_resolver_t* resolver = dns_config->resolver[i];
+ if (!resolver->n_nameserver)
+ continue;
+ if (resolver->options && !strcmp(resolver->options, "mdns"))
+ continue;
+ ++num_resolvers;
+ }
+ if (num_resolvers > 1)
+ return CONFIG_PARSE_POSIX_UNHANDLED_OPTIONS;
+ return CONFIG_PARSE_POSIX_OK;
+}
+
+} // naespace internal
+} // namespace net
diff --git a/chromium/net/dns/dns_config_watcher_mac.h b/chromium/net/dns/dns_config_watcher_mac.h
new file mode 100644
index 00000000000..0c3fc6a1a20
--- /dev/null
+++ b/chromium/net/dns/dns_config_watcher_mac.h
@@ -0,0 +1,26 @@
+// 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 "base/callback_forward.h"
+#include "net/dns/dns_config_service_posix.h"
+#include "net/dns/notify_watcher_mac.h"
+
+namespace net {
+namespace internal {
+
+// Watches DNS configuration on Mac.
+class DnsConfigWatcher {
+ public:
+ bool Watch(const base::Callback<void(bool succeeded)>& callback);
+
+ // Returns an error if the DNS configuration is invalid.
+ // Returns CONFIG_PARSE_POSIX_OK otherwise.
+ static ConfigParsePosixResult CheckDnsConfig();
+
+ private:
+ NotifyWatcherMac watcher_;
+};
+
+} // naespace internal
+} // namespace net
diff --git a/chromium/net/dns/dns_hosts.cc b/chromium/net/dns/dns_hosts.cc
index 3edea2a7abc..2fb627e81f7 100644
--- a/chromium/net/dns/dns_hosts.cc
+++ b/chromium/net/dns/dns_hosts.cc
@@ -147,7 +147,7 @@ bool ParseHostsFile(const base::FilePath& path, DnsHosts* dns_hosts) {
return true;
int64 size;
- if (!file_util::GetFileSize(path, &size))
+ if (!base::GetFileSize(path, &size))
return false;
UMA_HISTOGRAM_COUNTS("AsyncDNS.HostsSize", size);
diff --git a/chromium/net/dns/dns_socket_pool.cc b/chromium/net/dns/dns_socket_pool.cc
index 7a7ecd6ee8f..b446fa07d62 100644
--- a/chromium/net/dns/dns_socket_pool.cc
+++ b/chromium/net/dns/dns_socket_pool.cc
@@ -21,8 +21,7 @@ namespace {
// When we initialize the SocketPool, we allocate kInitialPoolSize sockets.
// When we allocate a socket, we ensure we have at least kAllocateMinSize
-// sockets to choose from. When we free a socket, we retain it if we have
-// less than kRetainMaxSize sockets in the pool.
+// sockets to choose from. Freed sockets are not retained.
// On Windows, we can't request specific (random) ports, since that will
// trigger firewall prompts, so request default ones, but keep a pile of
@@ -31,12 +30,10 @@ namespace {
const DatagramSocket::BindType kBindType = DatagramSocket::DEFAULT_BIND;
const unsigned kInitialPoolSize = 256;
const unsigned kAllocateMinSize = 256;
-const unsigned kRetainMaxSize = 0;
#else
const DatagramSocket::BindType kBindType = DatagramSocket::RANDOM_BIND;
const unsigned kInitialPoolSize = 0;
const unsigned kAllocateMinSize = 1;
-const unsigned kRetainMaxSize = 0;
#endif
} // namespace
@@ -82,7 +79,7 @@ scoped_ptr<DatagramClientSocket> DnsSocketPool::CreateConnectedSocket(
if (socket.get()) {
int rv = socket->Connect((*nameservers_)[server_index]);
if (rv != OK) {
- LOG(WARNING) << "Failed to connect socket: " << rv;
+ VLOG(1) << "Failed to connect socket: " << rv;
socket.reset();
}
} else {
@@ -208,15 +205,6 @@ void DefaultDnsSocketPool::FreeSocket(
unsigned server_index,
scoped_ptr<DatagramClientSocket> socket) {
DCHECK_LT(server_index, pools_.size());
-
- // In some builds, kRetainMaxSize will be 0 if we never reuse sockets.
- // In that case, don't compile this code to avoid a "tautological
- // comparison" warning from clang.
-#if kRetainMaxSize > 0
- SocketVector& pool = pools_[server_index];
- if (pool.size() < kRetainMaxSize)
- pool.push_back(socket.release());
-#endif
}
void DefaultDnsSocketPool::FillPool(unsigned server_index, unsigned size) {
diff --git a/chromium/net/dns/host_resolver.cc b/chromium/net/dns/host_resolver.cc
index 9b1e3314acd..0435091a54f 100644
--- a/chromium/net/dns/host_resolver.cc
+++ b/chromium/net/dns/host_resolver.cc
@@ -24,9 +24,6 @@ namespace {
// that limit this to 6, so we're temporarily holding it at that level.
const size_t kDefaultMaxProcTasks = 6u;
-// When configuring from field trial, do not allow
-const size_t kSaneMaxProcTasks = 20u;
-
PrioritizedDispatcher::Limits GetDispatcherLimits(
const HostResolver::Options& options) {
PrioritizedDispatcher::Limits limits(NUM_PRIORITIES,
diff --git a/chromium/net/dns/host_resolver_impl.cc b/chromium/net/dns/host_resolver_impl.cc
index e4098d003be..57ab3d63881 100644
--- a/chromium/net/dns/host_resolver_impl.cc
+++ b/chromium/net/dns/host_resolver_impl.cc
@@ -358,7 +358,7 @@ base::Value* NetLogJobAttachCallback(const NetLog::Source& source,
NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
source.AddToEventParameters(dict);
- dict->SetInteger("priority", priority);
+ dict->SetString("priority", RequestPriorityToString(priority));
return dict;
}
diff --git a/chromium/net/dns/host_resolver_impl_unittest.cc b/chromium/net/dns/host_resolver_impl_unittest.cc
index c314f80c24d..5d19fdcda12 100644
--- a/chromium/net/dns/host_resolver_impl_unittest.cc
+++ b/chromium/net/dns/host_resolver_impl_unittest.cc
@@ -628,7 +628,15 @@ TEST_F(HostResolverImplTest, EmptyDotsHost) {
}
}
-TEST_F(HostResolverImplTest, LongHost) {
+#if defined(THREAD_SANITIZER)
+// There's a data race in this test that may lead to use-after-free.
+// If the test starts to crash without ThreadSanitizer it needs to be disabled
+// globally. See http://crbug.com/268946.
+#define MAYBE_LongHost DISABLED_LongHost
+#else
+#define MAYBE_LongHost LongHost
+#endif
+TEST_F(HostResolverImplTest, MAYBE_LongHost) {
Request* req = CreateRequest(std::string(4097, 'a'), 5555);
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, req->Resolve());
}
diff --git a/chromium/net/dns/mapped_host_resolver.cc b/chromium/net/dns/mapped_host_resolver.cc
index 7b182077cfb..fedc05f0072 100644
--- a/chromium/net/dns/mapped_host_resolver.cc
+++ b/chromium/net/dns/mapped_host_resolver.cc
@@ -47,10 +47,18 @@ void MappedHostResolver::CancelRequest(RequestHandle req) {
impl_->CancelRequest(req);
}
+void MappedHostResolver::SetDnsClientEnabled(bool enabled) {
+ impl_->SetDnsClientEnabled(enabled);
+}
+
HostCache* MappedHostResolver::GetHostCache() {
return impl_->GetHostCache();
}
+base::Value* MappedHostResolver::GetDnsConfigAsValue() const {
+ return impl_->GetDnsConfigAsValue();
+}
+
int MappedHostResolver::ApplyRules(RequestInfo* info) const {
HostPortPair host_port(info->host_port_pair());
if (rules_.RewriteHost(&host_port)) {
diff --git a/chromium/net/dns/mapped_host_resolver.h b/chromium/net/dns/mapped_host_resolver.h
index a121d4ed4c4..c03a2a66d46 100644
--- a/chromium/net/dns/mapped_host_resolver.h
+++ b/chromium/net/dns/mapped_host_resolver.h
@@ -55,7 +55,9 @@ class NET_EXPORT MappedHostResolver : public HostResolver {
AddressList* addresses,
const BoundNetLog& net_log) OVERRIDE;
virtual void CancelRequest(RequestHandle req) OVERRIDE;
+ virtual void SetDnsClientEnabled(bool enabled) OVERRIDE;
virtual HostCache* GetHostCache() OVERRIDE;
+ virtual base::Value* GetDnsConfigAsValue() const OVERRIDE;
private:
// Modify the request |info| according to |rules_|. Returns either OK or
diff --git a/chromium/net/dns/mdns_client.cc b/chromium/net/dns/mdns_client.cc
index d0273c5784a..93f1d61d7cf 100644
--- a/chromium/net/dns/mdns_client.cc
+++ b/chromium/net/dns/mdns_client.cc
@@ -4,6 +4,7 @@
#include "net/dns/mdns_client.h"
+#include "net/base/net_errors.h"
#include "net/dns/dns_protocol.h"
#include "net/dns/mdns_client_impl.h"
@@ -23,24 +24,79 @@ IPEndPoint GetMDnsIPEndPoint(const char* address) {
dns_protocol::kDefaultPortMulticast);
}
+int Bind(const IPEndPoint& multicast_addr,
+ uint32 interface_index,
+ DatagramServerSocket* socket) {
+ IPAddressNumber address_any(multicast_addr.address().size());
+ IPEndPoint bind_endpoint(address_any, multicast_addr.port());
+
+ socket->AllowAddressReuse();
+ socket->SetMulticastInterface(interface_index);
+
+ int rv = socket->Listen(bind_endpoint);
+ if (rv < OK)
+ return rv;
+
+ return socket->JoinGroup(multicast_addr.address());
+}
+
} // namespace
// static
+scoped_ptr<MDnsSocketFactory> MDnsSocketFactory::CreateDefault() {
+ return scoped_ptr<MDnsSocketFactory>(new MDnsSocketFactoryImpl);
+}
+
+// static
scoped_ptr<MDnsClient> MDnsClient::CreateDefault() {
- return scoped_ptr<MDnsClient>(
- new MDnsClientImpl(MDnsConnection::SocketFactory::CreateDefault()));
+ return scoped_ptr<MDnsClient>(new MDnsClientImpl());
}
IPEndPoint GetMDnsIPEndPoint(AddressFamily address_family) {
switch (address_family) {
- case ADDRESS_FAMILY_IPV4:
- return GetMDnsIPEndPoint(kMDnsMulticastGroupIPv4);
- case ADDRESS_FAMILY_IPV6:
- return GetMDnsIPEndPoint(kMDnsMulticastGroupIPv6);
- default:
- NOTREACHED();
- return IPEndPoint();
+ case ADDRESS_FAMILY_IPV4:
+ return GetMDnsIPEndPoint(kMDnsMulticastGroupIPv4);
+ case ADDRESS_FAMILY_IPV6:
+ return GetMDnsIPEndPoint(kMDnsMulticastGroupIPv6);
+ default:
+ NOTREACHED();
+ return IPEndPoint();
+ }
+}
+
+InterfaceIndexFamilyList GetMDnsInterfacesToBind() {
+ NetworkInterfaceList network_list;
+ InterfaceIndexFamilyList interfaces;
+ if (!GetNetworkList(&network_list))
+ return interfaces;
+ for (size_t i = 0; i < network_list.size(); ++i) {
+ AddressFamily family = GetAddressFamily(network_list[i].address);
+ if (family == ADDRESS_FAMILY_IPV4 || family == ADDRESS_FAMILY_IPV6) {
+ interfaces.push_back(
+ std::make_pair(network_list[i].interface_index, family));
+ }
+ }
+ std::sort(interfaces.begin(), interfaces.end());
+ // Interfaces could have multiple addresses. Filter out duplicate entries.
+ interfaces.erase(std::unique(interfaces.begin(), interfaces.end()),
+ interfaces.end());
+ return interfaces;
+}
+
+scoped_ptr<DatagramServerSocket> CreateAndBindMDnsSocket(
+ AddressFamily address_family,
+ uint32 interface_index) {
+ scoped_ptr<DatagramServerSocket> socket(
+ new UDPServerSocket(NULL, NetLog::Source()));
+
+ IPEndPoint multicast_addr = GetMDnsIPEndPoint(address_family);
+ int rv = Bind(multicast_addr, interface_index, socket.get());
+ if (rv != OK) {
+ socket.reset();
+ VLOG(1) << "Bind failed, endpoint=" << multicast_addr.ToStringWithoutPort()
+ << ", error=" << rv;
}
+ return socket.PassAs<DatagramServerSocket>();
}
} // namespace net
diff --git a/chromium/net/dns/mdns_client.h b/chromium/net/dns/mdns_client.h
index 71006d69b01..ab7916ed47d 100644
--- a/chromium/net/dns/mdns_client.h
+++ b/chromium/net/dns/mdns_client.h
@@ -16,6 +16,7 @@
namespace net {
+class DatagramServerSocket;
class RecordParsed;
// Represents a one-time record lookup. A transaction takes one
@@ -120,6 +121,15 @@ class NET_EXPORT MDnsListener {
virtual uint16 GetType() const = 0;
};
+// Creates bound datagram sockets ready to use by MDnsClient.
+class NET_EXPORT MDnsSocketFactory {
+ public:
+ virtual ~MDnsSocketFactory() {}
+ virtual void CreateSockets(ScopedVector<DatagramServerSocket>* sockets) = 0;
+
+ static scoped_ptr<MDnsSocketFactory> CreateDefault();
+};
+
// Listens for Multicast DNS on the local network. You can access information
// regarding multicast DNS either by creating an |MDnsListener| to be notified
// of new records, or by creating an |MDnsTransaction| to look up the value of a
@@ -144,7 +154,7 @@ class NET_EXPORT MDnsClient {
int flags,
const MDnsTransaction::ResultCallback& callback) = 0;
- virtual bool StartListening() = 0;
+ virtual bool StartListening(MDnsSocketFactory* factory) = 0;
// Do not call this inside callbacks from related MDnsListener and
// MDnsTransaction objects.
@@ -155,7 +165,20 @@ class NET_EXPORT MDnsClient {
static scoped_ptr<MDnsClient> CreateDefault();
};
-IPEndPoint NET_EXPORT GetMDnsIPEndPoint(AddressFamily address_family);
+NET_EXPORT IPEndPoint GetMDnsIPEndPoint(AddressFamily address_family);
+
+typedef std::vector<std::pair<uint32, AddressFamily> > InterfaceIndexFamilyList;
+// Returns pairs of interface and address family to bind. Current
+// implementation returns unique list of all available interfaces.
+NET_EXPORT InterfaceIndexFamilyList GetMDnsInterfacesToBind();
+
+// Create sockets, binds socket to MDns endpoint, and sets multicast interface
+// and joins multicast group on for |interface_index|.
+// Returns NULL if failed.
+NET_EXPORT scoped_ptr<DatagramServerSocket> CreateAndBindMDnsSocket(
+ AddressFamily address_family,
+ uint32 interface_index);
} // namespace net
+
#endif // NET_DNS_MDNS_CLIENT_H_
diff --git a/chromium/net/dns/mdns_client_impl.cc b/chromium/net/dns/mdns_client_impl.cc
index 1dfc21b37c6..c95b86c6d17 100644
--- a/chromium/net/dns/mdns_client_impl.cc
+++ b/chromium/net/dns/mdns_client_impl.cc
@@ -24,32 +24,54 @@
namespace net {
namespace {
+
const unsigned MDnsTransactionTimeoutSeconds = 3;
+
+} // namespace
+
+void MDnsSocketFactoryImpl::CreateSockets(
+ ScopedVector<DatagramServerSocket>* sockets) {
+ InterfaceIndexFamilyList interfaces(GetMDnsInterfacesToBind());
+ for (size_t i = 0; i < interfaces.size(); ++i) {
+ DCHECK(interfaces[i].second == net::ADDRESS_FAMILY_IPV4 ||
+ interfaces[i].second == net::ADDRESS_FAMILY_IPV6);
+ scoped_ptr<DatagramServerSocket> socket(
+ CreateAndBindMDnsSocket(interfaces[i].second, interfaces[i].first));
+ if (socket)
+ sockets->push_back(socket.release());
+ }
}
MDnsConnection::SocketHandler::SocketHandler(
- MDnsConnection* connection, const IPEndPoint& multicast_addr,
- MDnsConnection::SocketFactory* socket_factory)
- : socket_(socket_factory->CreateSocket()), connection_(connection),
- response_(new DnsResponse(dns_protocol::kMaxMulticastSize)),
- multicast_addr_(multicast_addr) {
+ scoped_ptr<DatagramServerSocket> socket,
+ MDnsConnection* connection)
+ : socket_(socket.Pass()),
+ connection_(connection),
+ response_(dns_protocol::kMaxMulticastSize) {
}
MDnsConnection::SocketHandler::~SocketHandler() {
}
int MDnsConnection::SocketHandler::Start() {
+ IPEndPoint end_point;
+ int rv = socket_->GetLocalAddress(&end_point);
+ if (rv != OK)
+ return rv;
+ DCHECK(end_point.GetFamily() == ADDRESS_FAMILY_IPV4 ||
+ end_point.GetFamily() == ADDRESS_FAMILY_IPV6);
+ multicast_addr_ = GetMDnsIPEndPoint(end_point.GetFamily());
return DoLoop(0);
}
int MDnsConnection::SocketHandler::DoLoop(int rv) {
do {
if (rv > 0)
- connection_->OnDatagramReceived(response_.get(), recv_addr_, rv);
+ connection_->OnDatagramReceived(&response_, recv_addr_, rv);
rv = socket_->RecvFrom(
- response_->io_buffer(),
- response_->io_buffer()->size(),
+ response_.io_buffer(),
+ response_.io_buffer()->size(),
&recv_addr_,
base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived,
base::Unretained(this)));
@@ -70,31 +92,15 @@ void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) {
}
int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) {
- return socket_->SendTo(
- buffer, size, multicast_addr_,
- base::Bind(&MDnsConnection::SocketHandler::SendDone,
- base::Unretained(this) ));
+ return socket_->SendTo(buffer, size, multicast_addr_,
+ base::Bind(&MDnsConnection::SocketHandler::SendDone,
+ base::Unretained(this) ));
}
void MDnsConnection::SocketHandler::SendDone(int rv) {
// TODO(noamsml): Retry logic.
}
-int MDnsConnection::SocketHandler::Bind() {
- IPAddressNumber address_any(multicast_addr_.address().size());
-
- IPEndPoint bind_endpoint(address_any, multicast_addr_.port());
-
- socket_->AllowAddressReuse();
- int rv = socket_->Listen(bind_endpoint);
-
- if (rv < OK) return rv;
-
- socket_->SetMulticastLoopbackMode(false);
-
- return socket_->JoinGroup(multicast_addr_.address());
-}
-
MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) :
delegate_(delegate) {
}
@@ -102,34 +108,29 @@ MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) :
MDnsConnection::~MDnsConnection() {
}
-bool MDnsConnection::Init(MDnsConnection::SocketFactory* socket_factory) {
- // TODO(vitalybuka): crbug.com/297690 Make socket_factory return list
- // of initialized sockets.
- socket_handlers_.push_back(
- new SocketHandler(this, GetMDnsIPEndPoint(ADDRESS_FAMILY_IPV4),
- socket_factory));
- socket_handlers_.push_back(
- new SocketHandler(this, GetMDnsIPEndPoint(ADDRESS_FAMILY_IPV6),
- socket_factory));
+bool MDnsConnection::Init(MDnsSocketFactory* socket_factory) {
+ ScopedVector<DatagramServerSocket> sockets;
+ socket_factory->CreateSockets(&sockets);
- for (size_t i = 0; i < socket_handlers_.size();) {
- if (socket_handlers_[i]->Bind() != OK) {
- socket_handlers_.erase(socket_handlers_.begin() + i);
- } else {
- ++i;
- }
+ for (size_t i = 0; i < sockets.size(); ++i) {
+ socket_handlers_.push_back(
+ new MDnsConnection::SocketHandler(make_scoped_ptr(sockets[i]), this));
}
+ sockets.weak_clear();
// All unbound sockets need to be bound before processing untrusted input.
// This is done for security reasons, so that an attacker can't get an unbound
// socket.
for (size_t i = 0; i < socket_handlers_.size();) {
- if (socket_handlers_[i]->Start() != OK) {
+ int rv = socket_handlers_[i]->Start();
+ if (rv != OK) {
socket_handlers_.erase(socket_handlers_.begin() + i);
+ VLOG(1) << "Start failed, socket=" << i << ", error=" << rv;
} else {
++i;
}
}
+ VLOG(1) << "Sockets ready:" << socket_handlers_.size();
return !socket_handlers_.empty();
}
@@ -137,7 +138,11 @@ bool MDnsConnection::Send(IOBuffer* buffer, unsigned size) {
bool success = false;
for (size_t i = 0; i < socket_handlers_.size(); ++i) {
int rv = socket_handlers_[i]->Send(buffer, size);
- success = success || (rv >= OK || rv == ERR_IO_PENDING);
+ if (rv >= OK || rv == ERR_IO_PENDING) {
+ success = true;
+ } else {
+ VLOG(1) << "Send failed, socket=" << i << ", error=" << rv;
+ }
}
return success;
}
@@ -158,34 +163,6 @@ void MDnsConnection::OnDatagramReceived(
delegate_->HandlePacket(response, bytes_read);
}
-class MDnsConnectionSocketFactoryImpl
- : public MDnsConnection::SocketFactory {
- public:
- MDnsConnectionSocketFactoryImpl();
- virtual ~MDnsConnectionSocketFactoryImpl();
-
- virtual scoped_ptr<DatagramServerSocket> CreateSocket() OVERRIDE;
-};
-
-MDnsConnectionSocketFactoryImpl::MDnsConnectionSocketFactoryImpl() {
-}
-
-MDnsConnectionSocketFactoryImpl::~MDnsConnectionSocketFactoryImpl() {
-}
-
-scoped_ptr<DatagramServerSocket>
-MDnsConnectionSocketFactoryImpl::CreateSocket() {
- return scoped_ptr<DatagramServerSocket>(new UDPServerSocket(
- NULL, NetLog::Source()));
-}
-
-// static
-scoped_ptr<MDnsConnection::SocketFactory>
-MDnsConnection::SocketFactory::CreateDefault() {
- return scoped_ptr<MDnsConnection::SocketFactory>(
- new MDnsConnectionSocketFactoryImpl);
-}
-
MDnsClientImpl::Core::Core(MDnsClientImpl* client)
: client_(client), connection_(new MDnsConnection(this)) {
}
@@ -194,7 +171,7 @@ MDnsClientImpl::Core::~Core() {
STLDeleteValues(&listeners_);
}
-bool MDnsClientImpl::Core::Init(MDnsConnection::SocketFactory* socket_factory) {
+bool MDnsClientImpl::Core::Init(MDnsSocketFactory* socket_factory) {
return connection_->Init(socket_factory);
}
@@ -425,18 +402,16 @@ void MDnsClientImpl::Core::QueryCache(
cache_.FindDnsRecords(rrtype, name, records, base::Time::Now());
}
-MDnsClientImpl::MDnsClientImpl(
- scoped_ptr<MDnsConnection::SocketFactory> socket_factory)
- : socket_factory_(socket_factory.Pass()) {
+MDnsClientImpl::MDnsClientImpl() {
}
MDnsClientImpl::~MDnsClientImpl() {
}
-bool MDnsClientImpl::StartListening() {
+bool MDnsClientImpl::StartListening(MDnsSocketFactory* socket_factory) {
DCHECK(!core_.get());
core_.reset(new Core(this));
- if (!core_->Init(socket_factory_.get())) {
+ if (!core_->Init(socket_factory)) {
core_.reset();
return false;
}
diff --git a/chromium/net/dns/mdns_client_impl.h b/chromium/net/dns/mdns_client_impl.h
index b69677bb747..f75598560ab 100644
--- a/chromium/net/dns/mdns_client_impl.h
+++ b/chromium/net/dns/mdns_client_impl.h
@@ -23,19 +23,22 @@
namespace net {
-// A connection to the network for multicast DNS clients. It reads data into
-// DnsResponse objects and alerts the delegate that a packet has been received.
-class NET_EXPORT_PRIVATE MDnsConnection {
+class MDnsSocketFactoryImpl : public MDnsSocketFactory {
public:
- class SocketFactory {
- public:
- virtual ~SocketFactory() {}
+ MDnsSocketFactoryImpl() {};
+ virtual ~MDnsSocketFactoryImpl() {};
- virtual scoped_ptr<DatagramServerSocket> CreateSocket() = 0;
+ virtual void CreateSockets(
+ ScopedVector<DatagramServerSocket>* sockets) OVERRIDE;
- static scoped_ptr<SocketFactory> CreateDefault();
- };
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MDnsSocketFactoryImpl);
+};
+// A connection to the network for multicast DNS clients. It reads data into
+// DnsResponse objects and alerts the delegate that a packet has been received.
+class NET_EXPORT_PRIVATE MDnsConnection {
+ public:
class Delegate {
public:
// Handle an mDNS packet buffered in |response| with a size of |bytes_read|.
@@ -45,23 +48,20 @@ class NET_EXPORT_PRIVATE MDnsConnection {
};
explicit MDnsConnection(MDnsConnection::Delegate* delegate);
-
virtual ~MDnsConnection();
// Both methods return true if at least one of the socket handlers succeeded.
- bool Init(MDnsConnection::SocketFactory* socket_factory);
+ bool Init(MDnsSocketFactory* socket_factory);
bool Send(IOBuffer* buffer, unsigned size);
private:
class SocketHandler {
public:
- SocketHandler(MDnsConnection* connection,
- const IPEndPoint& multicast_addr,
- SocketFactory* socket_factory);
+ SocketHandler(scoped_ptr<DatagramServerSocket> socket,
+ MDnsConnection* connection);
~SocketHandler();
- int Bind();
- int Start();
+ int Start();
int Send(IOBuffer* buffer, unsigned size);
private:
@@ -72,11 +72,12 @@ class NET_EXPORT_PRIVATE MDnsConnection {
void SendDone(int rv);
scoped_ptr<DatagramServerSocket> socket_;
-
MDnsConnection* connection_;
IPEndPoint recv_addr_;
- scoped_ptr<DnsResponse> response_;
+ DnsResponse response_;
IPEndPoint multicast_addr_;
+
+ DISALLOW_COPY_AND_ASSIGN(SocketHandler);
};
// Callback for handling a datagram being received on either ipv4 or ipv6.
@@ -108,7 +109,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
virtual ~Core();
// Initialize the core. Returns true on success.
- bool Init(MDnsConnection::SocketFactory* socket_factory);
+ bool Init(MDnsSocketFactory* socket_factory);
// Send a query with a specific rrtype and name. Returns true on success.
bool SendQuery(uint16 rrtype, std::string name);
@@ -163,8 +164,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
DISALLOW_COPY_AND_ASSIGN(Core);
};
- explicit MDnsClientImpl(
- scoped_ptr<MDnsConnection::SocketFactory> socket_factory_);
+ MDnsClientImpl();
virtual ~MDnsClientImpl();
// MDnsClient implementation:
@@ -179,7 +179,7 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
int flags,
const MDnsTransaction::ResultCallback& callback) OVERRIDE;
- virtual bool StartListening() OVERRIDE;
+ virtual bool StartListening(MDnsSocketFactory* socket_factory) OVERRIDE;
virtual void StopListening() OVERRIDE;
virtual bool IsListening() const OVERRIDE;
@@ -188,8 +188,6 @@ class NET_EXPORT_PRIVATE MDnsClientImpl : public MDnsClient {
private:
scoped_ptr<Core> core_;
- scoped_ptr<MDnsConnection::SocketFactory> socket_factory_;
-
DISALLOW_COPY_AND_ASSIGN(MDnsClientImpl);
};
diff --git a/chromium/net/dns/mdns_client_unittest.cc b/chromium/net/dns/mdns_client_unittest.cc
index f524a5401c7..7ea4ac97448 100644
--- a/chromium/net/dns/mdns_client_unittest.cc
+++ b/chromium/net/dns/mdns_client_unittest.cc
@@ -372,10 +372,7 @@ class PtrRecordCopyContainer {
class MDnsTest : public ::testing::Test {
public:
- MDnsTest();
- virtual ~MDnsTest();
virtual void SetUp() OVERRIDE;
- virtual void TearDown() OVERRIDE;
void DeleteTransaction();
void DeleteBothListeners();
void RunFor(base::TimeDelta time_period);
@@ -392,9 +389,9 @@ class MDnsTest : public ::testing::Test {
void ExpectPacket(const uint8* packet, unsigned size);
void SimulatePacketReceive(const uint8* packet, unsigned size);
- scoped_ptr<MDnsClientImpl> test_client_;
+ MDnsClientImpl test_client_;
IPEndPoint mdns_ipv4_endpoint_;
- StrictMock<MockMDnsSocketFactory>* socket_factory_;
+ StrictMock<MockMDnsSocketFactory> socket_factory_;
// Transactions and listeners that can be deleted by class methods for
// reentrancy tests.
@@ -412,28 +409,16 @@ class MockListenerDelegate : public MDnsListener::Delegate {
MOCK_METHOD0(OnCachePurged, void());
};
-MDnsTest::MDnsTest() {
- socket_factory_ = new StrictMock<MockMDnsSocketFactory>();
- test_client_.reset(new MDnsClientImpl(
- scoped_ptr<MDnsConnection::SocketFactory>(socket_factory_)));
-}
-
-MDnsTest::~MDnsTest() {
-}
-
void MDnsTest::SetUp() {
- test_client_->StartListening();
-}
-
-void MDnsTest::TearDown() {
+ test_client_.StartListening(&socket_factory_);
}
void MDnsTest::SimulatePacketReceive(const uint8* packet, unsigned size) {
- socket_factory_->SimulateReceive(packet, size);
+ socket_factory_.SimulateReceive(packet, size);
}
void MDnsTest::ExpectPacket(const uint8* packet, unsigned size) {
- EXPECT_CALL(*socket_factory_, OnSendTo(MakeString(packet, size)))
+ EXPECT_CALL(socket_factory_, OnSendTo(MakeString(packet, size)))
.Times(2);
}
@@ -467,10 +452,12 @@ TEST_F(MDnsTest, PassiveListeners) {
PtrRecordCopyContainer record_privet;
PtrRecordCopyContainer record_printer;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
- scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
+ &delegate_privet);
+ scoped_ptr<MDnsListener> listener_printer =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local",
+ &delegate_printer);
ASSERT_TRUE(listener_privet->Start());
ASSERT_TRUE(listener_printer->Start());
@@ -509,8 +496,9 @@ TEST_F(MDnsTest, PassiveListenersCacheCleanup) {
PtrRecordCopyContainer record_privet;
PtrRecordCopyContainer record_privet2;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
+ &delegate_privet);
ASSERT_TRUE(listener_privet->Start());
@@ -543,8 +531,9 @@ TEST_F(MDnsTest, MalformedPacket) {
PtrRecordCopyContainer record_printer;
- scoped_ptr<MDnsListener> listener_printer = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_printer._tcp.local", &delegate_printer);
+ scoped_ptr<MDnsListener> listener_printer =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_printer._tcp.local",
+ &delegate_printer);
ASSERT_TRUE(listener_printer->Start());
@@ -574,7 +563,7 @@ TEST_F(MDnsTest, TransactionWithEmptyCache) {
ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
scoped_ptr<MDnsTransaction> transaction_privet =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -599,7 +588,7 @@ TEST_F(MDnsTest, TransactionWithEmptyCache) {
TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
scoped_ptr<MDnsTransaction> transaction_privet =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_CACHE |
MDnsTransaction::SINGLE_RESULT,
@@ -616,9 +605,10 @@ TEST_F(MDnsTest, TransactionCacheOnlyNoResult) {
TEST_F(MDnsTest, TransactionWithCache) {
// Listener to force the client to listen
StrictMock<MockListenerDelegate> delegate_irrelevant;
- scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
- dns_protocol::kTypeA, "codereview.chromium.local",
- &delegate_irrelevant);
+ scoped_ptr<MDnsListener> listener_irrelevant =
+ test_client_.CreateListener(dns_protocol::kTypeA,
+ "codereview.chromium.local",
+ &delegate_irrelevant);
ASSERT_TRUE(listener_irrelevant->Start());
@@ -632,7 +622,7 @@ TEST_F(MDnsTest, TransactionWithCache) {
&PtrRecordCopyContainer::SaveWithDummyArg));
scoped_ptr<MDnsTransaction> transaction_privet =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -651,9 +641,9 @@ TEST_F(MDnsTest, AdditionalRecords) {
PtrRecordCopyContainer record_privet;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local",
- &delegate_privet);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
+ &delegate_privet);
ASSERT_TRUE(listener_privet->Start());
@@ -674,7 +664,7 @@ TEST_F(MDnsTest, TransactionTimeout) {
ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
scoped_ptr<MDnsTransaction> transaction_privet =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -696,7 +686,7 @@ TEST_F(MDnsTest, TransactionMultipleRecords) {
ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
scoped_ptr<MDnsTransaction> transaction_privet =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE ,
@@ -733,7 +723,7 @@ TEST_F(MDnsTest, TransactionMultipleRecords) {
TEST_F(MDnsTest, TransactionReentrantDelete) {
ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
- transaction_ = test_client_->CreateTransaction(
+ transaction_ = test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -756,14 +746,14 @@ TEST_F(MDnsTest, TransactionReentrantDelete) {
TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
StrictMock<MockListenerDelegate> delegate_irrelevant;
- scoped_ptr<MDnsListener> listener_irrelevant = test_client_->CreateListener(
+ scoped_ptr<MDnsListener> listener_irrelevant = test_client_.CreateListener(
dns_protocol::kTypeA, "codereview.chromium.local",
&delegate_irrelevant);
ASSERT_TRUE(listener_irrelevant->Start());
SimulatePacketReceive(kSamplePacket1, sizeof(kSamplePacket1));
- transaction_ = test_client_->CreateTransaction(
+ transaction_ = test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE,
@@ -782,20 +772,22 @@ TEST_F(MDnsTest, TransactionReentrantDeleteFromCache) {
TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
ExpectPacket(kQueryPacketPrivet, sizeof(kQueryPacketPrivet));
- scoped_ptr<MDnsTransaction> transaction1 = test_client_->CreateTransaction(
- dns_protocol::kTypePTR, "_privet._tcp.local",
- MDnsTransaction::QUERY_NETWORK |
- MDnsTransaction::QUERY_CACHE |
- MDnsTransaction::SINGLE_RESULT,
- base::Bind(&MDnsTest::MockableRecordCallback,
- base::Unretained(this)));
+ scoped_ptr<MDnsTransaction> transaction1 =
+ test_client_.CreateTransaction(
+ dns_protocol::kTypePTR, "_privet._tcp.local",
+ MDnsTransaction::QUERY_NETWORK |
+ MDnsTransaction::QUERY_CACHE |
+ MDnsTransaction::SINGLE_RESULT,
+ base::Bind(&MDnsTest::MockableRecordCallback,
+ base::Unretained(this)));
- scoped_ptr<MDnsTransaction> transaction2 = test_client_->CreateTransaction(
- dns_protocol::kTypePTR, "_printer._tcp.local",
- MDnsTransaction::QUERY_CACHE |
- MDnsTransaction::SINGLE_RESULT,
- base::Bind(&MDnsTest::MockableRecordCallback2,
- base::Unretained(this)));
+ scoped_ptr<MDnsTransaction> transaction2 =
+ test_client_.CreateTransaction(
+ dns_protocol::kTypePTR, "_printer._tcp.local",
+ MDnsTransaction::QUERY_CACHE |
+ MDnsTransaction::SINGLE_RESULT,
+ base::Bind(&MDnsTest::MockableRecordCallback2,
+ base::Unretained(this)));
EXPECT_CALL(*this, MockableRecordCallback2(MDnsTransaction::RESULT_RECORD,
_))
@@ -815,7 +807,7 @@ TEST_F(MDnsTest, TransactionReentrantCacheLookupStart) {
TEST_F(MDnsTest, GoodbyePacketNotification) {
StrictMock<MockListenerDelegate> delegate_privet;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
+ scoped_ptr<MDnsListener> listener_privet = test_client_.CreateListener(
dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
ASSERT_TRUE(listener_privet->Start());
@@ -827,8 +819,9 @@ TEST_F(MDnsTest, GoodbyePacketNotification) {
TEST_F(MDnsTest, GoodbyePacketRemoval) {
StrictMock<MockListenerDelegate> delegate_privet;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
+ &delegate_privet);
ASSERT_TRUE(listener_privet->Start());
EXPECT_CALL(delegate_privet, OnRecordUpdate(MDnsListener::RECORD_ADDED, _))
@@ -851,13 +844,13 @@ TEST_F(MDnsTest, GoodbyePacketRemoval) {
TEST_F(MDnsTest, ListenerReentrantDelete) {
StrictMock<MockListenerDelegate> delegate_privet;
- listener1_ = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local",
- &delegate_privet);
+ listener1_ = test_client_.CreateListener(dns_protocol::kTypePTR,
+ "_privet._tcp.local",
+ &delegate_privet);
- listener2_ = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local",
- &delegate_privet);
+ listener2_ = test_client_.CreateListener(dns_protocol::kTypePTR,
+ "_privet._tcp.local",
+ &delegate_privet);
ASSERT_TRUE(listener1_->Start());
@@ -884,8 +877,9 @@ TEST_F(MDnsTest, DoubleRecordDisagreeing) {
IPAddressNumber address;
StrictMock<MockListenerDelegate> delegate_privet;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypeA, "privet.local", &delegate_privet);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypeA, "privet.local",
+ &delegate_privet);
ASSERT_TRUE(listener_privet->Start());
@@ -901,14 +895,16 @@ TEST_F(MDnsTest, DoubleRecordDisagreeing) {
TEST_F(MDnsTest, NsecWithListener) {
StrictMock<MockListenerDelegate> delegate_privet;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local",
+ &delegate_privet);
// Test to make sure nsec callback is NOT called for PTR
// (which is marked as existing).
StrictMock<MockListenerDelegate> delegate_privet2;
- scoped_ptr<MDnsListener> listener_privet2 = test_client_->CreateListener(
- dns_protocol::kTypePTR, "_privet._tcp.local", &delegate_privet2);
+ scoped_ptr<MDnsListener> listener_privet2 =
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
+ &delegate_privet2);
ASSERT_TRUE(listener_privet->Start());
@@ -921,7 +917,7 @@ TEST_F(MDnsTest, NsecWithListener) {
TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
scoped_ptr<MDnsTransaction> transaction_privet =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypeA, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -929,8 +925,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromNetwork) {
base::Bind(&MDnsTest::MockableRecordCallback,
base::Unretained(this)));
- EXPECT_CALL(*socket_factory_, OnSendTo(_))
- .Times(2);
+ EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
ASSERT_TRUE(transaction_privet->Start());
@@ -945,8 +940,8 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) {
// Force mDNS to listen.
StrictMock<MockListenerDelegate> delegate_irrelevant;
scoped_ptr<MDnsListener> listener_irrelevant =
- test_client_->CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
- &delegate_irrelevant);
+ test_client_.CreateListener(dns_protocol::kTypePTR, "_privet._tcp.local",
+ &delegate_irrelevant);
listener_irrelevant->Start();
SimulatePacketReceive(kSamplePacketNsec,
@@ -956,7 +951,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) {
MockableRecordCallback(MDnsTransaction::RESULT_NSEC, NULL));
scoped_ptr<MDnsTransaction> transaction_privet_a =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypeA, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -970,7 +965,7 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) {
// valid answer to the query
scoped_ptr<MDnsTransaction> transaction_privet_ptr =
- test_client_->CreateTransaction(
+ test_client_.CreateTransaction(
dns_protocol::kTypePTR, "_privet._tcp.local",
MDnsTransaction::QUERY_NETWORK |
MDnsTransaction::QUERY_CACHE |
@@ -978,16 +973,16 @@ TEST_F(MDnsTest, NsecWithTransactionFromCache) {
base::Bind(&MDnsTest::MockableRecordCallback,
base::Unretained(this)));
- EXPECT_CALL(*socket_factory_, OnSendTo(_))
- .Times(2);
+ EXPECT_CALL(socket_factory_, OnSendTo(_)).Times(2);
ASSERT_TRUE(transaction_privet_ptr->Start());
}
TEST_F(MDnsTest, NsecConflictRemoval) {
StrictMock<MockListenerDelegate> delegate_privet;
- scoped_ptr<MDnsListener> listener_privet = test_client_->CreateListener(
- dns_protocol::kTypeA, "_privet._tcp.local", &delegate_privet);
+ scoped_ptr<MDnsListener> listener_privet =
+ test_client_.CreateListener(dns_protocol::kTypeA, "_privet._tcp.local",
+ &delegate_privet);
ASSERT_TRUE(listener_privet->Start());
@@ -1015,27 +1010,20 @@ TEST_F(MDnsTest, NsecConflictRemoval) {
// Note: These tests assume that the ipv4 socket will always be created first.
// This is a simplifying assumption based on the way the code works now.
-
-class SimpleMockSocketFactory
- : public MDnsConnection::SocketFactory {
+class SimpleMockSocketFactory : public MDnsSocketFactory {
public:
- SimpleMockSocketFactory() {
- }
- virtual ~SimpleMockSocketFactory() {
- }
-
- virtual scoped_ptr<DatagramServerSocket> CreateSocket() OVERRIDE {
- MockMDnsDatagramServerSocket* socket = sockets_.back();
- sockets_.weak_erase(sockets_.end() - 1);
- return scoped_ptr<DatagramServerSocket>(socket);
+ virtual void CreateSockets(
+ ScopedVector<DatagramServerSocket>* sockets) OVERRIDE {
+ sockets->clear();
+ sockets->swap(sockets_);
}
- void PushSocket(MockMDnsDatagramServerSocket* socket) {
+ void PushSocket(DatagramServerSocket* socket) {
sockets_.push_back(socket);
}
private:
- ScopedVector<MockMDnsDatagramServerSocket> sockets_;
+ ScopedVector<DatagramServerSocket> sockets_;
};
class MockMDnsConnectionDelegate : public MDnsConnection::Delegate {
@@ -1057,29 +1045,13 @@ class MDnsConnectionTest : public ::testing::Test {
protected:
// Follow successful connection initialization.
virtual void SetUp() OVERRIDE {
- socket_ipv4_ = new MockMDnsDatagramServerSocket;
- socket_ipv6_ = new MockMDnsDatagramServerSocket;
+ socket_ipv4_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV4);
+ socket_ipv6_ = new MockMDnsDatagramServerSocket(ADDRESS_FAMILY_IPV6);
factory_.PushSocket(socket_ipv6_);
factory_.PushSocket(socket_ipv4_);
}
bool InitConnection() {
- EXPECT_CALL(*socket_ipv4_, AllowAddressReuse());
- EXPECT_CALL(*socket_ipv6_, AllowAddressReuse());
-
- EXPECT_CALL(*socket_ipv4_, SetMulticastLoopbackMode(false));
- EXPECT_CALL(*socket_ipv6_, SetMulticastLoopbackMode(false));
-
- EXPECT_CALL(*socket_ipv4_, ListenInternal("0.0.0.0:5353"))
- .WillOnce(Return(OK));
- EXPECT_CALL(*socket_ipv6_, ListenInternal("[::]:5353"))
- .WillOnce(Return(OK));
-
- EXPECT_CALL(*socket_ipv4_, JoinGroupInternal("224.0.0.251"))
- .WillOnce(Return(OK));
- EXPECT_CALL(*socket_ipv6_, JoinGroupInternal("ff02::fb"))
- .WillOnce(Return(OK));
-
return connection_.Init(&factory_);
}
diff --git a/chromium/net/dns/mock_mdns_socket_factory.cc b/chromium/net/dns/mock_mdns_socket_factory.cc
index 8c08c150cd1..0bb8c5401dd 100644
--- a/chromium/net/dns/mock_mdns_socket_factory.cc
+++ b/chromium/net/dns/mock_mdns_socket_factory.cc
@@ -12,31 +12,24 @@ using testing::Invoke;
namespace net {
-MockMDnsDatagramServerSocket::MockMDnsDatagramServerSocket() {
+MockMDnsDatagramServerSocket::MockMDnsDatagramServerSocket(
+ AddressFamily address_family) {
+ local_address_ = GetMDnsIPEndPoint(address_family);
}
MockMDnsDatagramServerSocket::~MockMDnsDatagramServerSocket() {
}
int MockMDnsDatagramServerSocket::SendTo(IOBuffer* buf, int buf_len,
- const IPEndPoint& address,
- const CompletionCallback& callback) {
- return SendToInternal(std::string(buf->data(), buf_len), address.ToString(),
- callback);
+ const IPEndPoint& address,
+ const CompletionCallback& callback) {
+ return SendToInternal(std::string(buf->data(), buf_len), address.ToString(),
+ callback);
}
-int MockMDnsDatagramServerSocket::Listen(const IPEndPoint& address) {
- return ListenInternal(address.ToString());
-}
-
-int MockMDnsDatagramServerSocket::JoinGroup(
- const IPAddressNumber& group_address) const {
- return JoinGroupInternal(IPAddressToString(group_address));
-}
-
-int MockMDnsDatagramServerSocket::LeaveGroup(
- const IPAddressNumber& group_address) const {
- return LeaveGroupInternal(IPAddressToString(group_address));
+int MockMDnsDatagramServerSocket::GetLocalAddress(IPEndPoint* address) const {
+ *address = local_address_;
+ return OK;
}
void MockMDnsDatagramServerSocket::SetResponsePacket(
@@ -67,9 +60,17 @@ MockMDnsSocketFactory::MockMDnsSocketFactory() {
MockMDnsSocketFactory::~MockMDnsSocketFactory() {
}
-scoped_ptr<DatagramServerSocket> MockMDnsSocketFactory::CreateSocket() {
- scoped_ptr<MockMDnsDatagramServerSocket> new_socket(
- new testing:: NiceMock<MockMDnsDatagramServerSocket>);
+void MockMDnsSocketFactory::CreateSockets(
+ ScopedVector<DatagramServerSocket>* sockets) {
+ CreateSocket(ADDRESS_FAMILY_IPV4, sockets);
+ CreateSocket(ADDRESS_FAMILY_IPV6, sockets);
+}
+
+void MockMDnsSocketFactory::CreateSocket(
+ AddressFamily address_family,
+ ScopedVector<DatagramServerSocket>* sockets) {
+ scoped_ptr<testing::NiceMock<MockMDnsDatagramServerSocket> > new_socket(
+ new testing::NiceMock<MockMDnsDatagramServerSocket>(address_family));
ON_CALL(*new_socket, SendToInternal(_, _, _))
.WillByDefault(Invoke(
@@ -81,7 +82,7 @@ scoped_ptr<DatagramServerSocket> MockMDnsSocketFactory::CreateSocket() {
this,
&MockMDnsSocketFactory::RecvFromInternal));
- return new_socket.PassAs<DatagramServerSocket>();
+ sockets->push_back(new_socket.release());
}
void MockMDnsSocketFactory::SimulateReceive(const uint8* packet, int size) {
diff --git a/chromium/net/dns/mock_mdns_socket_factory.h b/chromium/net/dns/mock_mdns_socket_factory.h
index f60b08c591b..7cc8fed9ab3 100644
--- a/chromium/net/dns/mock_mdns_socket_factory.h
+++ b/chromium/net/dns/mock_mdns_socket_factory.h
@@ -14,11 +14,11 @@ namespace net {
class MockMDnsDatagramServerSocket : public DatagramServerSocket {
public:
- MockMDnsDatagramServerSocket();
+ explicit MockMDnsDatagramServerSocket(AddressFamily address_family);
~MockMDnsDatagramServerSocket();
// DatagramServerSocket implementation:
- int Listen(const IPEndPoint& address);
+ MOCK_METHOD1(Listen, int(const IPEndPoint& address));
MOCK_METHOD1(ListenInternal, int(const std::string& address));
@@ -26,8 +26,8 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
IPEndPoint* address,
const CompletionCallback& callback));
- int SendTo(IOBuffer* buf, int buf_len, const IPEndPoint& address,
- const CompletionCallback& callback);
+ virtual int SendTo(IOBuffer* buf, int buf_len, const IPEndPoint& address,
+ const CompletionCallback& callback) OVERRIDE;
MOCK_METHOD3(SendToInternal, int(const std::string& packet,
const std::string address,
@@ -39,24 +39,21 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
MOCK_METHOD0(Close, void());
MOCK_CONST_METHOD1(GetPeerAddress, int(IPEndPoint* address));
- MOCK_CONST_METHOD1(GetLocalAddress, int(IPEndPoint* address));
+ virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE;
MOCK_CONST_METHOD0(NetLog, const BoundNetLog&());
MOCK_METHOD0(AllowAddressReuse, void());
MOCK_METHOD0(AllowBroadcast, void());
- int JoinGroup(const IPAddressNumber& group_address) const;
-
- MOCK_CONST_METHOD1(JoinGroupInternal, int(const std::string& group));
-
- int LeaveGroup(const IPAddressNumber& group_address) const;
-
- MOCK_CONST_METHOD1(LeaveGroupInternal, int(const std::string& group));
+ MOCK_CONST_METHOD1(JoinGroup, int(const IPAddressNumber& group_address));
+ MOCK_CONST_METHOD1(LeaveGroup, int(const IPAddressNumber& address));
+ MOCK_METHOD1(SetMulticastInterface, int(uint32 interface_index));
MOCK_METHOD1(SetMulticastTimeToLive, int(int ttl));
-
MOCK_METHOD1(SetMulticastLoopbackMode, int(bool loopback));
+ MOCK_METHOD1(SetDiffServCodePoint, int(DiffServCodePoint dscp));
+
void SetResponsePacket(std::string response_packet);
int HandleRecvNow(IOBuffer* buffer, int size, IPEndPoint* address,
@@ -67,15 +64,16 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
private:
std::string response_packet_;
+ IPEndPoint local_address_;
};
-class MockMDnsSocketFactory : public MDnsConnection::SocketFactory {
+class MockMDnsSocketFactory : public MDnsSocketFactory {
public:
MockMDnsSocketFactory();
-
virtual ~MockMDnsSocketFactory();
- virtual scoped_ptr<DatagramServerSocket> CreateSocket() OVERRIDE;
+ virtual void CreateSockets(
+ ScopedVector<DatagramServerSocket>* sockets) OVERRIDE;
void SimulateReceive(const uint8* packet, int size);
@@ -91,6 +89,9 @@ class MockMDnsSocketFactory : public MDnsConnection::SocketFactory {
IPEndPoint* address,
const CompletionCallback& callback);
+ void CreateSocket(AddressFamily address_family,
+ ScopedVector<DatagramServerSocket>* sockets);
+
scoped_refptr<IOBuffer> recv_buffer_;
int recv_buffer_size_;
CompletionCallback recv_callback_;
diff --git a/chromium/net/dns/serial_worker.cc b/chromium/net/dns/serial_worker.cc
index 394721c1a65..4da7df98ba2 100644
--- a/chromium/net/dns/serial_worker.cc
+++ b/chromium/net/dns/serial_worker.cc
@@ -11,11 +11,6 @@
namespace net {
-namespace {
- // Delay between calls to WorkerPool::PostTask
- const int kWorkerPoolRetryDelayMs = 100;
-}
-
SerialWorker::SerialWorker()
: message_loop_(base::MessageLoopProxy::current()),
state_(IDLE) {}
@@ -33,6 +28,7 @@ void SerialWorker::WorkNow() {
NOTREACHED() << "WorkerPool::PostTask is not expected to fail on posix";
#else
LOG(WARNING) << "Failed to WorkerPool::PostTask, will retry later";
+ const int kWorkerPoolRetryDelayMs = 100;
message_loop_->PostDelayedTask(
FROM_HERE,
base::Bind(&SerialWorker::RetryWork, this),
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
index a7389443500..313ef664c73 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
@@ -130,6 +130,10 @@ TEST_F(FtpDirectoryListingParserLsTest, Good) {
FtpDirectoryListingEntry::DIRECTORY, "swetzel", -1,
1994, 12, 22, 0, 0 },
+ { "drwxrwxr-x 1 500 244 660 Jan 1 00:0 bin",
+ FtpDirectoryListingEntry::DIRECTORY, "bin", -1,
+ 1994, 1, 1, 0, 0 },
+
// Garbage in date (but still parseable).
{ "lrw-rw-rw- 1 user group 542 "
"/t11/member/incomingFeb 8 2007 "
@@ -197,7 +201,6 @@ TEST_F(FtpDirectoryListingParserLsTest, Bad) {
"-rw-r--r-- ftp ftp 528 Foo 01 2007 README",
"-rw-r--r-- 1 ftp ftp",
"-rw-r--r-- 1 ftp ftp 528 Foo 01 2007 README",
- "drwxrwxrwx 1 owner group 1024 Sep 13 0:3 audio",
// Invalid month value (30).
"drwxrwxrwx 2 root root 4096 2012-30-07 00:31 notas_servico",
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc
index 73d19bc6cac..f27007aef37 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_unittest.cc
@@ -141,6 +141,7 @@ const char* kTestFiles[] = {
"dir-listing-ls-29",
"dir-listing-ls-30",
"dir-listing-ls-31",
+ "dir-listing-ls-32", // busybox
"dir-listing-netware-1",
"dir-listing-netware-2",
diff --git a/chromium/net/ftp/ftp_network_transaction.cc b/chromium/net/ftp/ftp_network_transaction.cc
index 9d0cbe2c596..23a043247d5 100644
--- a/chromium/net/ftp/ftp_network_transaction.cc
+++ b/chromium/net/ftp/ftp_network_transaction.cc
@@ -835,7 +835,7 @@ int FtpNetworkTransaction::ProcessResponseSYST(
// Remove all whitespace, to correctly handle cases like fancy "V M S"
// response instead of "VMS".
- RemoveChars(line, kWhitespaceASCII, &line);
+ base::RemoveChars(line, base::kWhitespaceASCII, &line);
// The "magic" strings we test for below have been gathered by an
// empirical study. VMS needs to come first because some VMS systems
diff --git a/chromium/net/ftp/ftp_util.cc b/chromium/net/ftp/ftp_util.cc
index c5e18c8f79d..e639c46edcc 100644
--- a/chromium/net/ftp/ftp_util.cc
+++ b/chromium/net/ftp/ftp_util.cc
@@ -245,29 +245,25 @@ bool FtpUtil::LsDateListingToTime(const base::string16& month,
return false;
if (!base::StringToInt(rest, &time_exploded.year)) {
- // Maybe it's time. Does it look like time (HH:MM)?
- if (rest.length() == 5 && rest[2] == ':') {
- if (!base::StringToInt(StringPiece16(rest.begin(), rest.begin() + 2),
- &time_exploded.hour)) {
- return false;
- }
+ // Maybe it's time. Does it look like time? Note that it can be any of
+ // "HH:MM", "H:MM", "HH:M" or maybe even "H:M".
+ if (rest.length() > 5)
+ return false;
- if (!base::StringToInt(StringPiece16(rest.begin() + 3, rest.begin() + 5),
- &time_exploded.minute)) {
- return false;
- }
- } else if (rest.length() == 4 && rest[1] == ':') {
- // Sometimes it's just H:MM.
- if (!base::StringToInt(StringPiece16(rest.begin(), rest.begin() + 1),
- &time_exploded.hour)) {
- return false;
- }
+ size_t colon_pos = rest.find(':');
+ if (colon_pos == base::string16::npos)
+ return false;
+ if (colon_pos > 2)
+ return false;
- if (!base::StringToInt(StringPiece16(rest.begin() + 2, rest.begin() + 4),
- &time_exploded.minute)) {
- return false;
- }
- } else {
+ if (!base::StringToInt(
+ StringPiece16(rest.begin(), rest.begin() + colon_pos),
+ &time_exploded.hour)) {
+ return false;
+ }
+ if (!base::StringToInt(
+ StringPiece16(rest.begin() + colon_pos + 1, rest.end()),
+ &time_exploded.minute)) {
return false;
}
diff --git a/chromium/net/http/http_auth_cache.cc b/chromium/net/http/http_auth_cache.cc
index 1c8c03fbb25..63bad076df1 100644
--- a/chromium/net/http/http_auth_cache.cc
+++ b/chromium/net/http/http_auth_cache.cc
@@ -43,7 +43,8 @@ bool IsEnclosingPath(const std::string& container, const std::string& path) {
void CheckOriginIsValid(const GURL& origin) {
DCHECK(origin.is_valid());
// Note that the scheme may be FTP when we're using a HTTP proxy.
- DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp"));
+ DCHECK(origin.SchemeIsHTTPOrHTTPS() || origin.SchemeIs("ftp") ||
+ origin.SchemeIsWSOrWSS());
DCHECK(origin.GetOrigin() == origin);
}
diff --git a/chromium/net/http/http_auth_gssapi_posix.cc b/chromium/net/http/http_auth_gssapi_posix.cc
index 4d7bf074061..41cbcdbcdc0 100644
--- a/chromium/net/http/http_auth_gssapi_posix.cc
+++ b/chromium/net/http/http_auth_gssapi_posix.cc
@@ -715,7 +715,7 @@ HttpAuth::AuthorizationResult HttpAuthGSSAPI::ParseChallenge(
}
int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials,
- const std::wstring& spn,
+ const std::string& spn,
std::string* auth_token) {
DCHECK(auth_token);
@@ -734,11 +734,7 @@ int HttpAuthGSSAPI::GenerateAuthToken(const AuthCredentials* credentials,
std::string encode_input(static_cast<char*>(output_token.value),
output_token.length);
std::string encode_output;
- bool base64_rv = base::Base64Encode(encode_input, &encode_output);
- if (!base64_rv) {
- LOG(ERROR) << "Base64 encoding of auth token failed.";
- return ERR_ENCODING_CONVERSION_FAILED;
- }
+ base::Base64Encode(encode_input, &encode_output);
*auth_token = scheme_ + " " + encode_output;
return OK;
}
@@ -837,12 +833,12 @@ int MapInitSecContextStatusToError(OM_uint32 major_status) {
}
-int HttpAuthGSSAPI::GetNextSecurityToken(const std::wstring& spn,
+int HttpAuthGSSAPI::GetNextSecurityToken(const std::string& spn,
gss_buffer_t in_token,
gss_buffer_t out_token) {
// Create a name for the principal
// TODO(cbentzel): Just do this on the first pass?
- std::string spn_principal = WideToASCII(spn);
+ std::string spn_principal = spn;
gss_buffer_desc spn_buffer = GSS_C_EMPTY_BUFFER;
spn_buffer.value = const_cast<char*>(spn_principal.c_str());
spn_buffer.length = spn_principal.size() + 1;
diff --git a/chromium/net/http/http_auth_gssapi_posix.h b/chromium/net/http/http_auth_gssapi_posix.h
index afa50a02c9f..db603f65da8 100644
--- a/chromium/net/http/http_auth_gssapi_posix.h
+++ b/chromium/net/http/http_auth_gssapi_posix.h
@@ -251,7 +251,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI {
// obtained using |*credentials|. If |credentials| is NULL, the default
// credentials are used instead.
int GenerateAuthToken(const AuthCredentials* credentials,
- const std::wstring& spn,
+ const std::string& spn,
std::string* auth_token);
// Delegation is allowed on the Kerberos ticket. This allows certain servers
@@ -260,7 +260,7 @@ class NET_EXPORT_PRIVATE HttpAuthGSSAPI {
void Delegate();
private:
- int GetNextSecurityToken(const std::wstring& spn,
+ int GetNextSecurityToken(const std::string& spn,
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 1c3d12b6c29..48d17a3ad64 100644
--- a/chromium/net/http/http_auth_gssapi_posix_unittest.cc
+++ b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
@@ -202,7 +202,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_TwoRounds) {
// Generate an auth token and create another thing.
EstablishInitialContext(&mock_library);
std::string auth_token;
- EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com",
+ EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
@@ -239,7 +239,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_MissingTokenSecondRound) {
EstablishInitialContext(&mock_library);
std::string auth_token;
- EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com",
+ EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate";
HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
@@ -262,7 +262,7 @@ TEST(HttpAuthGSSAPITest, ParseChallenge_NonBase64EncodedToken) {
EstablishInitialContext(&mock_library);
std::string auth_token;
- EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com",
+ EXPECT_EQ(OK, auth_gssapi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate =happyjoy=";
HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
diff --git a/chromium/net/http/http_auth_handler_basic.cc b/chromium/net/http/http_auth_handler_basic.cc
index af5f188b156..e445c93100c 100644
--- a/chromium/net/http/http_auth_handler_basic.cc
+++ b/chromium/net/http/http_auth_handler_basic.cc
@@ -91,13 +91,9 @@ int HttpAuthHandlerBasic::GenerateAuthTokenImpl(
DCHECK(credentials);
// TODO(eroman): is this the right encoding of username/password?
std::string base64_username_password;
- if (!base::Base64Encode(
- UTF16ToUTF8(credentials->username()) + ":" +
- UTF16ToUTF8(credentials->password()),
- &base64_username_password)) {
- LOG(ERROR) << "Unexpected problem Base64 encoding.";
- return ERR_UNEXPECTED;
- }
+ base::Base64Encode(UTF16ToUTF8(credentials->username()) + ":" +
+ UTF16ToUTF8(credentials->password()),
+ &base64_username_password);
*auth_token = "Basic " + base64_username_password;
return OK;
}
diff --git a/chromium/net/http/http_auth_handler_digest.cc b/chromium/net/http/http_auth_handler_digest.cc
index 904430ecb40..a8e301a02e8 100644
--- a/chromium/net/http/http_auth_handler_digest.cc
+++ b/chromium/net/http/http_auth_handler_digest.cc
@@ -18,6 +18,7 @@
#include "net/http/http_auth.h"
#include "net/http/http_request_info.h"
#include "net/http/http_util.h"
+#include "url/gurl.h"
namespace net {
@@ -304,7 +305,7 @@ void HttpAuthHandlerDigest::GetRequestMethodAndPath(
const GURL& url = request->url;
if (target_ == HttpAuth::AUTH_PROXY &&
- (url.SchemeIs("https") || url.SchemeIs("ws") || url.SchemeIs("wss"))) {
+ (url.SchemeIs("https") || url.SchemeIsWSOrWSS())) {
*method = "CONNECT";
*path = GetHostAndPort(url);
} else {
diff --git a/chromium/net/http/http_auth_handler_negotiate.cc b/chromium/net/http/http_auth_handler_negotiate.cc
index 13b106925b7..788b06750b6 100644
--- a/chromium/net/http/http_auth_handler_negotiate.cc
+++ b/chromium/net/http/http_auth_handler_negotiate.cc
@@ -7,9 +7,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
-#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
#include "net/base/address_family.h"
#include "net/base/net_errors.h"
#include "net/dns/host_resolver.h"
@@ -114,7 +112,7 @@ HttpAuthHandlerNegotiate::HttpAuthHandlerNegotiate(
HttpAuthHandlerNegotiate::~HttpAuthHandlerNegotiate() {
}
-std::wstring HttpAuthHandlerNegotiate::CreateSPN(
+std::string HttpAuthHandlerNegotiate::CreateSPN(
const AddressList& address_list, const GURL& origin) {
// Kerberos Web Server SPNs are in the form HTTP/<host>:<port> through SSPI,
// and in the form HTTP@<host>:<port> through GSSAPI
@@ -155,11 +153,10 @@ std::wstring HttpAuthHandlerNegotiate::CreateSPN(
static const char kSpnSeparator = '@';
#endif
if (port != 80 && port != 443 && use_port_) {
- return ASCIIToWide(base::StringPrintf("HTTP%c%s:%d", kSpnSeparator,
- server.c_str(), port));
+ return base::StringPrintf("HTTP%c%s:%d", kSpnSeparator, server.c_str(),
+ port);
} else {
- return ASCIIToWide(base::StringPrintf("HTTP%c%s", kSpnSeparator,
- server.c_str()));
+ return base::StringPrintf("HTTP%c%s", kSpnSeparator, server.c_str());
}
}
diff --git a/chromium/net/http/http_auth_handler_negotiate.h b/chromium/net/http/http_auth_handler_negotiate.h
index 6fd7aa9a068..d028178ed51 100644
--- a/chromium/net/http/http_auth_handler_negotiate.h
+++ b/chromium/net/http/http_auth_handler_negotiate.h
@@ -102,8 +102,8 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
virtual ~HttpAuthHandlerNegotiate();
// These are public for unit tests
- std::wstring CreateSPN(const AddressList& address_list, const GURL& orign);
- const std::wstring& spn() const { return spn_; }
+ std::string CreateSPN(const AddressList& address_list, const GURL& orign);
+ const std::string& spn() const { return spn_; }
// HttpAuthHandler:
virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
@@ -152,7 +152,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNegotiate : public HttpAuthHandler {
bool already_called_;
bool has_credentials_;
AuthCredentials credentials_;
- std::wstring spn_;
+ std::string spn_;
// 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 809f58e1fcc..64521a6177f 100644
--- a/chromium/net/http/http_auth_handler_negotiate_unittest.cc
+++ b/chromium/net/http/http_auth_handler_negotiate_unittest.cc
@@ -226,9 +226,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, DisableCname) {
EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info,
callback.callback(), &token));
#if defined(OS_WIN)
- EXPECT_EQ(L"HTTP/alias", auth_handler->spn());
+ EXPECT_EQ("HTTP/alias", auth_handler->spn());
#elif defined(OS_POSIX)
- EXPECT_EQ(L"HTTP@alias", auth_handler->spn());
+ EXPECT_EQ("HTTP@alias", auth_handler->spn());
#endif
}
@@ -244,9 +244,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameStandardPort) {
EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info,
callback.callback(), &token));
#if defined(OS_WIN)
- EXPECT_EQ(L"HTTP/alias", auth_handler->spn());
+ EXPECT_EQ("HTTP/alias", auth_handler->spn());
#elif defined(OS_POSIX)
- EXPECT_EQ(L"HTTP@alias", auth_handler->spn());
+ EXPECT_EQ("HTTP@alias", auth_handler->spn());
#endif
}
@@ -262,9 +262,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, DisableCnameNonstandardPort) {
EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info,
callback.callback(), &token));
#if defined(OS_WIN)
- EXPECT_EQ(L"HTTP/alias:500", auth_handler->spn());
+ EXPECT_EQ("HTTP/alias:500", auth_handler->spn());
#elif defined(OS_POSIX)
- EXPECT_EQ(L"HTTP@alias:500", auth_handler->spn());
+ EXPECT_EQ("HTTP@alias:500", auth_handler->spn());
#endif
}
@@ -280,9 +280,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, CnameSync) {
EXPECT_EQ(OK, auth_handler->GenerateAuthToken(NULL, &request_info,
callback.callback(), &token));
#if defined(OS_WIN)
- EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn());
+ EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn());
#elif defined(OS_POSIX)
- EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn());
+ EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn());
#endif
}
@@ -299,9 +299,9 @@ TEST_F(HttpAuthHandlerNegotiateTest, CnameAsync) {
NULL, &request_info, callback.callback(), &token));
EXPECT_EQ(OK, callback.WaitForResult());
#if defined(OS_WIN)
- EXPECT_EQ(L"HTTP/canonical.example.com", auth_handler->spn());
+ EXPECT_EQ("HTTP/canonical.example.com", auth_handler->spn());
#elif defined(OS_POSIX)
- EXPECT_EQ(L"HTTP@canonical.example.com", auth_handler->spn());
+ EXPECT_EQ("HTTP@canonical.example.com", auth_handler->spn());
#endif
}
diff --git a/chromium/net/http/http_auth_handler_ntlm.cc b/chromium/net/http/http_auth_handler_ntlm.cc
index 4c04234e22e..922800c71e1 100644
--- a/chromium/net/http/http_auth_handler_ntlm.cc
+++ b/chromium/net/http/http_auth_handler_ntlm.cc
@@ -89,13 +89,9 @@ int HttpAuthHandlerNTLM::GenerateAuthTokenImpl(
// Base64 encode data in output buffer and prepend "NTLM ".
std::string encode_input(static_cast<char*>(out_buf), out_buf_len);
std::string encode_output;
- bool base64_rv = base::Base64Encode(encode_input, &encode_output);
+ base::Base64Encode(encode_input, &encode_output);
// OK, we are done with |out_buf|
free(out_buf);
- if (!base64_rv) {
- LOG(ERROR) << "Unexpected problem Base64 encoding.";
- return ERR_UNEXPECTED;
- }
*auth_token = std::string("NTLM ") + encode_output;
return OK;
#endif
@@ -136,11 +132,11 @@ HttpAuth::AuthorizationResult HttpAuthHandlerNTLM::ParseChallenge(
}
// static
-std::wstring HttpAuthHandlerNTLM::CreateSPN(const GURL& origin) {
+std::string HttpAuthHandlerNTLM::CreateSPN(const GURL& origin) {
// The service principal name of the destination server. See
// http://msdn.microsoft.com/en-us/library/ms677949%28VS.85%29.aspx
- std::wstring target(L"HTTP/");
- target.append(ASCIIToWide(GetHostAndPort(origin)));
+ std::string target("HTTP/");
+ target.append(GetHostAndPort(origin));
return target;
}
diff --git a/chromium/net/http/http_auth_handler_ntlm.h b/chromium/net/http/http_auth_handler_ntlm.h
index 971dd1fc06f..98bd362d543 100644
--- a/chromium/net/http/http_auth_handler_ntlm.h
+++ b/chromium/net/http/http_auth_handler_ntlm.h
@@ -145,7 +145,7 @@ class NET_EXPORT_PRIVATE HttpAuthHandlerNTLM : public HttpAuthHandler {
uint32* out_token_len);
// Create an NTLM SPN to identify the |origin| server.
- static std::wstring CreateSPN(const GURL& origin);
+ static std::string CreateSPN(const GURL& origin);
#if defined(NTLM_SSPI)
HttpAuthSSPI auth_sspi_;
diff --git a/chromium/net/http/http_auth_sspi_win.cc b/chromium/net/http/http_auth_sspi_win.cc
index abc80508bd8..5718f9ef753 100644
--- a/chromium/net/http/http_auth_sspi_win.cc
+++ b/chromium/net/http/http_auth_sspi_win.cc
@@ -255,7 +255,7 @@ HttpAuth::AuthorizationResult HttpAuthSSPI::ParseChallenge(
}
int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials,
- const std::wstring& spn,
+ const std::string& spn,
std::string* auth_token) {
// Initial challenge.
if (!SecIsValidHandle(&cred_)) {
@@ -280,13 +280,9 @@ int HttpAuthSSPI::GenerateAuthToken(const AuthCredentials* credentials,
// Base64 encode data in output buffer and prepend the scheme.
std::string encode_input(static_cast<char*>(out_buf), out_buf_len);
std::string encode_output;
- bool base64_rv = base::Base64Encode(encode_input, &encode_output);
+ base::Base64Encode(encode_input, &encode_output);
// OK, we are done with |out_buf|
free(out_buf);
- if (!base64_rv) {
- LOG(ERROR) << "Base64 encoding of auth token failed.";
- return ERR_ENCODING_CONVERSION_FAILED;
- }
*auth_token = scheme_ + " " + encode_output;
return OK;
}
@@ -312,7 +308,7 @@ int HttpAuthSSPI::OnFirstRound(const AuthCredentials* credentials) {
}
int HttpAuthSSPI::GetNextSecurityToken(
- const std::wstring& spn,
+ const std::string& spn,
const void* in_token,
int in_token_len,
void** out_token,
@@ -362,10 +358,11 @@ int HttpAuthSSPI::GetNextSecurityToken(
// This returns a token that is passed to the remote server.
DWORD context_attribute;
+ std::wstring spn_wide = base::ASCIIToWide(spn);
SECURITY_STATUS status = library_->InitializeSecurityContext(
&cred_, // phCredential
ctxt_ptr, // phContext
- const_cast<wchar_t *>(spn.c_str()), // pszTargetName
+ const_cast<wchar_t *>(spn_wide.c_str()), // pszTargetName
context_flags, // fContextReq
0, // Reserved1 (must be 0)
SECURITY_NATIVE_DREP, // TargetDataRep
diff --git a/chromium/net/http/http_auth_sspi_win.h b/chromium/net/http/http_auth_sspi_win.h
index 57a3daacfc5..bc7da46c312 100644
--- a/chromium/net/http/http_auth_sspi_win.h
+++ b/chromium/net/http/http_auth_sspi_win.h
@@ -144,7 +144,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI {
// obtained using |*credentials|. If |credentials| is NULL, the credentials
// for the currently logged in user are used instead.
int GenerateAuthToken(const AuthCredentials* credentials,
- const std::wstring& spn,
+ const std::string& spn,
std::string* auth_token);
// Delegation is allowed on the Kerberos ticket. This allows certain servers
@@ -156,7 +156,7 @@ class NET_EXPORT_PRIVATE HttpAuthSSPI {
int OnFirstRound(const AuthCredentials* credentials);
int GetNextSecurityToken(
- const std::wstring& spn,
+ const std::string& spn,
const void* in_token,
int in_token_len,
void** out_token,
diff --git a/chromium/net/http/http_auth_sspi_win_unittest.cc b/chromium/net/http/http_auth_sspi_win_unittest.cc
index d8521375900..09fe6fa25ef 100644
--- a/chromium/net/http/http_auth_sspi_win_unittest.cc
+++ b/chromium/net/http/http_auth_sspi_win_unittest.cc
@@ -82,7 +82,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_TwoRounds) {
// Generate an auth token and create another thing.
std::string auth_token;
- EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com",
+ EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate Zm9vYmFy";
@@ -118,7 +118,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_MissingTokenSecondRound) {
auth_sspi.ParseChallenge(&first_challenge));
std::string auth_token;
- EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com",
+ EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate";
HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
@@ -140,7 +140,7 @@ TEST(HttpAuthSSPITest, ParseChallenge_NonBase64EncodedToken) {
auth_sspi.ParseChallenge(&first_challenge));
std::string auth_token;
- EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, L"HTTP/intranet.google.com",
+ EXPECT_EQ(OK, auth_sspi.GenerateAuthToken(NULL, "HTTP/intranet.google.com",
&auth_token));
std::string second_challenge_text = "Negotiate =happyjoy=";
HttpAuth::ChallengeTokenizer second_challenge(second_challenge_text.begin(),
diff --git a/chromium/net/http/http_basic_state.cc b/chromium/net/http/http_basic_state.cc
new file mode 100644
index 00000000000..2b173b0897b
--- /dev/null
+++ b/chromium/net/http/http_basic_state.cc
@@ -0,0 +1,68 @@
+// 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/http/http_basic_state.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "net/http/http_request_info.h"
+#include "net/http/http_response_body_drainer.h"
+#include "net/http/http_stream_parser.h"
+#include "net/http/http_util.h"
+#include "net/socket/client_socket_handle.h"
+#include "url/gurl.h"
+
+namespace net {
+
+HttpBasicState::HttpBasicState(ClientSocketHandle* connection, bool using_proxy)
+ : read_buf_(new GrowableIOBuffer()),
+ connection_(connection),
+ using_proxy_(using_proxy),
+ request_info_(NULL) {}
+
+HttpBasicState::~HttpBasicState() {}
+
+int HttpBasicState::Initialize(const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback) {
+ DCHECK(!parser_.get());
+ request_info_ = request_info;
+ parser_.reset(new HttpStreamParser(
+ connection_.get(), request_info, read_buf_.get(), net_log));
+ return OK;
+}
+
+scoped_ptr<ClientSocketHandle> HttpBasicState::ReleaseConnection() {
+ return connection_.Pass();
+}
+
+scoped_refptr<GrowableIOBuffer> HttpBasicState::read_buf() const {
+ return read_buf_;
+}
+
+void HttpBasicState::DeleteParser() { parser_.reset(); }
+
+std::string HttpBasicState::GenerateRequestLine() const {
+ static const char kSuffix[] = " HTTP/1.1\r\n";
+ const size_t kSuffixLen = arraysize(kSuffix) - 1;
+ DCHECK(request_info_);
+ const GURL& url = request_info_->url;
+ const std::string path = using_proxy_ ? HttpUtil::SpecForRequest(url)
+ : HttpUtil::PathForRequest(url);
+ // Don't use StringPrintf for concatenation because it is very inefficient.
+ std::string request_line;
+ const size_t expected_size = request_info_->method.size() + 1 + path.size() +
+ kSuffixLen;
+ request_line.reserve(expected_size);
+ request_line.append(request_info_->method);
+ request_line.append(1, ' ');
+ request_line.append(path);
+ request_line.append(kSuffix, kSuffixLen);
+ DCHECK_EQ(expected_size, request_line.size());
+ return request_line;
+}
+
+} // namespace net
diff --git a/chromium/net/http/http_basic_state.h b/chromium/net/http/http_basic_state.h
new file mode 100644
index 00000000000..259c5022252
--- /dev/null
+++ b/chromium/net/http/http_basic_state.h
@@ -0,0 +1,72 @@
+// 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.
+//
+// A class that stores the common state between HttpBasicStream and
+// WebSocketBasicHandshakeStream.
+
+#ifndef NET_HTTP_HTTP_BASIC_STATE_H_
+#define NET_HTTP_HTTP_BASIC_STATE_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_export.h"
+#include "net/base/request_priority.h"
+
+namespace net {
+
+class BoundNetLog;
+class ClientSocketHandle;
+class GrowableIOBuffer;
+class HttpStreamParser;
+struct HttpRequestInfo;
+
+class NET_EXPORT_PRIVATE HttpBasicState {
+ public:
+ HttpBasicState(ClientSocketHandle* connection, bool using_proxy);
+ ~HttpBasicState();
+
+ // Initialize() must be called before using any of the other methods.
+ int Initialize(const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback);
+
+ HttpStreamParser* parser() const { return parser_.get(); }
+
+ bool using_proxy() const { return using_proxy_; }
+
+ // Deletes |parser_| and sets it to NULL.
+ void DeleteParser();
+
+ ClientSocketHandle* connection() const { return connection_.get(); }
+
+ scoped_ptr<ClientSocketHandle> ReleaseConnection();
+
+ scoped_refptr<GrowableIOBuffer> read_buf() const;
+
+ // Generates a string of the form "METHOD PATH HTTP/1.1\r\n", based on the
+ // values of request_info_ and using_proxy_.
+ std::string GenerateRequestLine() const;
+
+ private:
+ scoped_refptr<GrowableIOBuffer> read_buf_;
+
+ scoped_ptr<HttpStreamParser> parser_;
+
+ scoped_ptr<ClientSocketHandle> connection_;
+
+ const bool using_proxy_;
+
+ const HttpRequestInfo* request_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpBasicState);
+};
+
+} // namespace net
+
+#endif // NET_HTTP_HTTP_BASIC_STATE_H_
diff --git a/chromium/net/http/http_basic_state_unittest.cc b/chromium/net/http/http_basic_state_unittest.cc
new file mode 100644
index 00000000000..e95cfd26b59
--- /dev/null
+++ b/chromium/net/http/http_basic_state_unittest.cc
@@ -0,0 +1,78 @@
+// 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/http/http_basic_state.h"
+
+#include "net/base/completion_callback.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_request_info.h"
+#include "net/socket/client_socket_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+TEST(HttpBasicStateTest, ConstructsProperly) {
+ ClientSocketHandle* const handle = new ClientSocketHandle;
+ // Ownership of handle is passed to |state|.
+ const HttpBasicState state(handle, true);
+ EXPECT_EQ(handle, state.connection());
+ EXPECT_TRUE(state.using_proxy());
+}
+
+TEST(HttpBasicStateTest, UsingProxyCanBeFalse) {
+ const HttpBasicState state(new ClientSocketHandle(), false);
+ EXPECT_FALSE(state.using_proxy());
+}
+
+TEST(HttpBasicStateTest, ReleaseConnectionWorks) {
+ ClientSocketHandle* const handle = new ClientSocketHandle;
+ HttpBasicState state(handle, false);
+ const scoped_ptr<ClientSocketHandle> released_connection(
+ state.ReleaseConnection());
+ EXPECT_EQ(NULL, state.connection());
+ EXPECT_EQ(handle, released_connection.get());
+}
+
+TEST(HttpBasicStateTest, InitializeWorks) {
+ HttpBasicState state(new ClientSocketHandle(), false);
+ const HttpRequestInfo request_info;
+ EXPECT_EQ(OK,
+ state.Initialize(
+ &request_info, LOW, BoundNetLog(), CompletionCallback()));
+ EXPECT_TRUE(state.parser());
+}
+
+TEST(HttpBasicStateTest, DeleteParser) {
+ HttpBasicState state(new ClientSocketHandle(), false);
+ const HttpRequestInfo request_info;
+ state.Initialize(&request_info, LOW, BoundNetLog(), CompletionCallback());
+ EXPECT_TRUE(state.parser());
+ state.DeleteParser();
+ EXPECT_EQ(NULL, state.parser());
+}
+
+TEST(HttpBasicStateTest, GenerateRequestLineNoProxy) {
+ const bool use_proxy = false;
+ HttpBasicState state(new ClientSocketHandle(), use_proxy);
+ HttpRequestInfo request_info;
+ request_info.url = GURL("http://www.example.com/path?foo=bar#hoge");
+ request_info.method = "PUT";
+ state.Initialize(&request_info, LOW, BoundNetLog(), CompletionCallback());
+ EXPECT_EQ("PUT /path?foo=bar HTTP/1.1\r\n", state.GenerateRequestLine());
+}
+
+TEST(HttpBasicStateTest, GenerateRequestLineWithProxy) {
+ const bool use_proxy = true;
+ HttpBasicState state(new ClientSocketHandle(), use_proxy);
+ HttpRequestInfo request_info;
+ request_info.url = GURL("http://www.example.com/path?foo=bar#hoge");
+ request_info.method = "PUT";
+ state.Initialize(&request_info, LOW, BoundNetLog(), CompletionCallback());
+ EXPECT_EQ("PUT http://www.example.com/path?foo=bar HTTP/1.1\r\n",
+ state.GenerateRequestLine());
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/http/http_basic_stream.cc b/chromium/net/http/http_basic_stream.cc
index c30e17d6203..87f6469ad61 100644
--- a/chromium/net/http/http_basic_stream.cc
+++ b/chromium/net/http/http_basic_stream.cc
@@ -4,122 +4,107 @@
#include "net/http/http_basic_stream.h"
-#include "base/strings/stringprintf.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
+#include "base/memory/scoped_ptr.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_body_drainer.h"
#include "net/http/http_stream_parser.h"
-#include "net/http/http_util.h"
#include "net/socket/client_socket_handle.h"
namespace net {
HttpBasicStream::HttpBasicStream(ClientSocketHandle* connection,
- HttpStreamParser* parser,
bool using_proxy)
- : read_buf_(new GrowableIOBuffer()),
- parser_(parser),
- connection_(connection),
- using_proxy_(using_proxy),
- request_info_(NULL) {
-}
+ : state_(connection, using_proxy) {}
HttpBasicStream::~HttpBasicStream() {}
-int HttpBasicStream::InitializeStream(
- const HttpRequestInfo* request_info,
- RequestPriority priority,
- const BoundNetLog& net_log,
- const CompletionCallback& callback) {
- DCHECK(!parser_.get());
- request_info_ = request_info;
- parser_.reset(new HttpStreamParser(
- connection_.get(), request_info, read_buf_.get(), net_log));
+int HttpBasicStream::InitializeStream(const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback) {
+ state_.Initialize(request_info, priority, net_log, callback);
return OK;
}
-
int HttpBasicStream::SendRequest(const HttpRequestHeaders& headers,
HttpResponseInfo* response,
const CompletionCallback& callback) {
- DCHECK(parser_.get());
- DCHECK(request_info_);
- const std::string path = using_proxy_ ?
- HttpUtil::SpecForRequest(request_info_->url) :
- HttpUtil::PathForRequest(request_info_->url);
- request_line_ = base::StringPrintf("%s %s HTTP/1.1\r\n",
- request_info_->method.c_str(),
- path.c_str());
- return parser_->SendRequest(request_line_, headers, response, callback);
+ DCHECK(parser());
+ return parser()->SendRequest(
+ state_.GenerateRequestLine(), headers, response, callback);
}
UploadProgress HttpBasicStream::GetUploadProgress() const {
- return parser_->GetUploadProgress();
+ return parser()->GetUploadProgress();
}
int HttpBasicStream::ReadResponseHeaders(const CompletionCallback& callback) {
- return parser_->ReadResponseHeaders(callback);
+ return parser()->ReadResponseHeaders(callback);
}
const HttpResponseInfo* HttpBasicStream::GetResponseInfo() const {
- return parser_->GetResponseInfo();
+ return parser()->GetResponseInfo();
}
-int HttpBasicStream::ReadResponseBody(IOBuffer* buf, int buf_len,
+int HttpBasicStream::ReadResponseBody(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) {
- return parser_->ReadResponseBody(buf, buf_len, callback);
+ return parser()->ReadResponseBody(buf, buf_len, callback);
}
void HttpBasicStream::Close(bool not_reusable) {
- parser_->Close(not_reusable);
+ parser()->Close(not_reusable);
}
HttpStream* HttpBasicStream::RenewStreamForAuth() {
DCHECK(IsResponseBodyComplete());
- DCHECK(!parser_->IsMoreDataBuffered());
- parser_.reset();
- return new HttpBasicStream(connection_.release(), NULL, using_proxy_);
+ DCHECK(!parser()->IsMoreDataBuffered());
+ // The HttpStreamParser object still has a pointer to the connection. Just to
+ // be extra-sure it doesn't touch the connection again, delete it here rather
+ // than leaving it until the destructor is called.
+ state_.DeleteParser();
+ return new HttpBasicStream(state_.ReleaseConnection().release(),
+ state_.using_proxy());
}
bool HttpBasicStream::IsResponseBodyComplete() const {
- return parser_->IsResponseBodyComplete();
+ return parser()->IsResponseBodyComplete();
}
bool HttpBasicStream::CanFindEndOfResponse() const {
- return parser_->CanFindEndOfResponse();
+ return parser()->CanFindEndOfResponse();
}
bool HttpBasicStream::IsConnectionReused() const {
- return parser_->IsConnectionReused();
+ return parser()->IsConnectionReused();
}
-void HttpBasicStream::SetConnectionReused() {
- parser_->SetConnectionReused();
-}
+void HttpBasicStream::SetConnectionReused() { parser()->SetConnectionReused(); }
bool HttpBasicStream::IsConnectionReusable() const {
- return parser_->IsConnectionReusable();
+ return parser()->IsConnectionReusable();
+}
+
+int64 HttpBasicStream::GetTotalReceivedBytes() const {
+ return parser()->received_bytes();
}
bool HttpBasicStream::GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const {
- return connection_->GetLoadTimingInfo(IsConnectionReused(), load_timing_info);
+ return state_.connection()->GetLoadTimingInfo(IsConnectionReused(),
+ load_timing_info);
}
void HttpBasicStream::GetSSLInfo(SSLInfo* ssl_info) {
- parser_->GetSSLInfo(ssl_info);
+ parser()->GetSSLInfo(ssl_info);
}
void HttpBasicStream::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
- parser_->GetSSLCertRequestInfo(cert_request_info);
+ parser()->GetSSLCertRequestInfo(cert_request_info);
}
-bool HttpBasicStream::IsSpdyHttpStream() const {
- return false;
-}
+bool HttpBasicStream::IsSpdyHttpStream() const { return false; }
void HttpBasicStream::Drain(HttpNetworkSession* session) {
HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
diff --git a/chromium/net/http/http_basic_stream.h b/chromium/net/http/http_basic_stream.h
index 2057837e9a9..4a67ccaac00 100644
--- a/chromium/net/http/http_basic_stream.h
+++ b/chromium/net/http/http_basic_stream.h
@@ -12,13 +12,13 @@
#include <string>
#include "base/basictypes.h"
+#include "net/http/http_basic_state.h"
#include "net/http/http_stream.h"
namespace net {
class BoundNetLog;
class ClientSocketHandle;
-class GrowableIOBuffer;
class HttpResponseInfo;
struct HttpRequestInfo;
class HttpRequestHeaders;
@@ -27,13 +27,9 @@ class IOBuffer;
class HttpBasicStream : public HttpStream {
public:
- // Constructs a new HttpBasicStream. If |parser| is NULL, then
- // InitializeStream should be called to initialize it correctly. If
- // |parser| is non-null, then InitializeStream should not be called,
- // as the stream is already initialized.
- HttpBasicStream(ClientSocketHandle* connection,
- HttpStreamParser* parser,
- bool using_proxy);
+ // Constructs a new HttpBasicStream. InitializeStream must be called to
+ // initialize it correctly.
+ HttpBasicStream(ClientSocketHandle* connection, bool using_proxy);
virtual ~HttpBasicStream();
// HttpStream methods:
@@ -52,7 +48,8 @@ class HttpBasicStream : public HttpStream {
virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
- virtual int ReadResponseBody(IOBuffer* buf, int buf_len,
+ virtual int ReadResponseBody(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual void Close(bool not_reusable) OVERRIDE;
@@ -69,6 +66,8 @@ class HttpBasicStream : public HttpStream {
virtual bool IsConnectionReusable() const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
@@ -84,17 +83,9 @@ class HttpBasicStream : public HttpStream {
virtual void SetPriority(RequestPriority priority) OVERRIDE;
private:
- scoped_refptr<GrowableIOBuffer> read_buf_;
-
- scoped_ptr<HttpStreamParser> parser_;
-
- scoped_ptr<ClientSocketHandle> connection_;
-
- bool using_proxy_;
-
- std::string request_line_;
+ HttpStreamParser* parser() const { return state_.parser(); }
- const HttpRequestInfo* request_info_;
+ HttpBasicState state_;
DISALLOW_COPY_AND_ASSIGN(HttpBasicStream);
};
diff --git a/chromium/net/http/http_byte_range.cc b/chromium/net/http/http_byte_range.cc
index 60683c5584f..b43cb2e8008 100644
--- a/chromium/net/http/http_byte_range.cc
+++ b/chromium/net/http/http_byte_range.cc
@@ -4,6 +4,9 @@
#include <algorithm>
+#include "base/format_macros.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
#include "net/http/http_byte_range.h"
namespace {
@@ -21,6 +24,29 @@ HttpByteRange::HttpByteRange()
has_computed_bounds_(false) {
}
+// static
+HttpByteRange HttpByteRange::Bounded(int64 first_byte_position,
+ int64 last_byte_position) {
+ HttpByteRange range;
+ range.set_first_byte_position(first_byte_position);
+ range.set_last_byte_position(last_byte_position);
+ return range;
+}
+
+// static
+HttpByteRange HttpByteRange::RightUnbounded(int64 first_byte_position) {
+ HttpByteRange range;
+ range.set_first_byte_position(first_byte_position);
+ return range;
+}
+
+// static
+HttpByteRange HttpByteRange::Suffix(int64 suffix_length) {
+ HttpByteRange range;
+ range.set_suffix_length(suffix_length);
+ return range;
+}
+
bool HttpByteRange::IsSuffixByteRange() const {
return suffix_length_ != kPositionNotSpecified;
}
@@ -41,6 +67,21 @@ bool HttpByteRange::IsValid() const {
last_byte_position_ >= first_byte_position_));
}
+std::string HttpByteRange::GetHeaderValue() const {
+ DCHECK(IsValid());
+
+ if (IsSuffixByteRange())
+ return base::StringPrintf("bytes=-%" PRId64, suffix_length());
+
+ DCHECK(HasFirstBytePosition());
+
+ if (!HasLastBytePosition())
+ return base::StringPrintf("bytes=%" PRId64 "-", first_byte_position());
+
+ return base::StringPrintf("bytes=%" PRId64 "-%" PRId64,
+ first_byte_position(), last_byte_position());
+}
+
bool HttpByteRange::ComputeBounds(int64 size) {
if (size < 0)
return false;
diff --git a/chromium/net/http/http_byte_range.h b/chromium/net/http/http_byte_range.h
index 2c06434439d..98708721a4f 100644
--- a/chromium/net/http/http_byte_range.h
+++ b/chromium/net/http/http_byte_range.h
@@ -5,6 +5,8 @@
#ifndef NET_HTTP_HTTP_BYTE_RANGE_H_
#define NET_HTTP_HTTP_BYTE_RANGE_H_
+#include <string>
+
#include "base/basictypes.h"
#include "net/base/net_export.h"
@@ -17,10 +19,16 @@ class NET_EXPORT HttpByteRange {
public:
HttpByteRange();
+ // Convenience constructors.
+ static HttpByteRange Bounded(int64 first_byte_position,
+ int64 last_byte_position);
+ static HttpByteRange RightUnbounded(int64 first_byte_position);
+ static HttpByteRange Suffix(int64 suffix_length);
+
// Since this class is POD, we use constructor, assignment operator
// and destructor provided by compiler.
int64 first_byte_position() const { return first_byte_position_; }
- void set_first_byte_position(int64 value) { first_byte_position_ = value; }
+ void set_first_byte_position(int64 value) { first_byte_position_ = value; }
int64 last_byte_position() const { return last_byte_position_; }
void set_last_byte_position(int64 value) { last_byte_position_ = value; }
@@ -38,6 +46,10 @@ class NET_EXPORT HttpByteRange {
// Returns true if this range is valid.
bool IsValid() const;
+ // Gets the header string, e.g. "bytes=0-100", "bytes=100-", "bytes=-100".
+ // Assumes range is valid.
+ std::string GetHeaderValue() const;
+
// A method that when given the size in bytes of a file, adjust the internal
// |first_byte_position_| and |last_byte_position_| values according to the
// range specified by this object. If the range specified is invalid with
diff --git a/chromium/net/http/http_byte_range_unittest.cc b/chromium/net/http/http_byte_range_unittest.cc
index 6629a7c3c59..5dc6e5237f3 100644
--- a/chromium/net/http/http_byte_range_unittest.cc
+++ b/chromium/net/http/http_byte_range_unittest.cc
@@ -76,3 +76,17 @@ TEST(HttpByteRangeTest, SetInstanceSize) {
}
}
}
+
+TEST(HttpByteRangeTest, GetHeaderValue) {
+ static const struct {
+ net::HttpByteRange range;
+ const char* expected;
+ } tests[] = {{net::HttpByteRange::Bounded(0, 0), "bytes=0-0"},
+ {net::HttpByteRange::Bounded(0, 100), "bytes=0-100"},
+ {net::HttpByteRange::Bounded(0, -1), "bytes=0-"},
+ {net::HttpByteRange::RightUnbounded(100), "bytes=100-"},
+ {net::HttpByteRange::Suffix(100), "bytes=-100"}, };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ EXPECT_EQ(tests[i].expected, tests[i].range.GetHeaderValue());
+ }
+}
diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc
index 83efcb135cd..88fb53a69c4 100644
--- a/chromium/net/http/http_cache_transaction.cc
+++ b/chromium/net/http/http_cache_transaction.cc
@@ -101,6 +101,23 @@ void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) {
}
}
+// TODO(rvargas): Remove once we get the data.
+void RecordVaryHeaderHistogram(const net::HttpResponseInfo* response) {
+ enum VaryType {
+ VARY_NOT_PRESENT,
+ VARY_UA,
+ VARY_OTHER,
+ VARY_MAX
+ };
+ VaryType vary = VARY_NOT_PRESENT;
+ if (response->vary_data.is_valid()) {
+ vary = VARY_OTHER;
+ if (response->headers->HasHeaderValue("vary", "user-agent"))
+ vary = VARY_UA;
+ }
+ UMA_HISTOGRAM_ENUMERATION("HttpCache.Vary", vary, VARY_MAX);
+}
+
} // namespace
namespace net {
@@ -196,7 +213,8 @@ HttpCache::Transaction::Transaction(
io_callback_(base::Bind(&Transaction::OnIOComplete,
weak_factory_.GetWeakPtr())),
transaction_pattern_(PATTERN_UNDEFINED),
- transaction_delegate_(transaction_delegate) {
+ transaction_delegate_(transaction_delegate),
+ websocket_handshake_stream_base_create_helper_(NULL) {
COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
arraysize(kValidationHeaders),
Invalid_number_of_validation_headers);
@@ -516,6 +534,13 @@ void HttpCache::Transaction::SetPriority(RequestPriority priority) {
network_trans_->SetPriority(priority_);
}
+void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
+ websocket_handshake_stream_base_create_helper_ = create_helper;
+ if (network_trans_)
+ network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
+}
+
//-----------------------------------------------------------------------------
void HttpCache::Transaction::DoCallback(int rv) {
@@ -843,6 +868,10 @@ int HttpCache::Transaction::DoSendRequest() {
// Old load timing information, if any, is now obsolete.
old_network_trans_load_timing_.reset();
+ if (websocket_handshake_stream_base_create_helper_)
+ network_trans_->SetWebSocketHandshakeStreamCreateHelper(
+ websocket_handshake_stream_base_create_helper_);
+
ReportNetworkActionStart();
next_state_ = STATE_SEND_REQUEST_COMPLETE;
rv = network_trans_->Start(request_, io_callback_, net_log_);
@@ -963,6 +992,8 @@ int HttpCache::Transaction::DoSuccessfulSendRequest() {
cache_->DoomMainEntryForUrl(request_->url);
}
+ RecordVaryHeaderHistogram(new_response);
+
// Are we expecting a response to a conditional query?
if (mode_ == READ_WRITE || mode_ == UPDATE) {
if (new_response->headers->response_code() == 304 || handling_206_) {
@@ -1499,20 +1530,12 @@ int HttpCache::Transaction::DoCacheQueryData() {
}
int HttpCache::Transaction::DoCacheQueryDataComplete(int result) {
-#if defined(OS_ANDROID)
if (result == ERR_NOT_IMPLEMENTED) {
// Restart the request overwriting the cache entry.
- //
- // Note: this would have fixed range requests for debug builds on all OSes,
- // not just Android, but karen@ prefers to limit the effect based on OS for
- // cherry-picked fixes.
- // TODO(pasko): remove the OS_ANDROID limitation as soon as the fix proves
- // useful after the cherry-pick.
// TODO(pasko): remove this workaround as soon as the SimpleBackendImpl
// supports Sparse IO.
return DoRestartPartialRequest();
}
-#endif
DCHECK_EQ(OK, result);
if (!cache_.get())
return ERR_UNEXPECTED;
@@ -2388,6 +2411,8 @@ bool HttpCache::Transaction::CanResume(bool has_data) {
if (request_->method != "GET")
return false;
+ // Note that if this is a 206, content-length was already fixed after calling
+ // PartialData::ResponseHeadersOK().
if (response_.headers->GetContentLength() <= 0 ||
response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
!response_.headers->HasStrongValidators()) {
diff --git a/chromium/net/http/http_cache_transaction.h b/chromium/net/http/http_cache_transaction.h
index b1f32bd820d..90c4db5a39c 100644
--- a/chromium/net/http/http_cache_transaction.h
+++ b/chromium/net/http/http_cache_transaction.h
@@ -130,6 +130,8 @@ class HttpCache::Transaction : public HttpTransaction {
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
virtual void SetPriority(RequestPriority priority) OVERRIDE;
+ virtual void SetWebSocketHandshakeStreamCreateHelper(
+ net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE;
private:
static const size_t kNumValidationHeaders = 2;
@@ -433,6 +435,15 @@ class HttpCache::Transaction : public HttpTransaction {
// 304 and 206 response cases, as the network transaction may be destroyed
// before the caller requests load timing information.
scoped_ptr<LoadTimingInfo> old_network_trans_load_timing_;
+
+ // The helper object to use to create WebSocketHandshakeStreamBase
+ // objects. Only relevant when establishing a WebSocket connection.
+ // This is passed to the underlying network transaction. It is stored here in
+ // case the transaction does not exist yet.
+ WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_handshake_stream_base_create_helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(Transaction);
};
} // namespace net
diff --git a/chromium/net/http/http_cache_unittest.cc b/chromium/net/http/http_cache_unittest.cc
index e47852c01ac..aa6056a4177 100644
--- a/chromium/net/http/http_cache_unittest.cc
+++ b/chromium/net/http/http_cache_unittest.cc
@@ -31,7 +31,9 @@
#include "net/http/http_transaction_unittest.h"
#include "net/http/http_util.h"
#include "net/http/mock_http_cache.h"
+#include "net/socket/client_socket_handle.h"
#include "net/ssl/ssl_cert_request_info.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::Time;
@@ -574,6 +576,21 @@ struct Context {
scoped_ptr<net::HttpTransaction> trans;
};
+class FakeWebSocketHandshakeStreamCreateHelper
+ : public net::WebSocketHandshakeStreamBase::CreateHelper {
+ public:
+ virtual ~FakeWebSocketHandshakeStreamCreateHelper() {}
+ virtual net::WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<net::ClientSocketHandle> connect, bool using_proxy) OVERRIDE {
+ return NULL;
+ }
+ virtual net::WebSocketHandshakeStreamBase* CreateSpdyStream(
+ const base::WeakPtr<net::SpdySession>& session,
+ bool use_relative_url) OVERRIDE {
+ return NULL;
+ }
+};
+
} // namespace
@@ -2785,7 +2802,7 @@ TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Hit) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, kUploadId);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), kUploadId);
MockHttpRequest request(transaction);
request.upload_data_stream = &upload_data_stream;
@@ -2816,7 +2833,7 @@ TEST(HttpCache, SimplePOST_WithRanges) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, kUploadId);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), kUploadId);
MockHttpRequest request(transaction);
request.upload_data_stream = &upload_data_stream;
@@ -2835,7 +2852,7 @@ TEST(HttpCache, SimplePOST_SeparateCache) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 1);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 1);
MockTransaction transaction(kSimplePOST_Transaction);
MockHttpRequest req1(transaction);
@@ -2874,7 +2891,7 @@ TEST(HttpCache, SimplePOST_Invalidate_205) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 1);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 1);
transaction.method = "POST";
transaction.status = "HTTP/1.1 205 No Content";
@@ -2913,7 +2930,7 @@ TEST(HttpCache, SimplePOST_NoUploadId_Invalidate_205) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
transaction.method = "POST";
transaction.status = "HTTP/1.1 205 No Content";
@@ -2944,7 +2961,7 @@ TEST(HttpCache, SimplePOST_NoUploadId_NoBackend) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
MockTransaction transaction(kSimplePOST_Transaction);
AddMockTransaction(&transaction);
@@ -2973,7 +2990,7 @@ TEST(HttpCache, SimplePOST_DontInvalidate_100) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 1);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 1);
transaction.method = "POST";
transaction.status = "HTTP/1.1 100 Continue";
@@ -3003,7 +3020,7 @@ TEST(HttpCache, SimplePUT_Miss) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
MockHttpRequest request(transaction);
request.upload_data_stream = &upload_data_stream;
@@ -3032,7 +3049,7 @@ TEST(HttpCache, SimplePUT_Invalidate) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
transaction.method = "PUT";
MockHttpRequest req2(transaction);
@@ -3068,7 +3085,7 @@ TEST(HttpCache, SimplePUT_Invalidate_305) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
transaction.method = "PUT";
transaction.status = "HTTP/1.1 305 Use Proxy";
@@ -3106,7 +3123,7 @@ TEST(HttpCache, SimplePUT_DontInvalidate_404) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
transaction.method = "PUT";
transaction.status = "HTTP/1.1 404 Not Found";
@@ -3136,7 +3153,7 @@ TEST(HttpCache, SimpleDELETE_Miss) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
MockHttpRequest request(transaction);
request.upload_data_stream = &upload_data_stream;
@@ -3165,7 +3182,7 @@ TEST(HttpCache, SimpleDELETE_Invalidate) {
ScopedVector<net::UploadElementReader> element_readers;
element_readers.push_back(new net::UploadBytesElementReader("hello", 5));
- net::UploadDataStream upload_data_stream(&element_readers, 0);
+ net::UploadDataStream upload_data_stream(element_readers.Pass(), 0);
transaction.method = "DELETE";
MockHttpRequest req2(transaction);
@@ -3395,6 +3412,37 @@ TEST(HttpCache, RangeGET_NoStrongValidators) {
RemoveMockTransaction(&transaction);
}
+// Tests that we cache partial responses that lack content-length.
+TEST(HttpCache, RangeGET_NoContentLength) {
+ MockHttpCache cache;
+ std::string headers;
+
+ // Attempt to write to the cache (40-49).
+ MockTransaction transaction(kRangeGET_TransactionOK);
+ AddMockTransaction(&transaction);
+ transaction.response_headers = "ETag: \"foo\"\n"
+ "Accept-Ranges: bytes\n"
+ "Content-Range: bytes 40-49/80\n";
+ transaction.handler = NULL;
+ RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers);
+
+ EXPECT_EQ(1, cache.network_layer()->transaction_count());
+ EXPECT_EQ(0, cache.disk_cache()->open_count());
+ EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+ // Now verify that there's no cached data.
+ transaction.handler = &RangeTransactionServer::RangeHandler;
+ RunTransactionTestWithResponse(cache.http_cache(), kRangeGET_TransactionOK,
+ &headers);
+
+ Verify206Response(headers, 40, 49);
+ EXPECT_EQ(2, cache.network_layer()->transaction_count());
+ EXPECT_EQ(1, cache.disk_cache()->open_count());
+ EXPECT_EQ(1, cache.disk_cache()->create_count());
+
+ RemoveMockTransaction(&transaction);
+}
+
// Tests that we can cache range requests and fetch random blocks from the
// cache and the network.
TEST(HttpCache, RangeGET_OK) {
@@ -3455,8 +3503,6 @@ TEST(HttpCache, RangeGET_OK) {
RemoveMockTransaction(&kRangeGET_TransactionOK);
}
-#if defined(OS_ANDROID)
-
// Checks that with a cache backend having Sparse IO unimplementes the cache
// entry would be doomed after a range request.
// TODO(pasko): remove when the SimpleBackendImpl implements Sparse IO.
@@ -3529,8 +3575,6 @@ TEST(HttpCache, RangeGET_SparseNotImplementedOnEmptyCache) {
RemoveMockTransaction(&transaction);
}
-#endif // OS_ANDROID
-
// Tests that we can cache range requests and fetch random blocks from the
// cache and the network, with synchronous responses.
TEST(HttpCache, RangeGET_SyncOK) {
@@ -6271,6 +6315,35 @@ TEST(HttpCache, SetPriority) {
EXPECT_EQ(net::OK, callback.WaitForResult());
}
+// Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache
+// transaction passes on its argument to the underlying network transaction.
+TEST(HttpCache, SetWebSocketHandshakeStreamCreateHelper) {
+ MockHttpCache cache;
+
+ FakeWebSocketHandshakeStreamCreateHelper create_helper;
+ scoped_ptr<net::HttpTransaction> trans;
+ EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(
+ net::IDLE, &trans, NULL));
+ ASSERT_TRUE(trans.get());
+
+ EXPECT_FALSE(cache.network_layer()->last_transaction());
+
+ net::HttpRequestInfo info;
+ info.url = GURL(kSimpleGET_Transaction.url);
+ net::TestCompletionCallback callback;
+ EXPECT_EQ(net::ERR_IO_PENDING,
+ trans->Start(&info, callback.callback(), net::BoundNetLog()));
+
+ ASSERT_TRUE(cache.network_layer()->last_transaction());
+ EXPECT_FALSE(cache.network_layer()->last_transaction()->
+ websocket_handshake_stream_create_helper());
+ trans->SetWebSocketHandshakeStreamCreateHelper(&create_helper);
+ EXPECT_EQ(&create_helper,
+ cache.network_layer()->last_transaction()->
+ websocket_handshake_stream_create_helper());
+ EXPECT_EQ(net::OK, callback.WaitForResult());
+}
+
// Make sure that a cache transaction passes on its priority to
// newly-created network transactions.
TEST(HttpCache, SetPriorityNewTransaction) {
diff --git a/chromium/net/http/http_chunked_decoder.cc b/chromium/net/http/http_chunked_decoder.cc
index ca07f24de06..0d8be9f7cd2 100644
--- a/chromium/net/http/http_chunked_decoder.cc
+++ b/chromium/net/http/http_chunked_decoder.cc
@@ -44,6 +44,8 @@
#include "net/http/http_chunked_decoder.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/net/http/http_network_layer.cc b/chromium/net/http/http_network_layer.cc
index e4d082eb0fd..7d3f1588006 100644
--- a/chromium/net/http/http_network_layer.cc
+++ b/chromium/net/http/http_network_layer.cc
@@ -5,6 +5,7 @@
#include "net/http/http_network_layer.h"
#include "base/logging.h"
+#include "base/power_monitor/power_monitor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -23,9 +24,19 @@ HttpNetworkLayer::HttpNetworkLayer(HttpNetworkSession* session)
: session_(session),
suspended_(false) {
DCHECK(session_.get());
+#if defined(OS_WIN)
+ base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+ if (power_monitor)
+ power_monitor->AddObserver(this);
+#endif
}
HttpNetworkLayer::~HttpNetworkLayer() {
+#if defined(OS_WIN)
+ base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+ if (power_monitor)
+ power_monitor->RemoveObserver(this);
+#endif
}
//-----------------------------------------------------------------------------
@@ -42,7 +53,7 @@ HttpTransactionFactory* HttpNetworkLayer::CreateFactory(
void HttpNetworkLayer::ForceAlternateProtocol() {
PortAlternateProtocolPair pair;
pair.port = 443;
- pair.protocol = NPN_SPDY_2;
+ pair.protocol = NPN_SPDY_3;
HttpServerPropertiesImpl::ForceAlternateProtocol(pair);
}
diff --git a/chromium/net/http/http_network_layer.h b/chromium/net/http/http_network_layer.h
index 4b41b7190e8..c4c41aec43e 100644
--- a/chromium/net/http/http_network_layer.h
+++ b/chromium/net/http/http_network_layer.h
@@ -7,6 +7,8 @@
#include <string>
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/power_monitor/power_observer.h"
@@ -36,7 +38,7 @@ class NET_EXPORT HttpNetworkLayer
// when network session is shared.
static HttpTransactionFactory* CreateFactory(HttpNetworkSession* session);
- // Forces an alternate protocol of SPDY/2 on port 443.
+ // Forces an alternate protocol of SPDY/3 on port 443.
// TODO(rch): eliminate this method.
static void ForceAlternateProtocol();
@@ -54,6 +56,8 @@ class NET_EXPORT HttpNetworkLayer
private:
const scoped_refptr<HttpNetworkSession> session_;
bool suspended_;
+
+ DISALLOW_COPY_AND_ASSIGN(HttpNetworkLayer);
};
} // namespace net
diff --git a/chromium/net/http/http_network_layer_unittest.cc b/chromium/net/http/http_network_layer_unittest.cc
index 6d2ea358071..98b8d4eaf44 100644
--- a/chromium/net/http/http_network_layer_unittest.cc
+++ b/chromium/net/http/http_network_layer_unittest.cc
@@ -4,6 +4,7 @@
#include "net/http/http_network_layer.h"
+#include "base/basictypes.h"
#include "base/strings/stringprintf.h"
#include "net/base/net_log.h"
#include "net/cert/mock_cert_verifier.h"
@@ -48,14 +49,27 @@ class HttpNetworkLayerTest : public PlatformTest {
factory_.reset(new HttpNetworkLayer(network_session_.get()));
}
- void ExecuteRequestExpectingContentAndHeader(const std::string& content,
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ std::string GetChromeProxy() {
+ return HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString();
+ }
+#endif
+
+#if defined(SPDY_PROXY_AUTH_ORIGIN) && defined(DATA_REDUCTION_FALLBACK_HOST)
+ std::string GetChromeFallbackProxy() {
+ return HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
+ }
+#endif
+
+ void ExecuteRequestExpectingContentAndHeader(const std::string& method,
+ const std::string& content,
const std::string& header,
const std::string& value) {
TestCompletionCallback callback;
HttpRequestInfo request_info;
request_info.url = GURL("http://www.google.com/");
- request_info.method = "GET";
+ request_info.method = method;
request_info.load_flags = LOAD_NORMAL;
scoped_ptr<HttpTransaction> trans;
@@ -80,68 +94,105 @@ class HttpNetworkLayerTest : public PlatformTest {
}
// Check that |proxy_count| proxies are in the retry list.
- // These will be, in order, "bad:8080" and "alsobad:8080".
- void TestBadProxies(unsigned int proxy_count) {
+ // These will be, in order, |bad_proxy| and |bad_proxy2|".
+ void TestBadProxies(unsigned int proxy_count, const std::string& bad_proxy,
+ const std::string& bad_proxy2) {
const ProxyRetryInfoMap& retry_info = proxy_service_->proxy_retry_info();
ASSERT_EQ(proxy_count, retry_info.size());
- ASSERT_TRUE(retry_info.find("bad:8080") != retry_info.end());
+ if (proxy_count > 0)
+ ASSERT_TRUE(retry_info.find(bad_proxy) != retry_info.end());
if (proxy_count > 1)
- ASSERT_TRUE(retry_info.find("alsobad:8080") != retry_info.end());
+ ASSERT_TRUE(retry_info.find(bad_proxy2) != retry_info.end());
}
// Simulates a request through a proxy which returns a bypass, which is then
// retried through a second proxy that doesn't bypass.
// Checks that the expected requests were issued, the expected content was
- // recieved, and the first proxy ("bad:8080") was marked as bad.
- void TestProxyFallback() {
+ // recieved, and the first proxy |bad_proxy| was marked as bad.
+ void TestProxyFallback(const std::string& bad_proxy) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: proxy-bypass\r\n\r\n"),
+ "Chrome-Proxy: bypass=0\r\n\r\n"),
MockRead("Bypass message"),
MockRead(SYNCHRONOUS, OK),
};
+ TestProxyFallbackWithMockReads(bad_proxy, "", data_reads,
+ arraysize(data_reads), 1u);
+ }
+
+ void TestProxyFallbackWithMockReads(const std::string& bad_proxy,
+ const std::string& bad_proxy2,
+ MockRead data_reads[],
+ int data_reads_size,
+ unsigned int expected_retry_info_size) {
+ TestProxyFallbackByMethodWithMockReads(bad_proxy, bad_proxy2, data_reads,
+ data_reads_size, "GET", "content",
+ true, expected_retry_info_size);
+ }
+
+ void TestProxyFallbackByMethodWithMockReads(
+ const std::string& bad_proxy,
+ const std::string& bad_proxy2,
+ MockRead data_reads[],
+ int data_reads_size,
+ std::string method,
+ std::string content,
+ bool retry_expected,
+ unsigned int expected_retry_info_size) {
+ std::string trailer =
+ (method == "HEAD" || method == "PUT" || method == "POST") ?
+ "Content-Length: 0\r\n\r\n" : "\r\n";
+ std::string request =
+ base::StringPrintf("%s http://www.google.com/ HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n"
+ "%s", method.c_str(), trailer.c_str());
+
MockWrite data_writes[] = {
- MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
+ MockWrite(request.c_str()),
};
- StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
+ StaticSocketDataProvider data1(data_reads, data_reads_size,
data_writes, arraysize(data_writes));
mock_socket_factory_.AddSocketDataProvider(&data1);
// Second data provider returns the expected content.
- MockRead data_reads2[] = {
- MockRead("HTTP/1.0 200 OK\r\n"
- "Server: not-proxy\r\n\r\n"),
- MockRead("content"),
- MockRead(SYNCHRONOUS, OK),
- };
+ MockRead data_reads2[3];
+ size_t data_reads2_index = 0;
+ data_reads2[data_reads2_index++] = MockRead("HTTP/1.0 200 OK\r\n"
+ "Server: not-proxy\r\n\r\n");
+ if (!content.empty())
+ data_reads2[data_reads2_index++] = MockRead(content.c_str());
+ data_reads2[data_reads2_index++] = MockRead(SYNCHRONOUS, OK);
+
MockWrite data_writes2[] = {
- MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
+ MockWrite(request.c_str()),
};
- StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
+ StaticSocketDataProvider data2(data_reads2, data_reads2_index,
data_writes2, arraysize(data_writes2));
mock_socket_factory_.AddSocketDataProvider(&data2);
// Expect that we get "content" and not "Bypass message", and that there's
// a "not-proxy" "Server:" header in the final response.
- ExecuteRequestExpectingContentAndHeader("content", "server", "not-proxy");
+ if (retry_expected) {
+ ExecuteRequestExpectingContentAndHeader(method, content,
+ "server", "not-proxy");
+ } else {
+ ExecuteRequestExpectingContentAndHeader(method, content, "", "");
+ }
// We should also observe the bad proxy in the retry list.
- TestBadProxies(1u);
+ TestBadProxies(expected_retry_info_size, bad_proxy, bad_proxy2);
}
// Simulates a request through a proxy which returns a bypass, which is then
// retried through a direct connection to the origin site.
// Checks that the expected requests were issued, the expected content was
- // received, and the proxy ("bad:8080") was marked as bad.
- void TestProxyFallbackToDirect() {
+ // received, and the proxy |bad_proxy| was marked as bad.
+ void TestProxyFallbackToDirect(const std::string& bad_proxy) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: proxy-bypass\r\n\r\n"),
+ "Chrome-Proxy: bypass=0\r\n\r\n"),
MockRead("Bypass message"),
MockRead(SYNCHRONOUS, OK),
};
@@ -172,10 +223,11 @@ class HttpNetworkLayerTest : public PlatformTest {
// Expect that we get "content" and not "Bypass message", and that there's
// a "not-proxy" "Server:" header in the final response.
- ExecuteRequestExpectingContentAndHeader("content", "server", "not-proxy");
+ ExecuteRequestExpectingContentAndHeader("GET", "content",
+ "server", "not-proxy");
// We should also observe the bad proxy in the retry list.
- TestBadProxies(1u);
+ TestBadProxies(1u, bad_proxy, "");
}
// Simulates a request through a proxy which returns a bypass, under a
@@ -183,10 +235,12 @@ class HttpNetworkLayerTest : public PlatformTest {
// are expected to be configured.
// Checks that the expected requests were issued, the bypass message was the
// final received content, and all proxies were marked as bad.
- void TestProxyFallbackFail(unsigned int proxy_count) {
+ void TestProxyFallbackFail(unsigned int proxy_count,
+ const std::string& bad_proxy,
+ const std::string& bad_proxy2) {
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: proxy-bypass\r\n\r\n"),
+ "Chrome-Proxy: bypass=0\r\n\r\n"),
MockRead("Bypass message"),
MockRead(SYNCHRONOUS, OK),
};
@@ -205,10 +259,10 @@ class HttpNetworkLayerTest : public PlatformTest {
mock_socket_factory_.AddSocketDataProvider(&data2);
// Expect that we get "Bypass message", and not "content"..
- ExecuteRequestExpectingContentAndHeader("Bypass message", "", "");
+ ExecuteRequestExpectingContentAndHeader("GET", "Bypass message", "", "");
// We should also observe the bad proxy or proxies in the retry list.
- TestBadProxies(proxy_count);
+ TestBadProxies(proxy_count, bad_proxy, bad_proxy2);
}
MockClientSocketFactory mock_socket_factory_;
@@ -289,7 +343,7 @@ TEST_F(HttpNetworkLayerTest, GET) {
}
// Proxy bypass tests. These tests run through various server-induced
-// proxy-bypass scenarios using both PAC file and fixed proxy params.
+// proxy bypass scenarios using both PAC file and fixed proxy params.
// The test scenarios are:
// - bypass with two proxies configured and the first but not the second
// is bypassed.
@@ -299,55 +353,133 @@ TEST_F(HttpNetworkLayerTest, GET) {
// - bypass with one proxy configured which is bypassed with no defined
// fallback
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassPac) {
+ std::string bad_proxy = GetChromeProxy();
ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY bad:8080; PROXY good:8080"));
- TestProxyFallback();
+ "PROXY " + bad_proxy + "; PROXY good:8080"));
+ TestProxyFallback(bad_proxy);
}
TEST_F(HttpNetworkLayerTest, ServerTwoProxyBypassFixed) {
- ConfigureTestDependencies(ProxyService::CreateFixed("bad:8080, good:8080"));
- TestProxyFallback();
+ std::string bad_proxy = GetChromeProxy();
+ ConfigureTestDependencies(
+ ProxyService::CreateFixed(bad_proxy +", good:8080"));
+ TestProxyFallback(bad_proxy);
+}
+
+TEST_F(HttpNetworkLayerTest, BypassAndRetryIdempotentMethods) {
+ std::string bad_proxy = GetChromeProxy();
+ const struct {
+ std::string method;
+ std::string content;
+ bool expected_to_retry;
+ } tests[] = {
+ {
+ "GET",
+ "content",
+ true,
+ },
+ {
+ "OPTIONS",
+ "content",
+ true,
+ },
+ {
+ "HEAD",
+ "",
+ true,
+ },
+ {
+ "PUT",
+ "",
+ true,
+ },
+ {
+ "DELETE",
+ "content",
+ true,
+ },
+ {
+ "TRACE",
+ "content",
+ true,
+ },
+ {
+ "POST",
+ "Bypass message",
+ false,
+ },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ ConfigureTestDependencies(
+ ProxyService::CreateFixed(bad_proxy +", good:8080"));
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"
+ "Chrome-Proxy: bypass=0\r\n\r\n"),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ TestProxyFallbackByMethodWithMockReads(bad_proxy, "", data_reads,
+ arraysize(data_reads),
+ tests[i].method,
+ tests[i].content,
+ tests[i].expected_to_retry, 1u);
+ }
}
TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassPac) {
+ std::string bad_proxy = GetChromeProxy();
ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY bad:8080; DIRECT"));
- TestProxyFallbackToDirect();
+ "PROXY " + bad_proxy + "; DIRECT"));
+ TestProxyFallbackToDirect(bad_proxy);
}
TEST_F(HttpNetworkLayerTest, ServerOneProxyWithDirectBypassFixed) {
- ConfigureTestDependencies(ProxyService::CreateFixed( "bad:8080, direct://"));
- TestProxyFallbackToDirect();
+ std::string bad_proxy = GetChromeProxy();
+ ConfigureTestDependencies(
+ ProxyService::CreateFixed(bad_proxy + ", direct://"));
+ TestProxyFallbackToDirect(bad_proxy);
}
+#if defined(DATA_REDUCTION_FALLBACK_HOST)
TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassPac) {
+ std::string bad_proxy = GetChromeProxy();
+ std::string bad_proxy2 =
+ HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY bad:8080; PROXY alsobad:8080"));
- TestProxyFallbackFail(2u);
+ "PROXY " + bad_proxy + "; PROXY " + bad_proxy2));
+ TestProxyFallbackFail(2u, bad_proxy, bad_proxy2);
}
TEST_F(HttpNetworkLayerTest, ServerTwoProxyDoubleBypassFixed) {
+ std::string bad_proxy = GetChromeProxy();
+ std::string bad_proxy2 =
+ HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)).ToString();
ConfigureTestDependencies(ProxyService::CreateFixed(
- "bad:8080, alsobad:8080"));
- TestProxyFallbackFail(2u);
+ bad_proxy + ", " + bad_proxy2));
+ TestProxyFallbackFail(2u, bad_proxy, bad_proxy2);
}
+#endif
TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassPac) {
+ std::string bad_proxy = GetChromeProxy();
ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
- "PROXY bad:8080"));
- TestProxyFallbackFail(1u);
+ "PROXY " + bad_proxy));
+ TestProxyFallbackFail(1u, bad_proxy, "");
}
TEST_F(HttpNetworkLayerTest, ServerOneProxyNoDirectBypassFixed) {
- ConfigureTestDependencies(ProxyService::CreateFixed("bad:8080"));
- TestProxyFallbackFail(1u);
+ std::string bad_proxy = GetChromeProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixed(bad_proxy));
+ TestProxyFallbackFail(1u, bad_proxy, "");
}
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
-TEST_F(HttpNetworkLayerTest, ServerFallbackOnInternalServerError) {
- // Verify that "500 Internal Server Error" via the data reduction proxy
- // induces proxy fallback to a second proxy, if configured.
+TEST_F(HttpNetworkLayerTest, ServerFallbackOn5xxError) {
+ // Verify that "500 Internal Server Error", "502 Bad Gateway", and
+ // "503 Service Unavailable" via the data reduction proxy induce proxy
+ // fallback to a second proxy, if configured.
// To configure this test, we need to wire up a custom proxy service to use
// a pair of proxies. We'll induce fallback via the first and return
@@ -356,79 +488,92 @@ TEST_F(HttpNetworkLayerTest, ServerFallbackOnInternalServerError) {
HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)).ToString());
std::string pac_string = base::StringPrintf(
"PROXY %s; PROXY good:8080", data_reduction_proxy.data());
- ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(pac_string));
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 500 Internal Server Error\r\n\r\n"),
- MockRead("Bypass message"),
- MockRead(SYNCHRONOUS, OK),
- };
- MockWrite data_writes[] = {
- MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
+ std::string headers[] = {
+ "HTTP/1.1 500 Internal Server Error\r\n\r\n",
+ "HTTP/1.1 502 Bad Gateway\r\n\r\n",
+ "HTTP/1.1 503 Service Unavailable\r\n\r\n"
};
- StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
- data_writes, arraysize(data_writes));
- mock_socket_factory_.AddSocketDataProvider(&data1);
- // Second data provider returns the expected content.
- MockRead data_reads2[] = {
- MockRead("HTTP/1.0 200 OK\r\n"
- "Server: not-proxy\r\n\r\n"),
- MockRead("content"),
- MockRead(SYNCHRONOUS, OK),
- };
- MockWrite data_writes2[] = {
- MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Proxy-Connection: keep-alive\r\n\r\n"),
- };
- StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
- data_writes2, arraysize(data_writes2));
- mock_socket_factory_.AddSocketDataProvider(&data2);
+ for (size_t i = 0; i < arraysize(headers); ++i) {
+ ConfigureTestDependencies(
+ ProxyService::CreateFixedFromPacResult(pac_string));
- TestCompletionCallback callback;
+ MockRead data_reads[] = {
+ MockRead(headers[i].c_str()),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
- HttpRequestInfo request_info;
- request_info.url = GURL("http://www.google.com/");
- request_info.method = "GET";
- request_info.load_flags = LOAD_NORMAL;
+ MockWrite data_writes[] = {
+ MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
- scoped_ptr<HttpTransaction> trans;
- int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
- EXPECT_EQ(OK, rv);
+ StaticSocketDataProvider data1(data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes));
+ mock_socket_factory_.AddSocketDataProvider(&data1);
- rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
- if (rv == ERR_IO_PENDING)
- rv = callback.WaitForResult();
- ASSERT_EQ(OK, rv);
+ // Second data provider returns the expected content.
+ MockRead data_reads2[] = {
+ MockRead("HTTP/1.0 200 OK\r\n"
+ "Server: not-proxy\r\n\r\n"),
+ MockRead("content"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+ MockWrite data_writes2[] = {
+ MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
+ "Host: www.google.com\r\n"
+ "Proxy-Connection: keep-alive\r\n\r\n"),
+ };
- std::string contents;
- rv = ReadTransaction(trans.get(), &contents);
- EXPECT_EQ(OK, rv);
+ StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
+ data_writes2, arraysize(data_writes2));
+ mock_socket_factory_.AddSocketDataProvider(&data2);
+
+ TestCompletionCallback callback;
+
+ HttpRequestInfo request_info;
+ request_info.url = GURL("http://www.google.com/");
+ request_info.method = "GET";
+ request_info.load_flags = LOAD_NORMAL;
+
+ scoped_ptr<HttpTransaction> trans;
+ int rv = factory_->CreateTransaction(DEFAULT_PRIORITY, &trans, NULL);
+ EXPECT_EQ(OK, rv);
+
+ rv = trans->Start(&request_info, callback.callback(), BoundNetLog());
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ ASSERT_EQ(OK, rv);
- // We should obtain content from the second socket provider write
- // corresponding to the fallback proxy.
- EXPECT_EQ("content", contents);
- // We also have a server header here that isn't set by the proxy.
- EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue(
- "server", "not-proxy"));
- // We should also observe the data reduction proxy in the retry list.
- ASSERT_TRUE(1u == proxy_service_->proxy_retry_info().size());
- EXPECT_EQ(data_reduction_proxy,
- (*proxy_service_->proxy_retry_info().begin()).first);
+ std::string contents;
+ rv = ReadTransaction(trans.get(), &contents);
+ EXPECT_EQ(OK, rv);
+
+ // We should obtain content from the second socket provider write
+ // corresponding to the fallback proxy.
+ EXPECT_EQ("content", contents);
+ // We also have a server header here that isn't set by the proxy.
+ EXPECT_TRUE(trans->GetResponseInfo()->headers->HasHeaderValue(
+ "server", "not-proxy"));
+ // We should also observe the data reduction proxy in the retry list.
+ ASSERT_EQ(1u, proxy_service_->proxy_retry_info().size());
+ EXPECT_EQ(data_reduction_proxy,
+ (*proxy_service_->proxy_retry_info().begin()).first);
+ }
}
#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnectionPac) {
- // Verify that a Connection: proxy-bypass header is ignored when returned
- // from a directly connected origin server.
+ // Verify that a Chrome-Proxy header is ignored when returned from a directly
+ // connected origin server.
ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult("DIRECT"));
MockRead data_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"
- "Connection: proxy-bypass\r\n\r\n"),
+ "Chrome-Proxy: bypass=0\r\n\r\n"),
MockRead("Bypass message"),
MockRead(SYNCHRONOUS, OK),
};
@@ -466,6 +611,132 @@ TEST_F(HttpNetworkLayerTest, ProxyBypassIgnoredOnDirectConnectionPac) {
ASSERT_EQ(0u, proxy_service_->proxy_retry_info().size());
}
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypass) {
+ // Verify that a Chrome-Proxy: bypass=<seconds> header induces proxy
+ // fallback to a second proxy, if configured.
+ std::string bad_proxy = GetChromeProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
+ "PROXY " + bad_proxy + "; PROXY good:8080"));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"
+ "Connection: keep-alive\r\n"
+ "Chrome-Proxy: bypass=86400\r\n"
+ "Via: 1.1 Chrome Compression Proxy\r\n\r\n"),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ TestProxyFallbackWithMockReads(bad_proxy, "", data_reads,
+ arraysize(data_reads), 1u);
+ EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
+ (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
+}
+
+TEST_F(HttpNetworkLayerTest, ServerFallbackWithWrongViaHeader) {
+ // Verify that a Via header that lacks the Chrome-Proxy induces proxy fallback
+ // to a second proxy, if configured.
+ std::string chrome_proxy = GetChromeProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
+ "PROXY " + chrome_proxy + "; PROXY good:8080"));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"
+ "Connection: keep-alive\r\n"
+ "Via: 1.0 some-other-proxy\r\n\r\n"),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads,
+ arraysize(data_reads), 1u);
+}
+
+TEST_F(HttpNetworkLayerTest, ServerFallbackWithNoViaHeader) {
+ // Verify that the lack of a Via header induces proxy fallback to a second
+ // proxy, if configured.
+ std::string chrome_proxy = GetChromeProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
+ "PROXY " + chrome_proxy + "; PROXY good:8080"));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ TestProxyFallbackWithMockReads(chrome_proxy, std::string(), data_reads,
+ arraysize(data_reads), 1u);
+}
+
+TEST_F(HttpNetworkLayerTest, NoServerFallbackWith304Response) {
+ // Verify that Chrome will not be induced to bypass the Chrome proxy when
+ // the Chrome Proxy via header is absent on a 304.
+ std::string chrome_proxy = GetChromeProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
+ "PROXY " + chrome_proxy + "; PROXY good:8080"));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 304 Not Modified\r\n"
+ "Connection: keep-alive\r\n\r\n"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
+ data_reads, arraysize(data_reads),
+ "GET", std::string(), false, 0);
+}
+
+TEST_F(HttpNetworkLayerTest, NoServerFallbackWithChainedViaHeader) {
+ // Verify that Chrome will not be induced to bypass the Chrome proxy when
+ // the Chrome Proxy via header is present, even if that header is chained.
+ std::string chrome_proxy = GetChromeProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
+ "PROXY " + chrome_proxy + "; PROXY good:8080"));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"
+ "Connection: keep-alive\r\n"
+ "Via: 1.1 Chrome Compression Proxy, 1.0 some-other-proxy\r\n\r\n"),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ TestProxyFallbackByMethodWithMockReads(chrome_proxy, std::string(),
+ data_reads, arraysize(data_reads),
+ "GET", "Bypass message", false, 0);
+}
+
+#if defined(DATA_REDUCTION_FALLBACK_HOST)
+TEST_F(HttpNetworkLayerTest, ServerFallbackWithProxyTimedBypassAll) {
+ // Verify that a Chrome-Proxy: block=<seconds> header bypasses a
+ // a configured Chrome-Proxy and fallback and induces proxy fallback to a
+ // third proxy, if configured.
+ std::string bad_proxy = GetChromeProxy();
+ std::string fallback_proxy = GetChromeFallbackProxy();
+ ConfigureTestDependencies(ProxyService::CreateFixedFromPacResult(
+ "PROXY " + bad_proxy + "; PROXY " + fallback_proxy +
+ "; PROXY good:8080"));
+
+ MockRead data_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"
+ "Connection: keep-alive\r\n"
+ "Chrome-Proxy: block=86400\r\n"
+ "Via: 1.1 Chrome Compression Proxy\r\n\r\n"),
+ MockRead("Bypass message"),
+ MockRead(SYNCHRONOUS, OK),
+ };
+
+ TestProxyFallbackWithMockReads(bad_proxy, fallback_proxy, data_reads,
+ arraysize(data_reads), 2u);
+ EXPECT_EQ(base::TimeDelta::FromSeconds(86400),
+ (*proxy_service_->proxy_retry_info().begin()).second.current_delay);
+}
+#endif // defined(DATA_REDUCTION_FALLBACK_HOST)
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
+
TEST_F(HttpNetworkLayerTest, NetworkVerified) {
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc
index 346cbbc8941..1be93fe5c3f 100644
--- a/chromium/net/http/http_network_session.cc
+++ b/chromium/net/http/http_network_session.cc
@@ -42,6 +42,7 @@ net::ClientSocketPoolManager* CreateSocketPoolManager(
params.cert_verifier,
params.server_bound_cert_service,
params.transport_security_state,
+ params.cert_transparency_verifier,
params.ssl_session_cache_shard,
params.proxy_service,
params.ssl_config_service,
@@ -58,6 +59,7 @@ HttpNetworkSession::Params::Params()
cert_verifier(NULL),
server_bound_cert_service(NULL),
transport_security_state(NULL),
+ cert_transparency_verifier(NULL),
proxy_service(NULL),
ssl_config_service(NULL),
http_auth_handler_factory(NULL),
@@ -71,7 +73,6 @@ HttpNetworkSession::Params::Params()
testing_fixed_https_port(0),
force_spdy_single_domain(false),
enable_spdy_ip_pooling(true),
- enable_spdy_credential_frames(false),
enable_spdy_compression(true),
enable_spdy_ping_based_connection_checking(true),
spdy_default_protocol(kProtoUnknown),
@@ -83,6 +84,7 @@ HttpNetworkSession::Params::Params()
enable_quic_https(false),
quic_clock(NULL),
quic_random(NULL),
+ quic_max_packet_length(kDefaultMaxPacketSize),
enable_user_alternate_protocol_ports(false),
quic_crypto_client_stream_factory(NULL) {
}
@@ -112,13 +114,13 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.quic_random ? params.quic_random :
QuicRandom::GetInstance(),
params.quic_clock ? params. quic_clock :
- new QuicClock()),
+ new QuicClock(),
+ params.quic_max_packet_length),
spdy_session_pool_(params.host_resolver,
params.ssl_config_service,
params.http_server_properties,
params.force_spdy_single_domain,
params.enable_spdy_ip_pooling,
- params.enable_spdy_credential_frames,
params.enable_spdy_compression,
params.enable_spdy_ping_based_connection_checking,
params.spdy_default_protocol,
@@ -128,7 +130,8 @@ HttpNetworkSession::HttpNetworkSession(const Params& params)
params.time_func,
params.trusted_spdy_proxy),
http_stream_factory_(new HttpStreamFactoryImpl(this, false)),
- websocket_stream_factory_(new HttpStreamFactoryImpl(this, true)),
+ http_stream_factory_for_websocket_(
+ new HttpStreamFactoryImpl(this, true)),
params_(params) {
DCHECK(proxy_service_);
DCHECK(ssl_config_service_.get());
diff --git a/chromium/net/http/http_network_session.h b/chromium/net/http/http_network_session.h
index c10bb1446f4..471041220ec 100644
--- a/chromium/net/http/http_network_session.h
+++ b/chromium/net/http/http_network_session.h
@@ -62,6 +62,7 @@ class NET_EXPORT HttpNetworkSession
CertVerifier* cert_verifier;
ServerBoundCertService* server_bound_cert_service;
TransportSecurityState* transport_security_state;
+ CTVerifier* cert_transparency_verifier;
ProxyService* proxy_service;
std::string ssl_session_cache_shard;
SSLConfigService* ssl_config_service;
@@ -77,7 +78,6 @@ class NET_EXPORT HttpNetworkSession
uint16 testing_fixed_https_port;
bool force_spdy_single_domain;
bool enable_spdy_ip_pooling;
- bool enable_spdy_credential_frames;
bool enable_spdy_compression;
bool enable_spdy_ping_based_connection_checking;
NextProto spdy_default_protocol;
@@ -91,6 +91,7 @@ class NET_EXPORT HttpNetworkSession
HostPortPair origin_to_force_quic_on;
QuicClock* quic_clock; // Will be owned by QuicStreamFactory.
QuicRandom* quic_random;
+ size_t quic_max_packet_length;
bool enable_user_alternate_protocol_ports;
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
};
@@ -141,8 +142,8 @@ class NET_EXPORT HttpNetworkSession
HttpStreamFactory* http_stream_factory() {
return http_stream_factory_.get();
}
- HttpStreamFactory* websocket_stream_factory() {
- return websocket_stream_factory_.get();
+ HttpStreamFactory* http_stream_factory_for_websocket() {
+ return http_stream_factory_for_websocket_.get();
}
NetLog* net_log() {
return net_log_;
@@ -198,7 +199,7 @@ class NET_EXPORT HttpNetworkSession
QuicStreamFactory quic_stream_factory_;
SpdySessionPool spdy_session_pool_;
scoped_ptr<HttpStreamFactory> http_stream_factory_;
- scoped_ptr<HttpStreamFactory> websocket_stream_factory_;
+ scoped_ptr<HttpStreamFactory> http_stream_factory_for_websocket_;
std::set<HttpResponseBodyDrainer*> response_drainers_;
Params params_;
diff --git a/chromium/net/http/http_network_session_peer.cc b/chromium/net/http/http_network_session_peer.cc
index 74b0d415310..a32e48b9ebb 100644
--- a/chromium/net/http/http_network_session_peer.cc
+++ b/chromium/net/http/http_network_session_peer.cc
@@ -21,8 +21,8 @@ HttpNetworkSessionPeer::HttpNetworkSessionPeer(
HttpNetworkSessionPeer::~HttpNetworkSessionPeer() {}
void HttpNetworkSessionPeer::SetClientSocketPoolManager(
- ClientSocketPoolManager* socket_pool_manager) {
- session_->normal_socket_pool_manager_.reset(socket_pool_manager);
+ scoped_ptr<ClientSocketPoolManager> socket_pool_manager) {
+ session_->normal_socket_pool_manager_.swap(socket_pool_manager);
}
void HttpNetworkSessionPeer::SetProxyService(ProxyService* proxy_service) {
@@ -30,13 +30,13 @@ void HttpNetworkSessionPeer::SetProxyService(ProxyService* proxy_service) {
}
void HttpNetworkSessionPeer::SetHttpStreamFactory(
- HttpStreamFactory* http_stream_factory) {
- session_->http_stream_factory_.reset(http_stream_factory);
+ scoped_ptr<HttpStreamFactory> http_stream_factory) {
+ session_->http_stream_factory_.swap(http_stream_factory);
}
-void HttpNetworkSessionPeer::SetWebSocketStreamFactory(
- HttpStreamFactory* http_stream_factory) {
- session_->websocket_stream_factory_.reset(http_stream_factory);
+void HttpNetworkSessionPeer::SetHttpStreamFactoryForWebSocket(
+ scoped_ptr<HttpStreamFactory> http_stream_factory) {
+ session_->http_stream_factory_for_websocket_.swap(http_stream_factory);
}
} // namespace net
diff --git a/chromium/net/http/http_network_session_peer.h b/chromium/net/http/http_network_session_peer.h
index eeccfefafd4..755e539cebb 100644
--- a/chromium/net/http/http_network_session_peer.h
+++ b/chromium/net/http/http_network_session_peer.h
@@ -6,6 +6,7 @@
#define NET_HTTP_HTTP_NETWORK_SESSION_PEER_H_
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "net/base/net_export.h"
namespace net {
@@ -22,12 +23,13 @@ class NET_EXPORT_PRIVATE HttpNetworkSessionPeer {
~HttpNetworkSessionPeer();
void SetClientSocketPoolManager(
- ClientSocketPoolManager* socket_pool_manager);
+ scoped_ptr<ClientSocketPoolManager> socket_pool_manager);
void SetProxyService(ProxyService* proxy_service);
- void SetHttpStreamFactory(HttpStreamFactory* http_stream_factory);
- void SetWebSocketStreamFactory(HttpStreamFactory* websocket_stream_factory);
+ void SetHttpStreamFactory(scoped_ptr<HttpStreamFactory> http_stream_factory);
+ void SetHttpStreamFactoryForWebSocket(
+ scoped_ptr<HttpStreamFactory> http_stream_factory_for_websocket);
private:
const scoped_refptr<HttpNetworkSession> session_;
diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc
index ff158a84e77..d7b3f41ff76 100644
--- a/chromium/net/http/http_network_transaction.cc
+++ b/chromium/net/http/http_network_transaction.cc
@@ -19,6 +19,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/auth.h"
@@ -60,7 +61,14 @@
#include "net/ssl/ssl_connection_status_flags.h"
#include "url/gurl.h"
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+#include <algorithm>
+#include "net/proxy/proxy_server.h"
+#endif
+
+
using base::Time;
+using base::TimeDelta;
namespace net {
@@ -111,6 +119,30 @@ base::Value* NetLogSSLVersionFallbackCallback(
return dict;
}
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+// Returns true if |response_headers| contains the data reduction proxy Via
+// header value.
+bool IsChromeProxyResponse(const net::HttpResponseHeaders* response_headers) {
+ if (!response_headers) {
+ return false;
+ }
+ const char kDataReductionProxyViaValue[] = "1.1 Chrome Compression Proxy";
+ size_t value_len = strlen(kDataReductionProxyViaValue);
+ void* iter = NULL;
+ std::string temp;
+ while (response_headers->EnumerateHeader(&iter, "Via", &temp)) {
+ std::string::const_iterator it =
+ std::search(temp.begin(), temp.end(),
+ kDataReductionProxyViaValue,
+ kDataReductionProxyViaValue + value_len,
+ base::CaseInsensitiveCompareASCII<char>());
+ if (it != temp.end())
+ return true;
+ }
+ return false;
+}
+#endif
+
} // namespace
//-----------------------------------------------------------------------------
@@ -125,10 +157,12 @@ HttpNetworkTransaction::HttpNetworkTransaction(RequestPriority priority,
priority_(priority),
headers_valid_(false),
logged_response_time_(false),
+ fallback_error_code_(ERR_SSL_INAPPROPRIATE_FALLBACK),
request_headers_(),
read_buf_len_(0),
next_state_(STATE_NONE),
- establishing_tunnel_(false) {
+ establishing_tunnel_(false),
+ websocket_handshake_stream_base_create_helper_(NULL) {
session->ssl_config_service()->GetSSLConfig(&server_ssl_config_);
if (session->http_stream_factory()->has_next_protos()) {
server_ssl_config_.next_protos =
@@ -159,10 +193,13 @@ HttpNetworkTransaction::~HttpNetworkTransaction() {
} else {
// Otherwise, we try to drain the response body.
HttpStreamBase* stream = stream_.release();
- stream->Drain(session_.get());
+ stream->Drain(session_);
}
}
}
+
+ if (request_ && request_->upload_data_stream)
+ request_->upload_data_stream->Reset(); // Invalidate pending callbacks.
}
int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
@@ -425,6 +462,11 @@ void HttpNetworkTransaction::SetPriority(RequestPriority priority) {
stream_->SetPriority(priority);
}
+void HttpNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
+ websocket_handshake_stream_base_create_helper_ = create_helper;
+}
+
void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStreamBase* stream) {
@@ -443,11 +485,11 @@ void HttpNetworkTransaction::OnStreamReady(const SSLConfig& used_ssl_config,
OnIOComplete(OK);
}
-void HttpNetworkTransaction::OnWebSocketStreamReady(
+void HttpNetworkTransaction::OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream) {
- NOTREACHED() << "This function should never be called.";
+ WebSocketHandshakeStreamBase* stream) {
+ OnStreamReady(used_ssl_config, used_proxy_info, stream);
}
void HttpNetworkTransaction::OnStreamFailed(int result,
@@ -653,14 +695,27 @@ int HttpNetworkTransaction::DoLoop(int result) {
int HttpNetworkTransaction::DoCreateStream() {
next_state_ = STATE_CREATE_STREAM_COMPLETE;
- stream_request_.reset(
- session_->http_stream_factory()->RequestStream(
- *request_,
- priority_,
- server_ssl_config_,
- proxy_ssl_config_,
- this,
- net_log_));
+ if (ForWebSocketHandshake()) {
+ stream_request_.reset(
+ session_->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(
+ *request_,
+ priority_,
+ server_ssl_config_,
+ proxy_ssl_config_,
+ this,
+ websocket_handshake_stream_base_create_helper_,
+ net_log_));
+ } else {
+ stream_request_.reset(
+ session_->http_stream_factory()->RequestStream(
+ *request_,
+ priority_,
+ server_ssl_config_,
+ proxy_ssl_config_,
+ this,
+ net_log_));
+ }
DCHECK(stream_request_.get());
return ERR_IO_PENDING;
}
@@ -894,6 +949,11 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
return result;
}
+ if (result == ERR_QUIC_HANDSHAKE_FAILED) {
+ ResetConnectionAndRequestForResend();
+ return OK;
+ }
+
if (result < 0 && result != ERR_CONNECTION_CLOSED)
return HandleIOError(result);
@@ -917,33 +977,85 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
}
DCHECK(response_.headers.get());
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
// Server-induced fallback; see: http://crbug.com/143712
if (response_.was_fetched_via_proxy && response_.headers.get() != NULL) {
- bool should_fallback =
- response_.headers->HasHeaderValue("connection", "proxy-bypass");
- // Additionally, fallback if a 500 is returned via the data reduction proxy.
- // This is conservative, as the 500 might have been generated by the origin,
- // and not the proxy.
-#if defined(SPDY_PROXY_AUTH_ORIGIN)
- if (!should_fallback) {
- should_fallback =
- response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR &&
- proxy_info_.proxy_server().host_port_pair().Equals(
- HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)));
+ ProxyService::DataReductionProxyBypassEventType proxy_bypass_event =
+ ProxyService::BYPASS_EVENT_TYPE_MAX;
+ net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info;
+ bool chrome_proxy_used =
+ proxy_info_.proxy_server().isDataReductionProxy();
+ bool chrome_fallback_proxy_used = false;
+#if defined(DATA_REDUCTION_FALLBACK_HOST)
+ if (!chrome_proxy_used) {
+ chrome_fallback_proxy_used =
+ proxy_info_.proxy_server().isDataReductionProxyFallback();
}
#endif
- if (should_fallback) {
- ProxyService* proxy_service = session_->proxy_service();
- if (proxy_service->MarkProxyAsBad(proxy_info_, net_log_)) {
- // Only retry in the case of GETs. We don't want to resubmit a POST
- // if the proxy took some action.
- if (request_->method == "GET") {
- ResetConnectionAndRequestForResend();
- return OK;
+
+ if (chrome_proxy_used || chrome_fallback_proxy_used) {
+ // A Via header might not be present in a 304. Since the goal of a 304
+ // response is to minimize information transfer, a sender in general
+ // should not generate representation metadata other than Cache-Control,
+ // Content-Location, Date, ETag, Expires, and Vary.
+ if (!IsChromeProxyResponse(response_.headers.get()) &&
+ (response_.headers->response_code() != HTTP_NOT_MODIFIED)) {
+ proxy_bypass_event = ProxyService::MISSING_VIA_HEADER;
+ } else if (response_.headers->GetChromeProxyInfo(&chrome_proxy_info)) {
+ if (chrome_proxy_info.bypass_duration < TimeDelta::FromMinutes(30))
+ proxy_bypass_event = ProxyService::SHORT_BYPASS;
+ else
+ proxy_bypass_event = ProxyService::LONG_BYPASS;
+ } else {
+ // Additionally, fallback if a 500, 502 or 503 is returned via the data
+ // reduction proxy. This is conservative, as the 500, 502 or 503 might
+ // have been generated by the origin, and not the proxy.
+ if (response_.headers->response_code() == HTTP_INTERNAL_SERVER_ERROR ||
+ response_.headers->response_code() == HTTP_BAD_GATEWAY ||
+ response_.headers->response_code() == HTTP_SERVICE_UNAVAILABLE) {
+ proxy_bypass_event = ProxyService::INTERNAL_SERVER_ERROR_BYPASS;
+ }
+ }
+
+ if (proxy_bypass_event < ProxyService::BYPASS_EVENT_TYPE_MAX) {
+ ProxyService* proxy_service = session_->proxy_service();
+
+ proxy_service->RecordDataReductionProxyBypassInfo(
+ chrome_proxy_used, proxy_info_.proxy_server(), proxy_bypass_event);
+
+ ProxyServer proxy_server;
+#if defined(DATA_REDUCTION_FALLBACK_HOST)
+ if (chrome_proxy_used && chrome_proxy_info.bypass_all) {
+ // TODO(bengr): Rename as DATA_REDUCTION_FALLBACK_ORIGIN.
+ GURL proxy_url(DATA_REDUCTION_FALLBACK_HOST);
+ if (proxy_url.SchemeIsHTTPOrHTTPS()) {
+ proxy_server = ProxyServer(proxy_url.SchemeIs("http") ?
+ ProxyServer::SCHEME_HTTP :
+ ProxyServer::SCHEME_HTTPS,
+ HostPortPair::FromURL(proxy_url));
+ }
+ }
+#endif
+ if (proxy_service->MarkProxiesAsBad(proxy_info_,
+ chrome_proxy_info.bypass_duration,
+ proxy_server,
+ net_log_)) {
+ // Only retry idempotent methods. We don't want to resubmit a POST
+ // if the proxy took some action.
+ if (request_->method == "GET" ||
+ request_->method == "OPTIONS" ||
+ request_->method == "HEAD" ||
+ request_->method == "PUT" ||
+ request_->method == "DELETE" ||
+ request_->method == "TRACE") {
+ ResetConnectionAndRequestForResend();
+ return OK;
+ }
}
}
}
}
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
// Like Net.HttpResponseCode, but only for MAIN_FRAME loads.
if (request_->load_flags & LOAD_MAIN_FRAME) {
@@ -969,7 +1081,9 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
// need to skip over it.
// We treat any other 1xx in this same way (although in practice getting
// a 1xx that isn't a 100 is rare).
- if (response_.headers->response_code() / 100 == 1) {
+ // Unless this is a WebSocket request, in which case we pass it on up.
+ if (response_.headers->response_code() / 100 == 1 &&
+ !ForWebSocketHandshake()) {
response_.headers = new HttpResponseHeaders(std::string());
next_state_ = STATE_READ_HEADERS;
return OK;
@@ -1210,17 +1324,21 @@ int HttpNetworkTransaction::HandleCertificateRequest(int error) {
return OK;
}
+void HttpNetworkTransaction::HandleClientAuthError(int error) {
+ if (server_ssl_config_.send_client_cert &&
+ (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
+ session_->ssl_client_auth_cache()->Remove(
+ GetHostAndPort(request_->url));
+ }
+}
+
// TODO(rch): This does not correctly handle errors when an SSL proxy is
// being used, as all of the errors are handled as if they were generated
// by the endpoint host, request_->url, rather than considering if they were
// generated by the SSL proxy. http://crbug.com/69329
int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
DCHECK(request_);
- if (server_ssl_config_.send_client_cert &&
- (error == ERR_SSL_PROTOCOL_ERROR || IsClientCertificateError(error))) {
- session_->ssl_client_auth_cache()->Remove(
- GetHostAndPort(request_->url));
- }
+ HandleClientAuthError(error);
bool should_fallback = false;
uint16 version_max = server_ssl_config_.version_max;
@@ -1246,16 +1364,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
// 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.
- // For now SSL 3.0 fallback is disabled for Google servers first,
- // and will be expanded to other servers after enough experiences
- // have been gained showing that this experiment works well with
- // today's Internet.
- if (version_max > SSL_PROTOCOL_VERSION_SSL3 ||
- (server_ssl_config_.unrestricted_ssl3_fallback_enabled ||
- !TransportSecurityState::IsGooglePinnedProperty(
- request_->url.host(), true /* include SNI */))) {
- should_fallback = true;
- }
+ should_fallback = true;
}
break;
case ERR_SSL_BAD_RECORD_MAC_ALERT:
@@ -1269,6 +1378,13 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
should_fallback = true;
}
break;
+ case ERR_SSL_INAPPROPRIATE_FALLBACK:
+ // The server told us that we should not have fallen back. A buggy server
+ // could trigger ERR_SSL_INAPPROPRIATE_FALLBACK with the initial
+ // connection. |fallback_error_code_| is initialised to
+ // ERR_SSL_INAPPROPRIATE_FALLBACK to catch this case.
+ error = fallback_error_code_;
+ break;
}
if (should_fallback) {
@@ -1277,6 +1393,7 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
base::Bind(&NetLogSSLVersionFallbackCallback,
&request_->url, error, server_ssl_config_.version_max,
version_max));
+ fallback_error_code_ = error;
server_ssl_config_.version_max = version_max;
server_ssl_config_.version_fallback = true;
ResetConnectionAndRequestForResend();
@@ -1291,13 +1408,9 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
// write errors or response header read errors. It should not be used in
// other cases, such as a Connect error.
int HttpNetworkTransaction::HandleIOError(int error) {
- // SSL errors may happen at any time during the stream and indicate issues
- // with the underlying connection. Because the peer may request
- // renegotiation at any time, check and handle any possible SSL handshake
- // related errors. In addition to renegotiation, TLS False Start may cause
- // SSL handshake errors (specifically servers with buggy DEFLATE support)
- // to be delayed until the first Read on the underlying connection.
- error = HandleSSLHandshakeError(error);
+ // Because the peer may request renegotiation with client authentication at
+ // any time, check and handle client authentication errors.
+ HandleClientAuthError(error);
switch (error) {
// If we try to reuse a connection that the server is in the process of
@@ -1332,6 +1445,7 @@ int HttpNetworkTransaction::HandleIOError(int error) {
break;
case ERR_SPDY_PING_FAILED:
case ERR_SPDY_SERVER_REFUSED_STREAM:
+ case ERR_QUIC_HANDSHAKE_FAILED:
net_log_.AddEventWithNetErrorCode(
NetLog::TYPE_HTTP_TRANSACTION_RESTART_AFTER_ERROR, error);
ResetConnectionAndRequestForResend();
@@ -1453,6 +1567,11 @@ GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const {
}
}
+bool HttpNetworkTransaction::ForWebSocketHandshake() const {
+ return websocket_handshake_stream_base_create_helper_ &&
+ request_->url.SchemeIsWSOrWSS();
+}
+
#define STATE_CASE(s) \
case s: \
description = base::StringPrintf("%s (0x%08X)", #s, s); \
diff --git a/chromium/net/http/http_network_transaction.h b/chromium/net/http/http_network_transaction.h
index 6228487e615..3ae1725d1de 100644
--- a/chromium/net/http/http_network_transaction.h
+++ b/chromium/net/http/http_network_transaction.h
@@ -21,6 +21,7 @@
#include "net/http/http_transaction.h"
#include "net/proxy/proxy_service.h"
#include "net/ssl/ssl_config_service.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
namespace net {
@@ -68,15 +69,17 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
virtual void SetPriority(RequestPriority priority) OVERRIDE;
+ virtual void SetWebSocketHandshakeStreamCreateHelper(
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper) OVERRIDE;
// HttpStreamRequest::Delegate methods:
virtual void OnStreamReady(const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStreamBase* stream) OVERRIDE;
- virtual void OnWebSocketStreamReady(
+ virtual void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream) OVERRIDE;
+ WebSocketHandshakeStreamBase* stream) OVERRIDE;
virtual void OnStreamFailed(int status,
const SSLConfig& used_ssl_config) OVERRIDE;
virtual void OnCertificateError(int status,
@@ -184,6 +187,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// Called to handle a client certificate request.
int HandleCertificateRequest(int error);
+ // Called to possibly handle a client authentication error.
+ void HandleClientAuthError(int error);
+
// Called to possibly recover from an SSL handshake error. Sets next_state_
// and returns OK if recovering from the error. Otherwise, the same error
// code is returned.
@@ -242,6 +248,9 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// Get the {scheme, host, path, port} for the authentication target
GURL AuthURL(HttpAuth::Target target) const;
+ // Returns true if this transaction is for a WebSocket handshake
+ bool ForWebSocketHandshake() const;
+
// Debug helper.
static std::string DescribeState(State state);
@@ -256,7 +265,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
CompletionCallback io_callback_;
CompletionCallback callback_;
- scoped_refptr<HttpNetworkSession> session_;
+ HttpNetworkSession* session_;
BoundNetLog net_log_;
const HttpRequestInfo* request_;
@@ -279,6 +288,12 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
SSLConfig server_ssl_config_;
SSLConfig proxy_ssl_config_;
+ // fallback_error_code contains the error code that caused the last TLS
+ // fallback. If the fallback connection results in
+ // ERR_SSL_INAPPROPRIATE_FALLBACK (i.e. the server indicated that the
+ // fallback should not have been needed) then we use this value to return the
+ // original error that triggered the fallback.
+ int fallback_error_code_;
HttpRequestHeaders request_headers_;
@@ -306,6 +321,11 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction
// read from the socket until the tunnel is done.
bool establishing_tunnel_;
+ // The helper object to use to create WebSocketHandshakeStreamBase
+ // objects. Only relevant when establishing a WebSocket connection.
+ WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_handshake_stream_base_create_helper_;
+
DISALLOW_COPY_AND_ASSIGN(HttpNetworkTransaction);
};
diff --git a/chromium/net/http/http_network_transaction_ssl_unittest.cc b/chromium/net/http/http_network_transaction_ssl_unittest.cc
index bb218498961..ab7eadf8928 100644
--- a/chromium/net/http/http_network_transaction_ssl_unittest.cc
+++ b/chromium/net/http/http_network_transaction_ssl_unittest.cc
@@ -103,148 +103,6 @@ class HttpNetworkTransactionSSLTest : public testing::Test {
ScopedVector<HttpRequestInfo> request_info_vector_;
};
-// Tests that HttpNetworkTransaction does not attempt to
-// fallback to SSL 3.0 when a TLS 1.0 handshake fails and:
-// * the site is pinned to the Google pin list (indicating that
-// it is a Google site);
-// * unrestricted SSL 3.0 fallback is disabled.
-TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackDisabled_Google) {
- // |ssl_data1| is for the first handshake (TLS 1.0), which will fail for
- // protocol reasons (e.g., simulating a version rollback attack).
- // Because unrestricted SSL 3.0 fallback is disabled, only this simulated
- // SSL handshake is consumed.
- SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1);
- StaticSocketDataProvider data1(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data1);
-
- // This extra handshake, which should be unconsumed, is provided to ensure
- // that even if the behaviour being tested here ever breaks (and Google
- // properties begin SSL 3.0 fallbacks), this test will not crash (and bring
- // down all of net_unittests), but it will fail gracefully.
- SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2);
- StaticSocketDataProvider data2(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data2);
-
- scoped_refptr<HttpNetworkSession> session(
- new HttpNetworkSession(session_params_));
- scoped_ptr<HttpNetworkTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
-
- SSLConfig& ssl_config = GetServerSSLConfig(trans.get());
- ssl_config.unrestricted_ssl3_fallback_enabled = false;
-
- TestCompletionCallback callback;
- // This will consume only |ssl_data1|. |ssl_data2| will not be consumed.
- int rv = callback.GetResult(
- trans->Start(GetRequestInfo("https://www.google.com/"),
- callback.callback(), BoundNetLog()));
- EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
-
- SocketDataProviderArray<SocketDataProvider>& mock_data =
- mock_socket_factory_.mock_data();
- // Confirms that only |ssl_data1| is consumed.
- EXPECT_EQ(1u, mock_data.next_index());
-
- // |version_max| never fallbacks to SSLv3 for Google properties.
- EXPECT_EQ(SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_max);
- EXPECT_FALSE(ssl_config.version_fallback);
-}
-
-// Tests that HttpNetworkTransaction attempts to fallback to SSL 3.0
-// when a TLS 1.0 handshake fails and:
-// * the site is pinned to the Google pin list (indicating that
-// it is a Google site);
-// * unrestricted SSL 3.0 fallback is enabled.
-TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackEnabled_Google) {
- // |ssl_data1| is for the first handshake (TLS 1.0), which will fail
- // for protocol reasons (e.g., simulating a version rollback attack).
- SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1);
- StaticSocketDataProvider data1(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data1);
-
- // |ssl_data2| contains the handshake result for a SSL 3.0
- // handshake which will be attempted after the TLS 1.0
- // handshake fails.
- SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2);
- StaticSocketDataProvider data2(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data2);
-
- scoped_refptr<HttpNetworkSession> session(
- new HttpNetworkSession(session_params_));
- scoped_ptr<HttpNetworkTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
-
- SSLConfig& ssl_config = GetServerSSLConfig(trans.get());
- ssl_config.unrestricted_ssl3_fallback_enabled = true;
-
- TestCompletionCallback callback;
- // This will consume |ssl_data1| and |ssl_data2|.
- int rv = callback.GetResult(
- trans->Start(GetRequestInfo("https://www.google.com/"),
- callback.callback(), BoundNetLog()));
- EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
-
- SocketDataProviderArray<SocketDataProvider>& mock_data =
- mock_socket_factory_.mock_data();
- // Confirms that both |ssl_data1| and |ssl_data2| are consumed.
- EXPECT_EQ(2u, mock_data.next_index());
-
- // |version_max| fallbacks to SSL 3.0 for Google properties when
- // |unrestricted_ssl3_fallback_enabled| is true.
- EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max);
- EXPECT_TRUE(ssl_config.version_fallback);
-}
-
-// Tests that HttpNetworkTransaction attempts to fallback to SSL 3.0
-// when a TLS 1.0 handshake fails and the site is not a Google domain,
-// even if unrestricted SSL 3.0 fallback is disabled.
-// TODO(thaidn): revise the above comment and this test when the
-// SSL 3.0 fallback experiment is applied for non-Google domains.
-TEST_F(HttpNetworkTransactionSSLTest, SSL3FallbackDisabled_Paypal) {
- // |ssl_data1| is for the first handshake (TLS 1.0), which will fail
- // for protocol reasons (e.g., simulating a version rollback attack).
- SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data1);
- StaticSocketDataProvider data1(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data1);
-
- // |ssl_data2| contains the handshake result for a SSL 3.0
- // handshake which will be attempted after the TLS 1.0
- // handshake fails.
- SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR);
- mock_socket_factory_.AddSSLSocketDataProvider(&ssl_data2);
- StaticSocketDataProvider data2(NULL, 0, NULL, 0);
- mock_socket_factory_.AddSocketDataProvider(&data2);
-
- scoped_refptr<HttpNetworkSession> session(
- new HttpNetworkSession(session_params_));
- scoped_ptr<HttpNetworkTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
-
- SSLConfig& ssl_config = GetServerSSLConfig(trans.get());
- ssl_config.unrestricted_ssl3_fallback_enabled = false;
-
- TestCompletionCallback callback;
- // This will consume |ssl_data1| and |ssl_data2|.
- int rv = callback.GetResult(
- trans->Start(GetRequestInfo("https://www.paypal.com/"),
- callback.callback(), BoundNetLog()));
- EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
-
- SocketDataProviderArray<SocketDataProvider>& mock_data =
- mock_socket_factory_.mock_data();
- // Confirms that both |ssl_data1| and |ssl_data2| are consumed.
- EXPECT_EQ(2u, mock_data.next_index());
-
- // |version_max| fallbacks to SSL 3.0.
- EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max);
- EXPECT_TRUE(ssl_config.version_fallback);
-}
-
// Tests that HttpNetworkTransaction attempts to fallback from
// TLS 1.1 to TLS 1.0, then from TLS 1.0 to SSL 3.0.
TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) {
@@ -278,9 +136,6 @@ TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) {
scoped_ptr<HttpNetworkTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
- SSLConfig& ssl_config = GetServerSSLConfig(trans.get());
- ssl_config.unrestricted_ssl3_fallback_enabled = true;
-
TestCompletionCallback callback;
// This will consume |ssl_data1|, |ssl_data2| and |ssl_data3|.
int rv = callback.GetResult(
@@ -293,6 +148,7 @@ TEST_F(HttpNetworkTransactionSSLTest, SSLFallback) {
// Confirms that |ssl_data1|, |ssl_data2| and |ssl_data3| are consumed.
EXPECT_EQ(3u, mock_data.next_index());
+ SSLConfig& ssl_config = GetServerSSLConfig(trans.get());
// |version_max| fallbacks to SSL 3.0.
EXPECT_EQ(SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max);
EXPECT_TRUE(ssl_config.version_fallback);
diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc
index a2165776c08..dd9eefecf37 100644
--- a/chromium/net/http/http_network_transaction_unittest.cc
+++ b/chromium/net/http/http_network_transaction_unittest.cc
@@ -64,6 +64,7 @@
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/ssl/ssl_info.h"
#include "net/test/cert_test_util.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "url/gurl.h"
@@ -111,7 +112,7 @@ bool GetHeaders(base::DictionaryValue* params, std::string* headers) {
return false;
std::string double_quote_headers;
base::JSONWriter::Write(header_list, &double_quote_headers);
- ReplaceChars(double_quote_headers, "\"", "'", headers);
+ base::ReplaceChars(double_quote_headers, "\"", "'", headers);
return true;
}
@@ -289,9 +290,9 @@ class HttpNetworkTransactionTest
CapturingBoundNetLog log;
session_deps_.net_log = log.bound().net_log();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
for (size_t i = 0; i < data_count; ++i) {
session_deps_.socket_factory->AddSocketDataProvider(data[i]);
@@ -386,7 +387,8 @@ class HttpNetworkTransactionTest
INSTANTIATE_TEST_CASE_P(
NextProto,
HttpNetworkTransactionTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
namespace {
@@ -510,6 +512,7 @@ CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
cert_verifier,
NULL,
NULL,
+ NULL,
std::string(),
NULL,
NULL,
@@ -565,9 +568,9 @@ bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
} // namespace
TEST_P(HttpNetworkTransactionTest, Basic) {
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
}
TEST_P(HttpNetworkTransactionTest, SimpleGET) {
@@ -860,9 +863,9 @@ TEST_P(HttpNetworkTransactionTest, TwoIdenticalLocationHeaders) {
request.url = GURL("http://redirect.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
@@ -904,9 +907,9 @@ TEST_P(HttpNetworkTransactionTest, Head) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("HEAD / HTTP/1.1\r\n"
@@ -1008,7 +1011,7 @@ TEST_P(HttpNetworkTransactionTest, ReuseConnection) {
TEST_P(HttpNetworkTransactionTest, Ignores100) {
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(new UploadBytesElementReader("foo", 3));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
@@ -1016,9 +1019,9 @@ TEST_P(HttpNetworkTransactionTest, Ignores100) {
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
@@ -1058,9 +1061,9 @@ TEST_P(HttpNetworkTransactionTest, Ignores1xx) {
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
@@ -1097,9 +1100,9 @@ TEST_P(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
@@ -1128,9 +1131,10 @@ TEST_P(HttpNetworkTransactionTest, EmptyResponse) {
request.url = GURL("http://www.foo.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
+
MockRead data_reads[] = {
MockRead(ASYNC, 0),
@@ -1258,9 +1262,9 @@ TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead(ASYNC, ERR_CONNECTION_RESET),
@@ -1506,9 +1510,9 @@ TEST_P(HttpNetworkTransactionTest, BasicAuth) {
CapturingNetLog log;
session_deps_.net_log = &log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -1599,9 +1603,9 @@ TEST_P(HttpNetworkTransactionTest, DoNotSendAuth) {
request.url = GURL("http://www.google.com/");
request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -2262,9 +2266,9 @@ TEST_P(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
request.load_flags = 0;
// We are using a DIRECT connection (i.e. no proxy) for this session.
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -3528,7 +3532,6 @@ void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
// Configure against proxy server "myproxy:70".
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
-
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
// Since we have proxy, should try to establish tunnel.
@@ -3740,11 +3743,12 @@ TEST_P(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ // Configure against proxy server "myproxy:70".
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
- // Configure against proxy server "myproxy:70".
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
@@ -4203,9 +4207,9 @@ TEST_P(HttpNetworkTransactionTest, LargeHeadersNoBody) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
// Respond with 300 kb of headers (we should fail after 256 kb).
std::string large_headers_string;
@@ -4563,7 +4567,7 @@ TEST_P(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
TEST_P(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(new UploadBytesElementReader("foo", 3));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request[2];
// Transaction 1: a GET request that succeeds. The socket is recycled
@@ -4658,9 +4662,9 @@ TEST_P(HttpNetworkTransactionTest, AuthIdentityInURL) {
request.url = GURL("http://foo:b@r@www.google.com/");
request.load_flags = LOAD_NORMAL;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
// The password contains an escaped character -- for this test to pass it
// will need to be unescaped by HttpNetworkTransaction.
@@ -4739,9 +4743,9 @@ TEST_P(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
request.load_flags = LOAD_NORMAL;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -4847,9 +4851,9 @@ TEST_P(HttpNetworkTransactionTest, AuthIdentityInURLSuppressed) {
request.url = GURL("http://foo:bar@www.google.com/");
request.load_flags = LOAD_DO_NOT_USE_EMBEDDED_IDENTITY;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes1[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -5438,9 +5442,9 @@ TEST_P(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
// Test the ResetStateForRestart() private method.
TEST_P(HttpNetworkTransactionTest, ResetStateForRestart) {
// Create a transaction (the dependencies aren't important).
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpNetworkTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
// Setup some state (which we expect ResetStateForRestart() will clear).
trans->read_buf_ = new IOBuffer(15);
@@ -5485,9 +5489,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificate) {
request.url = GURL("https://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -5589,9 +5593,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
for (int i = 0; i < 2; i++) {
session_deps_.socket_factory->ResetNextMockIndexes();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -5653,9 +5657,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
TestCompletionCallback callback;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -5711,9 +5715,9 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
TestCompletionCallback callback;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -5796,9 +5800,9 @@ TEST_P(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
TestCompletionCallback callback;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -5848,9 +5852,9 @@ TEST_P(HttpNetworkTransactionTest,
TestCompletionCallback callback;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -5909,9 +5913,9 @@ TEST_P(HttpNetworkTransactionTest,
TestCompletionCallback callback;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -6334,9 +6338,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
TestCompletionCallback callback;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -6363,9 +6367,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
"Chromium Ultra Awesome X Edition");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -6403,9 +6407,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
"Chromium Ultra Awesome X Edition");
session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70"));
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
@@ -6442,9 +6446,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_Referer) {
request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
"http://the.previous.site.com/");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -6479,9 +6483,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
request.method = "POST";
request.url = GURL("http://www.google.com/");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("POST / HTTP/1.1\r\n"
@@ -6516,9 +6520,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
request.method = "PUT";
request.url = GURL("http://www.google.com/");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("PUT / HTTP/1.1\r\n"
@@ -6553,9 +6557,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
request.method = "HEAD";
request.url = GURL("http://www.google.com/");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("HEAD / HTTP/1.1\r\n"
@@ -6591,9 +6595,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
request.url = GURL("http://www.google.com/");
request.load_flags = LOAD_BYPASS_CACHE;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -6631,9 +6635,9 @@ TEST_P(HttpNetworkTransactionTest,
request.url = GURL("http://www.google.com/");
request.load_flags = LOAD_VALIDATE_CACHE;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -6669,9 +6673,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
request.url = GURL("http://www.google.com/");
request.extra_headers.SetHeader("FooHeader", "Bar");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -6709,9 +6713,9 @@ TEST_P(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
request.extra_headers.SetHeader("hEllo", "Kitty");
request.extra_headers.SetHeader("FoO", "bar");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -6754,9 +6758,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
@@ -6813,9 +6817,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
@@ -6877,9 +6881,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS4_HTTP_GET_no_PAC) {
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
@@ -6936,9 +6940,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
@@ -7009,9 +7013,9 @@ TEST_P(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
CapturingNetLog net_log;
session_deps_.net_log = &net_log;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
@@ -7169,11 +7173,12 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
new CaptureGroupNameTransportSocketPool(NULL, NULL);
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
new CaptureGroupNameSSLSocketPool(NULL, NULL);
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
EXPECT_EQ(ERR_IO_PENDING,
GroupNameTransactionHelper(tests[i].url, session));
@@ -7235,11 +7240,12 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
new CaptureGroupNameSSLSocketPool(NULL, NULL);
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
EXPECT_EQ(ERR_IO_PENDING,
GroupNameTransactionHelper(tests[i].url, session));
@@ -7305,11 +7311,12 @@ TEST_P(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
CaptureGroupNameSSLSocketPool* ssl_conn_pool =
new CaptureGroupNameSSLSocketPool(NULL, NULL);
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -7337,9 +7344,9 @@ TEST_P(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
// connecting to both proxies (myproxy:70 and foobar:80).
session_deps_.host_resolver->rules()->AddSimulatedFailure("*");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
TestCompletionCallback callback;
@@ -7363,8 +7370,9 @@ void HttpNetworkTransactionTest::BypassHostCacheOnRefreshHelper(
// Select a host resolver that does caching.
session_deps_.host_resolver.reset(new MockCachingHostResolver);
- scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ scoped_ptr<HttpTransaction> trans(
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
// Warm up the host cache so it has an entry for "www.google.com".
AddressList addrlist;
@@ -7428,8 +7436,6 @@ TEST_P(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
// Make sure we can handle an error when writing the request.
TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
@@ -7441,12 +7447,12 @@ TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
StaticSocketDataProvider data(NULL, 0,
write_failure, arraysize(write_failure));
session_deps_.socket_factory->AddSocketDataProvider(&data);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -7457,8 +7463,6 @@ TEST_P(HttpNetworkTransactionTest, RequestWriteError) {
// Check that a connection closed after the start of the headers finishes ok.
TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.foo.com/");
@@ -7471,12 +7475,12 @@ TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback;
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -7499,8 +7503,6 @@ TEST_P(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
// Make sure that a dropped connection while draining the body for auth
// restart does the right thing.
TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
- scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
-
HttpRequestInfo request;
request.method = "GET";
request.url = GURL("http://www.google.com/");
@@ -7545,6 +7547,7 @@ TEST_P(HttpNetworkTransactionTest, DrainResetOK) {
StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
data_writes2, arraysize(data_writes2));
session_deps_.socket_factory->AddSocketDataProvider(&data2);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
TestCompletionCallback callback1;
@@ -7600,9 +7603,9 @@ TEST_P(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
session_deps_.socket_factory->ResetNextMockIndexes();
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -7617,9 +7620,9 @@ TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
@@ -7649,7 +7652,7 @@ TEST_P(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path));
const uint64 kFakeSize = 100000; // file is actually blank
UploadFileElementReader::ScopedOverridingContentLengthForTests
overriding_content_length(kFakeSize);
@@ -7661,7 +7664,7 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
0,
kuint64max,
base::Time()));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
@@ -7669,9 +7672,9 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n\r\n"),
@@ -7705,7 +7708,7 @@ TEST_P(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
base::FilePath temp_file;
- ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
+ ASSERT_TRUE(base::CreateTemporaryFile(&temp_file));
std::string temp_file_content("Unreadable file.");
ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
temp_file_content.length()));
@@ -7718,7 +7721,7 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
0,
kuint64max,
base::Time()));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
@@ -7726,25 +7729,12 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
- // If we try to upload an unreadable file, the network stack should report
- // the file size as zero and upload zero bytes for that file.
+ // If we try to upload an unreadable file, the transaction should fail.
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
- MockRead data_reads[] = {
- MockRead("HTTP/1.0 200 OK\r\n\r\n"),
- MockRead(SYNCHRONOUS, OK),
- };
- MockWrite data_writes[] = {
- MockWrite("POST /upload HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Connection: keep-alive\r\n"
- "Content-Length: 0\r\n\r\n"),
- MockWrite(SYNCHRONOUS, OK),
- };
- StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
- arraysize(data_writes));
+ StaticSocketDataProvider data(NULL, 0, NULL, 0);
session_deps_.socket_factory->AddSocketDataProvider(&data);
TestCompletionCallback callback;
@@ -7753,32 +7743,43 @@ TEST_P(HttpNetworkTransactionTest, UploadUnreadableFile) {
EXPECT_EQ(ERR_IO_PENDING, rv);
rv = callback.WaitForResult();
- EXPECT_EQ(OK, rv);
+ EXPECT_EQ(ERR_ACCESS_DENIED, rv);
const HttpResponseInfo* response = trans->GetResponseInfo();
- ASSERT_TRUE(response != NULL);
- EXPECT_TRUE(response->headers.get() != NULL);
- EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
+ EXPECT_FALSE(response);
base::DeleteFile(temp_file, false);
}
-TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
- base::FilePath temp_file;
- ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
- std::string temp_file_contents("Unreadable file.");
- std::string unreadable_contents(temp_file_contents.length(), '\0');
- ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
- temp_file_contents.length()));
+TEST_P(HttpNetworkTransactionTest, CancelDuringInitRequestBody) {
+ class FakeUploadElementReader : public UploadElementReader {
+ public:
+ FakeUploadElementReader() {}
+ virtual ~FakeUploadElementReader() {}
+
+ const CompletionCallback& callback() const { return callback_; }
+ // UploadElementReader overrides:
+ virtual int Init(const CompletionCallback& callback) OVERRIDE {
+ callback_ = callback;
+ return ERR_IO_PENDING;
+ }
+ virtual uint64 GetContentLength() const OVERRIDE { return 0; }
+ virtual uint64 BytesRemaining() const OVERRIDE { return 0; }
+ virtual int Read(IOBuffer* buf,
+ int buf_length,
+ const CompletionCallback& callback) OVERRIDE {
+ return ERR_FAILED;
+ }
+
+ private:
+ CompletionCallback callback_;
+ };
+
+ FakeUploadElementReader* fake_reader = new FakeUploadElementReader;
ScopedVector<UploadElementReader> element_readers;
- element_readers.push_back(
- new UploadFileElementReader(base::MessageLoopProxy::current().get(),
- temp_file,
- 0,
- kuint64max,
- base::Time()));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ element_readers.push_back(fake_reader);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
@@ -7786,72 +7787,24 @@ TEST_P(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
request.upload_data_stream = &upload_data_stream;
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
-
- MockRead data_reads[] = {
- MockRead("HTTP/1.1 401 Unauthorized\r\n"),
- MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
- MockRead("Content-Length: 0\r\n\r\n"), // No response body.
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Content-Length: 0\r\n\r\n"),
- MockRead(SYNCHRONOUS, OK),
- };
- MockWrite data_writes[] = {
- MockWrite("POST /upload HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Connection: keep-alive\r\n"
- "Content-Length: 16\r\n\r\n"),
- MockWrite(SYNCHRONOUS, temp_file_contents.c_str()),
-
- MockWrite("POST /upload HTTP/1.1\r\n"
- "Host: www.google.com\r\n"
- "Connection: keep-alive\r\n"
- "Content-Length: 0\r\n"
- "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
- MockWrite(SYNCHRONOUS, unreadable_contents.c_str(),
- temp_file_contents.length()),
- MockWrite(SYNCHRONOUS, OK),
- };
- StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
- arraysize(data_writes));
+ StaticSocketDataProvider data;
session_deps_.socket_factory->AddSocketDataProvider(&data);
- TestCompletionCallback callback1;
-
- int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
- EXPECT_EQ(ERR_IO_PENDING, rv);
-
- rv = callback1.WaitForResult();
- EXPECT_EQ(OK, rv);
-
- const HttpResponseInfo* response = trans->GetResponseInfo();
- ASSERT_TRUE(response != NULL);
- ASSERT_TRUE(response->headers.get() != NULL);
- EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
- EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
-
- // Now make the file unreadable and try again.
- ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
-
- TestCompletionCallback callback2;
-
- rv = trans->RestartWithAuth(
- AuthCredentials(kFoo, kBar), callback2.callback());
+ TestCompletionCallback callback;
+ int rv = trans->Start(&request, callback.callback(), BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
+ base::MessageLoop::current()->RunUntilIdle();
- rv = callback2.WaitForResult();
- EXPECT_EQ(OK, rv);
-
- response = trans->GetResponseInfo();
- ASSERT_TRUE(response != NULL);
- EXPECT_TRUE(response->headers.get() != NULL);
- EXPECT_TRUE(response->auth_challenge.get() == NULL);
- EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
+ // Transaction is pending on request body initialization.
+ ASSERT_FALSE(fake_reader->callback().is_null());
- base::DeleteFile(temp_file, false);
+ // Return Init()'s result after the transaction gets destroyed.
+ trans.reset();
+ fake_reader->callback().Run(OK); // Should not crash.
}
// Tests that changes to Auth realms are treated like auth rejections.
@@ -7938,9 +7891,9 @@ TEST_P(HttpNetworkTransactionTest, ChangeAuthRealms) {
TestCompletionCallback callback1;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
// Issue the first request with Authorize headers. There should be a
// password prompt for first_realm waiting to be filled in after the
@@ -9313,8 +9266,7 @@ TEST_P(HttpNetworkTransactionTest, GenerateAuthToken) {
request.load_flags = 0;
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
- HttpNetworkTransaction trans(
- DEFAULT_PRIORITY, CreateSession(&session_deps_));
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session);
for (int round = 0; round < test_config.num_auth_rounds; ++round) {
const TestRound& read_write_round = test_config.rounds[round];
@@ -9416,10 +9368,11 @@ TEST_P(HttpNetworkTransactionTest, MultiRoundAuth) {
session_deps_.host_resolver.get(),
session_deps_.socket_factory.get(),
session_deps_.net_log);
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_pool);
- session_peer.SetClientSocketPoolManager(mock_pool_manager);
+ session_peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
scoped_ptr<HttpTransaction> trans(
new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get()));
@@ -9869,9 +9822,9 @@ TEST_P(HttpNetworkTransactionTest, SimpleCancel) {
request.load_flags = 0;
session_deps_.host_resolver->set_synchronous_mode(true);
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
data.set_connect_data(mock_connect);
@@ -11551,9 +11504,9 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncConnectError) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockConnect mock_connect(SYNCHRONOUS, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider data;
@@ -11581,9 +11534,9 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncConnectError) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
StaticSocketDataProvider data;
@@ -11611,9 +11564,9 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncWriteError) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite(SYNCHRONOUS, ERR_CONNECTION_RESET),
@@ -11647,9 +11600,9 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncWriteError) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite(ASYNC, ERR_CONNECTION_RESET),
@@ -11683,9 +11636,9 @@ TEST_P(HttpNetworkTransactionTest, HttpSyncReadError) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -11721,9 +11674,9 @@ TEST_P(HttpNetworkTransactionTest, HttpAsyncReadError) {
request.url = GURL("http://www.google.com/");
request.load_flags = 0;
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -11760,9 +11713,9 @@ TEST_P(HttpNetworkTransactionTest, GetFullRequestHeadersIncludesExtraHeader) {
request.load_flags = 0;
request.extra_headers.SetHeader("X-Foo", "bar");
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
scoped_ptr<HttpTransaction> trans(
- new HttpNetworkTransaction(DEFAULT_PRIORITY,
- CreateSession(&session_deps_)));
+ new HttpNetworkTransaction(DEFAULT_PRIORITY, session));
MockWrite data_writes[] = {
MockWrite("GET / HTTP/1.1\r\n"
@@ -11862,6 +11815,11 @@ class FakeStream : public HttpStreamBase,
return false;
}
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE {
+ ADD_FAILURE();
+ return 0;
+ }
+
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE {
ADD_FAILURE();
@@ -11904,12 +11862,25 @@ class FakeStreamRequest : public HttpStreamRequest,
FakeStreamRequest(RequestPriority priority,
HttpStreamRequest::Delegate* delegate)
: priority_(priority),
- delegate_(delegate) {}
+ delegate_(delegate),
+ websocket_stream_create_helper_(NULL) {}
+
+ FakeStreamRequest(RequestPriority priority,
+ HttpStreamRequest::Delegate* delegate,
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper)
+ : priority_(priority),
+ delegate_(delegate),
+ websocket_stream_create_helper_(create_helper) {}
virtual ~FakeStreamRequest() {}
RequestPriority priority() const { return priority_; }
+ const WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_stream_create_helper() const {
+ return websocket_stream_create_helper_;
+ }
+
// Create a new FakeStream and pass it to the request's
// delegate. Returns a weak pointer to the FakeStream.
base::WeakPtr<FakeStream> FinishStreamRequest() {
@@ -11951,6 +11922,7 @@ class FakeStreamRequest : public HttpStreamRequest,
private:
RequestPriority priority_;
HttpStreamRequest::Delegate* const delegate_;
+ WebSocketHandshakeStreamBase::CreateHelper* websocket_stream_create_helper_;
DISALLOW_COPY_AND_ASSIGN(FakeStreamRequest);
};
@@ -11979,16 +11951,18 @@ class FakeStreamFactory : public HttpStreamFactory {
return fake_request;
}
- virtual HttpStreamRequest* RequestWebSocketStream(
+ virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* factory,
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) OVERRIDE {
- ADD_FAILURE();
- return NULL;
+ FakeStreamRequest* fake_request =
+ new FakeStreamRequest(priority, delegate, create_helper);
+ last_stream_request_ = fake_request->AsWeakPtr();
+ return fake_request;
}
virtual void PreconnectStreams(int num_streams,
@@ -12015,6 +11989,33 @@ class FakeStreamFactory : public HttpStreamFactory {
DISALLOW_COPY_AND_ASSIGN(FakeStreamFactory);
};
+// TODO(yhirano): Split this class out into a net/websockets file, if it is
+// worth doing.
+class FakeWebSocketStreamCreateHelper :
+ public WebSocketHandshakeStreamBase::CreateHelper {
+ public:
+ virtual WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) OVERRIDE {
+ NOTREACHED();
+ return NULL;
+ }
+
+ virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
+ const base::WeakPtr<SpdySession>& session,
+ bool use_relative_url) OVERRIDE {
+ NOTREACHED();
+ return NULL;
+ };
+
+ virtual ~FakeWebSocketStreamCreateHelper() {}
+
+ virtual scoped_ptr<WebSocketStream> Upgrade() {
+ NOTREACHED();
+ return scoped_ptr<WebSocketStream>();
+ }
+};
+
} // namespace
// Make sure that HttpNetworkTransaction passes on its priority to its
@@ -12023,7 +12024,7 @@ TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriorityOnStart) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
- peer.SetHttpStreamFactory(fake_factory);
+ peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
@@ -12046,7 +12047,7 @@ TEST_P(HttpNetworkTransactionTest, SetStreamRequestPriority) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
- peer.SetHttpStreamFactory(fake_factory);
+ peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
@@ -12071,7 +12072,7 @@ TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
HttpNetworkSessionPeer peer(session);
FakeStreamFactory* fake_factory = new FakeStreamFactory();
- peer.SetHttpStreamFactory(fake_factory);
+ peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(fake_factory));
HttpNetworkTransaction trans(LOW, session);
@@ -12091,6 +12092,39 @@ TEST_P(HttpNetworkTransactionTest, SetStreamPriority) {
EXPECT_EQ(LOWEST, fake_stream->priority());
}
+TEST_P(HttpNetworkTransactionTest, CreateWebSocketHandshakeStream) {
+ // The same logic needs to be tested for both ws: and wss: schemes, but this
+ // test is already parameterised on NextProto, so it uses a loop to verify
+ // that the different schemes work.
+ std::string test_cases[] = {"ws://www.google.com/", "wss://www.google.com/"};
+ for (size_t i = 0; i < arraysize(test_cases); ++i) {
+ scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
+ HttpNetworkSessionPeer peer(session);
+ FakeStreamFactory* fake_factory = new FakeStreamFactory();
+ FakeWebSocketStreamCreateHelper websocket_stream_create_helper;
+ peer.SetHttpStreamFactoryForWebSocket(
+ scoped_ptr<HttpStreamFactory>(fake_factory));
+
+ HttpNetworkTransaction trans(LOW, session);
+ trans.SetWebSocketHandshakeStreamCreateHelper(
+ &websocket_stream_create_helper);
+
+ HttpRequestInfo request;
+ TestCompletionCallback callback;
+ request.method = "GET";
+ request.url = GURL(test_cases[i]);
+
+ EXPECT_EQ(ERR_IO_PENDING,
+ trans.Start(&request, callback.callback(), BoundNetLog()));
+
+ base::WeakPtr<FakeStreamRequest> fake_request =
+ fake_factory->last_stream_request();
+ ASSERT_TRUE(fake_request != NULL);
+ EXPECT_EQ(&websocket_stream_create_helper,
+ fake_request->websocket_stream_create_helper());
+ }
+}
+
// Tests that when a used socket is returned to the SSL socket pool, it's closed
// if the transport socket pool is stalled on the global socket limit.
TEST_P(HttpNetworkTransactionTest, CloseSSLSocketOnIdleForHttpRequest) {
diff --git a/chromium/net/http/http_pipelined_connection_impl.cc b/chromium/net/http/http_pipelined_connection_impl.cc
index e2e53de47ba..284b25406d8 100644
--- a/chromium/net/http/http_pipelined_connection_impl.cc
+++ b/chromium/net/http/http_pipelined_connection_impl.cc
@@ -653,6 +653,13 @@ void HttpPipelinedConnectionImpl::SetConnectionReused(int pipeline_id) {
connection_->set_is_reused(true);
}
+int64 HttpPipelinedConnectionImpl::GetTotalReceivedBytes(
+ int pipeline_id) const {
+ CHECK(ContainsKey(stream_info_map_, pipeline_id));
+ CHECK(stream_info_map_.find(pipeline_id)->second.parser.get());
+ return stream_info_map_.find(pipeline_id)->second.parser->received_bytes();
+}
+
bool HttpPipelinedConnectionImpl::GetLoadTimingInfo(
int pipeline_id, LoadTimingInfo* load_timing_info) const {
return connection_->GetLoadTimingInfo(IsConnectionReused(pipeline_id),
diff --git a/chromium/net/http/http_pipelined_connection_impl.h b/chromium/net/http/http_pipelined_connection_impl.h
index f8246a06f9b..d558e47eb0b 100644
--- a/chromium/net/http/http_pipelined_connection_impl.h
+++ b/chromium/net/http/http_pipelined_connection_impl.h
@@ -125,6 +125,8 @@ class NET_EXPORT_PRIVATE HttpPipelinedConnectionImpl
void SetConnectionReused(int pipeline_id);
+ int64 GetTotalReceivedBytes(int pipeline_id) const;
+
bool GetLoadTimingInfo(int pipeline_id,
LoadTimingInfo* load_timing_info) const;
diff --git a/chromium/net/http/http_pipelined_host_forced_unittest.cc b/chromium/net/http/http_pipelined_host_forced_unittest.cc
index 37732aa800f..b86dd96d50a 100644
--- a/chromium/net/http/http_pipelined_host_forced_unittest.cc
+++ b/chromium/net/http/http_pipelined_host_forced_unittest.cc
@@ -37,7 +37,7 @@ class HttpPipelinedHostForcedTest : public testing::Test {
MatchesOrigin(key_.origin()),
Ref(ssl_config_), Ref(proxy_info_),
Ref(net_log_), true,
- kProtoSPDY2))
+ kProtoSPDY3))
.Times(1)
.WillOnce(Return(pipeline));
EXPECT_CALL(*pipeline, CreateNewStream())
@@ -45,7 +45,7 @@ class HttpPipelinedHostForcedTest : public testing::Test {
.WillOnce(Return(kDummyStream));
EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline(
&connection_, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY2));
+ kProtoSPDY3));
return pipeline;
}
diff --git a/chromium/net/http/http_pipelined_host_impl_unittest.cc b/chromium/net/http/http_pipelined_host_impl_unittest.cc
index ea49e12c105..2658472138d 100644
--- a/chromium/net/http/http_pipelined_host_impl_unittest.cc
+++ b/chromium/net/http/http_pipelined_host_impl_unittest.cc
@@ -48,7 +48,7 @@ class HttpPipelinedHostImplTest : public testing::Test {
MatchesOrigin(key_.origin()),
Ref(ssl_config_), Ref(proxy_info_),
Ref(net_log_), true,
- kProtoSPDY2))
+ kProtoSPDY3))
.Times(1)
.WillOnce(Return(pipeline));
EXPECT_CALL(*pipeline, CreateNewStream())
@@ -56,7 +56,7 @@ class HttpPipelinedHostImplTest : public testing::Test {
.WillOnce(Return(kDummyStream));
EXPECT_EQ(kDummyStream, host_->CreateStreamOnNewPipeline(
kDummyConnection, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY2));
+ kProtoSPDY3));
return pipeline;
}
@@ -208,7 +208,7 @@ TEST_F(HttpPipelinedHostImplTest, ShutsDownOnOldVersion) {
ClearTestPipeline(pipeline);
EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline(
kDummyConnection, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY2));
+ kProtoSPDY3));
}
TEST_F(HttpPipelinedHostImplTest, ShutsDownOnAuthenticationRequired) {
@@ -227,7 +227,7 @@ TEST_F(HttpPipelinedHostImplTest, ShutsDownOnAuthenticationRequired) {
ClearTestPipeline(pipeline);
EXPECT_EQ(NULL, host_->CreateStreamOnNewPipeline(
kDummyConnection, ssl_config_, proxy_info_, net_log_, true,
- kProtoSPDY2));
+ kProtoSPDY3));
}
TEST_F(HttpPipelinedHostImplTest, ConnectionCloseHasNoEffect) {
diff --git a/chromium/net/http/http_pipelined_stream.cc b/chromium/net/http/http_pipelined_stream.cc
index df5743556d1..cc267e2510e 100644
--- a/chromium/net/http/http_pipelined_stream.cc
+++ b/chromium/net/http/http_pipelined_stream.cc
@@ -99,6 +99,10 @@ bool HttpPipelinedStream::IsConnectionReusable() const {
return pipeline_->usable();
}
+int64 HttpPipelinedStream::GetTotalReceivedBytes() const {
+ return pipeline_->GetTotalReceivedBytes(pipeline_id_);
+}
+
bool HttpPipelinedStream::GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const {
return pipeline_->GetLoadTimingInfo(pipeline_id_, load_timing_info);
diff --git a/chromium/net/http/http_pipelined_stream.h b/chromium/net/http/http_pipelined_stream.h
index d3a7991e5ca..7a853abc1a7 100644
--- a/chromium/net/http/http_pipelined_stream.h
+++ b/chromium/net/http/http_pipelined_stream.h
@@ -69,6 +69,8 @@ class HttpPipelinedStream : public HttpStream {
virtual bool IsConnectionReusable() const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const 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 808305240ad..a70fe6ab067 100644
--- a/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/chromium/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -41,7 +41,7 @@ enum HttpProxyType {
struct HttpProxyClientSocketPoolTestParams {
HttpProxyClientSocketPoolTestParams()
: proxy_type(HTTP),
- protocol(kProtoSPDY2) {}
+ protocol(kProtoSPDY3) {}
HttpProxyClientSocketPoolTestParams(
HttpProxyType proxy_type,
@@ -77,6 +77,7 @@ class HttpProxyClientSocketPoolTest
session_deps_.cert_verifier.get(),
NULL /* server_bound_cert_store */,
NULL /* transport_security_state */,
+ NULL /* cert_transparency_verifier */,
std::string() /* ssl_session_cache_shard */,
session_deps_.deterministic_socket_factory.get(),
&transport_socket_pool_,
@@ -238,9 +239,9 @@ INSTANTIATE_TEST_CASE_P(
HttpProxyClientSocketPoolTests,
HttpProxyClientSocketPoolTest,
::testing::Values(
- HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY2),
- HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY2),
- HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY2),
+ HttpProxyClientSocketPoolTestParams(HTTP, kProtoDeprecatedSPDY2),
+ HttpProxyClientSocketPoolTestParams(HTTPS, kProtoDeprecatedSPDY2),
+ HttpProxyClientSocketPoolTestParams(SPDY, kProtoDeprecatedSPDY2),
HttpProxyClientSocketPoolTestParams(HTTP, kProtoSPDY3),
HttpProxyClientSocketPoolTestParams(HTTPS, kProtoSPDY3),
HttpProxyClientSocketPoolTestParams(SPDY, kProtoSPDY3),
diff --git a/chromium/net/http/http_request_headers.cc b/chromium/net/http/http_request_headers.cc
index bf557df37b8..8c9c4289336 100644
--- a/chromium/net/http/http_request_headers.cc
+++ b/chromium/net/http/http_request_headers.cc
@@ -11,6 +11,18 @@
#include "base/values.h"
#include "net/http/http_util.h"
+namespace {
+
+bool ShouldShowHttpHeaderValue(const std::string& header_name) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (header_name == "Proxy-Authorization")
+ return false;
+#endif
+ return true;
+}
+
+} // namespace
+
namespace net {
const char HttpRequestHeaders::kGetMethod[] = "GET";
@@ -191,10 +203,11 @@ base::Value* HttpRequestHeaders::NetLogCallback(
base::ListValue* headers = new base::ListValue();
for (HeaderVector::const_iterator it = headers_.begin();
it != headers_.end(); ++it) {
- headers->Append(
- new base::StringValue(base::StringPrintf("%s: %s",
- it->key.c_str(),
- it->value.c_str())));
+ headers->Append(new base::StringValue(
+ base::StringPrintf("%s: %s",
+ it->key.c_str(),
+ (ShouldShowHttpHeaderValue(it->key) ?
+ it->value.c_str() : "[elided]"))));
}
dict->Set("headers", headers);
return dict;
diff --git a/chromium/net/http/http_request_info.cc b/chromium/net/http/http_request_info.cc
index 7feb4ac3d7f..bffc96ccfae 100644
--- a/chromium/net/http/http_request_info.cc
+++ b/chromium/net/http/http_request_info.cc
@@ -10,7 +10,6 @@ HttpRequestInfo::HttpRequestInfo()
: upload_data_stream(NULL),
load_flags(0),
motivation(NORMAL_MOTIVATION),
- request_id(0),
privacy_mode(kPrivacyModeDisabled) {
}
diff --git a/chromium/net/http/http_request_info.h b/chromium/net/http/http_request_info.h
index 607bba5806d..a587a421b58 100644
--- a/chromium/net/http/http_request_info.h
+++ b/chromium/net/http/http_request_info.h
@@ -49,10 +49,6 @@ struct NET_EXPORT HttpRequestInfo {
// The motivation behind this request.
RequestMotivation motivation;
- // An optional globally unique identifier for this request for use by the
- // consumer. 0 is invalid.
- uint64 request_id;
-
// If enabled, then request must be sent over connection that cannot be
// tracked by the server (e.g. without channel id).
PrivacyMode privacy_mode;
diff --git a/chromium/net/http/http_response_body_drainer.cc b/chromium/net/http/http_response_body_drainer.cc
index d8f00853509..a1ba35ad31e 100644
--- a/chromium/net/http/http_response_body_drainer.cc
+++ b/chromium/net/http/http_response_body_drainer.cc
@@ -9,11 +9,11 @@
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_network_session.h"
-#include "net/http/http_stream.h"
+#include "net/http/http_stream_base.h"
namespace net {
-HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStream* stream)
+HttpResponseBodyDrainer::HttpResponseBodyDrainer(HttpStreamBase* stream)
: read_size_(0),
stream_(stream),
next_state_(STATE_NONE),
diff --git a/chromium/net/http/http_response_body_drainer.h b/chromium/net/http/http_response_body_drainer.h
index 915305cda46..284d08a99cd 100644
--- a/chromium/net/http/http_response_body_drainer.h
+++ b/chromium/net/http/http_response_body_drainer.h
@@ -15,7 +15,7 @@
namespace net {
-class HttpStream;
+class HttpStreamBase;
class IOBuffer;
class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
@@ -27,7 +27,7 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
static const int kDrainBodyBufferSize = 16384;
static const int kTimeoutInSeconds = 5;
- explicit HttpResponseBodyDrainer(HttpStream* stream);
+ explicit HttpResponseBodyDrainer(HttpStreamBase* stream);
~HttpResponseBodyDrainer();
// Starts reading the body until completion, or we hit the buffer limit, or we
@@ -56,7 +56,7 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
int read_size_;
scoped_refptr<IOBuffer> read_buf_;
- const scoped_ptr<HttpStream> stream_;
+ const scoped_ptr<HttpStreamBase> stream_;
State next_state_;
int total_read_;
CompletionCallback user_callback_;
diff --git a/chromium/net/http/http_response_body_drainer_unittest.cc b/chromium/net/http/http_response_body_drainer_unittest.cc
index 70134cce1ea..f587b908529 100644
--- a/chromium/net/http/http_response_body_drainer_unittest.cc
+++ b/chromium/net/http/http_response_body_drainer_unittest.cc
@@ -101,6 +101,7 @@ class MockHttpStream : public HttpStream {
virtual bool IsConnectionReused() const OVERRIDE { return false; }
virtual void SetConnectionReused() OVERRIDE {}
virtual bool IsConnectionReusable() const OVERRIDE { return false; }
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; }
virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {}
virtual void GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) OVERRIDE {}
diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc
index 6047aa12ac8..289facd4f9e 100644
--- a/chromium/net/http/http_response_headers.cc
+++ b/chromium/net/http/http_response_headers.cc
@@ -113,6 +113,14 @@ void CheckDoesNotHaveEmbededNulls(const std::string& str) {
CHECK(str.find('\0') == std::string::npos);
}
+bool ShouldShowHttpHeaderValue(const std::string& header_name) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (header_name == "Proxy-Authenticate")
+ return false;
+#endif
+ return true;
+}
+
} // namespace
struct HttpResponseHeaders::ParsedHeader {
@@ -1309,9 +1317,11 @@ base::Value* HttpResponseHeaders::NetLogCallback(
std::string value;
while (EnumerateHeaderLines(&iterator, &name, &value)) {
headers->Append(
- new base::StringValue(base::StringPrintf("%s: %s",
- name.c_str(),
- value.c_str())));
+ new base::StringValue(
+ base::StringPrintf("%s: %s",
+ name.c_str(),
+ (ShouldShowHttpHeaderValue(name) ?
+ value.c_str() : "[elided]"))));
}
dict->Set("headers", headers);
return dict;
@@ -1354,4 +1364,59 @@ bool HttpResponseHeaders::IsChunkEncoded() const {
HasHeaderValue("Transfer-Encoding", "chunked");
}
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+bool HttpResponseHeaders::GetChromeProxyBypassDuration(
+ const std::string& action_prefix,
+ base::TimeDelta* duration) const {
+ void* iter = NULL;
+ std::string value;
+ std::string name = "chrome-proxy";
+
+ while (EnumerateHeader(&iter, name, &value)) {
+ if (value.size() > action_prefix.size()) {
+ if (LowerCaseEqualsASCII(value.begin(),
+ value.begin() + action_prefix.size(),
+ action_prefix.c_str())) {
+ int64 seconds;
+ if (!base::StringToInt64(
+ StringPiece(value.begin() + action_prefix.size(), value.end()),
+ &seconds) || seconds < 0) {
+ continue; // In case there is a well formed instruction.
+ }
+ *duration = TimeDelta::FromSeconds(seconds);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool HttpResponseHeaders::GetChromeProxyInfo(
+ ChromeProxyInfo* proxy_info) const {
+ DCHECK(proxy_info);
+ proxy_info->bypass_all = false;
+ proxy_info->bypass_duration = base::TimeDelta();
+
+ // Support header of the form Chrome-Proxy: bypass|block=<duration>, where
+ // <duration> is the number of seconds to wait before retrying
+ // the proxy. If the duration is 0, then the default proxy retry delay
+ // (specified in |ProxyList::UpdateRetryInfoOnFallback|) will be used.
+ // 'bypass' instructs Chrome to bypass the currently connected Chrome proxy,
+ // whereas 'block' instructs Chrome to bypass all available Chrome proxies.
+
+ // 'block' takes precedence over 'bypass', so look for it first.
+ // TODO(bengr): Reduce checks for 'block' and 'bypass' to a single loop.
+ if (GetChromeProxyBypassDuration("block=", &proxy_info->bypass_duration)) {
+ proxy_info->bypass_all = true;
+ return true;
+ }
+
+ // Next, look for 'bypass'.
+ if (GetChromeProxyBypassDuration("bypass=", &proxy_info->bypass_duration))
+ return true;
+
+ return false;
+}
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
+
} // namespace net
diff --git a/chromium/net/http/http_response_headers.h b/chromium/net/http/http_response_headers.h
index 61075979535..e54ac5df669 100644
--- a/chromium/net/http/http_response_headers.h
+++ b/chromium/net/http/http_response_headers.h
@@ -250,6 +250,28 @@ class NET_EXPORT HttpResponseHeaders
// Returns true if the response is chunk-encoded.
bool IsChunkEncoded() const;
+#if defined (SPDY_PROXY_AUTH_ORIGIN)
+ // Contains instructions contained in the Chrome-Proxy header.
+ struct ChromeProxyInfo {
+ ChromeProxyInfo() : bypass_all(false) {}
+
+ // True if Chrome should bypass all available Chrome proxies. False if only
+ // the currently connected Chrome proxy should be bypassed.
+ bool bypass_all;
+
+ // Amount of time to bypass the Chrome proxy or proxies.
+ base::TimeDelta bypass_duration;
+ };
+
+ // Returns true if the Chrome-Proxy header is present and contains a bypass
+ // delay. Sets |proxy_info->bypass_duration| to the specified delay if greater
+ // than 0, and to 0 otherwise to indicate that the default proxy delay
+ // (as specified in |ProxyList::UpdateRetryInfoOnFallback|) should be used.
+ // If all available Chrome proxies should by bypassed, |bypass_all| is set to
+ // true. |proxy_info| must be non-NULL.
+ bool GetChromeProxyInfo(ChromeProxyInfo* proxy_info) const;
+#endif
+
// Creates a Value for use with the NetLog containing the response headers.
base::Value* NetLogCallback(NetLog::LogLevel log_level) const;
@@ -348,6 +370,13 @@ class NET_EXPORT HttpResponseHeaders
// Adds the set of transport security state headers.
static void AddSecurityStateHeaders(HeaderSet* header_names);
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ // Searches for the specified Chrome-Proxy action, and if present interprets
+ // its value as a duration in seconds.
+ bool GetChromeProxyBypassDuration(const std::string& action_prefix,
+ base::TimeDelta* duration) const;
+#endif
+
// We keep a list of ParsedHeader objects. These tell us where to locate the
// header-value pairs within raw_headers_.
HeaderList parsed_;
diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc
index 8bde289ed84..4be74783b74 100644
--- a/chromium/net/http/http_response_headers_unittest.cc
+++ b/chromium/net/http/http_response_headers_unittest.cc
@@ -1877,3 +1877,156 @@ TEST(HttpResponseHeadersTest, ToNetLogParamAndBackAgain) {
parsed->GetNormalizedHeaders(&normalized_recreated);
EXPECT_EQ(normalized_parsed, normalized_recreated);
}
+
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+TEST(HttpResponseHeadersTest, GetProxyBypassInfo) {
+ const struct {
+ const char* headers;
+ bool expected_result;
+ int64 expected_retry_delay;
+ bool expected_bypass_all;
+ } tests[] = {
+ { "HTTP/1.1 200 OK\n"
+ "Content-Length: 999\n",
+ false,
+ 0,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Content-Length: 999\n",
+ false,
+ 0,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 86400,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=0\n"
+ "Content-Length: 999\n",
+ true,
+ 0,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=-1\n"
+ "Content-Length: 999\n",
+ false,
+ 0,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=xyz\n"
+ "Content-Length: 999\n",
+ false,
+ 0,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass\n"
+ "Content-Length: 999\n",
+ false,
+ 0,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: foo=abc, bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 86400,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=86400, bar=abc\n"
+ "Content-Length: 999\n",
+ true,
+ 86400,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=3600\n"
+ "Chrome-Proxy: bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 3600,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=3600, bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 3600,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=, bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 86400,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass\n"
+ "Chrome-Proxy: bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 86400,
+ false,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: block=, block=3600\n"
+ "Content-Length: 999\n",
+ true,
+ 3600,
+ true,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n"
+ "Chrome-Proxy: bypass=86400, block=3600\n"
+ "Content-Length: 999\n",
+ true,
+ 3600,
+ true,
+ },
+ { "HTTP/1.1 200 OK\n"
+ "connection: proxy-bypass\n"
+ "Chrome-Proxy: block=, bypass=86400\n"
+ "Content-Length: 999\n",
+ true,
+ 86400,
+ false,
+ },
+ };
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
+ std::string headers(tests[i].headers);
+ HeadersToRaw(&headers);
+ scoped_refptr<net::HttpResponseHeaders> parsed(
+ new net::HttpResponseHeaders(headers));
+
+ net::HttpResponseHeaders::ChromeProxyInfo chrome_proxy_info;
+ EXPECT_EQ(tests[i].expected_result,
+ parsed->GetChromeProxyInfo(&chrome_proxy_info));
+ EXPECT_EQ(tests[i].expected_retry_delay,
+ chrome_proxy_info.bypass_duration.InSeconds());
+ EXPECT_EQ(tests[i].expected_bypass_all,
+ chrome_proxy_info.bypass_all);
+ }
+}
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
diff --git a/chromium/net/http/http_response_info.cc b/chromium/net/http/http_response_info.cc
index 0b57a4e774b..4f9e014cfb2 100644
--- a/chromium/net/http/http_response_info.cc
+++ b/chromium/net/http/http_response_info.cc
@@ -10,6 +10,7 @@
#include "net/base/auth.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
#include "net/http/http_response_headers.h"
#include "net/ssl/ssl_cert_request_info.h"
@@ -87,6 +88,9 @@ enum {
// This bit is set if the request has http authentication.
RESPONSE_INFO_USE_HTTP_AUTHENTICATION = 1 << 19,
+ // This bit is set if ssl_info has SCTs.
+ RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS = 1 << 20,
+
// TODO(darin): Add other bits to indicate alternate request methods.
// For now, we don't support storing those.
};
@@ -207,6 +211,22 @@ bool HttpResponseInfo::InitFromPickle(const Pickle& pickle,
ssl_info.connection_status = connection_status;
}
+ if (flags & RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS) {
+ int num_scts;
+ if (!pickle.ReadInt(&iter, &num_scts))
+ return false;
+ for (int i = 0; i < num_scts; ++i) {
+ scoped_refptr<ct::SignedCertificateTimestamp> sct(
+ ct::SignedCertificateTimestamp::CreateFromPickle(&iter));
+ uint16 status;
+ if (!sct.get() || !pickle.ReadUInt16(&iter, &status))
+ return false;
+ ssl_info.signed_certificate_timestamps.push_back(
+ SignedCertificateTimestampAndStatus(
+ sct, static_cast<ct::SCTVerifyStatus>(status)));
+ }
+ }
+
// Read vary-data
if (flags & RESPONSE_INFO_HAS_VARY_DATA) {
if (!vary_data.InitFromPickle(pickle, &iter))
@@ -286,6 +306,8 @@ void HttpResponseInfo::Persist(Pickle* pickle,
flags |= RESPONSE_INFO_HAS_CONNECTION_INFO;
if (did_use_http_auth)
flags |= RESPONSE_INFO_USE_HTTP_AUTHENTICATION;
+ if (!ssl_info.signed_certificate_timestamps.empty())
+ flags |= RESPONSE_INFO_HAS_SIGNED_CERTIFICATE_TIMESTAMPS;
pickle->WriteInt(flags);
pickle->WriteInt64(request_time.ToInternalValue());
@@ -313,6 +335,15 @@ void HttpResponseInfo::Persist(Pickle* pickle,
pickle->WriteInt(ssl_info.security_bits);
if (ssl_info.connection_status != 0)
pickle->WriteInt(ssl_info.connection_status);
+ if (!ssl_info.signed_certificate_timestamps.empty()) {
+ pickle->WriteInt(ssl_info.signed_certificate_timestamps.size());
+ for (SignedCertificateTimestampAndStatusList::const_iterator it =
+ ssl_info.signed_certificate_timestamps.begin(); it !=
+ ssl_info.signed_certificate_timestamps.end(); ++it) {
+ it->sct_->Persist(pickle);
+ pickle->WriteUInt16(it->status_);
+ }
+ }
}
if (vary_data.is_valid())
@@ -331,8 +362,8 @@ void HttpResponseInfo::Persist(Pickle* pickle,
HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto(
NextProto next_proto) {
switch (next_proto) {
- case kProtoSPDY2:
- return CONNECTION_INFO_SPDY2;
+ case kProtoDeprecatedSPDY2:
+ return CONNECTION_INFO_DEPRECATED_SPDY2;
case kProtoSPDY3:
case kProtoSPDY31:
return CONNECTION_INFO_SPDY3;
@@ -345,8 +376,6 @@ HttpResponseInfo::ConnectionInfo HttpResponseInfo::ConnectionInfoFromNextProto(
case kProtoUnknown:
case kProtoHTTP11:
- case kProtoSPDY1:
- case kProtoSPDY21:
break;
}
@@ -362,7 +391,7 @@ std::string HttpResponseInfo::ConnectionInfoToString(
return "unknown";
case CONNECTION_INFO_HTTP1:
return "http/1";
- case CONNECTION_INFO_SPDY2:
+ case CONNECTION_INFO_DEPRECATED_SPDY2:
return "spdy/2";
case CONNECTION_INFO_SPDY3:
return "spdy/3";
diff --git a/chromium/net/http/http_response_info.h b/chromium/net/http/http_response_info.h
index 907ec96a570..f0908b0ab46 100644
--- a/chromium/net/http/http_response_info.h
+++ b/chromium/net/http/http_response_info.h
@@ -35,7 +35,7 @@ class NET_EXPORT HttpResponseInfo {
enum ConnectionInfo {
CONNECTION_INFO_UNKNOWN = 0,
CONNECTION_INFO_HTTP1 = 1,
- CONNECTION_INFO_SPDY2 = 2,
+ CONNECTION_INFO_DEPRECATED_SPDY2 = 2,
CONNECTION_INFO_SPDY3 = 3,
CONNECTION_INFO_SPDY4A2 = 4,
CONNECTION_INFO_QUIC1_SPDY3 = 5,
diff --git a/chromium/net/http/http_security_headers.cc b/chromium/net/http/http_security_headers.cc
index 9fc7627cc5e..0c3305f6e42 100644
--- a/chromium/net/http/http_security_headers.cc
+++ b/chromium/net/http/http_security_headers.cc
@@ -325,7 +325,18 @@ bool ParseHPKPHeader(const std::string& value,
*include_subdomains = include_subdomains_candidate;
for (HashValueVector::const_iterator i = pins.begin();
i != pins.end(); ++i) {
- hashes->push_back(*i);
+ bool found = false;
+
+ for (HashValueVector::const_iterator j = hashes->begin();
+ j != hashes->end(); ++j) {
+ if (j->Equals(*i)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ hashes->push_back(*i);
}
return true;
diff --git a/chromium/net/http/http_security_headers_unittest.cc b/chromium/net/http/http_security_headers_unittest.cc
index 0cc81b57eb8..42a5ee98960 100644
--- a/chromium/net/http/http_security_headers_unittest.cc
+++ b/chromium/net/http/http_security_headers_unittest.cc
@@ -416,6 +416,20 @@ static void TestValidPKPHeaders(HashValueTag tag) {
expect_max_age = base::TimeDelta::FromSeconds(kMaxHSTSAgeSecs);
EXPECT_EQ(expect_max_age, max_age);
EXPECT_FALSE(include_subdomains);
+
+ // Test that parsing the same header twice doesn't duplicate the recorded
+ // hashes.
+ hashes.clear();
+ EXPECT_TRUE(ParseHPKPHeader(
+ " max-age=999; " +
+ backup_pin + ";" + good_pin + "; ",
+ chain_hashes, &max_age, &include_subdomains, &hashes));
+ EXPECT_EQ(2u, hashes.size());
+ EXPECT_TRUE(ParseHPKPHeader(
+ " max-age=999; " +
+ backup_pin + ";" + good_pin + "; ",
+ chain_hashes, &max_age, &include_subdomains, &hashes));
+ EXPECT_EQ(2u, hashes.size());
}
TEST_F(HttpSecurityHeadersTest, BogusPinsHeadersSHA1) {
diff --git a/chromium/net/http/http_server_properties.cc b/chromium/net/http/http_server_properties.cc
index bff262ade45..a10d5060c06 100644
--- a/chromium/net/http/http_server_properties.cc
+++ b/chromium/net/http/http_server_properties.cc
@@ -16,7 +16,6 @@ namespace {
// The order of these strings much match the order of the enum definition
// for AlternateProtocol.
const char* const kAlternateProtocolStrings[] = {
- "npn-spdy/1",
"npn-spdy/2",
"npn-spdy/3",
"npn-spdy/3.1",
@@ -26,25 +25,28 @@ const char* const kAlternateProtocolStrings[] = {
};
const char kBrokenAlternateProtocol[] = "Broken";
-COMPILE_ASSERT(arraysize(kAlternateProtocolStrings) == NUM_ALTERNATE_PROTOCOLS,
- kAlternateProtocolStringsSize_NUM_ALTERNATE_PROTOCOLS_nut_equal);
+COMPILE_ASSERT(
+ arraysize(kAlternateProtocolStrings) == NUM_VALID_ALTERNATE_PROTOCOLS,
+ kAlternateProtocolStringsSize_kNumValidAlternateProtocols_not_equal);
} // namespace
+bool IsAlternateProtocolValid(AlternateProtocol protocol) {
+ return protocol >= ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION &&
+ protocol <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION;
+}
+
const char* AlternateProtocolToString(AlternateProtocol protocol) {
switch (protocol) {
- case NPN_SPDY_1:
- case NPN_SPDY_2:
+ case DEPRECATED_NPN_SPDY_2:
case NPN_SPDY_3:
case NPN_SPDY_3_1:
case NPN_SPDY_4A2:
case NPN_HTTP2_DRAFT_04:
case QUIC:
- DCHECK_LT(static_cast<size_t>(protocol),
- arraysize(kAlternateProtocolStrings));
- return kAlternateProtocolStrings[protocol];
- case NUM_ALTERNATE_PROTOCOLS:
- break;
+ DCHECK(IsAlternateProtocolValid(protocol));
+ return kAlternateProtocolStrings[
+ protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION];
case ALTERNATE_PROTOCOL_BROKEN:
return kBrokenAlternateProtocol;
case UNINITIALIZED_ALTERNATE_PROTOCOL:
@@ -54,19 +56,22 @@ const char* AlternateProtocolToString(AlternateProtocol protocol) {
return "";
}
-AlternateProtocol AlternateProtocolFromString(const std::string& protocol) {
- for (int i = NPN_SPDY_1; i < NUM_ALTERNATE_PROTOCOLS; ++i)
- if (protocol == kAlternateProtocolStrings[i])
- return static_cast<AlternateProtocol>(i);
- if (protocol == kBrokenAlternateProtocol)
+AlternateProtocol AlternateProtocolFromString(const std::string& str) {
+ for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
+ i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
+ AlternateProtocol protocol = static_cast<AlternateProtocol>(i);
+ if (str == AlternateProtocolToString(protocol))
+ return protocol;
+ }
+ if (str == kBrokenAlternateProtocol)
return ALTERNATE_PROTOCOL_BROKEN;
return UNINITIALIZED_ALTERNATE_PROTOCOL;
}
AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) {
switch (next_proto) {
- case kProtoSPDY2:
- return NPN_SPDY_2;
+ case kProtoDeprecatedSPDY2:
+ return DEPRECATED_NPN_SPDY_2;
case kProtoSPDY3:
return NPN_SPDY_3;
case kProtoSPDY31:
@@ -80,8 +85,6 @@ AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) {
case kProtoUnknown:
case kProtoHTTP11:
- case kProtoSPDY1:
- case kProtoSPDY21:
break;
}
diff --git a/chromium/net/http/http_server_properties.h b/chromium/net/http/http_server_properties.h
index 654d262024a..72fda4355b1 100644
--- a/chromium/net/http/http_server_properties.h
+++ b/chromium/net/http/http_server_properties.h
@@ -18,9 +18,9 @@
namespace net {
enum AlternateProtocol {
- NPN_SPDY_1 = 0,
- NPN_SPDY_MINIMUM_VERSION = NPN_SPDY_1,
- NPN_SPDY_2,
+ DEPRECATED_NPN_SPDY_2 = 0,
+ ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION = DEPRECATED_NPN_SPDY_2,
+ NPN_SPDY_MINIMUM_VERSION = DEPRECATED_NPN_SPDY_2,
NPN_SPDY_3,
NPN_SPDY_3_1,
NPN_SPDY_4A2,
@@ -28,14 +28,25 @@ enum AlternateProtocol {
NPN_HTTP2_DRAFT_04,
NPN_SPDY_MAXIMUM_VERSION = NPN_HTTP2_DRAFT_04,
QUIC,
- NUM_ALTERNATE_PROTOCOLS,
+ ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION = QUIC,
ALTERNATE_PROTOCOL_BROKEN, // The alternate protocol is known to be broken.
UNINITIALIZED_ALTERNATE_PROTOCOL,
};
+// Simply returns whether |protocol| is between
+// ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION and
+// ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION (inclusive).
+NET_EXPORT bool IsAlternateProtocolValid(AlternateProtocol protocol);
+
+enum AlternateProtocolSize {
+ NUM_VALID_ALTERNATE_PROTOCOLS =
+ ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION -
+ ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION + 1,
+};
+
NET_EXPORT const char* AlternateProtocolToString(AlternateProtocol protocol);
NET_EXPORT AlternateProtocol AlternateProtocolFromString(
- const std::string& protocol);
+ const std::string& str);
NET_EXPORT_PRIVATE AlternateProtocol AlternateProtocolFromNextProto(
NextProto next_proto);
diff --git a/chromium/net/http/http_server_properties_impl.cc b/chromium/net/http/http_server_properties_impl.cc
index a0b287de588..a4ac6dc3804 100644
--- a/chromium/net/http/http_server_properties_impl.cc
+++ b/chromium/net/http/http_server_properties_impl.cc
@@ -18,9 +18,9 @@ namespace net {
static const int kDefaultNumHostsToRemember = 200;
HttpServerPropertiesImpl::HttpServerPropertiesImpl()
- : weak_ptr_factory_(this),
- pipeline_capability_map_(
- new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)) {
+ : pipeline_capability_map_(
+ new CachedPipelineCapabilityMap(kDefaultNumHostsToRemember)),
+ weak_ptr_factory_(this) {
}
HttpServerPropertiesImpl::~HttpServerPropertiesImpl() {
diff --git a/chromium/net/http/http_server_properties_impl.h b/chromium/net/http/http_server_properties_impl.h
index c1e2d4ba20b..cf96b7d4f32 100644
--- a/chromium/net/http/http_server_properties_impl.h
+++ b/chromium/net/http/http_server_properties_impl.h
@@ -145,14 +145,14 @@ class NET_EXPORT HttpServerPropertiesImpl
// pair) that either support or not support SPDY protocol.
typedef base::hash_map<std::string, bool> SpdyServerHostPortTable;
- base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_;
-
SpdyServerHostPortTable spdy_servers_table_;
AlternateProtocolMap alternate_protocol_map_;
SpdySettingsMap spdy_settings_map_;
scoped_ptr<CachedPipelineCapabilityMap> pipeline_capability_map_;
+ base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(HttpServerPropertiesImpl);
};
diff --git a/chromium/net/http/http_server_properties_impl_unittest.cc b/chromium/net/http/http_server_properties_impl_unittest.cc
index d125adcc40c..cf3a4643f9d 100644
--- a/chromium/net/http/http_server_properties_impl_unittest.cc
+++ b/chromium/net/http/http_server_properties_impl_unittest.cc
@@ -189,12 +189,12 @@ typedef HttpServerPropertiesImplTest AlternateProtocolServerPropertiesTest;
TEST_F(AlternateProtocolServerPropertiesTest, Basic) {
HostPortPair test_host_port_pair("foo", 80);
EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
- impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_1);
+ impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3);
ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
const PortAlternateProtocolPair alternate =
impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(443, alternate.port);
- EXPECT_EQ(NPN_SPDY_1, alternate.protocol);
+ EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
impl_.Clear();
EXPECT_FALSE(impl_.HasAlternateProtocol(test_host_port_pair));
@@ -204,12 +204,12 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
HostPortPair test_host_port_pair1("foo1", 80);
impl_.SetBrokenAlternateProtocol(test_host_port_pair1);
HostPortPair test_host_port_pair2("foo2", 80);
- impl_.SetAlternateProtocol(test_host_port_pair2, 443, NPN_SPDY_1);
+ impl_.SetAlternateProtocol(test_host_port_pair2, 443, NPN_SPDY_3);
AlternateProtocolMap alternate_protocol_map;
PortAlternateProtocolPair port_alternate_protocol_pair;
port_alternate_protocol_pair.port = 123;
- port_alternate_protocol_pair.protocol = NPN_SPDY_2;
+ port_alternate_protocol_pair.protocol = NPN_SPDY_3;
alternate_protocol_map[test_host_port_pair2] = port_alternate_protocol_pair;
impl_.InitializeAlternateProtocolServers(&alternate_protocol_map);
@@ -221,7 +221,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Initialize) {
port_alternate_protocol_pair =
impl_.GetAlternateProtocol(test_host_port_pair2);
EXPECT_EQ(123, port_alternate_protocol_pair.port);
- EXPECT_EQ(NPN_SPDY_2, port_alternate_protocol_pair.protocol);
+ EXPECT_EQ(NPN_SPDY_3, port_alternate_protocol_pair.protocol);
}
TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
@@ -235,7 +235,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, SetBroken) {
impl_.SetAlternateProtocol(
test_host_port_pair,
1234,
- NPN_SPDY_1);
+ NPN_SPDY_3);
alternate = impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol)
<< "Second attempt should be ignored.";
@@ -246,7 +246,7 @@ TEST_F(AlternateProtocolServerPropertiesTest, Forced) {
PortAlternateProtocolPair default_protocol;
default_protocol.port = 1234;
- default_protocol.protocol = NPN_SPDY_2;
+ default_protocol.protocol = NPN_SPDY_3;
HttpServerPropertiesImpl::ForceAlternateProtocol(default_protocol);
// Verify the forced protocol.
@@ -258,11 +258,11 @@ TEST_F(AlternateProtocolServerPropertiesTest, Forced) {
EXPECT_EQ(default_protocol.protocol, alternate.protocol);
// Verify the real protocol overrides the forced protocol.
- impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_1);
+ impl_.SetAlternateProtocol(test_host_port_pair, 443, NPN_SPDY_3);
ASSERT_TRUE(impl_.HasAlternateProtocol(test_host_port_pair));
alternate = impl_.GetAlternateProtocol(test_host_port_pair);
EXPECT_EQ(443, alternate.port);
- EXPECT_EQ(NPN_SPDY_1, alternate.protocol);
+ EXPECT_EQ(NPN_SPDY_3, alternate.protocol);
// Turn off the static, forced alternate protocol so that tests don't
// have this state.
diff --git a/chromium/net/http/http_stream_base.h b/chromium/net/http/http_stream_base.h
index 596ed75dff1..f5dcc29409e 100644
--- a/chromium/net/http/http_stream_base.h
+++ b/chromium/net/http/http_stream_base.h
@@ -5,7 +5,7 @@
// HttpStreamBase is an interface for reading and writing data to an
// HTTP-like stream that keeps the client agnostic of the actual underlying
// transport layer. This provides an abstraction for HttpStream and
-// WebSocketStream.
+// WebSocketHandshakeStreamBase.
#ifndef NET_HTTP_HTTP_STREAM_BASE_H_
#define NET_HTTP_HTTP_STREAM_BASE_H_
@@ -110,6 +110,9 @@ class NET_EXPORT_PRIVATE HttpStreamBase {
// allows it to be reused.
virtual bool IsConnectionReusable() const = 0;
+ // Get the total number of bytes received from network for this stream.
+ virtual int64 GetTotalReceivedBytes() const = 0;
+
// Populates the connection establishment part of |load_timing_info|, and
// socket ID. |load_timing_info| must have all null times when called.
// Returns false and does nothing if there is no underlying connection, either
diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc
index a55ed075bb5..e88046fba3c 100644
--- a/chromium/net/http/http_stream_factory.cc
+++ b/chromium/net/http/http_stream_factory.cc
@@ -19,7 +19,7 @@ namespace net {
// static
std::vector<std::string>* HttpStreamFactory::next_protos_ = NULL;
// static
-bool HttpStreamFactory::enabled_protocols_[NUM_ALTERNATE_PROTOCOLS];
+bool HttpStreamFactory::enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS];
// static
bool HttpStreamFactory::spdy_enabled_ = true;
// static
@@ -34,6 +34,28 @@ std::list<HostPortPair>* HttpStreamFactory::forced_spdy_exclusions_ = NULL;
HttpStreamFactory::~HttpStreamFactory() {}
// static
+bool HttpStreamFactory::IsProtocolEnabled(AlternateProtocol protocol) {
+ DCHECK(IsAlternateProtocolValid(protocol));
+ return enabled_protocols_[
+ protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION];
+}
+
+// static
+void HttpStreamFactory::SetProtocolEnabled(AlternateProtocol protocol) {
+ DCHECK(IsAlternateProtocolValid(protocol));
+ enabled_protocols_[
+ protocol - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = true;
+}
+
+// static
+void HttpStreamFactory::ResetEnabledProtocols() {
+ for (int i = ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION;
+ i <= ALTERNATE_PROTOCOL_MAXIMUM_VALID_VERSION; ++i) {
+ enabled_protocols_[i - ALTERNATE_PROTOCOL_MINIMUM_VALID_VERSION] = false;
+ }
+}
+
+// static
void HttpStreamFactory::ResetStaticSettingsToInit() {
// WARNING: These must match the initializers above.
delete next_protos_;
@@ -44,8 +66,7 @@ void HttpStreamFactory::ResetStaticSettingsToInit() {
force_spdy_over_ssl_ = true;
force_spdy_always_ = false;
forced_spdy_exclusions_ = NULL;
- for (int i = 0; i < NUM_ALTERNATE_PROTOCOLS; ++i)
- enabled_protocols_[i] = false;
+ ResetEnabledProtocols();
}
void HttpStreamFactory::ProcessAlternateProtocol(
@@ -55,31 +76,31 @@ void HttpStreamFactory::ProcessAlternateProtocol(
std::vector<std::string> port_protocol_vector;
base::SplitString(alternate_protocol_str, ':', &port_protocol_vector);
if (port_protocol_vector.size() != 2) {
- DLOG(WARNING) << kAlternateProtocolHeader
- << " header has too many tokens: "
- << alternate_protocol_str;
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has too many tokens: "
+ << alternate_protocol_str;
return;
}
int port;
if (!base::StringToInt(port_protocol_vector[0], &port) ||
port <= 0 || port >= 1 << 16) {
- DLOG(WARNING) << kAlternateProtocolHeader
- << " header has unrecognizable port: "
- << port_protocol_vector[0];
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has unrecognizable port: "
+ << port_protocol_vector[0];
return;
}
AlternateProtocol protocol =
AlternateProtocolFromString(port_protocol_vector[1]);
- if (protocol < NUM_ALTERNATE_PROTOCOLS && !enabled_protocols_[protocol])
+ if (IsAlternateProtocolValid(protocol) && !IsProtocolEnabled(protocol)) {
protocol = ALTERNATE_PROTOCOL_BROKEN;
+ }
if (protocol == ALTERNATE_PROTOCOL_BROKEN) {
- // Currently, we only recognize the npn-spdy protocol.
- DLOG(WARNING) << kAlternateProtocolHeader
- << " header has unrecognized protocol: "
- << port_protocol_vector[1];
+ DVLOG(1) << kAlternateProtocolHeader
+ << " header has unrecognized protocol: "
+ << port_protocol_vector[1];
return;
}
@@ -136,16 +157,6 @@ bool HttpStreamFactory::HasSpdyExclusion(const HostPortPair& endpoint) {
}
// static
-void HttpStreamFactory::EnableNpnSpdy() {
- set_use_alternate_protocols(true);
- std::vector<NextProto> next_protos;
- next_protos.push_back(kProtoHTTP11);
- next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY2);
- SetNextProtos(next_protos);
-}
-
-// static
void HttpStreamFactory::EnableNpnHttpOnly() {
// Avoid alternate protocol in this case. Otherwise, browser will try SSL
// and then fallback to http. This introduces extra load.
@@ -161,7 +172,6 @@ void HttpStreamFactory::EnableNpnSpdy3() {
std::vector<NextProto> next_protos;
next_protos.push_back(kProtoHTTP11);
next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY2);
next_protos.push_back(kProtoSPDY3);
SetNextProtos(next_protos);
}
@@ -172,7 +182,18 @@ void HttpStreamFactory::EnableNpnSpdy31() {
std::vector<NextProto> next_protos;
next_protos.push_back(kProtoHTTP11);
next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY2);
+ next_protos.push_back(kProtoSPDY3);
+ next_protos.push_back(kProtoSPDY31);
+ SetNextProtos(next_protos);
+}
+
+// static
+void HttpStreamFactory::EnableNpnSpdy31WithSpdy2() {
+ set_use_alternate_protocols(true);
+ std::vector<NextProto> next_protos;
+ next_protos.push_back(kProtoHTTP11);
+ next_protos.push_back(kProtoQUIC1SPDY3);
+ next_protos.push_back(kProtoDeprecatedSPDY2);
next_protos.push_back(kProtoSPDY3);
next_protos.push_back(kProtoSPDY31);
SetNextProtos(next_protos);
@@ -184,7 +205,6 @@ void HttpStreamFactory::EnableNpnSpdy4a2() {
std::vector<NextProto> next_protos;
next_protos.push_back(kProtoHTTP11);
next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY2);
next_protos.push_back(kProtoSPDY3);
next_protos.push_back(kProtoSPDY31);
next_protos.push_back(kProtoSPDY4a2);
@@ -197,7 +217,6 @@ void HttpStreamFactory::EnableNpnHttp2Draft04() {
std::vector<NextProto> next_protos;
next_protos.push_back(kProtoHTTP11);
next_protos.push_back(kProtoQUIC1SPDY3);
- next_protos.push_back(kProtoSPDY2);
next_protos.push_back(kProtoSPDY3);
next_protos.push_back(kProtoSPDY31);
next_protos.push_back(kProtoSPDY4a2);
@@ -212,8 +231,7 @@ void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) {
next_protos_->clear();
- for (uint32 i = 0; i < NUM_ALTERNATE_PROTOCOLS; ++i)
- enabled_protocols_[i] = false;
+ ResetEnabledProtocols();
// TODO(rtenneti): bug 116575 - consider combining the NextProto and
// AlternateProtocol.
@@ -229,11 +247,11 @@ void HttpStreamFactory::SetNextProtos(const std::vector<NextProto>& value) {
// which has not corresponding alternative.
if (proto != kProtoHTTP11) {
AlternateProtocol alternate = AlternateProtocolFromNextProto(proto);
- if (alternate == UNINITIALIZED_ALTERNATE_PROTOCOL) {
+ if (!IsAlternateProtocolValid(alternate)) {
NOTREACHED() << "Invalid next proto: " << proto;
continue;
}
- enabled_protocols_[alternate] = true;
+ SetProtocolEnabled(alternate);
}
}
}
diff --git a/chromium/net/http/http_stream_factory.h b/chromium/net/http/http_stream_factory.h
index 0de3b65bc57..0d854a5dd9d 100644
--- a/chromium/net/http/http_stream_factory.h
+++ b/chromium/net/http/http_stream_factory.h
@@ -21,7 +21,7 @@
// 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_stream_base.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
class GURL;
@@ -71,17 +71,17 @@ class NET_EXPORT_PRIVATE HttpStreamRequest {
const ProxyInfo& used_proxy_info,
HttpStreamBase* stream) = 0;
- // This is the success case for RequestWebSocketStream.
+ // This is the success case for RequestWebSocketHandshakeStream.
// |stream| is now owned by the delegate.
// |used_ssl_config| indicates the actual SSL configuration used for this
// stream, since the HttpStreamRequest may have modified the configuration
// during stream processing.
// |used_proxy_info| indicates the actual ProxyInfo used for this stream,
// since the HttpStreamRequest performs the proxy resolution.
- virtual void OnWebSocketStreamReady(
+ virtual void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream) = 0;
+ WebSocketHandshakeStreamBase* stream) = 0;
// This is the failure to create a stream case.
// |used_ssl_config| indicates the actual SSL configuration used for this
@@ -197,15 +197,16 @@ class NET_EXPORT HttpStreamFactory {
HttpStreamRequest::Delegate* delegate,
const BoundNetLog& net_log) = 0;
- // Request a WebSocket stream.
- // Will call delegate->OnWebSocketStreamReady on successful completion.
- virtual HttpStreamRequest* RequestWebSocketStream(
+ // Request a WebSocket handshake stream.
+ // Will call delegate->OnWebSocketHandshakeStreamReady on successful
+ // completion.
+ virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* factory,
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) = 0;
// Requests that enough connections for |num_streams| be opened.
@@ -265,25 +266,24 @@ class NET_EXPORT HttpStreamFactory {
// Sets http/1.1 as the only protocol supported via NPN or Alternate-Protocol.
static void EnableNpnHttpOnly();
- // Sets http/1.1, quic and spdy/2 (the default spdy protocol) as the protocols
- // supported via NPN or Alternate-Protocol.
- static void EnableNpnSpdy();
-
- // Sets http/1.1, quic, spdy/2, and spdy/3 as the protocols supported via NPN
- // or Alternate-Protocol.
+ // Sets http/1.1, quic, and spdy/3 as the protocols supported via
+ // NPN or Alternate-Protocol.
static void EnableNpnSpdy3();
- // Sets http/1.1, quic, spdy/2, spdy/3, and spdy/3.1 as the protocols
+ // Sets http/1.1, quic, spdy/3, and spdy/3.1 as the protocols
// supported via NPN or Alternate-Protocol.
static void EnableNpnSpdy31();
- // Sets http/1.1, quic, spdy/2, spdy/3, spdy/3.1, and spdy/4a2 as
- // the protocols supported via NPN or Alternate-Protocol.
+ // Sets http/1.1, quic, spdy/2, spdy/3, and spdy/3.1 as the
+ // protocols supported via NPN or Alternate-Protocol.
+ static void EnableNpnSpdy31WithSpdy2();
+
+ // Sets http/1.1, quic, spdy/3, spdy/3.1, and spdy/4a2 as the
+ // protocols supported via NPN or Alternate-Protocol.
static void EnableNpnSpdy4a2();
- // Sets http/1.1, quic, spdy/2, spdy/3, spdy/3.1, spdy/4a2, and
- // http/2 draft 04 as the protocols supported via NPN or
- // Alternate-Protocol.
+ // Sets http/1.1, quic, spdy/3, spdy/3.1, spdy/4a2, and http/2 draft
+ // 04 as the protocols supported via NPN or Alternate-Protocol.
static void EnableNpnHttp2Draft04();
// Sets the protocols supported by NPN (next protocol negotiation) during the
@@ -298,8 +298,13 @@ class NET_EXPORT HttpStreamFactory {
HttpStreamFactory();
private:
+ // |protocol| must be a valid protocol value.
+ static bool IsProtocolEnabled(AlternateProtocol protocol);
+ static void SetProtocolEnabled(AlternateProtocol protocol);
+ static void ResetEnabledProtocols();
+
static std::vector<std::string>* next_protos_;
- static bool enabled_protocols_[NUM_ALTERNATE_PROTOCOLS];
+ static bool enabled_protocols_[NUM_VALID_ALTERNATE_PROTOCOLS];
static bool spdy_enabled_;
static bool use_alternate_protocols_;
static bool force_spdy_over_ssl_;
diff --git a/chromium/net/http/http_stream_factory_impl.cc b/chromium/net/http/http_stream_factory_impl.cc
index 35d94d779f8..056a0f6b879 100644
--- a/chromium/net/http/http_stream_factory_impl.cc
+++ b/chromium/net/http/http_stream_factory_impl.cc
@@ -82,22 +82,22 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStream(
net_log);
}
-HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketStream(
+HttpStreamRequest* HttpStreamFactoryImpl::RequestWebSocketHandshakeStream(
const HttpRequestInfo& request_info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* factory,
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) {
DCHECK(for_websockets_);
- DCHECK(factory);
+ DCHECK(create_helper);
return RequestStreamInternal(request_info,
priority,
server_ssl_config,
proxy_ssl_config,
delegate,
- factory,
+ create_helper,
net_log);
}
@@ -107,12 +107,13 @@ HttpStreamRequest* HttpStreamFactoryImpl::RequestStreamInternal(
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* websocket_stream_factory,
+ WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_handshake_stream_create_helper,
const BoundNetLog& net_log) {
Request* request = new Request(request_info.url,
this,
delegate,
- websocket_stream_factory,
+ websocket_handshake_stream_create_helper,
net_log);
GURL alternate_url;
@@ -207,11 +208,10 @@ PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
if (alternate.protocol == ALTERNATE_PROTOCOL_BROKEN)
return kNoAlternateProtocol;
- DCHECK_LE(NPN_SPDY_1, alternate.protocol);
- DCHECK_GT(NUM_ALTERNATE_PROTOCOLS, alternate.protocol);
-
- if (alternate.protocol < NPN_SPDY_2)
+ if (!IsAlternateProtocolValid(alternate.protocol)) {
+ NOTREACHED();
return kNoAlternateProtocol;
+ }
// Some shared unix systems may have user home directories (like
// http://foo.com/~mike) which allow users to emit headers. This is a bad
@@ -290,15 +290,15 @@ void HttpStreamFactoryImpl::OnNewSpdySessionReady(
using_spdy,
net_log);
if (for_websockets_) {
- WebSocketStreamBase::Factory* factory =
- request->websocket_stream_factory();
- DCHECK(factory);
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper =
+ request->websocket_handshake_stream_create_helper();
+ DCHECK(create_helper);
bool use_relative_url = direct || request->url().SchemeIs("wss");
- request->OnWebSocketStreamReady(
+ request->OnWebSocketHandshakeStreamReady(
NULL,
used_ssl_config,
used_proxy_info,
- factory->CreateSpdyStream(spdy_session, use_relative_url));
+ create_helper->CreateSpdyStream(spdy_session, use_relative_url));
} else {
bool use_relative_url = direct || request->url().SchemeIs("https");
request->OnStreamReady(
diff --git a/chromium/net/http/http_stream_factory_impl.h b/chromium/net/http/http_stream_factory_impl.h
index 4339fd350d7..4824dece14f 100644
--- a/chromium/net/http/http_stream_factory_impl.h
+++ b/chromium/net/http/http_stream_factory_impl.h
@@ -30,7 +30,8 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
public HttpPipelinedHostPool::Delegate {
public:
// RequestStream may only be called if |for_websockets| is false.
- // RequestWebSocketStream may only be called if |for_websockets| is true.
+ // RequestWebSocketHandshakeStream may only be called if |for_websockets|
+ // is true.
HttpStreamFactoryImpl(HttpNetworkSession* session, bool for_websockets);
virtual ~HttpStreamFactoryImpl();
@@ -43,13 +44,13 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
HttpStreamRequest::Delegate* delegate,
const BoundNetLog& net_log) OVERRIDE;
- virtual HttpStreamRequest* RequestWebSocketStream(
+ virtual HttpStreamRequest* RequestWebSocketHandshakeStream(
const HttpRequestInfo& info,
RequestPriority priority,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* factory,
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log) OVERRIDE;
virtual void PreconnectStreams(int num_streams,
@@ -84,7 +85,7 @@ class NET_EXPORT_PRIVATE HttpStreamFactoryImpl :
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* factory,
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper,
const BoundNetLog& net_log);
PortAlternateProtocolPair GetAlternateProtocolRequestFor(
diff --git a/chromium/net/http/http_stream_factory_impl_job.cc b/chromium/net/http/http_stream_factory_impl_job.cc
index c0383f4772d..c86bee7495b 100644
--- a/chromium/net/http/http_stream_factory_impl_job.cc
+++ b/chromium/net/http/http_stream_factory_impl_job.cc
@@ -52,7 +52,7 @@ base::Value* NetLogHttpStreamJobCallback(const GURL* original_url,
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetString("original_url", original_url->GetOrigin().spec());
dict->SetString("url", url->GetOrigin().spec());
- dict->SetInteger("priority", priority);
+ dict->SetString("priority", RequestPriorityToString(priority));
return dict;
}
@@ -221,9 +221,9 @@ void HttpStreamFactoryImpl::Job::Orphan(const Request* request) {
connection_->socket()->Disconnect();
stream_factory_->OnOrphanedJobComplete(this);
} else if (stream_factory_->for_websockets_) {
- // We cancel this job because WebSocketStream can't be created
- // without a WebSocketStreamBase::Factory which is stored in Request class
- // and isn't accessible from this job.
+ // We cancel this job because a WebSocketHandshakeStream can't be created
+ // without a WebSocketHandshakeStreamBase::CreateHelper which is stored in
+ // the Request class and isn't accessible from this job.
if (connection_ && connection_->socket())
connection_->socket()->Disconnect();
stream_factory_->OnOrphanedJobComplete(this);
@@ -314,7 +314,7 @@ void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
// |this| may be deleted after this call.
}
-void HttpStreamFactoryImpl::Job::OnWebSocketStreamReadyCallback() {
+void HttpStreamFactoryImpl::Job::OnWebSocketHandshakeStreamReadyCallback() {
DCHECK(websocket_stream_);
DCHECK(!IsPreconnecting());
DCHECK(stream_factory_->for_websockets_);
@@ -325,10 +325,10 @@ void HttpStreamFactoryImpl::Job::OnWebSocketStreamReadyCallback() {
protocol_negotiated(),
using_spdy(),
net_log_);
- request_->OnWebSocketStreamReady(this,
- server_ssl_config_,
- proxy_info_,
- websocket_stream_.release());
+ request_->OnWebSocketHandshakeStreamReady(this,
+ server_ssl_config_,
+ proxy_info_,
+ websocket_stream_.release());
// |this| may be deleted after this call.
}
@@ -532,9 +532,8 @@ int HttpStreamFactoryImpl::Job::RunLoop(int result) {
DCHECK(websocket_stream_);
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(
- &Job::OnWebSocketStreamReadyCallback,
- ptr_factory_.GetWeakPtr()));
+ base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback,
+ ptr_factory_.GetWeakPtr()));
} else {
DCHECK(stream_.get());
base::MessageLoop::current()->PostTask(
@@ -1065,10 +1064,10 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
CHECK(stream_.get());
} else if (stream_factory_->for_websockets_) {
DCHECK(request_);
- DCHECK(request_->websocket_stream_factory());
+ DCHECK(request_->websocket_handshake_stream_create_helper());
websocket_stream_.reset(
- request_->websocket_stream_factory()->CreateBasicStream(
- connection_.release(), using_proxy));
+ request_->websocket_handshake_stream_create_helper()
+ ->CreateBasicStream(connection_.Pass(), using_proxy));
} else if (!using_proxy && IsRequestEligibleForPipelining()) {
// TODO(simonjam): Support proxies.
stream_.reset(
@@ -1082,8 +1081,7 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
protocol_negotiated_));
CHECK(stream_.get());
} else {
- stream_.reset(new HttpBasicStream(connection_.release(), NULL,
- using_proxy));
+ stream_.reset(new HttpBasicStream(connection_.release(), using_proxy));
}
return OK;
}
@@ -1143,10 +1141,10 @@ int HttpStreamFactoryImpl::Job::DoCreateStream() {
if (stream_factory_->for_websockets_) {
DCHECK(request_);
- DCHECK(request_->websocket_stream_factory());
+ DCHECK(request_->websocket_handshake_stream_create_helper());
bool use_relative_url = direct || request_info_.url.SchemeIs("wss");
websocket_stream_.reset(
- request_->websocket_stream_factory()->CreateSpdyStream(
+ request_->websocket_handshake_stream_create_helper()->CreateSpdyStream(
spdy_session, use_relative_url));
} else {
bool use_relative_url = direct || request_info_.url.SchemeIs("https");
diff --git a/chromium/net/http/http_stream_factory_impl_job.h b/chromium/net/http/http_stream_factory_impl_job.h
index 01a794a1bc7..1970b5be08b 100644
--- a/chromium/net/http/http_stream_factory_impl_job.h
+++ b/chromium/net/http/http_stream_factory_impl_job.h
@@ -130,7 +130,7 @@ class HttpStreamFactoryImpl::Job {
};
void OnStreamReadyCallback();
- void OnWebSocketStreamReadyCallback();
+ void OnWebSocketHandshakeStreamReadyCallback();
// This callback function is called when a new SPDY session is created.
void OnNewSpdySessionReadyCallback();
void OnStreamFailedCallback(int result);
@@ -297,7 +297,7 @@ class HttpStreamFactoryImpl::Job {
bool establishing_tunnel_;
scoped_ptr<HttpStream> stream_;
- scoped_ptr<WebSocketStreamBase> websocket_stream_;
+ scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_;
// True if we negotiated NPN.
bool was_npn_negotiated_;
diff --git a/chromium/net/http/http_stream_factory_impl_request.cc b/chromium/net/http/http_stream_factory_impl_request.cc
index 57190ed72e7..d731d414b71 100644
--- a/chromium/net/http/http_stream_factory_impl_request.cc
+++ b/chromium/net/http/http_stream_factory_impl_request.cc
@@ -17,11 +17,13 @@ HttpStreamFactoryImpl::Request::Request(
const GURL& url,
HttpStreamFactoryImpl* factory,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* websocket_stream_factory,
+ WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_handshake_stream_create_helper,
const BoundNetLog& net_log)
: url_(url),
factory_(factory),
- websocket_stream_factory_(websocket_stream_factory),
+ websocket_handshake_stream_create_helper_(
+ websocket_handshake_stream_create_helper),
delegate_(delegate),
net_log_(net_log),
completed_(false),
@@ -110,17 +112,18 @@ void HttpStreamFactoryImpl::Request::OnStreamReady(
delegate_->OnStreamReady(used_ssl_config, used_proxy_info, stream);
}
-void HttpStreamFactoryImpl::Request::OnWebSocketStreamReady(
+void HttpStreamFactoryImpl::Request::OnWebSocketHandshakeStreamReady(
Job* job,
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream) {
+ WebSocketHandshakeStreamBase* stream) {
DCHECK(factory_->for_websockets_);
DCHECK(stream);
DCHECK(completed_);
OnJobSucceeded(job);
- delegate_->OnWebSocketStreamReady(used_ssl_config, used_proxy_info, stream);
+ delegate_->OnWebSocketHandshakeStreamReady(
+ used_ssl_config, used_proxy_info, stream);
}
void HttpStreamFactoryImpl::Request::OnStreamFailed(
@@ -315,13 +318,13 @@ void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady(
// Cache this so we can still use it if the request is deleted.
HttpStreamFactoryImpl* factory = factory_;
if (factory->for_websockets_) {
- DCHECK(websocket_stream_factory_);
+ DCHECK(websocket_handshake_stream_create_helper_);
bool use_relative_url = direct || url().SchemeIs("wss");
- delegate_->OnWebSocketStreamReady(
+ delegate_->OnWebSocketHandshakeStreamReady(
job->server_ssl_config(),
job->proxy_info(),
- websocket_stream_factory_->CreateSpdyStream(spdy_session,
- use_relative_url));
+ websocket_handshake_stream_create_helper_->CreateSpdyStream(
+ spdy_session, use_relative_url));
} else {
bool use_relative_url = direct || url().SchemeIs("https");
delegate_->OnStreamReady(
diff --git a/chromium/net/http/http_stream_factory_impl_request.h b/chromium/net/http/http_stream_factory_impl_request.h
index d6f9b02cbef..3d3b2c8bd63 100644
--- a/chromium/net/http/http_stream_factory_impl_request.h
+++ b/chromium/net/http/http_stream_factory_impl_request.h
@@ -23,7 +23,8 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
Request(const GURL& url,
HttpStreamFactoryImpl* factory,
HttpStreamRequest::Delegate* delegate,
- WebSocketStreamBase::Factory* websocket_stream_factory,
+ WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_handshake_stream_create_helper,
const BoundNetLog& net_log);
virtual ~Request();
@@ -66,8 +67,9 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
const base::WeakPtr<SpdySession>& spdy_session,
bool direct);
- WebSocketStreamBase::Factory* websocket_stream_factory() {
- return websocket_stream_factory_;
+ WebSocketHandshakeStreamBase::CreateHelper*
+ websocket_handshake_stream_create_helper() {
+ return websocket_handshake_stream_create_helper_;
}
// HttpStreamRequest::Delegate methods which we implement. Note we don't
@@ -77,10 +79,10 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStreamBase* stream);
- void OnWebSocketStreamReady(Job* job,
- const SSLConfig& used_ssl_config,
- const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream);
+ void OnWebSocketHandshakeStreamReady(Job* job,
+ const SSLConfig& used_ssl_config,
+ const ProxyInfo& used_proxy_info,
+ WebSocketHandshakeStreamBase* stream);
void OnStreamFailed(Job* job, int status, const SSLConfig& used_ssl_config);
void OnCertificateError(Job* job,
int status,
@@ -124,7 +126,8 @@ class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
const GURL url_;
HttpStreamFactoryImpl* const factory_;
- WebSocketStreamBase::Factory* const websocket_stream_factory_;
+ WebSocketHandshakeStreamBase::CreateHelper* const
+ websocket_handshake_stream_create_helper_;
HttpStreamRequest::Delegate* const delegate_;
const BoundNetLog net_log_;
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 1f38a2e56f6..b3b12bfa5a3 100644
--- a/chromium/net/http/http_stream_factory_impl_request_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_request_unittest.cc
@@ -19,7 +19,8 @@ class HttpStreamFactoryImplRequestTest
INSTANTIATE_TEST_CASE_P(
NextProto,
HttpStreamFactoryImplRequestTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
namespace {
@@ -35,10 +36,10 @@ class DoNothingRequestDelegate : public HttpStreamRequest::Delegate {
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
HttpStreamBase* stream) OVERRIDE {}
- virtual void OnWebSocketStreamReady(
+ virtual void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream) OVERRIDE {}
+ WebSocketHandshakeStreamBase* stream) OVERRIDE {}
virtual void OnStreamFailed(
int status,
const SSLConfig& used_ssl_config) OVERRIDE {}
diff --git a/chromium/net/http/http_stream_factory_impl_unittest.cc b/chromium/net/http/http_stream_factory_impl_unittest.cc
index f378c93ea18..e3169b65993 100644
--- a/chromium/net/http/http_stream_factory_impl_unittest.cc
+++ b/chromium/net/http/http_stream_factory_impl_unittest.cc
@@ -36,7 +36,7 @@
// 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_stream_base.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -57,23 +57,66 @@ class UseAlternateProtocolsScopedSetter {
bool use_alternate_protocols_;
};
-class MockWebSocketStream : public WebSocketStreamBase {
+class MockWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
public:
enum StreamType {
kStreamTypeBasic,
kStreamTypeSpdy,
};
- explicit MockWebSocketStream(StreamType type) : type_(type) {}
+ explicit MockWebSocketHandshakeStream(StreamType type) : type_(type) {}
- virtual ~MockWebSocketStream() {}
-
- virtual WebSocketStream* AsWebSocketStream() OVERRIDE { return NULL; }
+ virtual ~MockWebSocketHandshakeStream() {}
StreamType type() const {
return type_;
}
+ // HttpStreamBase methods
+ virtual int InitializeStream(const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
+ HttpResponseInfo* response,
+ const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+ virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+ virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
+ return NULL;
+ }
+ virtual int ReadResponseBody(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+ virtual void Close(bool not_reusable) OVERRIDE {}
+ virtual bool IsResponseBodyComplete() const OVERRIDE { return false; }
+ virtual bool CanFindEndOfResponse() const OVERRIDE { return false; }
+ virtual bool IsConnectionReused() const OVERRIDE { return false; }
+ virtual void SetConnectionReused() OVERRIDE {}
+ virtual bool IsConnectionReusable() const OVERRIDE { return false; }
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; }
+ virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const
+ OVERRIDE {
+ return false;
+ }
+ virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {}
+ virtual void GetSSLCertRequestInfo(
+ SSLCertRequestInfo* cert_request_info) OVERRIDE {}
+ virtual bool IsSpdyHttpStream() const OVERRIDE { return false; }
+ virtual void Drain(HttpNetworkSession* session) OVERRIDE {}
+ virtual void SetPriority(RequestPriority priority) OVERRIDE {}
+
+ virtual scoped_ptr<WebSocketStream> Upgrade() OVERRIDE {
+ return scoped_ptr<WebSocketStream>();
+ }
+
private:
const StreamType type_;
};
@@ -128,10 +171,10 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
used_proxy_info_ = used_proxy_info;
}
- virtual void OnWebSocketStreamReady(
+ virtual void OnWebSocketHandshakeStreamReady(
const SSLConfig& used_ssl_config,
const ProxyInfo& used_proxy_info,
- WebSocketStreamBase* stream) OVERRIDE {
+ WebSocketHandshakeStreamBase* stream) OVERRIDE {
stream_done_ = true;
if (waiting_for_stream_)
base::MessageLoop::current()->Quit();
@@ -182,8 +225,8 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
return stream_.get();
}
- MockWebSocketStream* websocket_stream() {
- return static_cast<MockWebSocketStream*>(websocket_stream_.get());
+ MockWebSocketHandshakeStream* websocket_stream() {
+ return static_cast<MockWebSocketHandshakeStream*>(websocket_stream_.get());
}
bool stream_done() const { return stream_done_; }
@@ -192,19 +235,21 @@ class StreamRequestWaiter : public HttpStreamRequest::Delegate {
bool waiting_for_stream_;
bool stream_done_;
scoped_ptr<HttpStreamBase> stream_;
- scoped_ptr<WebSocketStreamBase> websocket_stream_;
+ scoped_ptr<WebSocketHandshakeStreamBase> websocket_stream_;
SSLConfig used_ssl_config_;
ProxyInfo used_proxy_info_;
DISALLOW_COPY_AND_ASSIGN(StreamRequestWaiter);
};
-class WebSocketSpdyStream : public MockWebSocketStream {
+class WebSocketSpdyHandshakeStream : public MockWebSocketHandshakeStream {
public:
- explicit WebSocketSpdyStream(const base::WeakPtr<SpdySession>& spdy_session)
- : MockWebSocketStream(kStreamTypeSpdy), spdy_session_(spdy_session) {}
+ explicit WebSocketSpdyHandshakeStream(
+ const base::WeakPtr<SpdySession>& spdy_session)
+ : MockWebSocketHandshakeStream(kStreamTypeSpdy),
+ spdy_session_(spdy_session) {}
- virtual ~WebSocketSpdyStream() {}
+ virtual ~WebSocketSpdyHandshakeStream() {}
SpdySession* spdy_session() { return spdy_session_.get(); }
@@ -212,12 +257,14 @@ class WebSocketSpdyStream : public MockWebSocketStream {
base::WeakPtr<SpdySession> spdy_session_;
};
-class WebSocketBasicStream : public MockWebSocketStream {
+class WebSocketBasicHandshakeStream : public MockWebSocketHandshakeStream {
public:
- explicit WebSocketBasicStream(ClientSocketHandle* connection)
- : MockWebSocketStream(kStreamTypeBasic), connection_(connection) {}
+ explicit WebSocketBasicHandshakeStream(
+ scoped_ptr<ClientSocketHandle> connection)
+ : MockWebSocketHandshakeStream(kStreamTypeBasic),
+ connection_(connection.Pass()) {}
- virtual ~WebSocketBasicStream() {
+ virtual ~WebSocketBasicHandshakeStream() {
connection_->socket()->Disconnect();
}
@@ -227,19 +274,21 @@ class WebSocketBasicStream : public MockWebSocketStream {
scoped_ptr<ClientSocketHandle> connection_;
};
-class WebSocketStreamFactory : public WebSocketStreamBase::Factory {
+class WebSocketStreamCreateHelper
+ : public WebSocketHandshakeStreamBase::CreateHelper {
public:
- virtual ~WebSocketStreamFactory() {}
+ virtual ~WebSocketStreamCreateHelper() {}
- virtual WebSocketStreamBase* CreateBasicStream(ClientSocketHandle* connection,
- bool using_proxy) OVERRIDE {
- return new WebSocketBasicStream(connection);
+ virtual WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) OVERRIDE {
+ return new WebSocketBasicHandshakeStream(connection.Pass());
}
- virtual WebSocketStreamBase* CreateSpdyStream(
+ virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
const base::WeakPtr<SpdySession>& spdy_session,
bool use_relative_url) OVERRIDE {
- return new WebSocketSpdyStream(spdy_session);
+ return new WebSocketSpdyHandshakeStream(spdy_session);
}
};
@@ -261,7 +310,7 @@ void PreconnectHelperForURL(int num_streams,
HttpNetworkSessionPeer peer(session);
MockHttpStreamFactoryImplForPreconnect* mock_factory =
new MockHttpStreamFactoryImplForPreconnect(session, false);
- peer.SetHttpStreamFactory(mock_factory);
+ peer.SetHttpStreamFactory(scoped_ptr<HttpStreamFactory>(mock_factory));
SSLConfig ssl_config;
session->ssl_config_service()->GetSSLConfig(&ssl_config);
@@ -376,6 +425,7 @@ CapturePreconnectsSSLSocketPool::CapturePreconnectsSocketPool(
cert_verifier,
NULL,
NULL,
+ NULL,
std::string(),
NULL,
NULL,
@@ -392,7 +442,8 @@ class HttpStreamFactoryTest : public ::testing::Test,
INSTANTIATE_TEST_CASE_P(
NextProto,
HttpStreamFactoryTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
TEST_P(HttpStreamFactoryTest, PreconnectDirect) {
@@ -410,11 +461,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectDirect) {
new CapturePreconnectsSSLSocketPool(
session_deps.host_resolver.get(),
session_deps.cert_verifier.get());
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
PreconnectHelper(kTests[i], session.get());
if (kTests[i].ssl)
EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams());
@@ -439,11 +491,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectHttpProxy) {
new CapturePreconnectsSSLSocketPool(
session_deps.host_resolver.get(),
session_deps.cert_verifier.get());
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
PreconnectHelper(kTests[i], session.get());
if (kTests[i].ssl)
EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams());
@@ -468,11 +521,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectSocksProxy) {
new CapturePreconnectsSSLSocketPool(
session_deps.host_resolver.get(),
session_deps.cert_verifier.get());
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_proxy_pool);
mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
PreconnectHelper(kTests[i], session.get());
if (kTests[i].ssl)
EXPECT_EQ(kTests[i].num_streams, ssl_conn_pool->last_num_streams());
@@ -503,11 +557,12 @@ TEST_P(HttpStreamFactoryTest, PreconnectDirectWithExistingSpdySession) {
new CapturePreconnectsSSLSocketPool(
session_deps.host_resolver.get(),
session_deps.cert_verifier.get());
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
PreconnectHelper(kTests[i], session.get());
// We shouldn't be preconnecting if we have an existing session, which is
// the case for https://www.google.com.
@@ -534,10 +589,11 @@ TEST_P(HttpStreamFactoryTest, PreconnectUnsafePort) {
new CapturePreconnectsTransportSocketPool(
session_deps.host_resolver.get(),
session_deps.cert_verifier.get());
- MockClientSocketPoolManager* mock_pool_manager =
- new MockClientSocketPoolManager;
+ scoped_ptr<MockClientSocketPoolManager> mock_pool_manager(
+ new MockClientSocketPoolManager);
mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
- peer.SetClientSocketPoolManager(mock_pool_manager);
+ peer.SetClientSocketPoolManager(
+ mock_pool_manager.PassAs<ClientSocketPoolManager>());
PreconnectHelperForURL(1, GURL("http://www.google.com:7"), session.get());
@@ -864,7 +920,7 @@ TEST_P(HttpStreamFactoryTest, RequestHttpStreamOverProxy) {
EXPECT_FALSE(waiter.used_proxy_info().is_direct());
}
-TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) {
+TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) {
SpdySessionDependencies session_deps(
GetParam(), ProxyService::CreateDirect());
@@ -883,21 +939,21 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) {
SSLConfig ssl_config;
StreamRequestWaiter waiter;
- WebSocketStreamFactory factory;
+ WebSocketStreamCreateHelper create_helper;
scoped_ptr<HttpStreamRequest> request(
- session->websocket_stream_factory()->RequestWebSocketStream(
- request_info,
- DEFAULT_PRIORITY,
- ssl_config,
- ssl_config,
- &waiter,
- &factory,
- BoundNetLog()));
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter,
+ &create_helper,
+ BoundNetLog()));
waiter.WaitForStream();
EXPECT_TRUE(waiter.stream_done());
EXPECT_TRUE(NULL == waiter.stream());
ASSERT_TRUE(NULL != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketStream::kStreamTypeBasic,
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
waiter.websocket_stream()->type());
EXPECT_EQ(0, GetSocketPoolGroupCount(
session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)));
@@ -911,7 +967,7 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStream) {
EXPECT_TRUE(waiter.used_proxy_info().is_direct());
}
-TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) {
+TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverSSL) {
SpdySessionDependencies session_deps(
GetParam(), ProxyService::CreateDirect());
@@ -934,21 +990,21 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) {
SSLConfig ssl_config;
StreamRequestWaiter waiter;
- WebSocketStreamFactory factory;
+ WebSocketStreamCreateHelper create_helper;
scoped_ptr<HttpStreamRequest> request(
- session->websocket_stream_factory()->RequestWebSocketStream(
- request_info,
- DEFAULT_PRIORITY,
- ssl_config,
- ssl_config,
- &waiter,
- &factory,
- BoundNetLog()));
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter,
+ &create_helper,
+ BoundNetLog()));
waiter.WaitForStream();
EXPECT_TRUE(waiter.stream_done());
EXPECT_TRUE(NULL == waiter.stream());
ASSERT_TRUE(NULL != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketStream::kStreamTypeBasic,
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
waiter.websocket_stream()->type());
EXPECT_EQ(0, GetSocketPoolGroupCount(
session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)));
@@ -962,7 +1018,7 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverSSL) {
EXPECT_TRUE(waiter.used_proxy_info().is_direct());
}
-TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) {
+TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStreamOverProxy) {
SpdySessionDependencies session_deps(
GetParam(), ProxyService::CreateFixed("myproxy:8888"));
@@ -982,21 +1038,21 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketBasicStreamOverProxy) {
SSLConfig ssl_config;
StreamRequestWaiter waiter;
- WebSocketStreamFactory factory;
+ WebSocketStreamCreateHelper create_helper;
scoped_ptr<HttpStreamRequest> request(
- session->websocket_stream_factory()->RequestWebSocketStream(
- request_info,
- DEFAULT_PRIORITY,
- ssl_config,
- ssl_config,
- &waiter,
- &factory,
- BoundNetLog()));
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter,
+ &create_helper,
+ BoundNetLog()));
waiter.WaitForStream();
EXPECT_TRUE(waiter.stream_done());
EXPECT_TRUE(NULL == waiter.stream());
ASSERT_TRUE(NULL != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketStream::kStreamTypeBasic,
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeBasic,
waiter.websocket_stream()->type());
EXPECT_EQ(0, GetSocketPoolGroupCount(
session->GetTransportSocketPool(
@@ -1071,7 +1127,7 @@ TEST_P(HttpStreamFactoryTest, RequestSpdyHttpStream) {
EXPECT_TRUE(waiter.used_proxy_info().is_direct());
}
-TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyStream) {
+TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyHandshakeStream) {
SpdySessionDependencies session_deps(GetParam(),
ProxyService::CreateDirect());
@@ -1096,44 +1152,44 @@ TEST_P(HttpStreamFactoryTest, RequestWebSocketSpdyStream) {
SSLConfig ssl_config;
StreamRequestWaiter waiter1;
- WebSocketStreamFactory factory;
+ WebSocketStreamCreateHelper create_helper;
scoped_ptr<HttpStreamRequest> request1(
- session->websocket_stream_factory()->RequestWebSocketStream(
- request_info,
- DEFAULT_PRIORITY,
- ssl_config,
- ssl_config,
- &waiter1,
- &factory,
- BoundNetLog()));
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter1,
+ &create_helper,
+ BoundNetLog()));
waiter1.WaitForStream();
EXPECT_TRUE(waiter1.stream_done());
ASSERT_TRUE(NULL != waiter1.websocket_stream());
- EXPECT_EQ(MockWebSocketStream::kStreamTypeSpdy,
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy,
waiter1.websocket_stream()->type());
EXPECT_TRUE(NULL == waiter1.stream());
StreamRequestWaiter waiter2;
scoped_ptr<HttpStreamRequest> request2(
- session->websocket_stream_factory()->RequestWebSocketStream(
- request_info,
- DEFAULT_PRIORITY,
- ssl_config,
- ssl_config,
- &waiter2,
- &factory,
- BoundNetLog()));
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter2,
+ &create_helper,
+ BoundNetLog()));
waiter2.WaitForStream();
EXPECT_TRUE(waiter2.stream_done());
ASSERT_TRUE(NULL != waiter2.websocket_stream());
- EXPECT_EQ(MockWebSocketStream::kStreamTypeSpdy,
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy,
waiter2.websocket_stream()->type());
EXPECT_TRUE(NULL == waiter2.stream());
EXPECT_NE(waiter2.websocket_stream(), waiter1.websocket_stream());
- EXPECT_EQ(static_cast<WebSocketSpdyStream*>(waiter2.websocket_stream())->
- spdy_session(),
- static_cast<WebSocketSpdyStream*>(waiter1.websocket_stream())->
- spdy_session());
+ EXPECT_EQ(static_cast<WebSocketSpdyHandshakeStream*>(
+ waiter2.websocket_stream())->spdy_session(),
+ static_cast<WebSocketSpdyHandshakeStream*>(
+ waiter1.websocket_stream())->spdy_session());
EXPECT_EQ(0, GetSocketPoolGroupCount(
session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL)));
@@ -1186,21 +1242,21 @@ TEST_P(HttpStreamFactoryTest, OrphanedWebSocketStream) {
SSLConfig ssl_config;
StreamRequestWaiter waiter;
- WebSocketStreamFactory factory;
+ WebSocketStreamCreateHelper create_helper;
scoped_ptr<HttpStreamRequest> request(
- session->websocket_stream_factory()->RequestWebSocketStream(
- request_info,
- DEFAULT_PRIORITY,
- ssl_config,
- ssl_config,
- &waiter,
- &factory,
- BoundNetLog()));
+ session->http_stream_factory_for_websocket()
+ ->RequestWebSocketHandshakeStream(request_info,
+ DEFAULT_PRIORITY,
+ ssl_config,
+ ssl_config,
+ &waiter,
+ &create_helper,
+ BoundNetLog()));
waiter.WaitForStream();
EXPECT_TRUE(waiter.stream_done());
EXPECT_TRUE(NULL == waiter.stream());
ASSERT_TRUE(NULL != waiter.websocket_stream());
- EXPECT_EQ(MockWebSocketStream::kStreamTypeSpdy,
+ EXPECT_EQ(MockWebSocketHandshakeStream::kStreamTypeSpdy,
waiter.websocket_stream()->type());
// Make sure that there was an alternative connection
@@ -1218,7 +1274,7 @@ TEST_P(HttpStreamFactoryTest, OrphanedWebSocketStream) {
// Make sure there is no orphaned job. it is already canceled.
ASSERT_EQ(0u, static_cast<HttpStreamFactoryImpl*>(
- session->websocket_stream_factory())->num_orphaned_jobs());
+ session->http_stream_factory_for_websocket())->num_orphaned_jobs());
}
} // namespace
diff --git a/chromium/net/http/http_stream_parser.cc b/chromium/net/http/http_stream_parser.cc
index 853414a106a..0821c848652 100644
--- a/chromium/net/http/http_stream_parser.cc
+++ b/chromium/net/http/http_stream_parser.cc
@@ -179,6 +179,7 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
read_buf_(read_buffer),
read_buf_unused_offset_(0),
response_header_start_offset_(-1),
+ received_bytes_(0),
response_body_length_(-1),
response_body_read_(0),
user_read_buf_(NULL),
@@ -693,6 +694,9 @@ int HttpStreamParser::DoReadBodyComplete(int result) {
result = ERR_CONTENT_LENGTH_MISMATCH;
}
+ if (result > 0)
+ received_bytes_ += result;
+
// Filter incoming data if appropriate. FilterBuf may return an error.
if (result > 0 && chunked_decoder_.get()) {
result = chunked_decoder_->FilterBuf(user_read_buf_->data(), result);
@@ -734,6 +738,7 @@ int HttpStreamParser::DoReadBodyComplete(int result) {
}
if (save_amount) {
+ received_bytes_ -= save_amount;
memcpy(read_buf_->StartOfBuffer(), user_read_buf_->data() + result,
save_amount);
}
@@ -788,6 +793,7 @@ int HttpStreamParser::DoParseResponseHeaders(int end_offset) {
DCHECK_EQ(0, read_buf_unused_offset_);
if (response_header_start_offset_ >= 0) {
+ received_bytes_ += end_offset;
headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders(
read_buf_->StartOfBuffer(), end_offset));
} else {
diff --git a/chromium/net/http/http_stream_parser.h b/chromium/net/http/http_stream_parser.h
index 43e1514c2fe..e3690322bbd 100644
--- a/chromium/net/http/http_stream_parser.h
+++ b/chromium/net/http/http_stream_parser.h
@@ -77,6 +77,8 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
bool IsConnectionReusable() const;
+ int64 received_bytes() const { return received_bytes_; }
+
void GetSSLInfo(SSLInfo* ssl_info);
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
@@ -186,6 +188,10 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
// -1 if not found yet.
int response_header_start_offset_;
+ // The amount of received data. If connection is reused then intermediate
+ // value may be bigger than final.
+ int64 received_bytes_;
+
// The parsed response headers. Owned by the caller.
HttpResponseInfo* response_;
diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc
index 6e0053e6255..dcaf1f3e9c3 100644
--- a/chromium/net/http/http_stream_parser_unittest.cc
+++ b/chromium/net/http/http_stream_parser_unittest.cc
@@ -4,6 +4,10 @@
#include "net/http/http_stream_parser.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
@@ -19,6 +23,7 @@
#include "net/base/upload_file_element_reader.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
+#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socket_test_util.h"
@@ -27,6 +32,8 @@
namespace net {
+namespace {
+
const size_t kOutputSize = 1024; // Just large enough for this test.
// The number of bytes that can fit in a buffer of kOutputSize.
const size_t kMaxPayloadSize =
@@ -98,7 +105,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_NoBody) {
TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_EmptyBody) {
ScopedVector<UploadElementReader> element_readers;
- scoped_ptr<UploadDataStream> body(new UploadDataStream(&element_readers, 0));
+ scoped_ptr<UploadDataStream> body(
+ new UploadDataStream(element_readers.Pass(), 0));
ASSERT_EQ(OK, body->Init(CompletionCallback()));
// Shouldn't be merged if upload data is empty.
ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
@@ -124,8 +132,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
base::FilePath temp_file_path;
- ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir.path(),
- &temp_file_path));
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(),
+ &temp_file_path));
element_readers.push_back(
new UploadFileElementReader(base::MessageLoopProxy::current().get(),
@@ -135,7 +143,7 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_FileBody) {
base::Time()));
scoped_ptr<UploadDataStream> body(
- new UploadDataStream(&element_readers, 0));
+ new UploadDataStream(element_readers.Pass(), 0));
TestCompletionCallback callback;
ASSERT_EQ(ERR_IO_PENDING, body->Init(callback.callback()));
ASSERT_EQ(OK, callback.WaitForResult());
@@ -153,7 +161,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_SmallBodyInMemory) {
element_readers.push_back(new UploadBytesElementReader(
payload.data(), payload.size()));
- scoped_ptr<UploadDataStream> body(new UploadDataStream(&element_readers, 0));
+ scoped_ptr<UploadDataStream> body(
+ new UploadDataStream(element_readers.Pass(), 0));
ASSERT_EQ(OK, body->Init(CompletionCallback()));
// Yes, should be merged if the in-memory body is small here.
ASSERT_TRUE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
@@ -166,7 +175,8 @@ TEST(HttpStreamParser, ShouldMergeRequestHeadersAndBody_LargeBodyInMemory) {
element_readers.push_back(new UploadBytesElementReader(
payload.data(), payload.size()));
- scoped_ptr<UploadDataStream> body(new UploadDataStream(&element_readers, 0));
+ scoped_ptr<UploadDataStream> body(
+ new UploadDataStream(element_readers.Pass(), 0));
ASSERT_EQ(OK, body->Init(CompletionCallback()));
// Shouldn't be merged if the in-memory body is large here.
ASSERT_FALSE(HttpStreamParser::ShouldMergeRequestHeadersAndBody(
@@ -419,4 +429,381 @@ TEST(HttpStreamParser, TruncatedHeaders) {
}
}
+// Confirm that on 101 response, the headers are parsed but the data that
+// follows remains in the buffer.
+TEST(HttpStreamParser, Websocket101Response) {
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, 1,
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "\r\n"
+ "a fake websocket frame"),
+ };
+
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, 0, "GET / HTTP/1.1\r\n\r\n"),
+ };
+
+ DeterministicSocketData data(reads, arraysize(reads),
+ writes, arraysize(writes));
+ data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ data.SetStop(2);
+
+ scoped_ptr<DeterministicMockTCPClientSocket> transport(
+ new DeterministicMockTCPClientSocket(NULL, &data));
+ data.set_delegate(transport->AsWeakPtr());
+
+ TestCompletionCallback callback;
+ int rv = transport->Connect(callback.callback());
+ rv = callback.GetResult(rv);
+ ASSERT_EQ(OK, rv);
+
+ scoped_ptr<ClientSocketHandle> socket_handle(new ClientSocketHandle);
+ socket_handle->SetSocket(transport.PassAs<StreamSocket>());
+
+ HttpRequestInfo request_info;
+ request_info.method = "GET";
+ request_info.url = GURL("http://localhost");
+ request_info.load_flags = LOAD_NORMAL;
+
+ scoped_refptr<GrowableIOBuffer> read_buffer(new GrowableIOBuffer);
+ HttpStreamParser parser(
+ socket_handle.get(), &request_info, read_buffer.get(), BoundNetLog());
+
+ HttpRequestHeaders request_headers;
+ HttpResponseInfo response_info;
+ rv = parser.SendRequest("GET / HTTP/1.1\r\n", request_headers,
+ &response_info, callback.callback());
+ ASSERT_EQ(OK, rv);
+
+ rv = parser.ReadResponseHeaders(callback.callback());
+ EXPECT_EQ(OK, rv);
+ ASSERT_TRUE(response_info.headers.get());
+ EXPECT_EQ(101, response_info.headers->response_code());
+ EXPECT_TRUE(response_info.headers->HasHeaderValue("Connection", "Upgrade"));
+ EXPECT_TRUE(response_info.headers->HasHeaderValue("Upgrade", "websocket"));
+ EXPECT_EQ(read_buffer->capacity(), read_buffer->offset());
+ EXPECT_EQ("a fake websocket frame",
+ base::StringPiece(read_buffer->StartOfBuffer(),
+ read_buffer->capacity()));
+}
+
+// Helper class for constructing HttpStreamParser and running GET requests.
+class SimpleGetRunner {
+ public:
+ SimpleGetRunner() : read_buffer_(new GrowableIOBuffer), sequence_number_(0) {
+ writes_.push_back(MockWrite(
+ SYNCHRONOUS, sequence_number_++, "GET / HTTP/1.1\r\n\r\n"));
+ }
+
+ HttpStreamParser* parser() { return parser_.get(); }
+ GrowableIOBuffer* read_buffer() { return read_buffer_.get(); }
+ HttpResponseInfo* response_info() { return &response_info_; }
+
+ void AddInitialData(const std::string& data) {
+ int offset = read_buffer_->offset();
+ int size = data.size();
+ read_buffer_->SetCapacity(offset + size);
+ memcpy(read_buffer_->StartOfBuffer() + offset, data.data(), size);
+ read_buffer_->set_offset(offset + size);
+ }
+
+ void AddRead(const std::string& data) {
+ reads_.push_back(MockRead(SYNCHRONOUS, sequence_number_++, data.data()));
+ }
+
+ void SetupParserAndSendRequest() {
+ reads_.push_back(MockRead(SYNCHRONOUS, 0, sequence_number_++)); // EOF
+
+ socket_handle_.reset(new ClientSocketHandle);
+ data_.reset(new DeterministicSocketData(
+ &reads_.front(), reads_.size(), &writes_.front(), writes_.size()));
+ data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ data_->SetStop(reads_.size() + writes_.size());
+
+ transport_.reset(new DeterministicMockTCPClientSocket(NULL, data_.get()));
+ data_->set_delegate(transport_->AsWeakPtr());
+
+ TestCompletionCallback callback;
+ int rv = transport_->Connect(callback.callback());
+ rv = callback.GetResult(rv);
+ ASSERT_EQ(OK, rv);
+
+ socket_handle_->SetSocket(transport_.PassAs<StreamSocket>());
+
+ request_info_.method = "GET";
+ request_info_.url = GURL("http://localhost");
+ request_info_.load_flags = LOAD_NORMAL;
+
+ parser_.reset(new HttpStreamParser(
+ socket_handle_.get(), &request_info_, read_buffer(), BoundNetLog()));
+
+ rv = parser_->SendRequest("GET / HTTP/1.1\r\n", request_headers_,
+ &response_info_, callback.callback());
+ ASSERT_EQ(OK, rv);
+ }
+
+ void ReadHeaders() {
+ TestCompletionCallback callback;
+ EXPECT_EQ(OK, parser_->ReadResponseHeaders(callback.callback()));
+ }
+
+ void ReadBody(int user_buf_len, int* read_lengths) {
+ TestCompletionCallback callback;
+ scoped_refptr<IOBuffer> buffer = new IOBuffer(user_buf_len);
+ int rv;
+ int i = 0;
+ while (true) {
+ rv = parser_->ReadResponseBody(buffer, user_buf_len, callback.callback());
+ EXPECT_EQ(read_lengths[i], rv);
+ i++;
+ if (rv <= 0)
+ return;
+ }
+ }
+
+ private:
+ HttpRequestHeaders request_headers_;
+ HttpResponseInfo response_info_;
+ HttpRequestInfo request_info_;
+ scoped_refptr<GrowableIOBuffer> read_buffer_;
+ std::vector<MockRead> reads_;
+ std::vector<MockWrite> writes_;
+ scoped_ptr<ClientSocketHandle> socket_handle_;
+ scoped_ptr<DeterministicSocketData> data_;
+ scoped_ptr<DeterministicMockTCPClientSocket> transport_;
+ scoped_ptr<HttpStreamParser> parser_;
+ int sequence_number_;
+};
+
+// Test that HTTP/0.9 response size is correctly calculated.
+TEST(HttpStreamParser, ReceivedBytesNoHeaders) {
+ std::string response = "hello\r\nworld\r\n";
+
+ SimpleGetRunner get_runner;
+ get_runner.AddRead(response);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ EXPECT_EQ(0, get_runner.parser()->received_bytes());
+ int response_size = response.size();
+ int read_lengths[] = {response_size, 0};
+ get_runner.ReadBody(response_size, read_lengths);
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+}
+
+// Test basic case where there is no keep-alive or extra data from the socket,
+// and the entire response is received in a single read.
+TEST(HttpStreamParser, ReceivedBytesNormal) {
+ std::string headers = "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 7\r\n\r\n";
+ std::string body = "content";
+ std::string response = headers + body;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddRead(response);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ int64 headers_size = headers.size();
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int body_size = body.size();
+ int read_lengths[] = {body_size, 0};
+ get_runner.ReadBody(body_size, read_lengths);
+ int64 response_size = response.size();
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+}
+
+// Test that bytes that represent "next" response are not counted
+// as current response "received_bytes".
+TEST(HttpStreamParser, ReceivedBytesExcludesNextResponse) {
+ std::string headers = "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 8\r\n\r\n";
+ std::string body = "content8";
+ std::string response = headers + body;
+ std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
+ std::string data = response + next_response;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddRead(data);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ EXPECT_EQ(39, get_runner.parser()->received_bytes());
+ int64 headers_size = headers.size();
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int body_size = body.size();
+ int read_lengths[] = {body_size, 0};
+ get_runner.ReadBody(body_size, read_lengths);
+ int64 response_size = response.size();
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+ int64 next_response_size = next_response.size();
+ EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
+}
+
+// Test that "received_bytes" calculation works fine when last read
+// contains more data than requested by user.
+// We send data in two reads:
+// 1) Headers + beginning of response
+// 2) remaining part of response + next response start
+// We setup user read buffer so it fully accepts the beginnig of response
+// body, but it is larger that remaining part of body.
+TEST(HttpStreamParser, ReceivedBytesMultiReadExcludesNextResponse) {
+ std::string headers = "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 36\r\n\r\n";
+ int64 user_buf_len = 32;
+ std::string body_start = std::string(user_buf_len, '#');
+ int body_start_size = body_start.size();
+ EXPECT_EQ(user_buf_len, body_start_size);
+ std::string response_start = headers + body_start;
+ std::string body_end = "abcd";
+ std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
+ std::string response_end = body_end + next_response;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddRead(response_start);
+ get_runner.AddRead(response_end);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ int64 headers_size = headers.size();
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int body_end_size = body_end.size();
+ int read_lengths[] = {body_start_size, body_end_size, 0};
+ get_runner.ReadBody(body_start_size, read_lengths);
+ int64 response_size = response_start.size() + body_end_size;
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+ int64 next_response_size = next_response.size();
+ EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
+}
+
+// Test that "received_bytes" calculation works fine when there is no
+// network activity at all; that is when all data is read from read buffer.
+// In this case read buffer contains two responses. We expect that only
+// bytes that correspond to the first one are taken into account.
+TEST(HttpStreamParser, ReceivedBytesFromReadBufExcludesNextResponse) {
+ std::string headers = "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 7\r\n\r\n";
+ std::string body = "content";
+ std::string response = headers + body;
+ std::string next_response = "HTTP/1.1 200 OK\r\n\r\nFOO";
+ std::string data = response + next_response;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddInitialData(data);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ int64 headers_size = headers.size();
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int body_size = body.size();
+ int read_lengths[] = {body_size, 0};
+ get_runner.ReadBody(body_size, read_lengths);
+ int64 response_size = response.size();
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+ int64 next_response_size = next_response.size();
+ EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
+}
+
+// Test calculating "received_bytes" when part of request has been already
+// loaded and placed to read buffer by previous stream parser.
+TEST(HttpStreamParser, ReceivedBytesUseReadBuf) {
+ std::string buffer = "HTTP/1.1 200 OK\r\n";
+ std::string remaining_headers = "Content-Length: 7\r\n\r\n";
+ int64 headers_size = buffer.size() + remaining_headers.size();
+ std::string body = "content";
+ std::string response = remaining_headers + body;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddInitialData(buffer);
+ get_runner.AddRead(response);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int body_size = body.size();
+ int read_lengths[] = {body_size, 0};
+ get_runner.ReadBody(body_size, read_lengths);
+ EXPECT_EQ(headers_size + body_size, get_runner.parser()->received_bytes());
+ EXPECT_EQ(0, get_runner.read_buffer()->offset());
+}
+
+// Test the case when the resulting read_buf contains both unused bytes and
+// bytes ejected by chunked-encoding filter.
+TEST(HttpStreamParser, ReceivedBytesChunkedTransferExcludesNextResponse) {
+ std::string response = "HTTP/1.1 200 OK\r\n"
+ "Transfer-Encoding: chunked\r\n\r\n"
+ "7\r\nChunk 1\r\n"
+ "8\r\nChunky 2\r\n"
+ "6\r\nTest 3\r\n"
+ "0\r\n\r\n";
+ std::string next_response = "foo bar\r\n";
+ std::string data = response + next_response;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddInitialData(data);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ int read_lengths[] = {4, 3, 6, 2, 6, 0};
+ get_runner.ReadBody(7, read_lengths);
+ int64 response_size = response.size();
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+ int64 next_response_size = next_response.size();
+ EXPECT_EQ(next_response_size, get_runner.read_buffer()->offset());
+}
+
+// Test that data transfered in multiple reads is correctly processed.
+// We feed data into 4-bytes reads. Also we set length of read
+// buffer to 5-bytes to test all possible buffer misaligments.
+TEST(HttpStreamParser, ReceivedBytesMultipleReads) {
+ std::string headers = "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 33\r\n\r\n";
+ std::string body = "foo bar baz\r\n"
+ "sputnik mir babushka";
+ std::string response = headers + body;
+
+ size_t receive_length = 4;
+ std::vector<std::string> blocks;
+ for (size_t i = 0; i < response.size(); i += receive_length) {
+ size_t length = std::min(receive_length, response.size() - i);
+ blocks.push_back(response.substr(i, length));
+ }
+
+ SimpleGetRunner get_runner;
+ for (std::vector<std::string>::size_type i = 0; i < blocks.size(); ++i)
+ get_runner.AddRead(blocks[i]);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ int64 headers_size = headers.size();
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int read_lengths[] = {1, 4, 4, 4, 4, 4, 4, 4, 4, 0};
+ get_runner.ReadBody(receive_length + 1, read_lengths);
+ int64 response_size = response.size();
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+}
+
+// Test that "continue" HTTP header is counted as "received_bytes".
+TEST(HttpStreamParser, ReceivedBytesIncludesContinueHeader) {
+ std::string status100 = "HTTP/1.1 100 OK\r\n\r\n";
+ std::string headers = "HTTP/1.1 200 OK\r\n"
+ "Content-Length: 7\r\n\r\n";
+ int64 headers_size = status100.size() + headers.size();
+ std::string body = "content";
+ std::string response = headers + body;
+
+ SimpleGetRunner get_runner;
+ get_runner.AddRead(status100);
+ get_runner.AddRead(response);
+ get_runner.SetupParserAndSendRequest();
+ get_runner.ReadHeaders();
+ EXPECT_EQ(100, get_runner.response_info()->headers->response_code());
+ int64 status100_size = status100.size();
+ EXPECT_EQ(status100_size, get_runner.parser()->received_bytes());
+ get_runner.ReadHeaders();
+ EXPECT_EQ(200, get_runner.response_info()->headers->response_code());
+ EXPECT_EQ(headers_size, get_runner.parser()->received_bytes());
+ int64 response_size = headers_size + body.size();
+ int body_size = body.size();
+ int read_lengths[] = {body_size, 0};
+ get_runner.ReadBody(body_size, read_lengths);
+ EXPECT_EQ(response_size, get_runner.parser()->received_bytes());
+}
+
+} // namespace
+
} // namespace net
diff --git a/chromium/net/http/http_transaction.h b/chromium/net/http/http_transaction.h
index d44050080ba..849d03af50c 100644
--- a/chromium/net/http/http_transaction.h
+++ b/chromium/net/http/http_transaction.h
@@ -10,6 +10,7 @@
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
#include "net/base/upload_progress.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
namespace net {
@@ -134,6 +135,12 @@ class NET_EXPORT_PRIVATE HttpTransaction {
// Called when the priority of the parent job changes.
virtual void SetPriority(RequestPriority priority) = 0;
+
+ // Set the WebSocketHandshakeStreamBase::CreateHelper to be used for the
+ // request. Only relevant to WebSocket transactions. Must be called before
+ // Start(). Ownership of |create_helper| remains with the caller.
+ virtual void SetWebSocketHandshakeStreamCreateHelper(
+ WebSocketHandshakeStreamBase::CreateHelper* create_helper) = 0;
};
} // namespace net
diff --git a/chromium/net/http/http_transaction_unittest.cc b/chromium/net/http/http_transaction_unittest.cc
index 9aa81cf608e..e161ecac506 100644
--- a/chromium/net/http/http_transaction_unittest.cc
+++ b/chromium/net/http/http_transaction_unittest.cc
@@ -228,6 +228,7 @@ MockNetworkTransaction::MockNetworkTransaction(
: weak_factory_(this),
data_cursor_(0),
priority_(priority),
+ websocket_handshake_stream_create_helper_(NULL),
transaction_factory_(factory->AsWeakPtr()),
socket_log_id_(net::NetLog::Source::kInvalidId) {
}
@@ -375,6 +376,11 @@ void MockNetworkTransaction::SetPriority(net::RequestPriority priority) {
priority_ = priority;
}
+void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
+ net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
+ websocket_handshake_stream_create_helper_ = create_helper;
+}
+
void MockNetworkTransaction::CallbackLater(
const net::CompletionCallback& callback, int result) {
base::MessageLoop::current()->PostTask(
diff --git a/chromium/net/http/http_transaction_unittest.h b/chromium/net/http/http_transaction_unittest.h
index 407fc9fff9a..3d6bb0287fb 100644
--- a/chromium/net/http/http_transaction_unittest.h
+++ b/chromium/net/http/http_transaction_unittest.h
@@ -162,6 +162,7 @@ class MockNetworkLayer;
class MockNetworkTransaction
: public net::HttpTransaction,
public base::SupportsWeakPtr<MockNetworkTransaction> {
+ typedef net::WebSocketHandshakeStreamBase::CreateHelper CreateHelper;
public:
MockNetworkTransaction(net::RequestPriority priority,
MockNetworkLayer* factory);
@@ -205,6 +206,12 @@ class MockNetworkTransaction
virtual void SetPriority(net::RequestPriority priority) OVERRIDE;
+ virtual void SetWebSocketHandshakeStreamCreateHelper(
+ CreateHelper* create_helper) OVERRIDE;
+
+ CreateHelper* websocket_handshake_stream_create_helper() {
+ return websocket_handshake_stream_create_helper_;
+ }
net::RequestPriority priority() const { return priority_; }
private:
@@ -217,6 +224,7 @@ class MockNetworkTransaction
int data_cursor_;
int test_mode_;
net::RequestPriority priority_;
+ CreateHelper* websocket_handshake_stream_create_helper_;
base::WeakPtr<MockNetworkLayer> transaction_factory_;
// NetLog ID of the fake / non-existent underlying socket used by the
diff --git a/chromium/net/http/http_util_icu.cc b/chromium/net/http/http_util_icu.cc
index 4f38f84d75b..88ad5906e7b 100644
--- a/chromium/net/http/http_util_icu.cc
+++ b/chromium/net/http/http_util_icu.cc
@@ -14,7 +14,8 @@ namespace net {
// static
std::string HttpUtil::PathForRequest(const GURL& url) {
- DCHECK(url.is_valid() && url.SchemeIsHTTPOrHTTPS());
+ DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() ||
+ url.SchemeIsWSOrWSS()));
if (url.has_query())
return url.path() + "?" + url.query();
return url.path();
@@ -23,8 +24,8 @@ std::string HttpUtil::PathForRequest(const GURL& url) {
// 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")));
+ DCHECK(url.is_valid() && (url.SchemeIsHTTPOrHTTPS() || url.SchemeIs("ftp") ||
+ url.SchemeIsWSOrWSS()));
return SimplifyUrlForRequest(url).spec();
}
diff --git a/chromium/net/http/http_util_unittest.cc b/chromium/net/http/http_util_unittest.cc
index fe2d8b47496..54acf68d3c3 100644
--- a/chromium/net/http/http_util_unittest.cc
+++ b/chromium/net/http/http_util_unittest.cc
@@ -612,6 +612,21 @@ TEST(HttpUtilTest, RequestUrlSanitize) {
"http://user:pass@google.com",
"http://google.com/",
"/"
+ },
+ { // https scheme
+ "https://www.google.com:78/foobar?query=1#hash",
+ "https://www.google.com:78/foobar?query=1",
+ "/foobar?query=1"
+ },
+ { // WebSocket's ws scheme
+ "ws://www.google.com:78/foobar?query=1#hash",
+ "ws://www.google.com:78/foobar?query=1",
+ "/foobar?query=1"
+ },
+ { // WebSocket's wss scheme
+ "wss://www.google.com:78/foobar?query=1#hash",
+ "wss://www.google.com:78/foobar?query=1",
+ "/foobar?query=1"
}
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
@@ -624,6 +639,13 @@ TEST(HttpUtilTest, RequestUrlSanitize) {
}
}
+// Test SpecForRequest() for "ftp" scheme.
+TEST(HttpUtilTest, SpecForRequestForUrlWithFtpScheme) {
+ GURL ftp_url("ftp://user:pass@google.com/pub/chromium/");
+ EXPECT_EQ("ftp://google.com/pub/chromium/",
+ HttpUtil::SpecForRequest(ftp_url));
+}
+
TEST(HttpUtilTest, GenerateAcceptLanguageHeader) {
EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"),
HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de"));
diff --git a/chromium/net/http/partial_data.cc b/chromium/net/http/partial_data.cc
index 02fda6cc9b1..ee3678b5ea0 100644
--- a/chromium/net/http/partial_data.cc
+++ b/chromium/net/http/partial_data.cc
@@ -25,19 +25,6 @@ const char kLengthHeader[] = "Content-Length";
const char kRangeHeader[] = "Content-Range";
const int kDataStream = 1;
-void AddRangeHeader(int64 start, int64 end, HttpRequestHeaders* headers) {
- DCHECK(start >= 0 || end >= 0);
- std::string my_start, my_end;
- if (start >= 0)
- my_start = base::Int64ToString(start);
- if (end >= 0)
- my_end = base::Int64ToString(end);
-
- headers->SetHeader(
- HttpRequestHeaders::kRange,
- base::StringPrintf("bytes=%s-%s", my_start.c_str(), my_end.c_str()));
-}
-
} // namespace
// A core object that can be detached from the Partialdata object at destruction
@@ -156,8 +143,17 @@ void PartialData::RestoreHeaders(HttpRequestHeaders* headers) const {
byte_range_.suffix_length() : byte_range_.last_byte_position();
headers->CopyFrom(extra_headers_);
- if (!truncated_ && byte_range_.IsValid())
- AddRangeHeader(current_range_start_, end, headers);
+ if (truncated_ || !byte_range_.IsValid())
+ return;
+
+ if (current_range_start_ < 0) {
+ headers->SetHeader(HttpRequestHeaders::kRange,
+ HttpByteRange::Suffix(end).GetHeaderValue());
+ } else {
+ headers->SetHeader(HttpRequestHeaders::kRange,
+ HttpByteRange::Bounded(
+ current_range_start_, end).GetHeaderValue());
+ }
}
int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
@@ -222,11 +218,17 @@ void PartialData::PrepareCacheValidation(disk_cache::Entry* entry,
range_present_ = true;
if (len == cached_min_len_)
final_range_ = true;
- AddRangeHeader(current_range_start_, cached_start_ + cached_min_len_ - 1,
- headers);
+ headers->SetHeader(
+ HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(
+ current_range_start_,
+ cached_start_ + cached_min_len_ - 1).GetHeaderValue());
} else {
// This range is not in the cache.
- AddRangeHeader(current_range_start_, cached_start_ - 1, headers);
+ headers->SetHeader(
+ HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(
+ current_range_start_, cached_start_ - 1).GetHeaderValue());
}
}
@@ -337,8 +339,12 @@ bool PartialData::ResponseHeadersOK(const HttpResponseHeaders* headers) {
if (total_length <= 0)
return false;
+ DCHECK_EQ(headers->response_code(), 206);
+
+ // A server should return a valid content length with a 206 (per the standard)
+ // but relax the requirement because some servers don't do that.
int64 content_length = headers->GetContentLength();
- if (content_length < 0 || content_length != end - start + 1)
+ if (content_length > 0 && content_length != end - start + 1)
return false;
if (!resource_size_) {
diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.cc b/chromium/net/http/proxy_connect_redirect_http_stream.cc
index 59bb0146953..0857a7451ca 100644
--- a/chromium/net/http/proxy_connect_redirect_http_stream.cc
+++ b/chromium/net/http/proxy_connect_redirect_http_stream.cc
@@ -82,6 +82,10 @@ bool ProxyConnectRedirectHttpStream::IsConnectionReusable() const {
return false;
}
+int64 ProxyConnectRedirectHttpStream::GetTotalReceivedBytes() const {
+ return 0;
+}
+
bool ProxyConnectRedirectHttpStream::GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const {
if (!has_load_timing_info_)
diff --git a/chromium/net/http/proxy_connect_redirect_http_stream.h b/chromium/net/http/proxy_connect_redirect_http_stream.h
index c335c218c71..0547654ab92 100644
--- a/chromium/net/http/proxy_connect_redirect_http_stream.h
+++ b/chromium/net/http/proxy_connect_redirect_http_stream.h
@@ -50,6 +50,8 @@ class ProxyConnectRedirectHttpStream : public HttpStream {
virtual void SetConnectionReused() OVERRIDE;
virtual bool IsConnectionReusable() const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+
// This function may be called.
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
diff --git a/chromium/net/http/transport_security_persister.cc b/chromium/net/http/transport_security_persister.cc
new file mode 100644
index 00000000000..771d07dc1bc
--- /dev/null
+++ b/chromium/net/http/transport_security_persister.cc
@@ -0,0 +1,318 @@
+// 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/http/transport_security_persister.h"
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task_runner_util.h"
+#include "base/values.h"
+#include "crypto/sha2.h"
+#include "net/cert/x509_certificate.h"
+#include "net/http/transport_security_state.h"
+
+using net::HashValue;
+using net::HashValueTag;
+using net::HashValueVector;
+using net::TransportSecurityState;
+
+namespace {
+
+ListValue* SPKIHashesToListValue(const HashValueVector& hashes) {
+ ListValue* pins = new ListValue;
+ for (size_t i = 0; i != hashes.size(); i++)
+ pins->Append(new StringValue(hashes[i].ToString()));
+ return pins;
+}
+
+void SPKIHashesFromListValue(const ListValue& pins, HashValueVector* hashes) {
+ size_t num_pins = pins.GetSize();
+ for (size_t i = 0; i < num_pins; ++i) {
+ std::string type_and_base64;
+ HashValue fingerprint;
+ if (pins.GetString(i, &type_and_base64) &&
+ fingerprint.FromString(type_and_base64)) {
+ hashes->push_back(fingerprint);
+ }
+ }
+}
+
+// This function converts the binary hashes to a base64 string which we can
+// include in a JSON file.
+std::string HashedDomainToExternalString(const std::string& hashed) {
+ std::string out;
+ base::Base64Encode(hashed, &out);
+ return out;
+}
+
+// This inverts |HashedDomainToExternalString|, above. It turns an external
+// string (from a JSON file) into an internal (binary) string.
+std::string ExternalStringToHashedDomain(const std::string& external) {
+ std::string out;
+ if (!base::Base64Decode(external, &out) ||
+ out.size() != crypto::kSHA256Length) {
+ return std::string();
+ }
+
+ return out;
+}
+
+const char kIncludeSubdomains[] = "include_subdomains";
+const char kStsIncludeSubdomains[] = "sts_include_subdomains";
+const char kPkpIncludeSubdomains[] = "pkp_include_subdomains";
+const char kMode[] = "mode";
+const char kExpiry[] = "expiry";
+const char kDynamicSPKIHashesExpiry[] = "dynamic_spki_hashes_expiry";
+const char kStaticSPKIHashes[] = "static_spki_hashes";
+const char kPreloadedSPKIHashes[] = "preloaded_spki_hashes";
+const char kDynamicSPKIHashes[] = "dynamic_spki_hashes";
+const char kForceHTTPS[] = "force-https";
+const char kStrict[] = "strict";
+const char kDefault[] = "default";
+const char kPinningOnly[] = "pinning-only";
+const char kCreated[] = "created";
+
+std::string LoadState(const base::FilePath& path) {
+ std::string result;
+ if (!base::ReadFileToString(path, &result)) {
+ return "";
+ }
+ return result;
+}
+
+} // namespace
+
+
+namespace net {
+
+TransportSecurityPersister::TransportSecurityPersister(
+ TransportSecurityState* state,
+ const base::FilePath& profile_path,
+ base::SequencedTaskRunner* background_runner,
+ bool readonly)
+ : transport_security_state_(state),
+ writer_(profile_path.AppendASCII("TransportSecurity"), background_runner),
+ foreground_runner_(base::MessageLoop::current()->message_loop_proxy()),
+ background_runner_(background_runner),
+ readonly_(readonly),
+ weak_ptr_factory_(this) {
+ transport_security_state_->SetDelegate(this);
+
+ base::PostTaskAndReplyWithResult(
+ background_runner_,
+ FROM_HERE,
+ base::Bind(&::LoadState, writer_.path()),
+ base::Bind(&TransportSecurityPersister::CompleteLoad,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+TransportSecurityPersister::~TransportSecurityPersister() {
+ DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+
+ if (writer_.HasPendingWrite())
+ writer_.DoScheduledWrite();
+
+ transport_security_state_->SetDelegate(NULL);
+}
+
+void TransportSecurityPersister::StateIsDirty(
+ TransportSecurityState* state) {
+ DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+ DCHECK_EQ(transport_security_state_, state);
+
+ if (!readonly_)
+ writer_.ScheduleWrite(this);
+}
+
+bool TransportSecurityPersister::SerializeData(std::string* output) {
+ DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+
+ DictionaryValue toplevel;
+ base::Time now = base::Time::Now();
+ TransportSecurityState::Iterator state(*transport_security_state_);
+ for (; state.HasNext(); state.Advance()) {
+ const std::string& hostname = state.hostname();
+ const TransportSecurityState::DomainState& domain_state =
+ state.domain_state();
+
+ DictionaryValue* serialized = new DictionaryValue;
+ serialized->SetBoolean(kStsIncludeSubdomains,
+ domain_state.sts_include_subdomains);
+ serialized->SetBoolean(kPkpIncludeSubdomains,
+ domain_state.pkp_include_subdomains);
+ serialized->SetDouble(kCreated, domain_state.created.ToDoubleT());
+ serialized->SetDouble(kExpiry, domain_state.upgrade_expiry.ToDoubleT());
+ serialized->SetDouble(kDynamicSPKIHashesExpiry,
+ domain_state.dynamic_spki_hashes_expiry.ToDoubleT());
+
+ switch (domain_state.upgrade_mode) {
+ case TransportSecurityState::DomainState::MODE_FORCE_HTTPS:
+ serialized->SetString(kMode, kForceHTTPS);
+ break;
+ case TransportSecurityState::DomainState::MODE_DEFAULT:
+ serialized->SetString(kMode, kDefault);
+ break;
+ default:
+ NOTREACHED() << "DomainState with unknown mode";
+ delete serialized;
+ continue;
+ }
+
+ serialized->Set(kStaticSPKIHashes,
+ SPKIHashesToListValue(domain_state.static_spki_hashes));
+
+ if (now < domain_state.dynamic_spki_hashes_expiry) {
+ serialized->Set(kDynamicSPKIHashes,
+ SPKIHashesToListValue(domain_state.dynamic_spki_hashes));
+ }
+
+ toplevel.Set(HashedDomainToExternalString(hostname), serialized);
+ }
+
+ base::JSONWriter::WriteWithOptions(&toplevel,
+ base::JSONWriter::OPTIONS_PRETTY_PRINT,
+ output);
+ return true;
+}
+
+bool TransportSecurityPersister::LoadEntries(const std::string& serialized,
+ bool* dirty) {
+ DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+
+ transport_security_state_->ClearDynamicData();
+ return Deserialize(serialized, dirty, transport_security_state_);
+}
+
+// static
+bool TransportSecurityPersister::Deserialize(const std::string& serialized,
+ bool* dirty,
+ TransportSecurityState* state) {
+ scoped_ptr<Value> value(base::JSONReader::Read(serialized));
+ DictionaryValue* dict_value = NULL;
+ if (!value.get() || !value->GetAsDictionary(&dict_value))
+ return false;
+
+ const base::Time current_time(base::Time::Now());
+ bool dirtied = false;
+
+ for (DictionaryValue::Iterator i(*dict_value); !i.IsAtEnd(); i.Advance()) {
+ const DictionaryValue* parsed = NULL;
+ if (!i.value().GetAsDictionary(&parsed)) {
+ LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry";
+ continue;
+ }
+
+ std::string mode_string;
+ double created;
+ double expiry;
+ double dynamic_spki_hashes_expiry = 0.0;
+ TransportSecurityState::DomainState domain_state;
+
+ // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and
+ // kPkpIncludeSubdomains. Parse at least one of these properties,
+ // preferably the new ones.
+ bool include_subdomains = false;
+ bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains,
+ &include_subdomains);
+ domain_state.sts_include_subdomains = include_subdomains;
+ domain_state.pkp_include_subdomains = include_subdomains;
+ if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) {
+ domain_state.sts_include_subdomains = include_subdomains;
+ parsed_include_subdomains = true;
+ }
+ if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) {
+ domain_state.pkp_include_subdomains = include_subdomains;
+ parsed_include_subdomains = true;
+ }
+
+ if (!parsed_include_subdomains ||
+ !parsed->GetString(kMode, &mode_string) ||
+ !parsed->GetDouble(kExpiry, &expiry)) {
+ LOG(WARNING) << "Could not parse some elements of entry " << i.key()
+ << "; skipping entry";
+ continue;
+ }
+
+ // Don't fail if this key is not present.
+ parsed->GetDouble(kDynamicSPKIHashesExpiry,
+ &dynamic_spki_hashes_expiry);
+
+ const ListValue* pins_list = NULL;
+ // preloaded_spki_hashes is a legacy synonym for static_spki_hashes.
+ if (parsed->GetList(kStaticSPKIHashes, &pins_list))
+ SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes);
+ else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list))
+ SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes);
+
+ if (parsed->GetList(kDynamicSPKIHashes, &pins_list))
+ SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes);
+
+ if (mode_string == kForceHTTPS || mode_string == kStrict) {
+ domain_state.upgrade_mode =
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
+ } else if (mode_string == kDefault || mode_string == kPinningOnly) {
+ domain_state.upgrade_mode =
+ TransportSecurityState::DomainState::MODE_DEFAULT;
+ } else {
+ LOG(WARNING) << "Unknown TransportSecurityState mode string "
+ << mode_string << " found for entry " << i.key()
+ << "; skipping entry";
+ continue;
+ }
+
+ domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry);
+ domain_state.dynamic_spki_hashes_expiry =
+ base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
+ if (parsed->GetDouble(kCreated, &created)) {
+ domain_state.created = base::Time::FromDoubleT(created);
+ } else {
+ // We're migrating an old entry with no creation date. Make sure we
+ // write the new date back in a reasonable time frame.
+ dirtied = true;
+ domain_state.created = base::Time::Now();
+ }
+
+ if (domain_state.upgrade_expiry <= current_time &&
+ domain_state.dynamic_spki_hashes_expiry <= current_time) {
+ // Make sure we dirty the state if we drop an entry.
+ dirtied = true;
+ continue;
+ }
+
+ std::string hashed = ExternalStringToHashedDomain(i.key());
+ if (hashed.empty()) {
+ dirtied = true;
+ continue;
+ }
+
+ state->AddOrUpdateEnabledHosts(hashed, domain_state);
+ }
+
+ *dirty = dirtied;
+ return true;
+}
+
+void TransportSecurityPersister::CompleteLoad(const std::string& state) {
+ DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+
+ if (state.empty())
+ return;
+
+ bool dirty = false;
+ if (!LoadEntries(state, &dirty)) {
+ LOG(ERROR) << "Failed to deserialize state: " << state;
+ return;
+ }
+ if (dirty)
+ StateIsDirty(transport_security_state_);
+}
+
+} // namespace net
diff --git a/chromium/net/http/transport_security_persister.h b/chromium/net/http/transport_security_persister.h
new file mode 100644
index 00000000000..7725ba124e6
--- /dev/null
+++ b/chromium/net/http/transport_security_persister.h
@@ -0,0 +1,138 @@
+// 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.
+
+// TransportSecurityState maintains an in memory database containing the
+// list of hosts that currently have transport security enabled. This
+// singleton object deals with writing that data out to disk as needed and
+// loading it at startup.
+
+// At startup we need to load the transport security state from the
+// disk. For the moment, we don't want to delay startup for this load, so we
+// let the TransportSecurityState run for a while without being loaded.
+// This means that it's possible for pages opened very quickly not to get the
+// correct transport security information.
+//
+// To load the state, we schedule a Task on file_task_runner, which
+// deserializes and configures the TransportSecurityState.
+//
+// The TransportSecurityState object supports running a callback function
+// when it changes. This object registers the callback, pointing at itself.
+//
+// TransportSecurityState calls...
+// TransportSecurityPersister::StateIsDirty
+// since the callback isn't allowed to block or reenter, we schedule a Task
+// on the file task runner after some small amount of time
+//
+// ...
+//
+// TransportSecurityPersister::SerializeState
+// copies the current state of the TransportSecurityState, serializes
+// and writes to disk.
+
+#ifndef NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_
+#define NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/important_file_writer.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "net/base/net_export.h"
+#include "net/http/transport_security_state.h"
+
+namespace base {
+class SequencedTaskRunner;
+}
+
+namespace net {
+
+// Reads and updates on-disk TransportSecurity state. Clients of this class
+// should create, destroy, and call into it from one thread.
+//
+// file_task_runner is the task runner this class should use internally to
+// perform file IO, and can optionally be associated with a different thread.
+class NET_EXPORT TransportSecurityPersister
+ : public TransportSecurityState::Delegate,
+ public base::ImportantFileWriter::DataSerializer {
+ public:
+ TransportSecurityPersister(TransportSecurityState* state,
+ const base::FilePath& profile_path,
+ base::SequencedTaskRunner* file_task_runner,
+ bool readonly);
+ virtual ~TransportSecurityPersister();
+
+ // Called by the TransportSecurityState when it changes its state.
+ virtual void StateIsDirty(TransportSecurityState*) OVERRIDE;
+
+ // ImportantFileWriter::DataSerializer:
+ //
+ // Serializes |transport_security_state_| into |*output|. Returns true if
+ // all DomainStates were serialized correctly.
+ //
+ // The serialization format is JSON; the JSON represents a dictionary of
+ // host:DomainState pairs (host is a string). The DomainState is
+ // represented as a dictionary containing the following keys and value
+ // types (not all keys will always be present):
+ //
+ // "sts_include_subdomains": true|false
+ // "pkp_include_subdomains": true|false
+ // "created": double
+ // "expiry": double
+ // "dynamic_spki_hashes_expiry": double
+ // "mode": "default"|"force-https"
+ // legacy value synonyms "strict" = "force-https"
+ // "pinning-only" = "default"
+ // legacy value "spdy-only" is unused and ignored
+ // "static_spki_hashes": list of strings
+ // legacy key synonym "preloaded_spki_hashes"
+ // "bad_static_spki_hashes": list of strings
+ // legacy key synonym "bad_preloaded_spki_hashes"
+ // "dynamic_spki_hashes": list of strings
+ //
+ // The JSON dictionary keys are strings containing
+ // Base64(SHA256(TransportSecurityState::CanonicalizeHost(domain))).
+ // The reason for hashing them is so that the stored state does not
+ // trivially reveal a user's browsing history to an attacker reading the
+ // serialized state on disk.
+ virtual bool SerializeData(std::string* data) OVERRIDE;
+
+ // Clears any existing non-static entries, and then re-populates
+ // |transport_security_state_|.
+ //
+ // Sets |*dirty| to true if the new state differs from the persisted
+ // state; false otherwise.
+ bool LoadEntries(const std::string& serialized, bool* dirty);
+
+ private:
+ // Populates |state| from the JSON string |serialized|. Returns true if
+ // all entries were parsed and deserialized correctly.
+ //
+ // Sets |*dirty| to true if the new state differs from the persisted
+ // state; false otherwise.
+ static bool Deserialize(const std::string& serialized,
+ bool* dirty,
+ TransportSecurityState* state);
+
+ void CompleteLoad(const std::string& state);
+
+ TransportSecurityState* transport_security_state_;
+
+ // Helper for safely writing the data.
+ base::ImportantFileWriter writer_;
+
+ scoped_refptr<base::SequencedTaskRunner> foreground_runner_;
+ scoped_refptr<base::SequencedTaskRunner> background_runner_;
+
+ // Whether or not we're in read-only mode.
+ const bool readonly_;
+
+ base::WeakPtrFactory<TransportSecurityPersister> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(TransportSecurityPersister);
+};
+
+} // namespace net
+
+#endif // NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_
diff --git a/chromium/net/http/transport_security_persister_unittest.cc b/chromium/net/http/transport_security_persister_unittest.cc
new file mode 100644
index 00000000000..8c41f9e81da
--- /dev/null
+++ b/chromium/net/http/transport_security_persister_unittest.cc
@@ -0,0 +1,201 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/http/transport_security_persister.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "net/http/transport_security_state.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using net::TransportSecurityPersister;
+using net::TransportSecurityState;
+
+class TransportSecurityPersisterTest : public testing::Test {
+ public:
+ TransportSecurityPersisterTest() {
+ }
+
+ virtual ~TransportSecurityPersisterTest() {
+ base::MessageLoopForIO::current()->RunUntilIdle();
+ }
+
+ virtual void SetUp() OVERRIDE {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ persister_.reset(new TransportSecurityPersister(
+ &state_,
+ temp_dir_.path(),
+ base::MessageLoopForIO::current()->message_loop_proxy(),
+ false));
+ }
+
+ protected:
+ base::ScopedTempDir temp_dir_;
+ TransportSecurityState state_;
+ scoped_ptr<TransportSecurityPersister> persister_;
+};
+
+TEST_F(TransportSecurityPersisterTest, SerializeData1) {
+ std::string output;
+ bool dirty;
+
+ EXPECT_TRUE(persister_->SerializeData(&output));
+ EXPECT_TRUE(persister_->LoadEntries(output, &dirty));
+ EXPECT_FALSE(dirty);
+}
+
+TEST_F(TransportSecurityPersisterTest, SerializeData2) {
+ TransportSecurityState::DomainState domain_state;
+ const base::Time current_time(base::Time::Now());
+ const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
+ static const char kYahooDomain[] = "yahoo.com";
+
+ EXPECT_FALSE(state_.GetDomainState(kYahooDomain, true, &domain_state));
+
+ bool include_subdomains = true;
+ state_.AddHSTS(kYahooDomain, expiry, include_subdomains);
+
+ std::string output;
+ bool dirty;
+ EXPECT_TRUE(persister_->SerializeData(&output));
+ EXPECT_TRUE(persister_->LoadEntries(output, &dirty));
+
+ EXPECT_TRUE(state_.GetDomainState(kYahooDomain, true, &domain_state));
+ EXPECT_EQ(domain_state.upgrade_mode,
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
+ EXPECT_TRUE(state_.GetDomainState("foo.yahoo.com", true, &domain_state));
+ EXPECT_EQ(domain_state.upgrade_mode,
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
+ EXPECT_TRUE(state_.GetDomainState("foo.bar.yahoo.com", true, &domain_state));
+ EXPECT_EQ(domain_state.upgrade_mode,
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
+ EXPECT_TRUE(state_.GetDomainState("foo.bar.baz.yahoo.com", true,
+ &domain_state));
+ EXPECT_EQ(domain_state.upgrade_mode,
+ TransportSecurityState::DomainState::MODE_FORCE_HTTPS);
+ EXPECT_FALSE(state_.GetDomainState("com", true, &domain_state));
+}
+
+TEST_F(TransportSecurityPersisterTest, SerializeData3) {
+ // Add an entry.
+ net::HashValue fp1(net::HASH_VALUE_SHA1);
+ memset(fp1.data(), 0, fp1.size());
+ net::HashValue fp2(net::HASH_VALUE_SHA1);
+ memset(fp2.data(), 1, fp2.size());
+ base::Time expiry =
+ base::Time::Now() + base::TimeDelta::FromSeconds(1000);
+ net::HashValueVector dynamic_spki_hashes;
+ dynamic_spki_hashes.push_back(fp1);
+ dynamic_spki_hashes.push_back(fp2);
+ bool include_subdomains = false;
+ state_.AddHSTS("www.example.com", expiry, include_subdomains);
+ state_.AddHPKP("www.example.com", expiry, include_subdomains,
+ dynamic_spki_hashes);
+
+ // Add another entry.
+ memset(fp1.data(), 2, fp1.size());
+ memset(fp2.data(), 3, fp2.size());
+ expiry =
+ base::Time::Now() + base::TimeDelta::FromSeconds(3000);
+ dynamic_spki_hashes.push_back(fp1);
+ dynamic_spki_hashes.push_back(fp2);
+ state_.AddHSTS("www.example.net", expiry, include_subdomains);
+ state_.AddHPKP("www.example.net", expiry, include_subdomains,
+ dynamic_spki_hashes);
+
+ // Save a copy of everything.
+ std::map<std::string, TransportSecurityState::DomainState> saved;
+ TransportSecurityState::Iterator i(state_);
+ while (i.HasNext()) {
+ saved[i.hostname()] = i.domain_state();
+ i.Advance();
+ }
+
+ std::string serialized;
+ EXPECT_TRUE(persister_->SerializeData(&serialized));
+
+ // Persist the data to the file. For the test to be fast and not flaky, we
+ // just do it directly rather than call persister_->StateIsDirty. (That uses
+ // ImportantFileWriter, which has an asynchronous commit interval rather
+ // than block.) Use a different basename just for cleanliness.
+ base::FilePath path =
+ temp_dir_.path().AppendASCII("TransportSecurityPersisterTest");
+ EXPECT_TRUE(file_util::WriteFile(path, serialized.c_str(),
+ serialized.size()));
+
+ // Read the data back.
+ std::string persisted;
+ EXPECT_TRUE(base::ReadFileToString(path, &persisted));
+ EXPECT_EQ(persisted, serialized);
+ bool dirty;
+ EXPECT_TRUE(persister_->LoadEntries(persisted, &dirty));
+ EXPECT_FALSE(dirty);
+
+ // Check that states are the same as saved.
+ size_t count = 0;
+ TransportSecurityState::Iterator j(state_);
+ while (j.HasNext()) {
+ count++;
+ j.Advance();
+ }
+ EXPECT_EQ(count, saved.size());
+}
+
+TEST_F(TransportSecurityPersisterTest, SerializeDataOld) {
+ // This is an old-style piece of transport state JSON, which has no creation
+ // date.
+ std::string output =
+ "{ "
+ "\"NiyD+3J1r6z1wjl2n1ALBu94Zj9OsEAMo0kCN8js0Uk=\": {"
+ "\"expiry\": 1266815027.983453, "
+ "\"include_subdomains\": false, "
+ "\"mode\": \"strict\" "
+ "}"
+ "}";
+ bool dirty;
+ EXPECT_TRUE(persister_->LoadEntries(output, &dirty));
+ EXPECT_TRUE(dirty);
+}
+
+TEST_F(TransportSecurityPersisterTest, PublicKeyHashes) {
+ TransportSecurityState::DomainState domain_state;
+ static const char kTestDomain[] = "example.com";
+ EXPECT_FALSE(state_.GetDomainState(kTestDomain, false, &domain_state));
+ net::HashValueVector hashes;
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
+
+ net::HashValue sha1(net::HASH_VALUE_SHA1);
+ memset(sha1.data(), '1', sha1.size());
+ domain_state.dynamic_spki_hashes.push_back(sha1);
+
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
+
+ hashes.push_back(sha1);
+ EXPECT_TRUE(domain_state.CheckPublicKeyPins(hashes));
+
+ hashes[0].data()[0] = '2';
+ EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes));
+
+ const base::Time current_time(base::Time::Now());
+ const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
+ bool include_subdomains = false;
+ state_.AddHSTS(kTestDomain, expiry, include_subdomains);
+ state_.AddHPKP(kTestDomain, expiry, include_subdomains,
+ domain_state.dynamic_spki_hashes);
+ std::string ser;
+ EXPECT_TRUE(persister_->SerializeData(&ser));
+ bool dirty;
+ EXPECT_TRUE(persister_->LoadEntries(ser, &dirty));
+ EXPECT_TRUE(state_.GetDomainState(kTestDomain, false, &domain_state));
+ EXPECT_EQ(1u, domain_state.dynamic_spki_hashes.size());
+ EXPECT_EQ(sha1.tag, domain_state.dynamic_spki_hashes[0].tag);
+ EXPECT_EQ(0, memcmp(domain_state.dynamic_spki_hashes[0].data(), sha1.data(),
+ sha1.size()));
+}
diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc
index d238e995568..f9ba807ff79 100644
--- a/chromium/net/http/transport_security_state.cc
+++ b/chromium/net/http/transport_security_state.cc
@@ -244,18 +244,8 @@ std::string TransportSecurityState::CanonicalizeHost(const std::string& host) {
break;
for (size_t j = 0; j < label_length; ++j) {
- // RFC 3490, 4.1, step 3
- if (!IsSTD3ASCIIValidCharacter(new_host[i + 1 + j]))
- return std::string();
-
new_host[i + 1 + j] = tolower(new_host[i + 1 + j]);
}
-
- // step 3(b)
- if (new_host[i + 1] == '-' ||
- new_host[i + label_length] == '-') {
- return std::string();
- }
}
return new_host;
@@ -522,6 +512,9 @@ enum SecondLevelDomainName {
DOMAIN_CHROMIUM_ORG,
DOMAIN_CRYPTO_CAT,
+ DOMAIN_LAVABIT_COM,
+
+ DOMAIN_GOOGLETAGMANAGER_COM,
// Boundary value for UMA_HISTOGRAM_ENUMERATION:
DOMAIN_NUM_EVENTS
diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h
index ccbc53a087d..97b4d7c1fc8 100644
--- a/chromium/net/http/transport_security_state.h
+++ b/chromium/net/http/transport_security_state.h
@@ -35,7 +35,7 @@ class SSLInfo;
class NET_EXPORT TransportSecurityState
: NON_EXPORTED_BASE(public base::NonThreadSafe) {
public:
- class Delegate {
+ class NET_EXPORT Delegate {
public:
// This function may not block and may be called with internal locks held.
// Thus it must not reenter the TransportSecurityState object.
diff --git a/chromium/net/http/transport_security_state_static.certs b/chromium/net/http/transport_security_state_static.certs
index ca6ef535bc8..718b7300f57 100644
--- a/chromium/net/http/transport_security_state_static.certs
+++ b/chromium/net/http/transport_security_state_static.certs
@@ -54,136 +54,12 @@ F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
-----END CERTIFICATE-----
-Google1024
------BEGIN CERTIFICATE-----
-MIICsDCCAhmgAwIBAgIDC2dxMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDkwNjA4MjA0MzI3WhcNMTMwNjA3MTk0MzI3
-WjBGMQswCQYDVQQGEwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzEiMCAGA1UEAxMZ
-R29vZ2xlIEludGVybmV0IEF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEAye23pIucV+eEPkB9hPSP0XFjU5nneXQUr0SZMyCSjXvlKAy6rWxJfoNf
-NFlOCnowzdDXxFdF7dWq1nMmzq0yE7jXDx07393cCDaob1FEm8rWIFJztyaHNWrb
-qeXUWaUr/GcZOfqTGBhs3t0lig4zFEfC7wFQeeT9adGnwKziV28CAwEAAaOBozCB
-oDAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFL/AMOv1QxE+Z7qekfv8atrjaxIk
-MB8GA1UdIwQYMBaAFEjmaPkr0rKV10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYB
-Af8CAQAwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20v
-Y3Jscy9zZWN1cmVjYS5jcmwwDQYJKoZIhvcNAQEFBQADgYEAuIojxkiWsRF8YHde
-BZqrocb6ghwYB8TrgbCoZutJqOkM0ymt9e8kTP3kS8p/XmOrmSfLnzYhLLkQYGfN
-0rTw8Ktx5YtaiScRhKqOv5nwnQkhClIZmloJ0pC3+gz4fniisIWvXEyZ2VxVKfml
-UUIuOss4jHg7y/j7lYe8vJD5UDI=
------END CERTIFICATE-----
-
-Google2048
-sha1/AbkhxY0L343gKf+cki7NVWp+ozk=
-
-GoogleBackup1024
-sha1/fVujyo43ZR18ccPjt3TN6XsbWUM=
-
GoogleBackup2048
sha1/vq7OyjSnqOco9nyMCDGdy77eijM=
GoogleG2
sha1/Q9rWMO5T+KmAym79hfRqo3mQ4Oo=
-ThawteSGCCA
------BEGIN CERTIFICATE-----
-MIIDIzCCAoygAwIBAgIEMAAAAjANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDMgUHVi
-bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNTEzMDAw
-MDAwWhcNMTQwNTEyMjM1OTU5WjBMMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
-d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEWMBQGA1UEAxMNVGhhd3RlIFNHQyBD
-QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1NNn0I0Vf67NMf59HZGhPwtx
-PKzMyGT7Y/wySweUvW+Aui/hBJPAM/wJMyPpC3QrccQDxtLN4i/1CWPN/0ilAL/g
-5/OIty0y3pg25gqtAHvEZEo7hHUD8nCSfQ5i9SGraTaEMXWQ+L/HbIgbBpV8yeWo
-3nWhLHpo39XKHIdYYBkCAwEAAaOB/jCB+zASBgNVHRMBAf8ECDAGAQH/AgEAMAsG
-A1UdDwQEAwIBBjARBglghkgBhvhCAQEEBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAX
-BgNVBAMTEFByaXZhdGVMYWJlbDMtMTUwMQYDVR0fBCowKDAmoCSgIoYgaHR0cDov
-L2NybC52ZXJpc2lnbi5jb20vcGNhMy5jcmwwMgYIKwYBBQUHAQEEJjAkMCIGCCsG
-AQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMDQGA1UdJQQtMCsGCCsGAQUF
-BwMBBggrBgEFBQcDAgYJYIZIAYb4QgQBBgpghkgBhvhFAQgBMA0GCSqGSIb3DQEB
-BQUAA4GBAFWsY+reod3SkF+fC852vhNRj5PZBSvIG3dLrWlQoe7e3P3bB+noOZTc
-q3J5Lwa/q4FwxKjt6lM07e8eU9kGx1Yr0Vz00YqOtCuxN5BICEIlxT6Ky3/rbwTR
-bcV0oveifHtgPHfNDs5IAn8BL7abN+AqKjbc1YXWrOU/VG+WHgWv
------END CERTIFICATE-----
-
-VeriSignClass3SSPIntermediateCA
------BEGIN CERTIFICATE-----
-MIIGVDCCBTygAwIBAgIQGYH0QFTS4OtUK7v7RciQfjANBgkqhkiG9w0BAQUFADCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMTk5OSBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
-ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5IC0gRzMwHhcNMTEwMTA3MDAwMDAwWhcNMTMxMjMxMjM1OTU5WjB2MQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxLTArBgNVBAMTJFZlcmlTaWduIENsYXNzIDMg
-U1NQIEludGVybWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBANfMaBonchSI7reVYNNe3hhSwUY/fbEmnDwCoonR2MFXsQkP9n8yNaU1nhRT
-Eovg4zAetI+e0bDAt9/0Lw/n1x/FdiTTPdMN6SxKLqc8z7xql0MZ+MBzyhsstmIB
-RmJWkGisFFAZ51BYB/k9AfLtHjQnvc1yHYBgo0ySG2a6ejkJd2r6U/dvjgbu2dSj
-Eo5XJGl//xSSLKs4HPhkuAsdZr2HqPiBwjlFpCd//Fs8he43JBI60+bRSBiUKpQC
-ssu6oAj2rvKcy2AMTvjIAlz9Iy3B92fB1Q1JxpbWcLochUca7/NFQTkKMaVeBXxy
-i2D+SFWfuBLtcl7p/kbtwqfiDbMCAwEAAaOCAocwggKDMA8GA1UdEwEB/wQFMAMB
-Af8wDgYDVR0PAQH/BAQDAgEGMIHoBgNVHSAEgeAwgd0wDwYNYIZIAYb4RQEHFwMB
-BjAPBg1ghkgBhvhFAQcXAwEHMA8GDWCGSAGG+EUBBxcDAQgwDwYNYIZIAYb4RQEH
-FwMBDTAPBg1ghkgBhvhFAQcXAwEOMA8GDWCGSAGG+EUBBxcDAQ8wDwYNYIZIAYb4
-RQEHFwMBETAPBg1ghkgBhvhFAQcXAwEUMA8GDWCGSAGG+EUBBxcDARcwDwYNYIZI
-AYb4RQEHFwMBGDAPBg1ghkgBhvhFAQcXAwEZMA8GDWCGSAGG+EUBBxcDARowDwYN
-YIZIAYb4RQEHFwMBGzA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vc3NwLWNybC52
-ZXJpc2lnbi5jb20vcGNhMy1nMy5jcmwwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMT
-EFZlcmlTaWduTVBLSS0xLTgwHQYDVR0OBBYEFCwx/8HOq/lN6IkVwGry5atCfUL6
-MIHxBgNVHSMEgekwgeahgdCkgc0wgcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5W
-ZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazE6
-MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXpl
-ZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMyBQdWJsaWMgUHJp
-bWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczghEAm34GSaM+YrnV7pBI
-cSnvVzANBgkqhkiG9w0BAQUFAAOCAQEAIS19vzG9j+KXiQ0G1bOuJCeiD9KKW1+8
-69cutvgDf3hEvrw39Gr2ek3cAdso7dvwW0Z17muzpHV08gWTjjKba8mBzjijmgr9
-I2vE2K/Ls72WJvTDUjCAHfBJKeK1q8v7xv1xtf2Jz7BV8sNH3kDB7jhhE++8zLVC
-gyFilU0KZfhBpLPVlVYnLozRdvsHfNnO/JskJvRqhDYbeC5ginQT0m5sTQiyTYqL
-/IU+i82TxANXjC7syl0dfcGr8pJ85T9bF1EZLxdgikAYLKPGTuXMwOGqT5bR0dKD
-lWShiGTRl7HW0KJMg05F0HjOnYpdOYGaFrQghecrkcrRPRevSdFVHQ==
------END CERTIFICATE-----
-
-EquifaxSecureCA
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
-
-Aetna
------BEGIN CERTIFICATE-----
-MIICsjCCAhugAwIBAgIDBe3YMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDUwODMxMjA0MDM3WhcNMTIwODMxMjA0MDM3
-WjBIMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQWV0bmEgSW5jLjEkMCIGA1UEAxMb
-QWV0bmEgSW5jLiBTZWN1cmUgU2VydmVyIENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQCnB2yrm4i44DG5epPu0fbe/pOZDWOvAS7qCcy6YbSkPfOHfH9Blmf3
-8L6D5yY1pzmTXaU7cDQu4qmj21toEIGwBziMmW6NsiV8nHtmtfXfHP6xrmyPUdN2
-DdTj937fnrYOoyMhGgBYEjiemeHFQxZSpKZdolFEFXbUa2/yWQafrQIDAQABo4Gj
-MIGgMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU2S4/xnaeitmFkzoxLnZeo33n
-H4owHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gjIBBPM5iQn9QwEgYDVR0TAQH/BAgw
-BgEB/wIBADA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNv
-bS9jcmxzL3NlY3VyZWNhLmNybDANBgkqhkiG9w0BAQUFAAOBgQBMSoZHIrD1rq8v
-UG3UYbN76xiF9FDRzWTs5Mvv4Psvf2kk426slzNO0ukFAsmwqN1mA/P9Nc4FlMMC
-YtcnLNwC/syEYdQBOJjxfTVGTqh5q6jDs7S3rPJv8mrFk8ldC8PxU1ZJVfSlFCDn
-6diMDgvOAJfUeJlIRLGu2k/ksI0Y1w==
------END CERTIFICATE-----
-
GeoTrustGlobal
-----BEGIN CERTIFICATE-----
MIIDfTCCAuagAwIBAgIDErvmMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
@@ -230,83 +106,6 @@ HoiVA8lJOq9nCEmw1Qj1ID2AkaDFh6P7yaMXkfmoL67pD9+Wcg91F4BdeAFNnx9t
e9j1QjgjGpmT9IO+OzV05zcTNXqstLaQgmwnpODsnjW9v+UpoUefWzL86Zl9Kzk=
-----END CERTIFICATE-----
-Intel
------BEGIN CERTIFICATE-----
-MIIFijCCBHKgAwIBAgIKYSCKYgAAAAAACDANBgkqhkiG9w0BAQUFADBSMQswCQYD
-VQQGEwJVUzEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24xJzAlBgNVBAMTHklu
-dGVsIEV4dGVybmFsIEJhc2ljIFBvbGljeSBDQTAeFw0wOTA1MTUxOTI3MjZaFw0x
-NTA1MTUxOTM3MjZaMFYxCzAJBgNVBAYTAlVTMRowGAYDVQQKExFJbnRlbCBDb3Jw
-b3JhdGlvbjErMCkGA1UEAxMiSW50ZWwgRXh0ZXJuYWwgQmFzaWMgSXNzdWluZyBD
-QSAzQjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKQEM1Wn9TU9vc9C
-+/Tc7KB+eiYElmrcEWE32WUdHvWG+IcQHVQsikTmMyKKojNLw2B5s6Iekc8ivDo/
-wCfjZzX9JyftMnc+AArc0la87Olybzm8K9jXEfTBvTnUSFSiI9ZYefITdiUgqlAF
-uljFZEHYKYtLuhrRacpmQfP4mV63NKdc2bT804HRf6YptZFa4k6YN94zlrGNrBuQ
-Q74WFzz/jLBusbUpEkro6Mu/ZYFOFWQrV9lBhF9Ruk8yN+3N6n9fUo/qBigiF2kE
-n9xVh1ykl7SCGL2jBUkXx4qgV27a6Si8lRRdgrHGtN/HWnSWlLXTH5l575H4Lq++
-77OFv38CAwEAAaOCAlwwggJYMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFA7G
-KvdZsggQkCVvw939imYxMCvFMAsGA1UdDwQEAwIBhjASBgkrBgEEAYI3FQEEBQID
-AQABMCMGCSsGAQQBgjcVAgQWBBQ5oFY2ekKQ/5Ktim+VdMeSWb4QWTAZBgkrBgEE
-AYI3FAIEDB4KAFMAdQBiAEMAQTAfBgNVHSMEGDAWgBQaxgxKxEdvqNutK/D0Vgaj
-7TdUDDCBvQYDVR0fBIG1MIGyMIGvoIGsoIGphk5odHRwOi8vd3d3LmludGVsLmNv
-bS9yZXBvc2l0b3J5L0NSTC9JbnRlbCUyMEV4dGVybmFsJTIwQmFzaWMlMjBQb2xp
-Y3klMjBDQS5jcmyGV2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuaW50ZWwuY29tL3JlcG9z
-aXRvcnkvQ1JML0ludGVsJTIwRXh0ZXJuYWwlMjBCYXNpYyUyMFBvbGljeSUyMENB
-LmNybDCB4wYIKwYBBQUHAQEEgdYwgdMwYwYIKwYBBQUHMAKGV2h0dHA6Ly93d3cu
-aW50ZWwuY29tL3JlcG9zaXRvcnkvY2VydGlmaWNhdGVzL0ludGVsJTIwRXh0ZXJu
-YWwlMjBCYXNpYyUyMFBvbGljeSUyMENBLmNydDBsBggrBgEFBQcwAoZgaHR0cDov
-L2NlcnRpZmljYXRlcy5pbnRlbC5jb20vcmVwb3NpdG9yeS9jZXJ0aWZpY2F0ZXMv
-SW50ZWwlMjBFeHRlcm5hbCUyMEJhc2ljJTIwUG9saWN5JTIwQ0EuY3J0MA0GCSqG
-SIb3DQEBBQUAA4IBAQCxtQEHchVQhXyjEqtMVUMe6gkmPsIczHxSeqNbo9dsD+6x
-bT65JT+oYgpIAtfEsYXeUJu1cChqpb22U5bMAz7eaQcW5bzefufWvA6lg2048B8o
-czBj/q+5P5NpYrUO8jOmN4jTjfJq3ElZ7yFWpy7rB3Vm/aN6ATYqWfMbS/xfh+JC
-xmH3droUmMJI0/aZJHsLtjbjFnNsHDNrJZX1vxlM78Lb1hjskTENPmhbVbfTj5i/
-ZGnhv4tmI8QZPCNtcegXJrfhRl2D9bWpdTOPrWiLDUqzy1Z6KL7TcOS/PCl8RHCJ
-XkPau/thTQCpIoDa2+c+3XA++gRTfAQ4svTO260N
------END CERTIFICATE-----
-
-TCTrustCenter
------BEGIN CERTIFICATE-----
-MIIDWzCCAsSgAwIBAgIDCaxIMA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDgwODE1MTY0NTE1WhcNMTMwMjE0MTc0NTE1
-WjBtMQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21iSDEe
-MBwGA1UECxMVVEMgVHJ1c3RDZW50ZXIgU1NMIENBMSAwHgYDVQQDExdUQyBUcnVz
-dENlbnRlciBTU0wgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AOkCoJoNbJw33wSxNWbDdmIfDIedR8Zmr/mjOhMkXdxRYb6qrl/WfMEuo4PBcysJ
-kF81LaDMkBH0zc7Hs1eYixrMVObkCmEUjxYylgOk4ExGwhmIWDJUWGslNBUIIhFf
-+ucDWuGZNfILQrwCWRHYBG0n/6lZPylCqopCMYhBK5sTI/PyuHEAzDL7+buep/Na
-zn+oy/a6x1nobsuL9X2oFaWZb7Z6ty5kZ/U56JHa7vnsLrg4ePwiQb8jtyUdz0fD
-uMHkNzK0gWxr4hm0v92otYFuOTZqNLEJneeiILxUCCMop2chr1obpq2zGVNxJ/rP
-StWmcu75KBGMpT+mzFgIyf0CAwEAAaOBozCBoDAOBgNVHQ8BAf8EBAMCAQYwHQYD
-VR0OBBYEFOe/bKlImXeG4tD/MKCQHQtk0IU6MB8GA1UdIwQYMBaAFEjmaPkr0rKV
-10fYIyAQTzOYkJ/UMBIGA1UdEwEB/wQIMAYBAf8CAQAwOgYDVR0fBDMwMTAvoC2g
-K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5jcmwwDQYJ
-KoZIhvcNAQEFBQADgYEAVKyJLbJha83PggEit8+dzh50wIsKXpTV2K6K4HnUI1kh
-xqocLVfQORluC+LS7L78D2EKTWLZ8WNujiP6DbbIPSTsMasuiBMQMBUlJMUqsp/M
-XmQJgIGAbxsr19MY6mmB30oWuo4cjHnkMzSCfhcON6Rxvbjijk2qCWXkk2T2HAk=
------END CERTIFICATE-----
-
-Vodafone
------BEGIN CERTIFICATE-----
-MIIDJDCCAo2gAwIBAgIDBfw3MA0GCSqGSIb3DQEBBQUAME4xCzAJBgNVBAYTAlVT
-MRAwDgYDVQQKEwdFcXVpZmF4MS0wKwYDVQQLEyRFcXVpZmF4IFNlY3VyZSBDZXJ0
-aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYwNzIxMTUwNTA2WhcNMTEwNzEyMTUwNTA2
-WjA5MQswCQYDVQQGEwJVSzEXMBUGA1UEChMOVm9kYWZvbmUgR3JvdXAxETAPBgNV
-BAMTCFZvZGFmb25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs61K
-wbMcB+GGGbjyo1dYEiVNGRYKRsDXfeOgeq03Vebf7D5Xq6a0Qs4Rvp6CuRTSNDPi
-M+0vuQRW5sib9UD8UB2x4znc6FriRV4FUpAyKNVqQ9NB0MOBpQekVlX9DzcXkn+p
-zWRi6tt3CtPsaDyHo06oAwX5qu3tW3pjtf0vnQqJWwwA6Mp4YJ/acHD/vVtt67hz
-a0Upz0O2DEJetb3OaqI5yaNZ91y6i7sK0KTvBQxZHeJs+y5UjluHv3ptMUZvmsf0
-SiKysXnkg5mtsZSFlfM+U7dADq1zNb764NV5sSlmbDLEkvohQyg1p9gh2HX9Jk4A
-e9nnF4hjw2U33HLBXwIDAQABo4GgMIGdMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
-FgQUR+YiAaq+68BPLD6l0UcvzlkcgvswHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwDwYDVR0TAQH/BAUwAwEB/zA6BgNVHR8EMzAxMC+gLaArhilodHRw
-Oi8vY3JsLmdlb3RydXN0LmNvbS9jcmxzL3NlY3VyZWNhLmNybDANBgkqhkiG9w0B
-AQUFAAOBgQCs37zuSY/KkPigCvJevu+ewWy9GP2bFZi5EaxKuHGF+tYFZUNkyc06
-ACYMM3ADPM6dVUYeXIDZnPfV8BJFCpdoAHkSNlg341AVjabCOWtzOYolBn0ua8Wi
-BM471XfzzXD7yMliek9J4fUn2vQU7MYgEkSAA53ZkMScGDkA/c1wMQ==
------END CERTIFICATE-----
-
RapidSSL
-----BEGIN CERTIFICATE-----
MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
@@ -1346,3 +1145,111 @@ TvwjIDhO+wtc3qXjtO1zej3+GBmGz7RcZckturc2pZe3NRWQ7wO8ZzWShWU/ii3z
2PftKlqZo3WAeJoUCPtQNsLnBFGvdUx2rUZwMhdgPuGeV4kEULAtu8M74xR5/Opz
nRGP22zr1K4q
-----END CERTIFICATE-----
+
+Libertylavabitcom
+-----BEGIN CERTIFICATE-----
+MIIGWjCCBUKgAwIBAgIHAMn6RGIIgjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
+BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
+BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm
+aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5
+IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky
+ODcwHhcNMTMxMDExMDgzNjAyWhcNMTQxMDExMDgzNjAyWjBBMSEwHwYDVQQLExhE
+b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxHDAaBgNVBAMTE2xpYmVydHkubGF2YWJp
+dC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCo/gQ2t5YtS2dj
+BhIo2ke667uC2qhnUbnroyuqyf+GZafWZC/cmPYpkAWclu14ETBsR3u+6QtDHhOe
+q3OBN0+IVLu5QwYSB2sqYUwyOHZ342uHQktWpPvNiwNHyfl1LsHL4WLuvQw3stK4
+DR+l6H/Ex11bl4KVvfk8uy+kXawcIQv7gr69OwEFEmGqeLSqr+fZdegLKPY20Ujx
+WHSe8ErtW0eMY2A/DvrDrnfw+rVX5sxJIKk77AutIoyt+Ce2TwMVQtfbeQVWy91g
+ST+sqC69wI5BOSguV5zECqIP1zxo939VVVciNGA3+3gyLJa+NDDpbT8xCwXClXN4
+3iektxfP7OgPjPwhDueZNhq54mA5mBY+qdkLyCmvURiczSNeoDTWouqaJq1lKjuh
+CgkAhgoaLueAQv+uGNlVFtbQHApEvYcdz8XTqoL24wf3kadu6vxhrYVS+hguVVEE
+YOc7LJsiQ3ERDjh1naFlL9h5khn6qhjw77oS6PWaCIJT8GfD8bjqCozdOdS1e+Sh
+Bbp2Yg48m/XyQ3ocpEUmTt7n3fRv41XOY4tmBhloqkdPIDccl5deUhI//1VgycJv
+uDqsMgRhyZvdS1kxhDAwbi1GtomURGdB/9kptYshUrR6xk1EP60pjWNxuvB7HMPg
+seGNxPa15U/4z+5h8iSFdKa2TLkk7wIDAQABo4IByzCCAccwDwYDVR0TAQH/BAUw
+AwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQD
+AgWgMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Rz
+MS0xMDAuY3JsMFMGA1UdIARMMEowSAYLYIZIAYb9bQEHFwEwOTA3BggrBgEFBQcC
+ARYraHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBvc2l0b3J5LzCB
+gAYIKwYBBQUHAQEEdDByMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5nb2RhZGR5
+LmNvbS8wSgYIKwYBBQUHMAKGPmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
+b20vcmVwb3NpdG9yeS9nZF9pbnRlcm1lZGlhdGUuY3J0MB8GA1UdIwQYMBaAFP2s
+YTKTbEXW4u6FX5q653aZaMznMDcGA1UdEQQwMC6CE2xpYmVydHkubGF2YWJpdC5j
+b22CF3d3dy5saWJlcnR5LmxhdmFiaXQuY29tMB0GA1UdDgQWBBSVRSbXCJKN6lms
+ZtlccHBz/xVLwDANBgkqhkiG9w0BAQUFAAOCAQEAKja1YxyoTuHD1RV4L7wULpiy
+ot4Z3OEuoOZTPJsoHfUCtOtKlUu2ZSwp5+IpaLnC3iCIxy1Yb6qu6Li5dqgtOkxl
+4JqrOooQ9IUzuTLhSzPf6rEtw9gnYN/dpQ2q0YLh+K5SgRUm9y0PHBV4acfSh2TJ
+vyaXDmuonX5zG7u3nz/oCo/qziW46Phz/leMhCAgLnZUYcAv6KPET+RMRmt4n8gg
+C0xlOcCQbMh9VIPZ0WSnmdFn5DUCW+oVlwhxDB/3CvWIa0k/WI6NNW8vg+VdSyW7
+p/dp4mikGH37Tc5VAhcYMbAem69nSg7Qfrs35tak/JPJlx1LWayERGHLvTy7Ag==
+-----END CERTIFICATE-----
+
+GlobalSignRootCA
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+GlobalSignRootCA_R2
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+GlobalSignRootCA_R3
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
diff --git a/chromium/net/http/transport_security_state_static.h b/chromium/net/http/transport_security_state_static.h
index a924550cbec..6a28ca4562b 100644
--- a/chromium/net/http/transport_security_state_static.h
+++ b/chromium/net/http/transport_security_state_static.h
@@ -22,18 +22,6 @@ static const char kSPKIHash_VeriSignClass3_G3[] =
"\x22\xf1\x9e\x2e\xc6\xea\xcc\xfc\x5d\x23"
"\x46\xf4\xc2\xe8\xf6\xc5\x54\xdd\x5e\x07";
-static const char kSPKIHash_Google1024[] =
- "\x40\xc5\x40\x1d\x6f\x8c\xba\xf0\x8b\x00"
- "\xed\xef\xb1\xee\x87\xd0\x05\xb3\xb9\xcd";
-
-static const char kSPKIHash_Google2048[] =
- "\x01\xb9\x21\xc5\x8d\x0b\xdf\x8d\xe0\x29"
- "\xff\x9c\x92\x2e\xcd\x55\x6a\x7e\xa3\x39";
-
-static const char kSPKIHash_GoogleBackup1024[] =
- "\x7d\x5b\xa3\xca\x8e\x37\x65\x1d\x7c\x71"
- "\xc3\xe3\xb7\x74\xcd\xe9\x7b\x1b\x59\x43";
-
static const char kSPKIHash_GoogleBackup2048[] =
"\xbe\xae\xce\xca\x34\xa7\xa8\xe7\x28\xf6"
"\x7c\x8c\x08\x31\x9d\xcb\xbe\xde\x8a\x33";
@@ -42,22 +30,6 @@ static const char kSPKIHash_GoogleG2[] =
"\x43\xda\xd6\x30\xee\x53\xf8\xa9\x80\xca"
"\x6e\xfd\x85\xf4\x6a\xa3\x79\x90\xe0\xea";
-static const char kSPKIHash_ThawteSGCCA[] =
- "\x87\x31\xea\x0e\x3d\xf5\xe8\x70\x3e\x83"
- "\x72\x57\x77\xa9\x65\x3b\x3b\xfa\x5e\x14";
-
-static const char kSPKIHash_VeriSignClass3SSPIntermediateCA[] =
- "\x99\x6a\x20\x6a\x85\x57\x62\xcb\x9a\xf2"
- "\x02\x37\xb3\xc0\x69\x5d\xa9\x1e\xc2\x22";
-
-static const char kSPKIHash_EquifaxSecureCA[] =
- "\x48\xe6\x68\xf9\x2b\xd2\xb2\x95\xd7\x47"
- "\xd8\x23\x20\x10\x4f\x33\x98\x90\x9f\xd4";
-
-static const char kSPKIHash_Aetna[] =
- "\x92\x52\xaa\x14\xde\xbf\x80\xae\x30\xaa"
- "\xd9\x4e\x60\x38\x70\x24\xa5\x43\x2f\x1a";
-
static const char kSPKIHash_GeoTrustGlobal[] =
"\xc0\x7a\x98\x68\x8d\x89\xfb\xab\x05\x64"
"\x0c\x11\x7d\xaa\x7d\x65\xb8\xca\xcc\x4e";
@@ -66,18 +38,6 @@ static const char kSPKIHash_GeoTrustPrimary[] =
"\xb0\x19\x89\xe7\xef\xfb\x4a\xaf\xcb\x14"
"\x8f\x58\x46\x39\x76\x22\x41\x50\xe1\xba";
-static const char kSPKIHash_Intel[] =
- "\x0e\xc6\x2a\xf7\x59\xb2\x08\x10\x90\x25"
- "\x6f\xc3\xdd\xfd\x8a\x66\x31\x30\x2b\xc5";
-
-static const char kSPKIHash_TCTrustCenter[] =
- "\x83\x3b\x84\x10\x00\x7f\x6e\x4a\x9d\x41"
- "\x2d\xc4\x22\x39\x36\x6f\x2e\xe5\x5b\xe9";
-
-static const char kSPKIHash_Vodafone[] =
- "\x0d\x7f\xe1\x5c\x55\x14\x36\x68\x99\xfc"
- "\x40\xd6\x22\x08\xef\x22\xeb\xd1\x15\x1c";
-
static const char kSPKIHash_RapidSSL[] =
"\xa3\x93\x99\xc4\x04\xc3\xb2\x09\xb0\x81"
"\xc2\x1f\x21\x62\x27\x78\xc2\x74\x8e\x4c";
@@ -250,6 +210,22 @@ static const char kSPKIHash_CryptoCat1[] =
"\x4c\x87\xce\x85\x2c\xf4\xc0\x4d\x67\xa9"
"\xe0\xec\x51\x0c\x7f\x3b\x14\xb3\xe9\xc9";
+static const char kSPKIHash_Libertylavabitcom[] =
+ "\x41\xbb\x3b\x8b\xc7\xcf\x3d\x13\x3f\x17"
+ "\xb3\x25\x7e\xe4\x03\xca\x8a\x5c\x6d\x36";
+
+static const char kSPKIHash_GlobalSignRootCA[] =
+ "\x87\xdb\xd4\x5f\xb0\x92\x8d\x4e\x1d\xf8"
+ "\x15\x67\xe7\xf2\xab\xaf\xd6\x2b\x67\x75";
+
+static const char kSPKIHash_GlobalSignRootCA_R2[] =
+ "\xa5\x06\x8a\x78\xcf\x84\xbd\x74\x32\xdd"
+ "\x58\xf9\x65\xeb\x3a\x55\xe7\xc7\x80\xdc";
+
+static const char kSPKIHash_GlobalSignRootCA_R3[] =
+ "\xf7\x93\x19\xef\xdf\xc1\xf5\x20\xfb\xac"
+ "\x85\x55\x2c\xf2\xd2\x8f\x5a\xb9\xca\x0b";
+
// The following is static data describing the hosts that are hardcoded with
// certificate pins or HSTS information.
@@ -268,29 +244,13 @@ static const char* const kTestAcceptableCerts[] = {
}
static const char* const kGoogleAcceptableCerts[] = {
- kSPKIHash_VeriSignClass3,
- kSPKIHash_VeriSignClass3_G3,
- kSPKIHash_Google1024,
- kSPKIHash_Google2048,
- kSPKIHash_GoogleBackup1024,
kSPKIHash_GoogleBackup2048,
kSPKIHash_GoogleG2,
- kSPKIHash_EquifaxSecureCA,
- kSPKIHash_GeoTrustGlobal,
- NULL,
-};
-static const char* const kGoogleRejectedCerts[] = {
- kSPKIHash_Aetna,
- kSPKIHash_Intel,
- kSPKIHash_TCTrustCenter,
- kSPKIHash_Vodafone,
- kSPKIHash_ThawteSGCCA,
- kSPKIHash_VeriSignClass3SSPIntermediateCA,
NULL,
};
#define kGooglePins { \
kGoogleAcceptableCerts, \
- kGoogleRejectedCerts, \
+ kNoRejectedPublicKeys, \
}
static const char* const kTorAcceptableCerts[] = {
@@ -377,6 +337,9 @@ static const char* const kTwitterCDNAcceptableCerts[] = {
kSPKIHash_UTNUSERFirstObject,
kSPKIHash_GTECyberTrustGlobalRoot,
kSPKIHash_BaltimoreCyberTrustRoot,
+ kSPKIHash_GlobalSignRootCA,
+ kSPKIHash_GlobalSignRootCA_R2,
+ kSPKIHash_GlobalSignRootCA_R3,
NULL,
};
#define kTwitterCDNPins { \
@@ -404,6 +367,15 @@ static const char* const kCryptoCatAcceptableCerts[] = {
kNoRejectedPublicKeys, \
}
+static const char* const kLavabitAcceptableCerts[] = {
+ kSPKIHash_Libertylavabitcom,
+ NULL,
+};
+#define kLavabitPins { \
+ kLavabitAcceptableCerts, \
+ kNoRejectedPublicKeys, \
+}
+
#define kNoPins {\
NULL, NULL, \
}
@@ -430,6 +402,10 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{19, true, "\006script\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{20, true, "\007history\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{21, true, "\010security\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+ {17, true, "\004goto\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+ {18, true, "\005cloud\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+ {18, true, "\005glass\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+ {17, false, "\004play\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
{20, true, "\006market\007android\003com", true, kGooglePins, DOMAIN_ANDROID_COM },
{26, true, "\003ssl\020google-analytics\003com", true, kGooglePins, DOMAIN_GOOGLE_ANALYTICS_COM },
{18, true, "\005drive\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
@@ -453,13 +429,14 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{13, true, "\007appspot\003com", false, kGooglePins, DOMAIN_APPSPOT_COM },
{23, true, "\021googlesyndication\003com", false, kGooglePins, DOMAIN_GOOGLESYNDICATION_COM },
{17, true, "\013doubleclick\003net", false, kGooglePins, DOMAIN_DOUBLECLICK_NET },
- {17, true, "\003ssl\007gstatic\003com", false, kGooglePins, DOMAIN_GSTATIC_COM },
+ {13, true, "\007gstatic\003com", false, kGooglePins, DOMAIN_GSTATIC_COM },
{10, true, "\005youtu\002be", false, kGooglePins, DOMAIN_YOUTU_BE },
{13, true, "\007android\003com", false, kGooglePins, DOMAIN_ANDROID_COM },
{20, true, "\016googlecommerce\003com", false, kGooglePins, DOMAIN_GOOGLECOMMERCE_COM },
{12, true, "\006urchin\003com", false, kGooglePins, DOMAIN_URCHIN_COM },
{8, true, "\003goo\002gl", false, kGooglePins, DOMAIN_GOO_GL },
{6, true, "\001g\002co", false, kGooglePins, DOMAIN_G_CO },
+ {22, true, "\020googletagmanager\003com", false, kGooglePins, DOMAIN_GOOGLETAGMANAGER_COM },
{11, true, "\006google\002ac", false, kGooglePins, DOMAIN_GOOGLE_AC },
{11, true, "\006google\002ad", false, kGooglePins, DOMAIN_GOOGLE_AD },
{11, true, "\006google\002ae", false, kGooglePins, DOMAIN_GOOGLE_AE },
@@ -753,8 +730,7 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{17, true, "\003dev\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER_COM },
{22, true, "\010business\007twitter\003com", false, kTwitterComPins, DOMAIN_TWITTER_COM },
{22, true, "\010platform\007twitter\003com", false, kTwitterCDNPins, DOMAIN_TWITTER_COM },
- {15, true, "\003si0\005twimg\003com", false, kTwitterCDNPins, DOMAIN_TWIMG_COM },
- {23, true, "\010twimg0-a\010akamaihd\003net", false, kTwitterCDNPins, DOMAIN_AKAMAIHD_NET },
+ {11, true, "\005twimg\003com", false, kTwitterCDNPins, DOMAIN_TWIMG_COM },
{22, true, "\020braintreegateway\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{23, false, "\021braintreepayments\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{27, false, "\003www\021braintreepayments\003com", true, kNoPins, DOMAIN_NOT_PINNED },
@@ -794,8 +770,12 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{17, false, "\003www\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{15, false, "\011mylookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{19, false, "\003www\011mylookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
- {16, false, "\002dm\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
- {18, false, "\002dm\011mylookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, true, "\002dm\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {22, true, "\010business\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\004blog\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\003faq\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {22, true, "\010platform\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, true, "\005email\007lookout\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{15, true, "\011itriskltd\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{15, true, "\012stocktrade\002de", true, kNoPins, DOMAIN_NOT_PINNED },
{22, true, "\011openshift\006redhat\003com", true, kNoPins, DOMAIN_NOT_PINNED },
@@ -855,8 +835,6 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{21, true, "\003www\013cyveillance\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{22, true, "\004blog\013cyveillance\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{12, true, "\006whonix\003org", true, kNoPins, DOMAIN_NOT_PINNED },
- {13, true, "\010blueseed\002co", true, kNoPins, DOMAIN_NOT_PINNED },
- {26, true, "\005forum\016quantifiedself\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{11, true, "\006shodan\002io", true, kNoPins, DOMAIN_NOT_PINNED },
{18, true, "\015rapidresearch\002me", true, kNoPins, DOMAIN_NOT_PINNED },
{14, true, "\010surkatty\003org", true, kNoPins, DOMAIN_NOT_PINNED },
@@ -873,6 +851,39 @@ static const struct HSTSPreload kPreloadedSTS[] = {
{22, true, "\020appseccalifornia\003org", true, kNoPins, DOMAIN_NOT_PINNED },
{17, true, "\013crowdcurity\003com", true, kNoPins, DOMAIN_NOT_PINNED },
{19, true, "\013saturngames\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, true, "\021strongest-privacy\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {25, true, "\011ecosystem\011atlassian\003net", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\002id\011atlassian\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\011bitbucket\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\007cupcake\002io", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\007cupcake\002is", true, kNoPins, DOMAIN_NOT_PINNED },
+ {9, true, "\004tent\002io", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\006cybozu\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, true, "\013davidlyness\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {12, true, "\006medium\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {21, true, "\007liberty\007lavabit\003com", true, kLavabitPins, DOMAIN_LAVABIT_COM },
+ {16, true, "\012getlantern\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\011kinsights\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {15, false, "\007simbolo\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, false, "\003www\007simbolo\002co\002uk", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, false, "\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\003www\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {20, false, "\003get\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, false, "\006errors\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {23, false, "\006manage\012zenpayroll\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, true, "\016gernert-server\002de", true, kNoPins, DOMAIN_NOT_PINNED },
+ {19, true, "\010skydrive\004live\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {21, true, "\011lifeguard\005aecom\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {17, false, "\004data\003qld\003gov\002au", true, kNoPins, DOMAIN_NOT_PINNED },
+ {25, false, "\014publications\003qld\003gov\002au", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\002go\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {16, true, "\005login\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\002my\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {18, true, "\007payroll\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {13, true, "\002in\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {14, true, "\003api\004xero\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+ {9, true, "\003eff\003org", true, kNoPins, DOMAIN_NOT_PINNED },
+ {9, true, "\004mail\002de", true, kNoPins, DOMAIN_NOT_PINNED },
};
static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
diff --git a/chromium/net/http/transport_security_state_static.json b/chromium/net/http/transport_security_state_static.json
index 67e5a86ccd8..500e1782110 100644
--- a/chromium/net/http/transport_security_state_static.json
+++ b/chromium/net/http/transport_security_state_static.json
@@ -42,23 +42,8 @@
{
"name": "google",
"static_spki_hashes": [
- "VeriSignClass3",
- "VeriSignClass3_G3",
- "Google1024",
- "Google2048",
- "GoogleBackup1024",
"GoogleBackup2048",
- "GoogleG2",
- "EquifaxSecureCA",
- "GeoTrustGlobal"
- ],
- "bad_static_spki_hashes": [
- "Aetna",
- "Intel",
- "TCTrustCenter",
- "Vodafone",
- "ThawteSGCCA",
- "VeriSignClass3SSPIntermediateCA"
+ "GoogleG2"
]
},
{
@@ -141,7 +126,10 @@
"UTNUSERFirstHardware",
"UTNUSERFirstObject",
"GTECyberTrustGlobalRoot",
- "BaltimoreCyberTrustRoot"
+ "BaltimoreCyberTrustRoot",
+ "GlobalSignRootCA",
+ "GlobalSignRootCA_R2",
+ "GlobalSignRootCA_R3"
]
},
{
@@ -157,6 +145,12 @@
"DigiCertEVRoot",
"CryptoCat1"
]
+ },
+ {
+ "name": "lavabit",
+ "static_spki_hashes": [
+ "Libertylavabitcom"
+ ]
}
],
@@ -187,6 +181,11 @@
{ "name": "script.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "history.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
{ "name": "security.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "goto.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "cloud.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ { "name": "glass.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+ // play.google.com doesn't have include_subdomains because of crbug.com/327834.
+ { "name": "play.google.com", "mode": "force-https", "pins": "google" },
// Other Google-related domains that must use HTTPS.
{ "name": "market.android.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
@@ -219,13 +218,14 @@
{ "name": "appspot.com", "include_subdomains": true, "pins": "google" },
{ "name": "googlesyndication.com", "include_subdomains": true, "pins": "google" },
{ "name": "doubleclick.net", "include_subdomains": true, "pins": "google" },
- { "name": "ssl.gstatic.com", "include_subdomains": true, "pins": "google" },
+ { "name": "gstatic.com", "include_subdomains": true, "pins": "google" },
{ "name": "youtu.be", "include_subdomains": true, "pins": "google" },
{ "name": "android.com", "include_subdomains": true, "pins": "google" },
{ "name": "googlecommerce.com", "include_subdomains": true, "pins": "google" },
{ "name": "urchin.com", "include_subdomains": true, "pins": "google" },
{ "name": "goo.gl", "include_subdomains": true, "pins": "google" },
{ "name": "g.co", "include_subdomains": true, "pins": "google" },
+ { "name": "googletagmanager.com", "include_subdomains": true, "pins": "google" },
{ "name": "google.ac", "include_subdomains": true, "pins": "google" },
{ "name": "google.ad", "include_subdomains": true, "pins": "google" },
{ "name": "google.ae", "include_subdomains": true, "pins": "google" },
@@ -523,8 +523,7 @@
{ "name": "dev.twitter.com", "include_subdomains": true, "pins": "twitterCom" },
{ "name": "business.twitter.com", "include_subdomains": true, "pins": "twitterCom" },
{ "name": "platform.twitter.com", "include_subdomains": true, "pins": "twitterCDN" },
- { "name": "si0.twimg.com", "include_subdomains": true, "pins": "twitterCDN" },
- { "name": "twimg0-a.akamaihd.net", "include_subdomains": true, "pins": "twitterCDN" },
+ { "name": "twimg.com", "include_subdomains": true, "pins": "twitterCDN" },
{ "name": "braintreegateway.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "braintreepayments.com", "mode": "force-https" },
{ "name": "www.braintreepayments.com", "mode": "force-https" },
@@ -564,8 +563,12 @@
{ "name": "www.lookout.com", "mode": "force-https" },
{ "name": "mylookout.com", "mode": "force-https" },
{ "name": "www.mylookout.com", "mode": "force-https" },
- { "name": "dm.lookout.com", "mode": "force-https" },
- { "name": "dm.mylookout.com", "mode": "force-https" },
+ { "name": "dm.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "business.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "blog.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "faq.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "platform.lookout.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "email.lookout.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "itriskltd.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "stocktrade.de", "include_subdomains": true, "mode": "force-https" },
{ "name": "openshift.redhat.com", "include_subdomains": true, "mode": "force-https" },
@@ -625,8 +628,6 @@
{ "name": "www.cyveillance.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "blog.cyveillance.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "whonix.org", "include_subdomains": true, "mode": "force-https" },
- { "name": "blueseed.co", "include_subdomains": true, "mode": "force-https" },
- { "name": "forum.quantifiedself.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "shodan.io", "include_subdomains": true, "mode": "force-https" },
{ "name": "rapidresearch.me", "include_subdomains": true, "mode": "force-https" },
{ "name": "surkatty.org", "include_subdomains": true, "mode": "force-https" },
@@ -643,6 +644,39 @@
{ "name": "appseccalifornia.org", "include_subdomains": true, "mode": "force-https" },
{ "name": "crowdcurity.com", "include_subdomains": true, "mode": "force-https" },
{ "name": "saturngames.co.uk", "include_subdomains": true, "mode": "force-https" },
+ { "name": "strongest-privacy.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "ecosystem.atlassian.net", "include_subdomains": true, "mode": "force-https" },
+ { "name": "id.atlassian.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "bitbucket.org", "mode": "force-https" },
+ { "name": "cupcake.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cupcake.is", "include_subdomains": true, "mode": "force-https" },
+ { "name": "tent.io", "include_subdomains": true, "mode": "force-https" },
+ { "name": "cybozu.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "davidlyness.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "medium.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "liberty.lavabit.com", "include_subdomains": true, "mode": "force-https", "pins": "lavabit" },
+ { "name": "getlantern.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "kinsights.com", "mode": "force-https" },
+ { "name": "simbolo.co.uk", "mode": "force-https" },
+ { "name": "www.simbolo.co.uk", "mode": "force-https" },
+ { "name": "zenpayroll.com", "mode": "force-https" },
+ { "name": "www.zenpayroll.com", "mode": "force-https" },
+ { "name": "get.zenpayroll.com", "mode": "force-https" },
+ { "name": "errors.zenpayroll.com", "mode": "force-https" },
+ { "name": "manage.zenpayroll.com", "mode": "force-https" },
+ { "name": "gernert-server.de", "include_subdomains": true, "mode": "force-https" },
+ { "name": "skydrive.live.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "lifeguard.aecom.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "data.qld.gov.au", "mode": "force-https" },
+ { "name": "publications.qld.gov.au", "mode": "force-https" },
+ { "name": "go.xero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "login.xero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "my.xero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "payroll.xero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "in.xero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "api.xero.com", "include_subdomains": true, "mode": "force-https" },
+ { "name": "eff.org", "include_subdomains": true, "mode": "force-https" },
+ { "name": "mail.de", "include_subdomains": true, "mode": "force-https" },
// Entries that are only valid if the client supports SNI.
{ "name": "gmail.com", "mode": "force-https", "pins": "google", "snionly": true },
diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc
index 936d5628249..c3d15da29f9 100644
--- a/chromium/net/http/transport_security_state_unittest.cc
+++ b/chromium/net/http/transport_security_state_unittest.cc
@@ -117,6 +117,19 @@ TEST_F(TransportSecurityStateTest, SubdomainMatches) {
EXPECT_FALSE(state.GetDomainState("com", true, &domain_state));
}
+TEST_F(TransportSecurityStateTest, InvalidDomains) {
+ TransportSecurityState state;
+ TransportSecurityState::DomainState domain_state;
+ const base::Time current_time(base::Time::Now());
+ const base::Time expiry = current_time + base::TimeDelta::FromSeconds(1000);
+
+ EXPECT_FALSE(state.GetDomainState("yahoo.com", true, &domain_state));
+ bool include_subdomains = true;
+ state.AddHSTS("yahoo.com", expiry, include_subdomains);
+ EXPECT_TRUE(state.GetDomainState("www-.foo.yahoo.com", true, &domain_state));
+ EXPECT_TRUE(state.GetDomainState("2\x01.foo.yahoo.com", true, &domain_state));
+}
+
TEST_F(TransportSecurityStateTest, DeleteAllDynamicDataSince) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
@@ -506,7 +519,8 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) {
EXPECT_TRUE(HasPublicKeyPins("apis.google.com"));
EXPECT_TRUE(HasPublicKeyPins("ssl.gstatic.com"));
- EXPECT_FALSE(HasPublicKeyPins("www.gstatic.com"));
+ EXPECT_TRUE(HasPublicKeyPins("gstatic.com"));
+ EXPECT_TRUE(HasPublicKeyPins("www.gstatic.com"));
EXPECT_TRUE(HasPublicKeyPins("ssl.google-analytics.com"));
EXPECT_TRUE(HasPublicKeyPins("www.googleplex.com"));
@@ -521,7 +535,6 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) {
EXPECT_TRUE(HasPublicKeyPins("business.twitter.com"));
EXPECT_TRUE(HasPublicKeyPins("platform.twitter.com"));
EXPECT_TRUE(HasPublicKeyPins("si0.twimg.com"));
- EXPECT_TRUE(HasPublicKeyPins("twimg0-a.akamaihd.net"));
}
static bool AddHash(const std::string& type_and_base64,
@@ -534,43 +547,6 @@ static bool AddHash(const std::string& type_and_base64,
return true;
}
-TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) {
- // kGoodPath is plus.google.com via Google Internet Authority.
- static const char* kGoodPath[] = {
- "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
- "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=",
- "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
- NULL,
- };
-
- // kBadPath is plus.google.com via Trustcenter, which contains a required
- // certificate (Equifax root), but also an excluded certificate
- // (Trustcenter).
- static const char* kBadPath[] = {
- "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=",
- "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=",
- "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=",
- NULL,
- };
-
- 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));
- }
-
- TransportSecurityState state;
- TransportSecurityState::DomainState domain_state;
- EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state));
- EXPECT_TRUE(domain_state.HasPublicKeyPins());
-
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(good_hashes));
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes));
-}
-
TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) {
// kGoodPath is blog.torproject.org.
static const char* kGoodPath[] = {
@@ -607,100 +583,6 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) {
EXPECT_FALSE(domain_state.CheckPublicKeyPins(bad_hashes));
}
-TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCertsMixedHashes) {
- static const char* ee_sha1 = "sha1/4BjDjn8v2lWeUFQnqSs0BgbIcrU=";
- static const char* ee_sha256 =
- "sha256/sRJBQqWhpaKIGcc1NA7/jJ4vgWj+47oYfyU7waOS1+I=";
- static const char* google_1024_sha1 = "sha1/QMVAHW+MuvCLAO3vse6H0AWzuc0=";
- static const char* google_1024_sha256 =
- "sha256/trlUMquuV/4CDLK3T0+fkXPIxwivyecyrOIyeQR8bQU=";
- static const char* equifax_sha1 = "sha1/SOZo+SvSspXXR9gjIBBPM5iQn9Q=";
- static const char* equifax_sha256 =
- "sha256//1aAzXOlcD2gSBegdf1GJQanNQbEuBoVg+9UlHjSZHY=";
- static const char* trustcenter_sha1 = "sha1/gzuEEAB/bkqdQS3EIjk2by7lW+k=";
- static const char* trustcenter_sha256 =
- "sha256/Dq58KIA4NMLsboWMLU8/aTREzaAGEFW+EtUule8dd/M=";
-
- // Good chains for plus.google.com chain up through google_1024_sha{1,256}
- // to equifax_sha{1,256}. Bad chains chain up to Equifax through
- // trustcenter_sha{1,256}, which is a blacklisted key. Even though Equifax
- // and Google1024 are known-good, the blacklistedness of Trustcenter
- // should override and cause pin validation failure.
-
- TransportSecurityState state;
- TransportSecurityState::DomainState domain_state;
- EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state));
- EXPECT_TRUE(domain_state.HasPublicKeyPins());
-
- // The statically-defined pins are all SHA-1, so we add some SHA-256 pins
- // manually:
- EXPECT_TRUE(AddHash(google_1024_sha256, &domain_state.static_spki_hashes));
- EXPECT_TRUE(AddHash(trustcenter_sha256,
- &domain_state.bad_static_spki_hashes));
-
- // Try an all-good SHA1 chain.
- HashValueVector validated_chain;
- EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try an all-bad SHA1 chain.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try an all-good SHA-256 chain.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try an all-bad SHA-256 chain.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try a mixed-hash good chain.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try a mixed-hash bad chain.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try a chain with all good hashes.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(google_1024_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(google_1024_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
- EXPECT_TRUE(domain_state.CheckPublicKeyPins(validated_chain));
-
- // Try a chain with all bad hashes.
- validated_chain.clear();
- EXPECT_TRUE(AddHash(ee_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(trustcenter_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha1, &validated_chain));
- EXPECT_TRUE(AddHash(ee_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(trustcenter_sha256, &validated_chain));
- EXPECT_TRUE(AddHash(equifax_sha256, &validated_chain));
- EXPECT_FALSE(domain_state.CheckPublicKeyPins(validated_chain));
-}
-
TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) {
TransportSecurityState state;
TransportSecurityState::DomainState domain_state;
@@ -744,38 +626,6 @@ TEST_F(TransportSecurityStateTest, OverrideBuiltins) {
EXPECT_TRUE(state.GetDomainState("www.google.com", true, &domain_state));
}
-static const uint8 kSidePinLeafSPKI[] = {
- 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
- 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xe4,
- 0x1d, 0xcc, 0xf2, 0x92, 0xe7, 0x7a, 0xc6, 0x36, 0xf7, 0x1a, 0x62, 0x31, 0x7d,
- 0x37, 0xea, 0x0d, 0xa2, 0xa8, 0x12, 0x2b, 0xc2, 0x1c, 0x82, 0x3e, 0xa5, 0x70,
- 0x4a, 0x83, 0x5d, 0x9b, 0x84, 0x82, 0x70, 0xa4, 0x88, 0x98, 0x98, 0x41, 0x29,
- 0x31, 0xcb, 0x6e, 0x2a, 0x54, 0x65, 0x14, 0x60, 0xcc, 0x00, 0xe8, 0x10, 0x30,
- 0x0a, 0x4a, 0xd1, 0xa7, 0x52, 0xfe, 0x2d, 0x31, 0x2a, 0x1d, 0x0d, 0x02, 0x03,
- 0x01, 0x00, 0x01,
-};
-
-static const uint8 kSidePinInfo[] = {
- 0x01, 0x00, 0x53, 0x50, 0x49, 0x4e, 0xa0, 0x00, 0x03, 0x00, 0x53, 0x49, 0x47,
- 0x00, 0x50, 0x55, 0x42, 0x4b, 0x41, 0x4c, 0x47, 0x4f, 0x47, 0x00, 0x41, 0x00,
- 0x04, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xfb, 0x26, 0xd5, 0xe8, 0x76, 0x35,
- 0x96, 0x6d, 0x91, 0x9b, 0x5b, 0x27, 0xe6, 0x09, 0x1c, 0x7b, 0x6c, 0xcd, 0xc8,
- 0x10, 0x25, 0x95, 0xc0, 0xa5, 0xf6, 0x6c, 0x6f, 0xfb, 0x59, 0x1e, 0x2d, 0xf4,
- 0x02, 0x20, 0x33, 0x0a, 0xf8, 0x8b, 0x3e, 0xc4, 0xca, 0x75, 0x28, 0xdf, 0x5f,
- 0xab, 0xe4, 0x46, 0xa0, 0xdd, 0x2d, 0xe5, 0xad, 0xc3, 0x81, 0x44, 0x70, 0xb2,
- 0x10, 0x87, 0xe8, 0xc3, 0xd6, 0x6e, 0x12, 0x5d, 0x04, 0x67, 0x0b, 0x7d, 0xf2,
- 0x99, 0x75, 0x57, 0x99, 0x3a, 0x98, 0xf8, 0xe4, 0xdf, 0x79, 0xdf, 0x8e, 0x02,
- 0x2c, 0xbe, 0xd8, 0xfd, 0x75, 0x80, 0x18, 0xb1, 0x6f, 0x43, 0xd9, 0x8a, 0x79,
- 0xc3, 0x6e, 0x18, 0xdf, 0x79, 0xc0, 0x59, 0xab, 0xd6, 0x77, 0x37, 0x6a, 0x94,
- 0x5a, 0x7e, 0xfb, 0xa9, 0xc5, 0x54, 0x14, 0x3a, 0x7b, 0x97, 0x17, 0x2a, 0xb6,
- 0x1e, 0x59, 0x4f, 0x2f, 0xb1, 0x15, 0x1a, 0x34, 0x50, 0x32, 0x35, 0x36,
-};
-
-static const uint8 kSidePinExpectedHash[20] = {
- 0xb5, 0x91, 0x66, 0x47, 0x43, 0x16, 0x62, 0x86, 0xd4, 0x1e, 0x5d, 0x36, 0xe1,
- 0xc4, 0x09, 0x3d, 0x2d, 0x1d, 0xea, 0x1e,
-};
-
TEST_F(TransportSecurityStateTest, GooglePinnedProperties) {
EXPECT_FALSE(TransportSecurityState::IsGooglePinnedProperty(
"www.example.com", true));
diff --git a/chromium/net/net.gyp b/chromium/net/net.gyp
index b28600d1618..c2d618ef220 100644
--- a/chromium/net/net.gyp
+++ b/chromium/net/net.gyp
@@ -9,11 +9,11 @@
'linux_link_kerberos%': 0,
'use_tracing_cache_backend%': 0,
'conditions': [
- ['chromeos==1 or OS=="android" or OS=="ios"', {
+ ['chromeos==1 or embedded==1 or OS=="android" or OS=="ios"', {
# Disable Kerberos on ChromeOS, Android and iOS, at least for now.
# It needs configuration (krb5.conf and so on).
'use_kerberos%': 0,
- }, { # chromeos == 0
+ }, { # chromeos == 0 and embedded==0 and OS!="android" and OS!="ios"
'use_kerberos%': 1,
}],
['OS=="android" and target_arch != "ia32"', {
@@ -207,6 +207,7 @@
'base/rand_callback.h',
'base/registry_controlled_domains/registry_controlled_domain.cc',
'base/registry_controlled_domains/registry_controlled_domain.h',
+ 'base/request_priority.cc',
'base/request_priority.h',
'base/sdch_filter.cc',
'base/sdch_filter.h',
@@ -269,25 +270,47 @@
'cert/cert_verify_result.h',
'cert/crl_set.cc',
'cert/crl_set.h',
+ 'cert/ct_known_logs.cc',
+ 'cert/ct_known_logs.h',
+ 'cert/ct_log_verifier.cc',
+ 'cert/ct_log_verifier.h',
+ 'cert/ct_log_verifier_nss.cc',
+ 'cert/ct_log_verifier_openssl.cc',
+ 'cert/ct_objects_extractor.h',
+ 'cert/ct_objects_extractor_nss.cc',
+ 'cert/ct_objects_extractor_openssl.cc',
+ 'cert/ct_serialization.cc',
+ 'cert/ct_serialization.h',
+ 'cert/ct_signed_certificate_timestamp_log_param.cc',
+ 'cert/ct_signed_certificate_timestamp_log_param.h',
+ 'cert/ct_verifier.h',
+ 'cert/ct_verify_result.cc',
+ 'cert/ct_verify_result.h',
'cert/ev_root_ca_metadata.cc',
'cert/ev_root_ca_metadata.h',
'cert/jwk_serializer_nss.cc',
'cert/jwk_serializer_openssl.cc',
'cert/jwk_serializer.h',
+ 'cert/multi_log_ct_verifier.cc',
+ 'cert/multi_log_ct_verifier.h',
'cert/multi_threaded_cert_verifier.cc',
'cert/multi_threaded_cert_verifier.h',
'cert/nss_cert_database.cc',
'cert/nss_cert_database.h',
'cert/pem_tokenizer.cc',
'cert/pem_tokenizer.h',
+ 'cert/scoped_nss_types.h',
+ 'cert/sct_status_flags.h',
+ 'cert/signed_certificate_timestamp.cc',
+ 'cert/signed_certificate_timestamp.h',
'cert/single_request_cert_verifier.cc',
'cert/single_request_cert_verifier.h',
'cert/test_root_certs.cc',
'cert/test_root_certs.h',
+ 'cert/test_root_certs_android.cc',
'cert/test_root_certs_mac.cc',
'cert/test_root_certs_nss.cc',
'cert/test_root_certs_openssl.cc',
- 'cert/test_root_certs_android.cc',
'cert/test_root_certs_win.cc',
'cert/x509_cert_types.cc',
'cert/x509_cert_types.h',
@@ -302,8 +325,10 @@
'cert/x509_certificate_nss.cc',
'cert/x509_certificate_openssl.cc',
'cert/x509_certificate_win.cc',
- 'cert/x509_util.h',
'cert/x509_util.cc',
+ 'cert/x509_util.h',
+ 'cert/x509_util_android.cc',
+ 'cert/x509_util_android.h',
'cert/x509_util_ios.cc',
'cert/x509_util_ios.h',
'cert/x509_util_mac.cc',
@@ -351,6 +376,7 @@
'disk_cache/file.cc',
'disk_cache/file.h',
'disk_cache/file_block.h',
+ 'disk_cache/file_ios.cc',
'disk_cache/file_lock.cc',
'disk_cache/file_lock.h',
'disk_cache/file_posix.cc',
@@ -442,6 +468,8 @@
'dns/dns_config_service_posix.h',
'dns/dns_config_service_win.cc',
'dns/dns_config_service_win.h',
+ 'dns/dns_config_watcher_mac.cc',
+ 'dns/dns_config_watcher_mac.h',
'dns/dns_hosts.cc',
'dns/dns_hosts.h',
'dns/dns_protocol.h',
@@ -542,6 +570,8 @@
'http/http_auth_handler_ntlm_win.cc',
'http/http_auth_sspi_win.cc',
'http/http_auth_sspi_win.h',
+ 'http/http_basic_state.cc',
+ 'http/http_basic_state.h',
'http/http_basic_stream.cc',
'http/http_basic_stream.h',
'http/http_byte_range.cc',
@@ -627,6 +657,8 @@
'http/proxy_client_socket.cc',
'http/proxy_connect_redirect_http_stream.h',
'http/proxy_connect_redirect_http_stream.cc',
+ 'http/transport_security_persister.cc',
+ 'http/transport_security_persister.h',
'http/transport_security_state.cc',
'http/transport_security_state.h',
'http/transport_security_state_static.h',
@@ -725,8 +757,8 @@
'quic/congestion_control/leaky_bucket.h',
'quic/congestion_control/paced_sender.cc',
'quic/congestion_control/paced_sender.h',
- 'quic/congestion_control/quic_congestion_manager.cc',
- 'quic/congestion_control/quic_congestion_manager.h',
+ 'quic/congestion_control/pacing_sender.cc',
+ 'quic/congestion_control/pacing_sender.h',
'quic/congestion_control/quic_max_sized_map.h',
'quic/congestion_control/receive_algorithm_interface.cc',
'quic/congestion_control/receive_algorithm_interface.h',
@@ -757,8 +789,6 @@
'quic/crypto/crypto_protocol.h',
'quic/crypto/crypto_secret_boxer.cc',
'quic/crypto/crypto_secret_boxer.h',
- 'quic/crypto/crypto_server_config.cc',
- 'quic/crypto/crypto_server_config.h',
'quic/crypto/crypto_server_config_protobuf.cc',
'quic/crypto/crypto_server_config_protobuf.h',
'quic/crypto/crypto_utils.cc',
@@ -767,6 +797,8 @@
'quic/crypto/curve25519_key_exchange.h',
'quic/crypto/ephemeral_key_source.h',
'quic/crypto/key_exchange.h',
+ 'quic/crypto/local_strike_register_client.cc',
+ 'quic/crypto/local_strike_register_client.h',
'quic/crypto/null_decrypter.cc',
'quic/crypto/null_decrypter.h',
'quic/crypto/null_encrypter.cc',
@@ -780,6 +812,10 @@
'quic/crypto/proof_verifier.cc',
'quic/crypto/proof_verifier_chromium.cc',
'quic/crypto/proof_verifier_chromium.h',
+ 'quic/crypto/quic_crypto_client_config.cc',
+ 'quic/crypto/quic_crypto_client_config.h',
+ 'quic/crypto/quic_crypto_server_config.cc',
+ 'quic/crypto/quic_crypto_server_config.h',
'quic/crypto/quic_decrypter.cc',
'quic/crypto/quic_decrypter.h',
'quic/crypto/quic_encrypter.cc',
@@ -790,10 +826,17 @@
'quic/crypto/scoped_evp_cipher_ctx.h',
'quic/crypto/strike_register.cc',
'quic/crypto/strike_register.h',
+ 'quic/crypto/strike_register_client.h',
'quic/crypto/source_address_token.cc',
'quic/crypto/source_address_token.h',
+ 'quic/iovector.cc',
+ 'quic/iovector.h',
+ 'quic/port_suggester.cc',
+ 'quic/port_suggester.h',
'quic/quic_ack_notifier.cc',
'quic/quic_ack_notifier.h',
+ 'quic/quic_ack_notifier_manager.cc',
+ 'quic/quic_ack_notifier_manager.h',
'quic/quic_alarm.cc',
'quic/quic_alarm.h',
'quic/quic_bandwidth.cc',
@@ -801,17 +844,10 @@
'quic/quic_blocked_writer_interface.h',
'quic/quic_client_session.cc',
'quic/quic_client_session.h',
- 'quic/quic_config.cc',
- 'quic/quic_config.h',
- 'quic/quic_crypto_client_stream.cc',
- 'quic/quic_crypto_client_stream.h',
- 'quic/quic_crypto_client_stream_factory.h',
- 'quic/quic_crypto_server_stream.cc',
- 'quic/quic_crypto_server_stream.h',
- 'quic/quic_crypto_stream.cc',
- 'quic/quic_crypto_stream.h',
'quic/quic_clock.cc',
'quic/quic_clock.h',
+ 'quic/quic_config.cc',
+ 'quic/quic_config.h',
'quic/quic_connection.cc',
'quic/quic_connection.h',
'quic/quic_connection_helper.cc',
@@ -820,10 +856,21 @@
'quic/quic_connection_logger.h',
'quic/quic_connection_stats.cc',
'quic/quic_connection_stats.h',
+ 'quic/quic_crypto_client_stream.cc',
+ 'quic/quic_crypto_client_stream.h',
+ 'quic/quic_crypto_client_stream_factory.h',
+ 'quic/quic_crypto_server_stream.cc',
+ 'quic/quic_crypto_server_stream.h',
+ 'quic/quic_crypto_stream.cc',
+ 'quic/quic_crypto_stream.h',
'quic/quic_data_reader.cc',
'quic/quic_data_reader.h',
+ 'quic/quic_data_stream.cc',
+ 'quic/quic_data_stream.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_framer.cc',
@@ -836,6 +883,7 @@
'quic/quic_packet_creator.h',
'quic/quic_packet_generator.cc',
'quic/quic_packet_generator.h',
+ 'quic/quic_packet_writer.h',
'quic/quic_protocol.cc',
'quic/quic_protocol.h',
'quic/quic_received_packet_manager.cc',
@@ -909,6 +957,8 @@
'socket/ssl_server_socket_nss.cc',
'socket/ssl_server_socket_nss.h',
'socket/ssl_server_socket_openssl.cc',
+ 'socket/ssl_session_cache_openssl.cc',
+ 'socket/ssl_session_cache_openssl.h',
'socket/ssl_socket.h',
'socket/stream_listen_socket.cc',
'socket/stream_listen_socket.h',
@@ -945,10 +995,6 @@
'spdy/spdy_buffer.h',
'spdy/spdy_buffer_producer.cc',
'spdy/spdy_buffer_producer.h',
- 'spdy/spdy_credential_builder.cc',
- 'spdy/spdy_credential_builder.h',
- 'spdy/spdy_credential_state.cc',
- 'spdy/spdy_credential_state.h',
'spdy/spdy_frame_builder.cc',
'spdy/spdy_frame_builder.h',
'spdy/spdy_frame_reader.cc',
@@ -982,10 +1028,12 @@
'spdy/spdy_write_queue.h',
'spdy/write_blocked_list.h',
'ssl/client_cert_store.h',
- 'ssl/client_cert_store_impl.h',
- 'ssl/client_cert_store_impl_mac.cc',
- 'ssl/client_cert_store_impl_nss.cc',
- 'ssl/client_cert_store_impl_win.cc',
+ 'ssl/client_cert_store_mac.cc',
+ 'ssl/client_cert_store_mac.h',
+ 'ssl/client_cert_store_nss.cc',
+ 'ssl/client_cert_store_nss.h',
+ 'ssl/client_cert_store_win.cc',
+ 'ssl/client_cert_store_win.h',
'ssl/default_server_bound_cert_store.cc',
'ssl/default_server_bound_cert_store.h',
'ssl/openssl_client_key_store.cc',
@@ -994,6 +1042,8 @@
'ssl/server_bound_cert_service.h',
'ssl/server_bound_cert_store.cc',
'ssl/server_bound_cert_store.h',
+ 'ssl/signed_certificate_timestamp_and_status.cc',
+ 'ssl/signed_certificate_timestamp_and_status.h',
'ssl/ssl_cert_request_info.cc',
'ssl/ssl_cert_request_info.h',
'ssl/ssl_cipher_suite_names.cc',
@@ -1103,12 +1153,21 @@
'url_request/url_request_throttler_manager.h',
'url_request/view_cache_helper.cc',
'url_request/view_cache_helper.h',
+ 'url_request/websocket_handshake_userdata_key.cc',
+ 'url_request/websocket_handshake_userdata_key.h',
+ 'websockets/websocket_basic_handshake_stream.cc',
+ 'websockets/websocket_basic_handshake_stream.h',
'websockets/websocket_basic_stream.cc',
'websockets/websocket_basic_stream.h',
'websockets/websocket_channel.cc',
'websockets/websocket_channel.h',
- 'websockets/websocket_deflater.h',
+ 'websockets/websocket_deflate_predictor.h',
+ 'websockets/websocket_deflate_predictor_impl.cc',
+ 'websockets/websocket_deflate_predictor_impl.h',
+ 'websockets/websocket_deflate_stream.cc',
+ 'websockets/websocket_deflate_stream.h',
'websockets/websocket_deflater.cc',
+ 'websockets/websocket_deflater.h',
'websockets/websocket_errors.cc',
'websockets/websocket_errors.h',
'websockets/websocket_extension.cc',
@@ -1123,6 +1182,11 @@
'websockets/websocket_handshake_constants.h',
'websockets/websocket_handshake_handler.cc',
'websockets/websocket_handshake_handler.h',
+ 'websockets/websocket_handshake_stream_base.h',
+ 'websockets/websocket_handshake_stream_create_helper.cc',
+ 'websockets/websocket_handshake_stream_create_helper.h',
+ 'websockets/websocket_inflater.cc',
+ 'websockets/websocket_inflater.h',
'websockets/websocket_job.cc',
'websockets/websocket_job.h',
'websockets/websocket_mux.h',
@@ -1130,7 +1194,6 @@
'websockets/websocket_net_log_params.h',
'websockets/websocket_stream.cc',
'websockets/websocket_stream.h',
- 'websockets/websocket_stream_base.h',
'websockets/websocket_throttle.cc',
'websockets/websocket_throttle.h',
],
@@ -1234,9 +1297,12 @@
'cert/cert_database_nss.cc',
'cert/cert_verify_proc_nss.cc',
'cert/cert_verify_proc_nss.h',
+ 'cert/ct_log_verifier_nss.cc',
+ 'cert/ct_objects_extractor_nss.cc',
'cert/jwk_serializer_nss.cc',
'cert/nss_cert_database.cc',
'cert/nss_cert_database.h',
+ 'cert/scoped_nss_types.h',
'cert/test_root_certs_nss.cc',
'cert/x509_certificate_nss.cc',
'cert/x509_util_nss.cc',
@@ -1253,7 +1319,6 @@
'socket/ssl_client_socket_nss.h',
'socket/ssl_server_socket_nss.cc',
'socket/ssl_server_socket_nss.h',
- 'ssl/client_cert_store_impl_nss.cc',
'third_party/mozilla_security_manager/nsKeygenHandler.cpp',
'third_party/mozilla_security_manager/nsKeygenHandler.h',
'third_party/mozilla_security_manager/nsNSSCertificateDB.cpp',
@@ -1272,6 +1337,8 @@
'cert/cert_database_openssl.cc',
'cert/cert_verify_proc_openssl.cc',
'cert/cert_verify_proc_openssl.h',
+ 'cert/ct_log_verifier_openssl.cc',
+ 'cert/ct_objects_extractor_openssl.cc',
'cert/jwk_serializer_openssl.cc',
'cert/test_root_certs_openssl.cc',
'cert/x509_certificate_openssl.cc',
@@ -1286,6 +1353,8 @@
'socket/ssl_client_socket_openssl.cc',
'socket/ssl_client_socket_openssl.h',
'socket/ssl_server_socket_openssl.cc',
+ 'socket/ssl_session_cache_openssl.cc',
+ 'socket/ssl_session_cache_openssl.h',
'ssl/openssl_client_key_store.cc',
'ssl/openssl_client_key_store.h',
],
@@ -1296,6 +1365,8 @@
'../build/linux/system.gyp:gconf',
'../build/linux/system.gyp:gio',
],
+ }],
+ [ 'desktop_linux == 1 or chromeos == 1', {
'conditions': [
['use_openssl==1', {
'dependencies': [
@@ -1356,7 +1427,8 @@
'sources!': [
'cert/cert_verify_proc_nss.cc',
'cert/cert_verify_proc_nss.h',
- 'ssl/client_cert_store_impl_nss.cc',
+ 'ssl/client_cert_store_nss.cc',
+ 'ssl/client_cert_store_nss.h',
],
}],
[ 'enable_websockets != 1', {
@@ -1388,7 +1460,6 @@
'http/http_auth_handler_ntlm_portable.cc',
'socket/tcp_socket_libevent.cc',
'socket/tcp_socket_libevent.h',
- 'ssl/client_cert_store_impl_nss.cc',
'udp/udp_socket_libevent.cc',
'udp/udp_socket_libevent.h',
],
@@ -1411,9 +1482,6 @@
},
],
[ 'OS == "mac"', {
- 'sources!': [
- 'ssl/client_cert_store_impl_nss.cc',
- ],
'dependencies': [
'../third_party/nss/nss.gyp:nspr',
'../third_party/nss/nss.gyp:nss',
@@ -1442,6 +1510,9 @@
'$(SDKROOT)/System/Library/Frameworks/SystemConfiguration.framework',
'$(SDKROOT)/usr/lib/libresolv.dylib',
],
+ 'sources!': [
+ 'disk_cache/file_posix.cc',
+ ],
},
},
],
@@ -1492,7 +1563,6 @@
['include', '^cert/test_root_certs_nss\\.cc$'],
['include', '^cert/x509_util_nss\\.cc$'],
['include', '^cert/x509_util_nss\\.h$'],
- ['include', '^dns/notify_watcher_mac\\.cc$'],
['include', '^proxy/proxy_resolver_mac\\.cc$'],
['include', '^proxy/proxy_server_mac\\.cc$'],
['include', '^ocsp/nss_ocsp\\.cc$'],
@@ -1558,11 +1628,16 @@
'base/url_util_unittest.cc',
'cert/cert_verify_proc_unittest.cc',
'cert/crl_set_unittest.cc',
+ 'cert/ct_log_verifier_unittest.cc',
+ 'cert/ct_objects_extractor_unittest.cc',
+ 'cert/ct_serialization_unittest.cc',
'cert/ev_root_ca_metadata_unittest.cc',
'cert/jwk_serializer_unittest.cc',
+ 'cert/multi_log_ct_verifier_unittest.cc',
'cert/multi_threaded_cert_verifier_unittest.cc',
'cert/nss_cert_database_unittest.cc',
'cert/pem_tokenizer_unittest.cc',
+ 'cert/signed_certificate_timestamp_unittest.cc',
'cert/test_root_certs_unittest.cc',
'cert/x509_certificate_unittest.cc',
'cert/x509_cert_types_unittest.cc',
@@ -1638,13 +1713,14 @@
'http/http_auth_handler_unittest.cc',
'http/http_auth_sspi_win_unittest.cc',
'http/http_auth_unittest.cc',
+ 'http/http_basic_state_unittest.cc',
'http/http_byte_range_unittest.cc',
'http/http_cache_unittest.cc',
'http/http_chunked_decoder_unittest.cc',
'http/http_content_disposition_unittest.cc',
'http/http_network_layer_unittest.cc',
- 'http/http_network_transaction_unittest.cc',
'http/http_network_transaction_ssl_unittest.cc',
+ 'http/http_network_transaction_unittest.cc',
'http/http_pipelined_connection_impl_unittest.cc',
'http/http_pipelined_host_forced_unittest.cc',
'http/http_pipelined_host_impl_unittest.cc',
@@ -1674,6 +1750,7 @@
'http/mock_http_cache.h',
'http/mock_sspi_library_win.cc',
'http/mock_sspi_library_win.h',
+ 'http/transport_security_persister_unittest.cc',
'http/transport_security_state_unittest.cc',
'http/url_security_manager_unittest.cc',
'ocsp/nss_ocsp_unittest.cc',
@@ -1709,8 +1786,7 @@
'quic/congestion_control/inter_arrival_sender_test.cc',
'quic/congestion_control/leaky_bucket_test.cc',
'quic/congestion_control/paced_sender_test.cc',
- 'quic/congestion_control/quic_congestion_control_test.cc',
- 'quic/congestion_control/quic_congestion_manager_test.cc',
+ 'quic/congestion_control/pacing_sender_test.cc',
'quic/congestion_control/quic_max_sized_map_test.cc',
'quic/congestion_control/tcp_cubic_sender_test.cc',
'quic/congestion_control/tcp_receiver_test.cc',
@@ -1720,22 +1796,28 @@
'quic/crypto/channel_id_test.cc',
'quic/crypto/common_cert_set_test.cc',
'quic/crypto/crypto_framer_test.cc',
- 'quic/crypto/crypto_handshake_test.cc',
'quic/crypto/crypto_secret_boxer_test.cc',
'quic/crypto/crypto_server_test.cc',
'quic/crypto/crypto_utils_test.cc',
'quic/crypto/curve25519_key_exchange_test.cc',
+ 'quic/crypto/local_strike_register_client_test.cc',
'quic/crypto/null_decrypter_test.cc',
'quic/crypto/null_encrypter_test.cc',
'quic/crypto/p256_key_exchange_test.cc',
'quic/crypto/proof_test.cc',
+ 'quic/crypto/quic_crypto_client_config_test.cc',
+ 'quic/crypto/quic_crypto_server_config_test.cc',
'quic/crypto/quic_random_test.cc',
'quic/crypto/strike_register_test.cc',
+ 'quic/iovector_test.cc',
+ 'quic/port_suggester_unittest.cc',
'quic/test_tools/crypto_test_utils.cc',
'quic/test_tools/crypto_test_utils.h',
'quic/test_tools/crypto_test_utils_chromium.cc',
'quic/test_tools/crypto_test_utils_nss.cc',
'quic/test_tools/crypto_test_utils_openssl.cc',
+ 'quic/test_tools/delayed_verify_strike_register_client.cc',
+ 'quic/test_tools/delayed_verify_strike_register_client.h',
'quic/test_tools/mock_clock.cc',
'quic/test_tools/mock_clock.h',
'quic/test_tools/mock_crypto_client_stream.cc',
@@ -1748,16 +1830,22 @@
'quic/test_tools/quic_client_session_peer.h',
'quic/test_tools/quic_connection_peer.cc',
'quic/test_tools/quic_connection_peer.h',
+ 'quic/test_tools/quic_data_stream_peer.cc',
+ 'quic/test_tools/quic_data_stream_peer.h',
'quic/test_tools/quic_framer_peer.cc',
'quic/test_tools/quic_framer_peer.h',
'quic/test_tools/quic_packet_creator_peer.cc',
'quic/test_tools/quic_packet_creator_peer.h',
'quic/test_tools/quic_received_packet_manager_peer.cc',
'quic/test_tools/quic_received_packet_manager_peer.h',
+ 'quic/test_tools/quic_sent_packet_manager_peer.cc',
+ 'quic/test_tools/quic_sent_packet_manager_peer.h',
'quic/test_tools/quic_session_peer.cc',
'quic/test_tools/quic_session_peer.h',
'quic/test_tools/quic_test_utils.cc',
'quic/test_tools/quic_test_utils.h',
+ 'quic/test_tools/quic_test_writer.cc',
+ 'quic/test_tools/quic_test_writer.h',
'quic/test_tools/reliable_quic_stream_peer.cc',
'quic/test_tools/reliable_quic_stream_peer.h',
'quic/test_tools/simple_quic_framer.cc',
@@ -1775,6 +1863,7 @@
'quic/quic_crypto_client_stream_test.cc',
'quic/quic_crypto_server_stream_test.cc',
'quic/quic_crypto_stream_test.cc',
+ 'quic/quic_data_stream_test.cc',
'quic/quic_data_writer_test.cc',
'quic/quic_fec_group_test.cc',
'quic/quic_framer_test.cc',
@@ -1810,6 +1899,7 @@
'socket/ssl_client_socket_pool_unittest.cc',
'socket/ssl_client_socket_unittest.cc',
'socket/ssl_server_socket_unittest.cc',
+ 'socket/ssl_session_cache_openssl_unittest.cc',
'socket/tcp_client_socket_unittest.cc',
'socket/tcp_listen_socket_unittest.cc',
'socket/tcp_listen_socket_unittest.h',
@@ -1821,9 +1911,7 @@
'socket_stream/socket_stream_metrics_unittest.cc',
'socket_stream/socket_stream_unittest.cc',
'spdy/buffered_spdy_framer_unittest.cc',
- 'spdy/spdy_credential_builder_unittest.cc',
'spdy/spdy_buffer_unittest.cc',
- 'spdy/spdy_credential_state_unittest.cc',
'spdy/spdy_frame_builder_test.cc',
'spdy/spdy_frame_reader_test.cc',
'spdy/spdy_framer_test.cc',
@@ -1851,7 +1939,10 @@
'spdy/spdy_websocket_test_util.h',
'spdy/spdy_write_queue_unittest.cc',
'spdy/write_blocked_list_test.cc',
- 'ssl/client_cert_store_impl_unittest.cc',
+ 'ssl/client_cert_store_mac_unittest.cc',
+ 'ssl/client_cert_store_nss_unittest.cc',
+ 'ssl/client_cert_store_unittest-inl.h',
+ 'ssl/client_cert_store_win_unittest.cc',
'ssl/default_server_bound_cert_store_unittest.cc',
'ssl/openssl_client_key_store_unittest.cc',
'ssl/server_bound_cert_service_unittest.cc',
@@ -1887,44 +1978,45 @@
'url_request/view_cache_helper_unittest.cc',
'websockets/websocket_basic_stream_test.cc',
'websockets/websocket_channel_test.cc',
+ 'websockets/websocket_deflate_predictor_impl_test.cc',
+ 'websockets/websocket_deflate_stream_test.cc',
'websockets/websocket_deflater_test.cc',
'websockets/websocket_errors_test.cc',
'websockets/websocket_extension_parser_test.cc',
'websockets/websocket_frame_parser_test.cc',
'websockets/websocket_frame_test.cc',
- 'websockets/websocket_handshake_handler_test.cc',
'websockets/websocket_handshake_handler_spdy_test.cc',
+ 'websockets/websocket_handshake_handler_test.cc',
+ 'websockets/websocket_handshake_stream_create_helper_test.cc',
+ 'websockets/websocket_inflater_test.cc',
'websockets/websocket_job_test.cc',
'websockets/websocket_net_log_params_test.cc',
+ 'websockets/websocket_stream_test.cc',
+ 'websockets/websocket_test_util.cc',
+ 'websockets/websocket_test_util.h',
'websockets/websocket_throttle_test.cc',
],
'conditions': [
['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
'dependencies': [
- 'quic_library',
- 'flip_in_mem_edsm_server_library',
- 'flip_balsa_and_epoll_library',
+ 'balsa',
+ 'epoll_server',
+ 'flip_in_mem_edsm_server_base',
+ 'quic_base',
],
'sources': [
- 'tools/flip_server/balsa_frame_test.cc',
- 'tools/flip_server/balsa_headers_test.cc',
- 'tools/flip_server/flip_test_utils.cc',
- 'tools/flip_server/flip_test_utils.h',
- 'tools/flip_server/http_interface_test.cc',
- 'tools/flip_server/mem_cache_test.cc',
- 'tools/flip_server/simple_buffer.cc',
- 'tools/flip_server/simple_buffer.h',
- 'tools/flip_server/spdy_interface_test.cc',
+ 'quic/quic_end_to_end_unittest.cc',
+ 'tools/balsa/balsa_frame_test.cc',
+ 'tools/balsa/balsa_headers_test.cc',
'tools/quic/end_to_end_test.cc',
'tools/quic/quic_client_session_test.cc',
'tools/quic/quic_dispatcher_test.cc',
'tools/quic/quic_epoll_clock_test.cc',
'tools/quic/quic_epoll_connection_helper_test.cc',
'tools/quic/quic_in_memory_cache_test.cc',
- 'tools/quic/quic_reliable_client_stream_test.cc',
- 'tools/quic/quic_reliable_server_stream_test.cc',
'tools/quic/quic_server_session_test.cc',
'tools/quic/quic_server_test.cc',
+ 'tools/quic/quic_spdy_client_stream_test.cc',
'tools/quic/quic_spdy_server_stream_test.cc',
'tools/quic/quic_time_wait_list_manager_test.cc',
'tools/quic/test_tools/http_message_test_utils.cc',
@@ -1933,14 +2025,22 @@
'tools/quic/test_tools/mock_epoll_server.h',
'tools/quic/test_tools/mock_quic_dispatcher.cc',
'tools/quic/test_tools/mock_quic_dispatcher.h',
+ 'tools/quic/test_tools/packet_dropping_test_writer.cc',
+ 'tools/quic/test_tools/packet_dropping_test_writer.h',
'tools/quic/test_tools/quic_client_peer.cc',
'tools/quic/test_tools/quic_client_peer.h',
- 'tools/quic/test_tools/quic_epoll_connection_helper_peer.cc',
- 'tools/quic/test_tools/quic_epoll_connection_helper_peer.h',
+ 'tools/quic/test_tools/quic_dispatcher_peer.cc',
+ 'tools/quic/test_tools/quic_dispatcher_peer.h',
+ 'tools/quic/test_tools/quic_in_memory_cache_peer.h',
+ 'tools/quic/test_tools/quic_in_memory_cache_peer.cc',
+ 'tools/quic/test_tools/quic_server_peer.cc',
+ 'tools/quic/test_tools/quic_server_peer.h',
'tools/quic/test_tools/quic_test_client.cc',
'tools/quic/test_tools/quic_test_client.h',
'tools/quic/test_tools/quic_test_utils.cc',
'tools/quic/test_tools/quic_test_utils.h',
+ 'tools/quic/test_tools/server_thread.h',
+ 'tools/quic/test_tools/server_thread.cc',
],
}],
['chromeos==1', {
@@ -1954,23 +2054,35 @@
# No res_ninit() et al on Android, so this doesn't make a lot of
# sense.
'dns/dns_config_service_posix_unittest.cc',
- 'ssl/client_cert_store_impl_unittest.cc',
],
'dependencies': [
'net_javatests',
'net_test_jni_headers',
],
}],
- [ 'use_glib == 1', {
- 'dependencies': [
- '../build/linux/system.gyp:ssl',
- ],
- }, { # else use_glib == 0: !posix || mac
- 'sources!': [
- 'cert/nss_cert_database_unittest.cc',
- ],
- },
- ],
+ [ 'use_nss != 1', {
+ 'sources!': [
+ 'ssl/client_cert_store_nss_unittest.cc',
+ ],
+ }],
+ [ 'use_openssl == 1', {
+ # Avoid compiling/linking with the system library.
+ 'dependencies': [
+ '../third_party/openssl/openssl.gyp:openssl',
+ ],
+ }, { # use_openssl == 0
+ 'conditions': [
+ [ 'desktop_linux == 1 or chromeos == 1', {
+ 'dependencies': [
+ '../build/linux/system.gyp:ssl',
+ ],
+ }, { # desktop_linux == 0 and chromeos == 0
+ 'sources!': [
+ 'cert/nss_cert_database_unittest.cc',
+ ],
+ }],
+ ],
+ }],
[ 'toolkit_uses_gtk == 1', {
'dependencies': [
'../build/linux/system.gyp:gtk',
@@ -1998,7 +2110,7 @@
'http/mock_gssapi_library_posix.h',
],
}],
- [ 'use_openssl == 1 or (use_glib == 0 and OS != "ios")', {
+ [ 'use_openssl == 1 or (desktop_linux == 0 and chromeos == 0 and OS != "ios")', {
# Only include this test when on Posix and using NSS for
# cert verification or on iOS (which also uses NSS for certs).
'sources!': [
@@ -2006,25 +2118,25 @@
],
}],
[ 'use_openssl==1', {
- # When building for OpenSSL, we need to exclude NSS specific tests.
+ # When building for OpenSSL, we need to exclude NSS specific tests
+ # or functionality not supported by OpenSSL yet.
# TODO(bulach): Add equivalent tests when the underlying
# functionality is ported to OpenSSL.
'sources!': [
+ 'cert/ct_objects_extractor_unittest.cc',
+ 'cert/multi_log_ct_verifier_unittest.cc',
'cert/nss_cert_database_unittest.cc',
'cert/x509_util_nss_unittest.cc',
'quic/test_tools/crypto_test_utils_nss.cc',
- 'ssl/client_cert_store_impl_unittest.cc',
],
}, { # else !use_openssl: remove the unneeded files
'sources!': [
'cert/x509_util_openssl_unittest.cc',
'quic/test_tools/crypto_test_utils_openssl.cc',
'socket/ssl_client_socket_openssl_unittest.cc',
+ 'socket/ssl_session_cache_openssl_unittest.cc',
'ssl/openssl_client_key_store_unittest.cc',
],
- 'sources/': [
- ['exclude', '^tools/flip_server'],
- ],
},
],
[ 'enable_websockets != 1', {
@@ -2127,7 +2239,6 @@
# Need TestServer.
'proxy/proxy_script_fetcher_impl_unittest.cc',
'socket/ssl_client_socket_unittest.cc',
- 'ssl/client_cert_store_impl_unittest.cc',
'url_request/url_fetcher_impl_unittest.cc',
'url_request/url_request_context_builder_unittest.cc',
# Needs GetAppOutput().
@@ -2138,31 +2249,6 @@
# OS is not "linux" or "freebsd" or "openbsd".
'socket/unix_domain_socket_posix_unittest.cc',
],
- 'conditions': [
- ['coverage != 0', {
- 'sources!': [
- # These sources can't be built with coverage due to a
- # toolchain bug: http://openradar.appspot.com/radar?id=1499403
- 'http/transport_security_state_unittest.cc',
-
- # These tests crash when run with coverage turned on due to an
- # issue with llvm_gcda_increment_indirect_counter:
- # http://crbug.com/156058
- 'cookies/cookie_monster_unittest.cc',
- 'cookies/cookie_store_unittest.h',
- 'http/http_auth_controller_unittest.cc',
- 'http/http_network_layer_unittest.cc',
- 'http/http_network_transaction_unittest.cc',
- 'spdy/spdy_http_stream_unittest.cc',
- 'spdy/spdy_proxy_client_socket_unittest.cc',
- 'spdy/spdy_session_unittest.cc',
-
- # These tests crash when run with coverage turned on:
- # http://crbug.com/177203
- 'proxy/proxy_service_unittest.cc',
- ],
- }],
- ],
}],
[ 'OS == "android"', {
'dependencies': [
@@ -2279,6 +2365,8 @@
'socket/socket_test_util.h',
'test/cert_test_util.cc',
'test/cert_test_util.h',
+ 'test/ct_test_util.cc',
+ 'test/ct_test_util.h',
'test/embedded_test_server/embedded_test_server.cc',
'test/embedded_test_server/embedded_test_server.h',
'test/embedded_test_server/http_connection.cc',
@@ -2641,32 +2729,45 @@
['os_posix == 1 and OS != "mac" and OS != "ios" and OS != "android"', {
'targets': [
{
- 'target_name': 'flip_balsa_and_epoll_library',
+ 'target_name': 'balsa',
'type': 'static_library',
'dependencies': [
'../base/base.gyp:base',
'net',
],
'sources': [
- 'tools/flip_server/balsa_enums.h',
- 'tools/flip_server/balsa_frame.cc',
- 'tools/flip_server/balsa_frame.h',
- 'tools/flip_server/balsa_headers.cc',
- 'tools/flip_server/balsa_headers.h',
- 'tools/flip_server/balsa_headers_token_utils.cc',
- 'tools/flip_server/balsa_headers_token_utils.h',
- 'tools/flip_server/balsa_visitor_interface.h',
- 'tools/flip_server/constants.h',
- 'tools/flip_server/epoll_server.cc',
- 'tools/flip_server/epoll_server.h',
- 'tools/flip_server/http_message_constants.cc',
- 'tools/flip_server/http_message_constants.h',
- 'tools/flip_server/split.h',
- 'tools/flip_server/split.cc',
+ 'tools/balsa/balsa_enums.h',
+ 'tools/balsa/balsa_frame.cc',
+ 'tools/balsa/balsa_frame.h',
+ 'tools/balsa/balsa_headers.cc',
+ 'tools/balsa/balsa_headers.h',
+ 'tools/balsa/balsa_headers_token_utils.cc',
+ 'tools/balsa/balsa_headers_token_utils.h',
+ 'tools/balsa/balsa_visitor_interface.h',
+ 'tools/balsa/http_message_constants.cc',
+ 'tools/balsa/http_message_constants.h',
+ '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',
],
},
{
- 'target_name': 'flip_in_mem_edsm_server_library',
+ 'target_name': 'epoll_server',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ 'net',
+ ],
+ 'sources': [
+ 'tools/epoll_server/epoll_server.cc',
+ 'tools/epoll_server/epoll_server.h',
+ ],
+ },
+ {
+ 'target_name': 'flip_in_mem_edsm_server_base',
'type': 'static_library',
'cflags': [
'-Wno-deprecated',
@@ -2674,7 +2775,8 @@
'dependencies': [
'../base/base.gyp:base',
'../third_party/openssl/openssl.gyp:openssl',
- 'flip_balsa_and_epoll_library',
+ 'balsa',
+ 'epoll_server',
'net',
],
'sources': [
@@ -2684,9 +2786,9 @@
'tools/dump_cache/url_utilities.cc',
'tools/flip_server/acceptor_thread.h',
'tools/flip_server/acceptor_thread.cc',
- 'tools/flip_server/buffer_interface.h',
'tools/flip_server/create_listener.cc',
'tools/flip_server/create_listener.h',
+ 'tools/flip_server/constants.h',
'tools/flip_server/flip_config.cc',
'tools/flip_server/flip_config.h',
'tools/flip_server/http_interface.cc',
@@ -2698,8 +2800,6 @@
'tools/flip_server/output_ordering.h',
'tools/flip_server/ring_buffer.cc',
'tools/flip_server/ring_buffer.h',
- 'tools/flip_server/simple_buffer.cc',
- 'tools/flip_server/simple_buffer.h',
'tools/flip_server/sm_connection.cc',
'tools/flip_server/sm_connection.h',
'tools/flip_server/sm_interface.h',
@@ -2711,7 +2811,26 @@
'tools/flip_server/spdy_util.h',
'tools/flip_server/streamer_interface.cc',
'tools/flip_server/streamer_interface.h',
- 'tools/flip_server/string_piece_utils.h',
+ ],
+ },
+ {
+ 'target_name': 'flip_in_mem_edsm_server_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ '../testing/gtest.gyp:gtest',
+ '../testing/gmock.gyp:gmock',
+ '../third_party/openssl/openssl.gyp:openssl',
+ 'flip_in_mem_edsm_server_base',
+ 'net',
+ 'net_test_support',
+ ],
+ 'sources': [
+ 'tools/flip_server/flip_test_utils.cc',
+ 'tools/flip_server/flip_test_utils.h',
+ 'tools/flip_server/http_interface_test.cc',
+ 'tools/flip_server/mem_cache_test.cc',
+ 'tools/flip_server/run_all_tests.cc',
+ 'tools/flip_server/spdy_interface_test.cc',
],
},
{
@@ -2722,8 +2841,7 @@
],
'dependencies': [
'../base/base.gyp:base',
- 'flip_balsa_and_epoll_library',
- 'flip_in_mem_edsm_server_library',
+ 'flip_in_mem_edsm_server_base',
'net',
],
'sources': [
@@ -2731,7 +2849,7 @@
],
},
{
- 'target_name': 'quic_library',
+ 'target_name': 'quic_base',
'type': 'static_library',
'dependencies': [
'../base/base.gyp:base',
@@ -2739,7 +2857,8 @@
'../crypto/crypto.gyp:crypto',
'../third_party/openssl/openssl.gyp:openssl',
'../url/url.gyp:url_lib',
- 'flip_balsa_and_epoll_library',
+ 'balsa',
+ 'epoll_server',
'net',
],
'sources': [
@@ -2747,6 +2866,8 @@
'tools/quic/quic_client.h',
'tools/quic/quic_client_session.cc',
'tools/quic/quic_client_session.h',
+ 'tools/quic/quic_default_packet_writer.cc',
+ 'tools/quic/quic_default_packet_writer.h',
'tools/quic/quic_dispatcher.h',
'tools/quic/quic_dispatcher.cc',
'tools/quic/quic_epoll_clock.cc',
@@ -2755,11 +2876,6 @@
'tools/quic/quic_epoll_connection_helper.h',
'tools/quic/quic_in_memory_cache.cc',
'tools/quic/quic_in_memory_cache.h',
- 'tools/quic/quic_packet_writer.h',
- 'tools/quic/quic_reliable_client_stream.cc',
- 'tools/quic/quic_reliable_client_stream.h',
- 'tools/quic/quic_reliable_server_stream.cc',
- 'tools/quic/quic_reliable_server_stream.h',
'tools/quic/quic_server.cc',
'tools/quic/quic_server.h',
'tools/quic/quic_server_session.cc',
@@ -2783,7 +2899,7 @@
'../base/base.gyp:base',
'../third_party/openssl/openssl.gyp:openssl',
'net',
- 'quic_library',
+ 'quic_base',
],
'sources': [
'tools/quic/quic_client_bin.cc',
@@ -2796,7 +2912,7 @@
'../base/base.gyp:base',
'../third_party/openssl/openssl.gyp:openssl',
'net',
- 'quic_library',
+ 'quic_base',
],
'sources': [
'tools/quic/quic_server_bin.cc',
@@ -2815,9 +2931,11 @@
'android/java/src/org/chromium/net/GURLUtils.java',
'android/java/src/org/chromium/net/NetworkChangeNotifier.java',
'android/java/src/org/chromium/net/ProxyChangeListener.java',
+ 'android/java/src/org/chromium/net/X509Util.java',
],
'variables': {
'jni_gen_package': 'net',
+ 'jni_generator_ptr_type': 'long',
},
'direct_dependent_settings': {
'include_dirs': [
@@ -2834,6 +2952,7 @@
],
'variables': {
'jni_gen_package': 'net',
+ 'jni_generator_ptr_type': 'long',
},
'direct_dependent_settings': {
'include_dirs': [
diff --git a/chromium/net/net_unittests.isolate b/chromium/net/net_unittests.isolate
index 9c88f77493d..2e04ea34544 100644
--- a/chromium/net/net_unittests.isolate
+++ b/chromium/net/net_unittests.isolate
@@ -16,23 +16,15 @@
],
},
}],
- ['OS=="linux"', {
+ ['OS=="linux" or OS=="mac" or OS=="win"', {
'variables': {
'command': [
- '../testing/xvfb.py',
- '<(PRODUCT_DIR)',
- '../tools/swarm_client/googletest/run_test_cases.py',
+ '../testing/test_env.py',
'<(PRODUCT_DIR)/net_unittests<(EXECUTABLE_SUFFIX)',
+ '--brave-new-test-launcher',
+ '--test-launcher-bot-mode',
],
'isolate_dependency_tracked': [
- '../testing/xvfb.py',
- '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)',
- ],
- },
- }],
- ['OS=="linux" or OS=="mac" or OS=="win"', {
- 'variables': {
- 'isolate_dependency_tracked': [
'../testing/test_env.py',
'<(PRODUCT_DIR)/net_unittests<(EXECUTABLE_SUFFIX)',
],
@@ -40,29 +32,17 @@
'../third_party/pyftpdlib/',
'../third_party/pywebsocket/',
'../third_party/tlslite/',
- '../tools/swarm_client/',
+ '../tools/swarming_client/',
'<(PRODUCT_DIR)/pyproto/',
'tools/testserver/',
],
},
}],
- ['OS=="mac" or OS=="win"', {
- 'variables': {
- 'command': [
- '../testing/test_env.py',
- '../tools/swarm_client/googletest/run_test_cases.py',
- '<(PRODUCT_DIR)/net_unittests<(EXECUTABLE_SUFFIX)',
- ],
- },
- }],
['OS=="win"', {
'variables': {
'isolate_dependency_tracked': [
'<(PRODUCT_DIR)/icudt.dll',
],
- 'isolate_dependency_untracked': [
- '../third_party/python_26/',
- ],
},
}],
],
diff --git a/chromium/net/ocsp/nss_ocsp.cc b/chromium/net/ocsp/nss_ocsp.cc
index aea8fc2ad41..33d1933f348 100644
--- a/chromium/net/ocsp/nss_ocsp.cc
+++ b/chromium/net/ocsp/nss_ocsp.cc
@@ -32,6 +32,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
+#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_request_headers.h"
@@ -87,7 +88,10 @@ class OCSPIOLoop {
base::AutoLock autolock(lock_);
DCHECK(base::MessageLoopForIO::current());
thread_checker_.DetachFromThread();
- thread_checker_.CalledOnValidThread();
+
+ // CalledOnValidThread is the only available API to reassociate
+ // thread_checker_ with the current thread. Result ignored intentionally.
+ ignore_result(thread_checker_.CalledOnValidThread());
shutdown_ = false;
used_ = false;
}
@@ -393,10 +397,11 @@ class OCSPRequestSession
g_ocsp_io_loop.Get().AddRequest(this);
}
- request_ = new URLRequest(url_, this, url_request_context);
+ request_ =
+ new URLRequest(url_, DEFAULT_PRIORITY, this, url_request_context);
// To meet the privacy requirements of incognito mode.
- request_->set_load_flags(LOAD_DISABLE_CACHE | LOAD_DO_NOT_SAVE_COOKIES |
- LOAD_DO_NOT_SEND_COOKIES);
+ request_->SetLoadFlags(LOAD_DISABLE_CACHE | LOAD_DO_NOT_SAVE_COOKIES |
+ LOAD_DO_NOT_SEND_COOKIES);
if (http_request_method_ == "POST") {
DCHECK(!upload_content_.empty());
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 676f6c3a4d6..569e8120782 100644
--- a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
+++ b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
+#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task_runner.h"
#include "base/time/time.h"
@@ -263,27 +264,32 @@ std::string DhcpProxyScriptAdapterFetcher::GetPacURLFromDhcp(
LOG(INFO) << "Error fetching PAC URL from DHCP: " << res;
UMA_HISTOGRAM_COUNTS("Net.DhcpWpadUnhandledDhcpError", 1);
} else if (wpad_params.nBytesData) {
-#ifndef NDEBUG
- // The result should be ASCII, not wide character. Some DHCP
- // servers appear to count the trailing NULL in nBytesData, others
- // do not.
- size_t count_without_null =
- strlen(reinterpret_cast<const char*>(wpad_params.Data));
- DCHECK(count_without_null == wpad_params.nBytesData ||
- count_without_null + 1 == wpad_params.nBytesData);
-#endif
- // Belt and suspenders: First, ensure we NULL-terminate after
- // nBytesData; this is the inner constructor with nBytesData as a
- // parameter. Then, return only up to the first null in case of
- // embedded NULLs; this is the outer constructor that takes the
- // result of c_str() on the inner. If the server is giving us
- // back a buffer with embedded NULLs, something is broken anyway.
- return std::string(
- std::string(reinterpret_cast<const char *>(wpad_params.Data),
- wpad_params.nBytesData).c_str());
+ return SanitizeDhcpApiString(
+ reinterpret_cast<const char*>(wpad_params.Data),
+ wpad_params.nBytesData);
}
return "";
}
+// static
+std::string DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
+ const char* data, size_t count_bytes) {
+ // The result should be ASCII, not wide character. Some DHCP
+ // servers appear to count the trailing NULL in nBytesData, others
+ // do not. A few (we've had one report, http://crbug.com/297810)
+ // do not NULL-terminate but may \n-terminate.
+ //
+ // Belt and suspenders and elastic waistband: First, ensure we
+ // NULL-terminate after nBytesData; this is the inner constructor
+ // with nBytesData as a parameter. Then, return only up to the
+ // first null in case of embedded NULLs; this is the outer
+ // constructor that takes the result of c_str() on the inner. If
+ // the server is giving us back a buffer with embedded NULLs,
+ // something is broken anyway. Finally, trim trailing whitespace.
+ std::string result(std::string(data, count_bytes).c_str());
+ TrimWhitespaceASCII(result, TRIM_TRAILING, &result);
+ return result;
+}
+
} // namespace net
diff --git a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h
index 59597d9a484..c89192c74ea 100644
--- a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h
+++ b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h
@@ -79,6 +79,10 @@ class NET_EXPORT_PRIVATE DhcpProxyScriptAdapterFetcher
// DHCP client API.
static std::string GetPacURLFromDhcp(const std::string& adapter_name);
+ // Sanitizes a string returned via the DHCP API.
+ static std::string SanitizeDhcpApiString(const char* data,
+ size_t count_bytes);
+
protected:
// This is the state machine for fetching from a given adapter.
//
diff --git a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
index 17285122e8e..821e4ebd62a 100644
--- a/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
+++ b/chromium/net/proxy/dhcp_proxy_script_adapter_fetcher_win_unittest.cc
@@ -5,9 +5,9 @@
#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
#include "base/synchronization/waitable_event.h"
-#include "base/test/perftimer.h"
#include "base/test/test_timeouts.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "base/timer/elapsed_timer.h"
#include "base/timer/timer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
@@ -72,7 +72,7 @@ class MockDhcpProxyScriptAdapterFetcher
std::string ImplGetPacURLFromDhcp(
const std::string& adapter_name) OVERRIDE {
- PerfTimer timer;
+ base::ElapsedTimer timer;
test_finished_event_.TimedWait(dhcp_delay_);
return configured_url_;
}
@@ -198,7 +198,7 @@ TEST(DhcpProxyScriptAdapterFetcher, TimeoutDuringDhcp) {
client.fetcher_->dhcp_delay_ = TestTimeouts::action_max_timeout();
client.fetcher_->timeout_ = base::TimeDelta::FromMilliseconds(25);
- PerfTimer timer;
+ base::ElapsedTimer timer;
client.RunTest();
// An error different from this would be received if the timeout didn't
// kick in.
@@ -310,6 +310,29 @@ TEST(DhcpProxyScriptAdapterFetcher, MockDhcpRealFetch) {
client.fetcher_->GetPacURL());
}
+#define BASE_URL "http://corpserver/proxy.pac"
+
+TEST(DhcpProxyScriptAdapterFetcher, SanitizeDhcpApiString) {
+ const size_t kBaseUrlLen = strlen(BASE_URL);
+
+ // Default case.
+ EXPECT_EQ(BASE_URL,
+ DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
+ BASE_URL, kBaseUrlLen));
+
+ // Trailing \n and no null-termination.
+ EXPECT_EQ(BASE_URL,
+ DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
+ BASE_URL "\nblablabla", kBaseUrlLen + 1));
+
+ // Embedded NULLs.
+ EXPECT_EQ(BASE_URL,
+ DhcpProxyScriptAdapterFetcher::SanitizeDhcpApiString(
+ BASE_URL "\0foo\0blat", kBaseUrlLen + 9));
+}
+
+#undef BASE_URL
+
} // namespace
} // namespace net
diff --git a/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc b/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc
index ac28e0fc075..037268f03a0 100644
--- a/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc
+++ b/chromium/net/proxy/dhcp_proxy_script_fetcher_win.cc
@@ -7,8 +7,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/metrics/histogram.h"
-#include "base/test/perftimer.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "base/timer/elapsed_timer.h"
#include "net/base/net_errors.h"
#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
@@ -324,7 +324,7 @@ bool DhcpProxyScriptFetcherWin::GetCandidateAdapterNames(
ULONG error = ERROR_SUCCESS;
int num_tries = 0;
- PerfTimer time_api_access;
+ base::ElapsedTimer time_api_access;
do {
adapters.reset(
reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(adapters_size)));
diff --git a/chromium/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc b/chromium/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc
index cf0cee05a14..743fb263fdd 100644
--- a/chromium/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc
+++ b/chromium/net/proxy/dhcp_proxy_script_fetcher_win_unittest.cc
@@ -10,9 +10,9 @@
#include "base/bind_helpers.h"
#include "base/message_loop/message_loop.h"
#include "base/rand_util.h"
-#include "base/test/perftimer.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
+#include "base/timer/elapsed_timer.h"
#include "net/base/completion_callback.h"
#include "net/proxy/dhcp_proxy_script_adapter_fetcher_win.h"
#include "net/url_request/url_request_test_util.h"
@@ -577,7 +577,7 @@ void TestShortCircuitLessPreferredAdapters(FetcherClient* client) {
// time to kick in before the timeout waiting for more adapters kicks in.
client->fetcher_.max_wait_ = TestTimeouts::action_timeout();
- PerfTimer timer;
+ base::ElapsedTimer timer;
client->RunTest();
client->RunMessageLoopUntilComplete();
ASSERT_TRUE(client->fetcher_.HasPendingFetchers());
diff --git a/chromium/net/proxy/proxy_config_service_android.cc b/chromium/net/proxy/proxy_config_service_android.cc
index 41bef8a4cd8..088621da83d 100644
--- a/chromium/net/proxy/proxy_config_service_android.cc
+++ b/chromium/net/proxy/proxy_config_service_android.cc
@@ -18,6 +18,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "jni/ProxyChangeListener_jni.h"
#include "net/base/host_port_pair.h"
#include "net/proxy/proxy_config.h"
@@ -159,6 +160,16 @@ std::string GetJavaProperty(const std::string& property) {
std::string() : ConvertJavaStringToUTF8(env, result.obj());
}
+void CreateStaticProxyConfig(const std::string& host, int port,
+ ProxyConfig* config) {
+ if (port != 0) {
+ std::string rules = base::StringPrintf("%s:%d", host.c_str(), port);
+ config->proxy_rules().ParseFromString(rules);
+ } else {
+ *config = ProxyConfig::CreateDirect();
+ }
+}
+
} // namespace
class ProxyConfigServiceAndroid::Delegate
@@ -185,7 +196,7 @@ class ProxyConfigServiceAndroid::Delegate
Java_ProxyChangeListener_start(
env,
java_proxy_change_listener_.obj(),
- reinterpret_cast<jint>(&jni_delegate_));
+ reinterpret_cast<intptr_t>(&jni_delegate_));
}
void FetchInitialConfig() {
@@ -237,6 +248,17 @@ class ProxyConfigServiceAndroid::Delegate
&Delegate::SetNewConfigOnNetworkThread, this, proxy_config));
}
+ // Called on the JNI thread.
+ void ProxySettingsChangedTo(const std::string& host, int port) {
+ DCHECK(OnJNIThread());
+ ProxyConfig proxy_config;
+ CreateStaticProxyConfig(host, port, &proxy_config);
+ network_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &Delegate::SetNewConfigOnNetworkThread, this, proxy_config));
+ }
+
private:
friend class base::RefCountedThreadSafe<Delegate>;
@@ -245,7 +267,13 @@ class ProxyConfigServiceAndroid::Delegate
explicit JNIDelegateImpl(Delegate* delegate) : delegate_(delegate) {}
// ProxyConfigServiceAndroid::JNIDelegate overrides.
- virtual void ProxySettingsChanged(JNIEnv*, jobject) OVERRIDE {
+ virtual void ProxySettingsChangedTo(JNIEnv* env, jobject jself,
+ jstring jhost, jint jport) OVERRIDE {
+ std::string host = ConvertJavaStringToUTF8(env, jhost);
+ delegate_->ProxySettingsChangedTo(host, jport);
+ }
+
+ virtual void ProxySettingsChanged(JNIEnv* env, jobject self) OVERRIDE {
delegate_->ProxySettingsChanged();
}
diff --git a/chromium/net/proxy/proxy_config_service_android.h b/chromium/net/proxy/proxy_config_service_android.h
index 3ddbaebe78e..949ec426ebc 100644
--- a/chromium/net/proxy/proxy_config_service_android.h
+++ b/chromium/net/proxy/proxy_config_service_android.h
@@ -39,7 +39,12 @@ class NET_EXPORT ProxyConfigServiceAndroid : public ProxyConfigService {
virtual ~JNIDelegate() {}
// Called from Java (on JNI thread) to signal that the proxy settings have
- // changed.
+ // changed. The string and int arguments (the host/port pair for the proxy)
+ // are either a host/port pair or ("", 0) to indicate "no proxy".
+ virtual void ProxySettingsChangedTo(JNIEnv*, jobject, jstring, jint) = 0;
+
+ // Called from Java (on JNI thread) to signal that the proxy settings have
+ // changed. New proxy settings are fetched from the system property store.
virtual void ProxySettingsChanged(JNIEnv*, jobject) = 0;
};
diff --git a/chromium/net/proxy/proxy_config_service_linux.cc b/chromium/net/proxy/proxy_config_service_linux.cc
index 2c21283ea75..d01e5e6b5be 100644
--- a/chromium/net/proxy/proxy_config_service_linux.cc
+++ b/chromium/net/proxy/proxy_config_service_linux.cc
@@ -886,8 +886,8 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
if (base::DirectoryExists(kde4_path)) {
base::PlatformFileInfo kde3_info;
base::PlatformFileInfo kde4_info;
- if (file_util::GetFileInfo(kde4_config, &kde4_info)) {
- if (file_util::GetFileInfo(kde3_config, &kde3_info)) {
+ if (base::GetFileInfo(kde4_config, &kde4_info)) {
+ if (base::GetFileInfo(kde3_config, &kde3_info)) {
use_kde4 = kde4_info.last_modified >= kde3_info.last_modified;
} else {
use_kde4 = true;
@@ -1171,7 +1171,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter,
// each relevant name-value pair to the appropriate value table.
void UpdateCachedSettings() {
base::FilePath kioslaverc = kde_config_dir_.Append("kioslaverc");
- file_util::ScopedFILE input(file_util::OpenFile(kioslaverc, "r"));
+ file_util::ScopedFILE input(base::OpenFile(kioslaverc, "r"));
if (!input.get())
return;
ResetCachedSettings();
diff --git a/chromium/net/proxy/proxy_config_service_linux_unittest.cc b/chromium/net/proxy/proxy_config_service_linux_unittest.cc
index 03bba04d994..99a3b570b25 100644
--- a/chromium/net/proxy/proxy_config_service_linux_unittest.cc
+++ b/chromium/net/proxy/proxy_config_service_linux_unittest.cc
@@ -356,11 +356,11 @@ class ProxyConfigServiceLinuxTest : public PlatformTest {
PlatformTest::SetUp();
// Set up a temporary KDE home directory.
std::string prefix("ProxyConfigServiceLinuxTest_user_home");
- file_util::CreateNewTempDirectory(prefix, &user_home_);
+ base::CreateNewTempDirectory(prefix, &user_home_);
kde_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde"));
base::FilePath path = kde_home_.Append(FILE_PATH_LITERAL("share"));
path = path.Append(FILE_PATH_LITERAL("config"));
- file_util::CreateDirectory(path);
+ base::CreateDirectory(path);
kioslaverc_ = path.Append(FILE_PATH_LITERAL("kioslaverc"));
// Set up paths but do not create the directory for .kde4.
kde4_home_ = user_home_.Append(FILE_PATH_LITERAL(".kde4"));
@@ -1548,7 +1548,7 @@ TEST_F(ProxyConfigServiceLinuxTest, KDEHomePicker) {
// Now create .kde4 and put a kioslaverc in the config directory.
// Note that its timestamp will be at least as new as the .kde one.
- file_util::CreateDirectory(kde4_config_);
+ base::CreateDirectory(kde4_config_);
file_util::WriteFile(kioslaverc4_, slaverc4.c_str(), slaverc4.length());
CHECK(base::PathExists(kioslaverc4_));
@@ -1597,7 +1597,7 @@ TEST_F(ProxyConfigServiceLinuxTest, KDEHomePicker) {
// Finally, make the .kde4 config directory older than the .kde directory
// and make sure we then use .kde instead of .kde4 since it's newer.
- file_util::SetLastModifiedTime(kde4_config_, base::Time());
+ base::TouchFile(kde4_config_, base::Time(), base::Time());
{ SCOPED_TRACE("KDE4, very old .kde4 directory present, use .kde");
MockEnvironment* env = new MockEnvironment;
diff --git a/chromium/net/proxy/proxy_config_service_mac.cc b/chromium/net/proxy/proxy_config_service_mac.cc
index c1bc5337e5d..8c2f55ebd90 100644
--- a/chromium/net/proxy/proxy_config_service_mac.cc
+++ b/chromium/net/proxy/proxy_config_service_mac.cc
@@ -22,8 +22,6 @@ namespace net {
namespace {
-const int kPollIntervalSec = 5;
-
// Utility function to pull out a boolean value from a dictionary and return it,
// returning a default value if the key is not present.
bool GetBoolFromDictionary(CFDictionaryRef dict,
diff --git a/chromium/net/proxy/proxy_list.cc b/chromium/net/proxy/proxy_list.cc
index baa638f6c7d..53284026128 100644
--- a/chromium/net/proxy/proxy_list.cc
+++ b/chromium/net/proxy/proxy_list.cc
@@ -185,23 +185,50 @@ bool ProxyList::Fallback(ProxyRetryInfoMap* proxy_retry_info,
NOTREACHED();
return false;
}
- UpdateRetryInfoOnFallback(proxy_retry_info, net_log);
+ UpdateRetryInfoOnFallback(proxy_retry_info, base::TimeDelta(), ProxyServer(),
+ net_log);
// Remove this proxy from our list.
proxies_.erase(proxies_.begin());
return !proxies_.empty();
}
+void ProxyList::AddProxyToRetryList(ProxyRetryInfoMap* proxy_retry_info,
+ base::TimeDelta retry_delay,
+ const std::string& proxy_key,
+ const BoundNetLog& net_log) const {
+ // Mark this proxy as bad.
+ ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(proxy_key);
+ if (iter != proxy_retry_info->end()) {
+ // TODO(nsylvain): This is not the first time we get this. We should
+ // double the retry time. Bug 997660.
+ iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay;
+ } else {
+ ProxyRetryInfo retry_info;
+ retry_info.current_delay = retry_delay;
+ retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay;
+ (*proxy_retry_info)[proxy_key] = retry_info;
+ }
+ net_log.AddEvent(NetLog::TYPE_PROXY_LIST_FALLBACK,
+ NetLog::StringCallback("bad_proxy", &proxy_key));
+}
+
void ProxyList::UpdateRetryInfoOnFallback(
- ProxyRetryInfoMap* proxy_retry_info, const BoundNetLog& net_log) const {
+ ProxyRetryInfoMap* proxy_retry_info,
+ base::TimeDelta retry_delay,
+ const ProxyServer& another_proxy_to_bypass,
+ const BoundNetLog& net_log) const {
// Time to wait before retrying a bad proxy server.
-#if defined(OS_ANDROID) || defined(OS_IOS)
- // Randomize the timeout over a range from one to five minutes.
- const TimeDelta proxy_retry_delay =
- TimeDelta::FromMilliseconds(base::RandInt(1 * 60 * 1000, 5 * 60 * 1000));
+ if (retry_delay == base::TimeDelta()) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ // Randomize the timeout over a range from one to five minutes.
+ retry_delay =
+ TimeDelta::FromMilliseconds(
+ base::RandInt(1 * 60 * 1000, 5 * 60 * 1000));
#else
- const TimeDelta proxy_retry_delay = TimeDelta::FromMinutes(5);
+ retry_delay = TimeDelta::FromMinutes(5);
#endif
+ }
if (proxies_.empty()) {
NOTREACHED();
@@ -210,20 +237,21 @@ void ProxyList::UpdateRetryInfoOnFallback(
if (!proxies_[0].is_direct()) {
std::string key = proxies_[0].ToURI();
- // Mark this proxy as bad.
- ProxyRetryInfoMap::iterator iter = proxy_retry_info->find(key);
- if (iter != proxy_retry_info->end()) {
- // TODO(nsylvain): This is not the first time we get this. We should
- // double the retry time. Bug 997660.
- iter->second.bad_until = TimeTicks::Now() + iter->second.current_delay;
- } else {
- ProxyRetryInfo retry_info;
- retry_info.current_delay = proxy_retry_delay;
- retry_info.bad_until = TimeTicks().Now() + retry_info.current_delay;
- (*proxy_retry_info)[key] = retry_info;
+ AddProxyToRetryList(proxy_retry_info, retry_delay, key, net_log);
+
+ // If additional proxies to bypass are specified, add these to the retry
+ // map as well.
+ if (another_proxy_to_bypass.is_valid()) {
+ // Start at index 1 because index 0 is already handled above.
+ for (size_t j = 1; j < proxies_.size(); ++j) {
+ if (proxies_[j].is_direct())
+ break;
+ if (another_proxy_to_bypass == proxies_[j]) {
+ key = proxies_[j].ToURI();
+ AddProxyToRetryList(proxy_retry_info, retry_delay, key, net_log);
+ }
+ }
}
- net_log.AddEvent(NetLog::TYPE_PROXY_LIST_FALLBACK,
- NetLog::StringCallback("bad_proxy", &key));
}
}
diff --git a/chromium/net/proxy/proxy_list.h b/chromium/net/proxy/proxy_list.h
index 9f5fa59db06..e8df0ba83fb 100644
--- a/chromium/net/proxy/proxy_list.h
+++ b/chromium/net/proxy/proxy_list.h
@@ -14,6 +14,7 @@
namespace base {
class ListValue;
+class TimeDelta;
}
namespace net {
@@ -89,11 +90,28 @@ class NET_EXPORT_PRIVATE ProxyList {
// Updates |proxy_retry_info| to indicate that the first proxy in the list
// is bad. This is distinct from Fallback(), above, to allow updating proxy
- // retry information without modifying a given transction's proxy list.
- void UpdateRetryInfoOnFallback(ProxyRetryInfoMap* proxy_retry_info,
- const BoundNetLog& net_log) const;
+ // retry information without modifying a given transction's proxy list. Will
+ // retry after |retry_delay| if positive, and will use the default proxy retry
+ // duration otherwise. Additionally updates |proxy_retry_info| with
+ // |another_proxy_to_bypass| if non-empty.
+ void UpdateRetryInfoOnFallback(
+ ProxyRetryInfoMap* proxy_retry_info,
+ base::TimeDelta retry_delay,
+ const ProxyServer& another_proxy_to_bypass,
+ const BoundNetLog& net_log) const;
private:
+ // Updates |proxy_retry_info| to indicate that the proxy in |proxies_| with
+ // the URI of |proxy_key| is bad. The |proxy_key| must start with the scheme
+ // (only if https) followed by the host and then an explicit port. For
+ // example, if the proxy origin is https://proxy.chromium.org:443/ the key is
+ // https://proxy.chrome.org:443 whereas if the origin is
+ // http://proxy.chrome.org/, the key is proxy.chrome.org:80.
+ void AddProxyToRetryList(ProxyRetryInfoMap* proxy_retry_info,
+ base::TimeDelta retry_delay,
+ const std::string& proxy_key,
+ const BoundNetLog& net_log) const;
+
// List of proxies.
std::vector<ProxyServer> proxies_;
};
diff --git a/chromium/net/proxy/proxy_resolver_v8.cc b/chromium/net/proxy/proxy_resolver_v8.cc
index 190a4c0c542..3de1c7a9f1d 100644
--- a/chromium/net/proxy/proxy_resolver_v8.cc
+++ b/chromium/net/proxy/proxy_resolver_v8.cc
@@ -155,30 +155,38 @@ base::string16 V8StringToUTF16(v8::Handle<v8::String> s) {
}
// Converts an ASCII std::string to a V8 string.
-v8::Local<v8::String> ASCIIStringToV8String(const std::string& s) {
+v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate,
+ const std::string& s) {
DCHECK(IsStringASCII(s));
- return v8::String::New(s.data(), s.size());
+ return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString,
+ s.size());
}
// Converts a UTF16 base::string16 (warpped by a ProxyResolverScriptData) to a
// V8 string.
v8::Local<v8::String> ScriptDataToV8String(
- const scoped_refptr<ProxyResolverScriptData>& s) {
+ v8::Isolate* isolate, const scoped_refptr<ProxyResolverScriptData>& s) {
if (s->utf16().size() * 2 <= kMaxStringBytesForCopy) {
- return v8::String::New(
+ return v8::String::NewFromTwoByte(
+ isolate,
reinterpret_cast<const uint16_t*>(s->utf16().data()),
+ v8::String::kNormalString,
s->utf16().size());
}
- return v8::String::NewExternal(new V8ExternalStringFromScriptData(s));
+ return v8::String::NewExternal(isolate,
+ new V8ExternalStringFromScriptData(s));
}
// Converts an ASCII string literal to a V8 string.
-v8::Local<v8::String> ASCIILiteralToV8String(const char* ascii) {
+v8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate,
+ const char* ascii) {
DCHECK(IsStringASCII(ascii));
size_t length = strlen(ascii);
if (length <= kMaxStringBytesForCopy)
- return v8::String::New(ascii, length);
- return v8::String::NewExternal(new V8ExternalASCIILiteral(ascii, length));
+ return v8::String::NewFromUtf8(isolate, ascii, v8::String::kNormalString,
+ length);
+ return v8::String::NewExternal(isolate,
+ new V8ExternalASCIILiteral(ascii, length));
}
// Stringizes a V8 object by calling its toString() method. Returns true
@@ -268,7 +276,7 @@ bool SortIpAddressList(const std::string& ip_address_list,
// Strip all whitespace (mimics IE behavior).
std::string cleaned_ip_address_list;
- RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list);
+ base::RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list);
if (cleaned_ip_address_list.empty())
return false;
@@ -342,9 +350,10 @@ class ProxyResolverV8::Context {
~Context() {
v8::Locker locked(isolate_);
+ v8::Isolate::Scope isolate_scope(isolate_);
- v8_this_.Dispose();
- v8_context_.Dispose();
+ v8_this_.Reset();
+ v8_context_.Reset();
}
JSBindings* js_bindings() {
@@ -353,6 +362,7 @@ class ProxyResolverV8::Context {
int ResolveProxy(const GURL& query_url, ProxyInfo* results) {
v8::Locker locked(isolate_);
+ v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope scope(isolate_);
v8::Local<v8::Context> context =
@@ -367,8 +377,8 @@ class ProxyResolverV8::Context {
}
v8::Handle<v8::Value> argv[] = {
- ASCIIStringToV8String(query_url.spec()),
- ASCIIStringToV8String(query_url.HostNoBrackets()),
+ ASCIIStringToV8String(isolate_, query_url.spec()),
+ ASCIIStringToV8String(isolate_, query_url.HostNoBrackets()),
};
v8::TryCatch try_catch;
@@ -406,48 +416,52 @@ class ProxyResolverV8::Context {
int InitV8(const scoped_refptr<ProxyResolverScriptData>& pac_script) {
v8::Locker locked(isolate_);
+ v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope scope(isolate_);
- v8_this_.Reset(isolate_, v8::External::New(this));
+ v8_this_.Reset(isolate_, v8::External::New(isolate_, this));
v8::Local<v8::External> v8_this =
v8::Local<v8::External>::New(isolate_, v8_this_);
v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
// Attach the javascript bindings.
v8::Local<v8::FunctionTemplate> alert_template =
- v8::FunctionTemplate::New(&AlertCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("alert"), alert_template);
+ v8::FunctionTemplate::New(isolate_, &AlertCallback, v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "alert"),
+ alert_template);
v8::Local<v8::FunctionTemplate> my_ip_address_template =
- v8::FunctionTemplate::New(&MyIpAddressCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("myIpAddress"),
- my_ip_address_template);
+ v8::FunctionTemplate::New(isolate_, &MyIpAddressCallback, v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddress"),
+ my_ip_address_template);
v8::Local<v8::FunctionTemplate> dns_resolve_template =
- v8::FunctionTemplate::New(&DnsResolveCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("dnsResolve"),
- dns_resolve_template);
+ v8::FunctionTemplate::New(isolate_, &DnsResolveCallback, v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolve"),
+ dns_resolve_template);
// Microsoft's PAC extensions:
v8::Local<v8::FunctionTemplate> dns_resolve_ex_template =
- v8::FunctionTemplate::New(&DnsResolveExCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("dnsResolveEx"),
+ v8::FunctionTemplate::New(isolate_, &DnsResolveExCallback, v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolveEx"),
dns_resolve_ex_template);
v8::Local<v8::FunctionTemplate> my_ip_address_ex_template =
- v8::FunctionTemplate::New(&MyIpAddressExCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("myIpAddressEx"),
+ v8::FunctionTemplate::New(isolate_, &MyIpAddressExCallback, v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddressEx"),
my_ip_address_ex_template);
v8::Local<v8::FunctionTemplate> sort_ip_address_list_template =
- v8::FunctionTemplate::New(&SortIpAddressListCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("sortIpAddressList"),
+ v8::FunctionTemplate::New(isolate_,
+ &SortIpAddressListCallback,
+ v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "sortIpAddressList"),
sort_ip_address_list_template);
v8::Local<v8::FunctionTemplate> is_in_net_ex_template =
- v8::FunctionTemplate::New(&IsInNetExCallback, v8_this);
- global_template->Set(ASCIILiteralToV8String("isInNetEx"),
+ v8::FunctionTemplate::New(isolate_, &IsInNetExCallback, v8_this);
+ global_template->Set(ASCIILiteralToV8String(isolate_, "isInNetEx"),
is_in_net_ex_template);
v8_context_.Reset(
@@ -462,6 +476,7 @@ class ProxyResolverV8::Context {
// Note that the two string literals are concatenated.
int rv = RunScript(
ASCIILiteralToV8String(
+ isolate_,
PROXY_RESOLVER_SCRIPT
PROXY_RESOLVER_SCRIPT_EX),
kPacUtilityResourceName);
@@ -471,7 +486,8 @@ class ProxyResolverV8::Context {
}
// Add the user's PAC code to the environment.
- rv = RunScript(ScriptDataToV8String(pac_script), kPacResourceName);
+ rv =
+ RunScript(ScriptDataToV8String(isolate_, pac_script), kPacResourceName);
if (rv != OK)
return rv;
@@ -489,15 +505,17 @@ class ProxyResolverV8::Context {
void PurgeMemory() {
v8::Locker locked(isolate_);
+ v8::Isolate::Scope isolate_scope(isolate_);
v8::V8::LowMemoryNotification();
}
private:
bool GetFindProxyForURL(v8::Local<v8::Value>* function) {
v8::Local<v8::Context> context =
- v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), v8_context_);
+ v8::Local<v8::Context>::New(isolate_, v8_context_);
*function =
- context->Global()->Get(ASCIILiteralToV8String("FindProxyForURL"));
+ context->Global()->Get(
+ ASCIILiteralToV8String(isolate_, "FindProxyForURL"));
return (*function)->IsFunction();
}
@@ -521,7 +539,7 @@ class ProxyResolverV8::Context {
// Compile the script.
v8::ScriptOrigin origin =
- v8::ScriptOrigin(ASCIILiteralToV8String(script_name));
+ v8::ScriptOrigin(ASCIILiteralToV8String(isolate_, script_name));
v8::Local<v8::Script> code = v8::Script::Compile(script, &origin);
// Execute.
@@ -612,7 +630,8 @@ class ProxyResolverV8::Context {
v8::V8::TerminateExecution(args.GetIsolate());
if (success) {
- args.GetReturnValue().Set(ASCIIStringToV8String(result));
+ args.GetReturnValue().Set(
+ ASCIIStringToV8String(args.GetIsolate(), result));
return;
}
@@ -625,7 +644,8 @@ class ProxyResolverV8::Context {
args.GetReturnValue().SetEmptyString();
return;
case JSBindings::MY_IP_ADDRESS:
- args.GetReturnValue().Set(ASCIILiteralToV8String("127.0.0.1"));
+ args.GetReturnValue().Set(
+ ASCIILiteralToV8String(args.GetIsolate(), "127.0.0.1"));
return;
case JSBindings::MY_IP_ADDRESS_EX:
args.GetReturnValue().SetEmptyString();
@@ -655,7 +675,8 @@ class ProxyResolverV8::Context {
args.GetReturnValue().Set(false);
return;
}
- args.GetReturnValue().Set(ASCIIStringToV8String(sorted_ip_address_list));
+ args.GetReturnValue().Set(
+ ASCIIStringToV8String(args.GetIsolate(), sorted_ip_address_list));
}
// V8 callback for when "isInNetEx()" is invoked by the PAC script.
@@ -730,7 +751,8 @@ void ProxyResolverV8::CancelSetPacScript() {
}
void ProxyResolverV8::PurgeMemory() {
- context_->PurgeMemory();
+ if (context_)
+ context_->PurgeMemory();
}
int ProxyResolverV8::SetPacScript(
@@ -790,6 +812,7 @@ size_t ProxyResolverV8::GetTotalHeapSize() {
return 0;
v8::Locker locked(g_default_isolate_);
+ v8::Isolate::Scope isolate_scope(g_default_isolate_);
v8::HeapStatistics heap_statistics;
g_default_isolate_->GetHeapStatistics(&heap_statistics);
return heap_statistics.total_heap_size();
@@ -801,6 +824,7 @@ size_t ProxyResolverV8::GetUsedHeapSize() {
return 0;
v8::Locker locked(g_default_isolate_);
+ v8::Isolate::Scope isolate_scope(g_default_isolate_);
v8::HeapStatistics heap_statistics;
g_default_isolate_->GetHeapStatistics(&heap_statistics);
return heap_statistics.used_heap_size();
diff --git a/chromium/net/proxy/proxy_resolver_v8_unittest.cc b/chromium/net/proxy/proxy_resolver_v8_unittest.cc
index cbbedcec618..7ff97702e52 100644
--- a/chromium/net/proxy/proxy_resolver_v8_unittest.cc
+++ b/chromium/net/proxy/proxy_resolver_v8_unittest.cc
@@ -102,6 +102,10 @@ class ProxyResolverV8WithMockBindings : public ProxyResolverV8 {
set_js_bindings(&mock_js_bindings_);
}
+ virtual ~ProxyResolverV8WithMockBindings() {
+ PurgeMemory();
+ }
+
MockJSBindings* mock_js_bindings() {
return &mock_js_bindings_;
}
@@ -206,13 +210,6 @@ TEST(ProxyResolverV8Test, Basic) {
EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size());
EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size());
}
-
- // We call this so we'll have code coverage of the function and valgrind will
- // make sure nothing bad happens.
- //
- // NOTE: This is here instead of in its own test so that we'll be calling it
- // after having done something, in hopes it won't be a no-op.
- resolver.PurgeMemory();
}
TEST(ProxyResolverV8Test, BadReturnType) {
diff --git a/chromium/net/proxy/proxy_script_decider.cc b/chromium/net/proxy/proxy_script_decider.cc
index 3db33fcc89a..eab59ac373c 100644
--- a/chromium/net/proxy/proxy_script_decider.cc
+++ b/chromium/net/proxy/proxy_script_decider.cc
@@ -153,8 +153,8 @@ ProxyScriptDecider::PacSourceList ProxyScriptDecider::
const ProxyConfig& config) const {
PacSourceList pac_sources;
if (config.auto_detect()) {
- pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL()));
- pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL()));
+ pac_sources.push_back(PacSource(PacSource::WPAD_DHCP, GURL(kWpadUrl)));
+ pac_sources.push_back(PacSource(PacSource::WPAD_DNS, GURL(kWpadUrl)));
}
if (config.has_pac_url())
pac_sources.push_back(PacSource(PacSource::CUSTOM, config.pac_url()));
@@ -240,7 +240,10 @@ int ProxyScriptDecider::DoWaitComplete(int result) {
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_PROXY_SCRIPT_DECIDER_WAIT,
result);
}
- next_state_ = GetStartState();
+ if (current_pac_source().type == PacSource::WPAD_DNS)
+ next_state_ = STATE_QUICK_CHECK;
+ else
+ next_state_ = GetStartState();
return OK;
}
@@ -251,38 +254,23 @@ int ProxyScriptDecider::DoQuickCheck() {
return OK;
}
- if (have_custom_pac_url_) {
- // If there's a custom URL, skip QuickCheck.
- next_state_ = GetStartState();
- return OK;
- }
-
quick_check_start_time_ = base::Time::Now();
- HostResolver::RequestInfo reqinfo(HostPortPair("wpad", 80));
+ std::string host = current_pac_source().url.host();
+ HostResolver::RequestInfo reqinfo(HostPortPair(host, 80));
reqinfo.set_host_resolver_flags(HOST_RESOLVER_SYSTEM_ONLY);
CompletionCallback callback = base::Bind(
&ProxyScriptDecider::OnIOCompletion,
base::Unretained(this));
+ next_state_ = STATE_QUICK_CHECK_COMPLETE;
+ quick_check_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(
+ kQuickCheckDelayMs),
+ base::Bind(callback, ERR_NAME_NOT_RESOLVED));
// We use HIGHEST here because proxy decision blocks doing any other requests.
- int rv = host_resolver_->Resolve(reqinfo, HIGHEST, &wpad_addresses_,
- callback, net_log_);
-
- // We can't get an error response - the name is known to be valid, and we
- // don't cache negative dns responses.
- DCHECK(rv == OK || rv == ERR_IO_PENDING);
-
- if (rv == OK) {
- next_state_ = GetStartState();
- } else {
- quick_check_timer_.Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(
- kQuickCheckDelayMs),
- base::Bind(callback, ERR_NAME_NOT_RESOLVED));
- next_state_ = STATE_QUICK_CHECK_COMPLETE;
- }
- return rv;
+ return host_resolver_->Resolve(reqinfo, HIGHEST, &wpad_addresses_,
+ callback, net_log_);
}
int ProxyScriptDecider::DoQuickCheckComplete(int result) {
@@ -293,8 +281,9 @@ int ProxyScriptDecider::DoQuickCheckComplete(int result) {
UMA_HISTOGRAM_TIMES("Net.WpadQuickCheckFailure", delta);
host_resolver_->Cancel();
quick_check_timer_.Stop();
- if (result == OK)
- next_state_ = GetStartState();
+ if (result != OK)
+ return TryToFallbackPacSource(result);
+ next_state_ = GetStartState();
return result;
}
@@ -420,8 +409,10 @@ int ProxyScriptDecider::TryToFallbackPacSource(int error) {
net_log_.AddEvent(
NetLog::TYPE_PROXY_SCRIPT_DECIDER_FALLING_BACK_TO_NEXT_PAC_SOURCE);
-
- next_state_ = GetStartState();
+ if (current_pac_source().type == PacSource::WPAD_DNS)
+ next_state_ = STATE_QUICK_CHECK;
+ else
+ next_state_ = GetStartState();
return OK;
}
diff --git a/chromium/net/proxy/proxy_script_decider_unittest.cc b/chromium/net/proxy/proxy_script_decider_unittest.cc
index 18d8c6f5dcd..5e2b489d619 100644
--- a/chromium/net/proxy/proxy_script_decider_unittest.cc
+++ b/chromium/net/proxy/proxy_script_decider_unittest.cc
@@ -126,6 +126,55 @@ class RuleBasedProxyScriptFetcher : public ProxyScriptFetcher {
URLRequestContext* request_context_;
};
+// A mock retriever, returns asynchronously when CompleteRequests() is called.
+class MockDhcpProxyScriptFetcher : public DhcpProxyScriptFetcher {
+ public:
+ MockDhcpProxyScriptFetcher();
+ virtual ~MockDhcpProxyScriptFetcher();
+
+ virtual int Fetch(base::string16* utf16_text,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual void Cancel() OVERRIDE;
+ virtual const GURL& GetPacURL() const OVERRIDE;
+
+ virtual void SetPacURL(const GURL& url);
+
+ virtual void CompleteRequests(int result, const base::string16& script);
+
+ private:
+ CompletionCallback callback_;
+ base::string16* utf16_text_;
+ GURL gurl_;
+ DISALLOW_COPY_AND_ASSIGN(MockDhcpProxyScriptFetcher);
+};
+
+MockDhcpProxyScriptFetcher::MockDhcpProxyScriptFetcher() { }
+
+MockDhcpProxyScriptFetcher::~MockDhcpProxyScriptFetcher() { }
+
+int MockDhcpProxyScriptFetcher::Fetch(base::string16* utf16_text,
+ const CompletionCallback& callback) {
+ utf16_text_ = utf16_text;
+ callback_ = callback;
+ return ERR_IO_PENDING;
+}
+
+void MockDhcpProxyScriptFetcher::Cancel() { }
+
+const GURL& MockDhcpProxyScriptFetcher::GetPacURL() const {
+ return gurl_;
+}
+
+void MockDhcpProxyScriptFetcher::SetPacURL(const GURL& url) {
+ gurl_ = url;
+}
+
+void MockDhcpProxyScriptFetcher::CompleteRequests(
+ int result, const base::string16& script) {
+ *utf16_text_ = script;
+ callback_.Run(result);
+}
+
// Succeed using custom PAC script.
TEST(ProxyScriptDeciderTest, CustomPacSucceeds) {
Rules rules;
@@ -278,17 +327,15 @@ class ProxyScriptDeciderQuickCheckTest : public ::testing::Test {
Rules rules_;
Rules::Rule rule_;
TestCompletionCallback callback_;
+ RuleBasedProxyScriptFetcher fetcher_;
+ ProxyConfig config_;
private:
URLRequestContext request_context_;
- RuleBasedProxyScriptFetcher fetcher_;
DoNothingDhcpProxyScriptFetcher dhcp_fetcher_;
-
- ProxyConfig config_;
};
-#if 0
// Fails if a synchronous DNS lookup success for wpad causes QuickCheck to fail.
TEST_F(ProxyScriptDeciderQuickCheckTest, SyncSuccess) {
resolver_.set_synchronous_mode(true);
@@ -339,7 +386,32 @@ TEST_F(ProxyScriptDeciderQuickCheckTest, AsyncTimeout) {
EXPECT_FALSE(resolver_.has_pending_requests());
EXPECT_FALSE(decider_->effective_config().has_pac_url());
}
-#endif
+
+// Fails if DHCP check doesn't take place before QuickCheck.
+TEST_F(ProxyScriptDeciderQuickCheckTest, QuickCheckInhibitsDhcp) {
+ MockDhcpProxyScriptFetcher dhcp_fetcher;
+ const char *kPac = "function FindProxyForURL(u,h) { return \"DIRECT\"; }";
+ base::string16 pac_contents = base::UTF8ToUTF16(kPac);
+ GURL url("http://foobar/baz");
+ dhcp_fetcher.SetPacURL(url);
+ decider_.reset(new ProxyScriptDecider(&fetcher_, &dhcp_fetcher, NULL));
+ EXPECT_EQ(ERR_IO_PENDING, StartDecider());
+ dhcp_fetcher.CompleteRequests(OK, pac_contents);
+ EXPECT_TRUE(decider_->effective_config().has_pac_url());
+ EXPECT_EQ(decider_->effective_config().pac_url(), url);
+}
+
+TEST_F(ProxyScriptDeciderQuickCheckTest, ExplicitPacUrl) {
+ const char *kCustomUrl = "http://custom/proxy.pac";
+ config_.set_pac_url(GURL(kCustomUrl));
+ Rules::Rule rule = rules_.AddSuccessRule(kCustomUrl);
+ resolver_.rules()->AddSimulatedFailure("wpad");
+ resolver_.rules()->AddRule("custom", "1.2.3.4");
+ EXPECT_EQ(ERR_IO_PENDING, StartDecider());
+ callback_.WaitForResult();
+ EXPECT_TRUE(decider_->effective_config().has_pac_url());
+ EXPECT_EQ(rule.url, decider_->effective_config().pac_url());
+}
// Fails at WPAD (downloading), but succeeds in choosing the custom PAC.
TEST(ProxyScriptDeciderTest, AutodetectFailCustomSuccess1) {
diff --git a/chromium/net/proxy/proxy_script_fetcher_impl.cc b/chromium/net/proxy/proxy_script_fetcher_impl.cc
index f8925fa9c3c..705bbbf26b0 100644
--- a/chromium/net/proxy/proxy_script_fetcher_impl.cc
+++ b/chromium/net/proxy/proxy_script_fetcher_impl.cc
@@ -13,6 +13,7 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
#include "net/cert/cert_status_flags.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request_context.h"
@@ -133,7 +134,8 @@ int ProxyScriptFetcherImpl::Fetch(
return OK;
}
- cur_request_.reset(url_request_context_->CreateRequest(url, this));
+ cur_request_ =
+ url_request_context_->CreateRequest(url, DEFAULT_PRIORITY, this);
cur_request_->set_method("GET");
// Make sure that the PAC script is downloaded using a direct connection,
@@ -145,8 +147,8 @@ int ProxyScriptFetcherImpl::Fetch(
// checking in order to avoid a circular dependency when attempting to fetch
// the OCSP response or CRL. We could make the revocation check go direct but
// the proxy might be the only way to the outside world.
- cur_request_->set_load_flags(LOAD_BYPASS_PROXY | LOAD_DISABLE_CACHE |
- LOAD_DISABLE_CERT_REVOCATION_CHECKING);
+ cur_request_->SetLoadFlags(LOAD_BYPASS_PROXY | LOAD_DISABLE_CACHE |
+ LOAD_DISABLE_CERT_REVOCATION_CHECKING);
// Save the caller's info for notification on completion.
callback_ = callback;
diff --git a/chromium/net/proxy/proxy_server.cc b/chromium/net/proxy/proxy_server.cc
index 6875b4a329b..a6ea5deafde 100644
--- a/chromium/net/proxy/proxy_server.cc
+++ b/chromium/net/proxy/proxy_server.cc
@@ -208,6 +208,22 @@ ProxyServer::Scheme ProxyServer::GetSchemeFromURI(const std::string& scheme) {
return GetSchemeFromURIInternal(scheme.begin(), scheme.end());
}
+// TODO(bengr): Use |scheme_| to indicate that this is the data reduction proxy.
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+bool ProxyServer::isDataReductionProxy() const {
+ return host_port_pair_.Equals(
+ HostPortPair::FromURL(GURL(SPDY_PROXY_AUTH_ORIGIN)));
+}
+
+bool ProxyServer::isDataReductionProxyFallback() const {
+#if defined(DATA_REDUCTION_FALLBACK_HOST)
+ return host_port_pair_.Equals(
+ HostPortPair::FromURL(GURL(DATA_REDUCTION_FALLBACK_HOST)));
+#endif // defined(DATA_REDUCTION_FALLBACK_HOST)
+ return false;
+}
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
+
// static
ProxyServer ProxyServer::FromSchemeHostAndPort(
Scheme scheme,
diff --git a/chromium/net/proxy/proxy_server.h b/chromium/net/proxy/proxy_server.h
index 00cc9fddaf6..08a20c0347c 100644
--- a/chromium/net/proxy/proxy_server.h
+++ b/chromium/net/proxy/proxy_server.h
@@ -146,6 +146,14 @@ class NET_EXPORT ProxyServer {
return host_port_pair_ < other.host_port_pair_;
}
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ // Returns true if this proxy server is the data reduction proxy or its
+ // fallback, respectively, as configured in gyp. These functions will return
+ // false for data reduction proxy servers specified on the command line.
+ bool isDataReductionProxy() const;
+ bool isDataReductionProxyFallback() const;
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
+
private:
// Creates a ProxyServer given a scheme, and host/port string. If parsing the
// host/port string fails, the returned instance will be invalid.
diff --git a/chromium/net/proxy/proxy_service.cc b/chromium/net/proxy/proxy_service.cc
index 33bbd490842..9d4125b6a34 100644
--- a/chromium/net/proxy/proxy_service.cc
+++ b/chromium/net/proxy/proxy_service.cc
@@ -45,6 +45,10 @@
#include "net/proxy/proxy_config_service_android.h"
#endif
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+#include "base/metrics/histogram.h"
+#endif
+
using base::TimeDelta;
using base::TimeTicks;
@@ -52,8 +56,6 @@ namespace net {
namespace {
-const size_t kMaxNumNetLogEntries = 100;
-
// When the IP address changes we don't immediately re-run proxy auto-config.
// Instead, we wait for |kDelayAfterNetworkChangesMs| before
// attempting to re-valuate proxy auto-config.
@@ -1171,6 +1173,16 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url,
return ResolveProxy(url, result, callback, pac_request, net_log);
}
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (result->proxy_server().isDataReductionProxy()) {
+ RecordDataReductionProxyBypassInfo(
+ true, result->proxy_server(), ERROR_BYPASS);
+ } else if (result->proxy_server().isDataReductionProxyFallback()) {
+ RecordDataReductionProxyBypassInfo(
+ false, result->proxy_server(), ERROR_BYPASS);
+ }
+#endif
+
// We don't have new proxy settings to try, try to fallback to the next proxy
// in the list.
bool did_fallback = result->Fallback(net_log);
@@ -1180,9 +1192,14 @@ int ProxyService::ReconsiderProxyAfterError(const GURL& url,
return did_fallback ? OK : ERR_FAILED;
}
-bool ProxyService::MarkProxyAsBad(const ProxyInfo& result,
- const BoundNetLog& net_log) {
- result.proxy_list_.UpdateRetryInfoOnFallback(&proxy_retry_info_, net_log);
+bool ProxyService::MarkProxiesAsBad(
+ const ProxyInfo& result,
+ base::TimeDelta retry_delay,
+ const ProxyServer& another_bad_proxy,
+ const BoundNetLog& net_log) {
+ result.proxy_list_.UpdateRetryInfoOnFallback(&proxy_retry_info_, retry_delay,
+ another_bad_proxy,
+ net_log);
return result.proxy_list_.HasUntriedProxies(proxy_retry_info_);
}
@@ -1393,6 +1410,25 @@ scoped_ptr<ProxyService::PacPollPolicy>
return scoped_ptr<PacPollPolicy>(new DefaultPollPolicy());
}
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+void ProxyService::RecordDataReductionProxyBypassInfo(
+ bool is_primary,
+ const ProxyServer& proxy_server,
+ DataReductionProxyBypassEventType bypass_type) const {
+ // Only record UMA if the proxy isn't already on the retry list.
+ if (proxy_retry_info_.find(proxy_server.ToURI()) != proxy_retry_info_.end())
+ return;
+
+ if (is_primary) {
+ UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassInfoPrimary",
+ bypass_type, BYPASS_EVENT_TYPE_MAX);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.BypassInfoFallback",
+ bypass_type, BYPASS_EVENT_TYPE_MAX);
+ }
+}
+#endif // defined(SPDY_PROXY_AUTH_ORIGIN)
+
void ProxyService::OnProxyConfigChanged(
const ProxyConfig& config,
ProxyConfigService::ConfigAvailability availability) {
diff --git a/chromium/net/proxy/proxy_service.h b/chromium/net/proxy/proxy_service.h
index 663991133a0..136ec6763f2 100644
--- a/chromium/net/proxy/proxy_service.h
+++ b/chromium/net/proxy/proxy_service.h
@@ -27,6 +27,7 @@ class GURL;
namespace base {
class MessageLoop;
class SingleThreadTaskRunner;
+class TimeDelta;
} // namespace base
namespace net {
@@ -147,10 +148,15 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
const BoundNetLog& net_log);
// Explicitly trigger proxy fallback for the given |results| by updating our
- // list of bad proxies to include the first entry of |results|. Returns true
- // if there will be at least one proxy remaining in the list after fallback
- // and false otherwise.
- bool MarkProxyAsBad(const ProxyInfo& results, const BoundNetLog& net_log);
+ // list of bad proxies to include the first entry of |results|, and,
+ // optionally, another bad proxy. Will retry after |retry_delay| if positive,
+ // and will use the default proxy retry duration otherwise. Returns true if
+ // there will be at least one proxy remaining in the list after fallback and
+ // false otherwise.
+ bool MarkProxiesAsBad(const ProxyInfo& results,
+ base::TimeDelta retry_delay,
+ const ProxyServer& another_bad_proxy,
+ const BoundNetLog& net_log);
// 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
@@ -257,6 +263,38 @@ class NET_EXPORT ProxyService : public NetworkChangeNotifier::IPAddressObserver,
// of the default internal PacPollPolicy used by ProxyService.
static scoped_ptr<PacPollPolicy> CreateDefaultPacPollPolicy();
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ // Values of the UMA DataReductionProxy.BypassInfo{Primary|Fallback}
+ // histograms. This enum must remain synchronized with the enum of the same
+ // name in metrics/histograms/histograms.xml.
+ enum DataReductionProxyBypassEventType {
+ // Bypass the proxy for less than 30 minutes.
+ SHORT_BYPASS = 0,
+
+ // Bypass the proxy for 30 minutes or more.
+ LONG_BYPASS,
+
+ // Bypass the proxy because of an internal server error.
+ INTERNAL_SERVER_ERROR_BYPASS,
+
+ // Bypass the proxy because of any other error.
+ ERROR_BYPASS,
+
+ // Bypass the proxy because responses appear not to be coming via it.
+ MISSING_VIA_HEADER,
+
+ // This must always be last.
+ BYPASS_EVENT_TYPE_MAX
+ };
+
+ // Records a |DataReductionProxyBypassEventType| for either the data reduction
+ // proxy (|is_primary| is true) or the data reduction proxy fallback.
+ void RecordDataReductionProxyBypassInfo(
+ bool is_primary,
+ const ProxyServer& proxy_server,
+ DataReductionProxyBypassEventType bypass_type) const;
+#endif
+
private:
FRIEND_TEST_ALL_PREFIXES(ProxyServiceTest, UpdateConfigAfterFailedAutodetect);
FRIEND_TEST_ALL_PREFIXES(ProxyServiceTest, UpdateConfigFromPACToDirect);
diff --git a/chromium/net/quic/congestion_control/channel_estimator.cc b/chromium/net/quic/congestion_control/channel_estimator.cc
index 54b96ae4e18..a012b666a39 100644
--- a/chromium/net/quic/congestion_control/channel_estimator.cc
+++ b/chromium/net/quic/congestion_control/channel_estimator.cc
@@ -38,7 +38,7 @@ void ChannelEstimator::OnAcknowledgedPacket(
return;
}
if (last_sequence_number_ != sequence_number - 1) {
- DLOG(INFO) << "Skip channel estimator due to lost packet(s)";
+ DVLOG(1) << "Skip channel estimator due to lost packet(s)";
} else if (last_send_time_.IsInitialized()) {
QuicTime::Delta sent_delta = send_time.Subtract(last_send_time_);
QuicTime::Delta received_delta = receive_time.Subtract(last_receive_time_);
@@ -88,7 +88,7 @@ ChannelEstimateState ChannelEstimator::GetChannelEstimate(
}
}
*estimate = median_bitrate;
- DLOG(INFO) << "Channel estimate is:"
+ DVLOG(1) << "Channel estimate is:"
<< median_bitrate.ToKBitsPerSecond() << " Kbit/s";
// If the bitrates in our 25th to 75th percentile window varies more than
// 25% of the median bitrate we consider the estimate to be uncertain.
diff --git a/chromium/net/quic/congestion_control/cubic.cc b/chromium/net/quic/congestion_control/cubic.cc
index 04b1e937cfd..3d03b9f60d1 100644
--- a/chromium/net/quic/congestion_control/cubic.cc
+++ b/chromium/net/quic/congestion_control/cubic.cc
@@ -4,6 +4,8 @@
#include "net/quic/congestion_control/cubic.h"
+#include <algorithm>
+
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/time/time.h"
@@ -17,8 +19,10 @@ const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3)
// where 0.100 is 100 ms which is the scaling
// round trip time.
const int kCubeCongestionWindowScale = 410;
-const uint64 kCubeFactor = (1ull << kCubeScale) / kCubeCongestionWindowScale;
-const uint32 kBeta = 717; // Back off factor after loss.
+const uint64 kCubeFactor = (GG_UINT64_C(1) << kCubeScale) /
+ kCubeCongestionWindowScale;
+const uint32 kBetaSPDY = 939; // Back off factor after loss for SPDY, reduces
+ // the CWND by 1/12th.
const uint32 kBetaLastMax = 871; // Additional back off factor after loss for
// the stored max value.
@@ -127,7 +131,7 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterPacketLoss(
last_max_congestion_window_ = current_congestion_window;
}
epoch_ = QuicTime::Zero(); // Reset time.
- return (current_congestion_window * kBeta) >> 10;
+ return (current_congestion_window * kBetaSPDY) >> 10;
}
QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck(
@@ -147,7 +151,7 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck(
if (!epoch_.IsInitialized()) {
// First ACK after a loss event.
- DLOG(INFO) << "Start of epoch";
+ DVLOG(1) << "Start of epoch";
epoch_ = current_time; // Start of epoch.
acked_packets_count_ = 1; // Reset count.
// Reset estimated_tcp_congestion_window_ to be in sync with cubic.
@@ -191,7 +195,7 @@ QuicTcpCongestionWindow Cubic::CongestionWindowAfterAck(
if (target_congestion_window < estimated_tcp_congestion_window_) {
target_congestion_window = estimated_tcp_congestion_window_;
}
- DLOG(INFO) << "Target congestion_window:" << target_congestion_window;
+ DVLOG(1) << "Target congestion_window:" << target_congestion_window;
return target_congestion_window;
}
diff --git a/chromium/net/quic/congestion_control/cubic_test.cc b/chromium/net/quic/congestion_control/cubic_test.cc
index 84f2a7bb53d..c01bb050643 100644
--- a/chromium/net/quic/congestion_control/cubic_test.cc
+++ b/chromium/net/quic/congestion_control/cubic_test.cc
@@ -109,10 +109,10 @@ TEST_F(CubicTest, LossEvents) {
clock_.AdvanceTime(one_ms_);
EXPECT_EQ(expected_cwnd,
cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
- expected_cwnd = current_cwnd * 717 / 1024;
+ expected_cwnd = current_cwnd * 939 / 1024;
EXPECT_EQ(expected_cwnd,
cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
- expected_cwnd = current_cwnd * 717 / 1024;
+ expected_cwnd = current_cwnd * 939 / 1024;
EXPECT_EQ(expected_cwnd,
cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
}
@@ -126,7 +126,7 @@ TEST_F(CubicTest, BelowOrgin) {
clock_.AdvanceTime(one_ms_);
EXPECT_EQ(expected_cwnd,
cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min));
- expected_cwnd = current_cwnd * 717 / 1024;
+ expected_cwnd = current_cwnd * 939 / 1024;
EXPECT_EQ(expected_cwnd,
cubic_->CongestionWindowAfterPacketLoss(current_cwnd));
current_cwnd = expected_cwnd;
@@ -142,7 +142,7 @@ TEST_F(CubicTest, BelowOrgin) {
clock_.AdvanceTime(hundred_ms_);
current_cwnd = cubic_->CongestionWindowAfterAck(current_cwnd, rtt_min);
}
- expected_cwnd = 422;
+ expected_cwnd = 440;
EXPECT_EQ(expected_cwnd, current_cwnd);
}
diff --git a/chromium/net/quic/congestion_control/fix_rate_sender.cc b/chromium/net/quic/congestion_control/fix_rate_sender.cc
index 99aa10fabf8..8280f1eeb31 100644
--- a/chromium/net/quic/congestion_control/fix_rate_sender.cc
+++ b/chromium/net/quic/congestion_control/fix_rate_sender.cc
@@ -6,6 +6,8 @@
#include <math.h>
+#include <algorithm>
+
#include "base/logging.h"
#include "net/quic/quic_protocol.h"
@@ -18,22 +20,32 @@ namespace net {
FixRateSender::FixRateSender(const QuicClock* clock)
: bitrate_(QuicBandwidth::FromBytesPerSecond(kInitialBitrate)),
+ max_segment_size_(kDefaultMaxPacketSize),
fix_rate_leaky_bucket_(bitrate_),
- paced_sender_(bitrate_),
+ paced_sender_(bitrate_, max_segment_size_),
data_in_flight_(0),
latest_rtt_(QuicTime::Delta::Zero()) {
- DLOG(INFO) << "FixRateSender";
+ DVLOG(1) << "FixRateSender";
}
FixRateSender::~FixRateSender() {
}
+void FixRateSender::SetFromConfig(const QuicConfig& config, bool is_server) {
+}
+
+void FixRateSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ max_segment_size_ = max_packet_size;
+ paced_sender_.set_max_segment_size(max_segment_size_);
+}
+
void FixRateSender::OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
const SentPacketsMap& /*sent_packets*/) {
- DCHECK(feedback.type == kFixRate) <<
- "Invalid incoming CongestionFeedbackType:" << feedback.type;
+ if (feedback.type != kFixRate) {
+ LOG(DFATAL) << "Invalid incoming CongestionFeedbackType:" << feedback.type;
+ }
if (feedback.type == kFixRate) {
bitrate_ = feedback.fix_rate.bitrate;
fix_rate_leaky_bucket_.SetDrainingRate(feedback_receive_time, bitrate_);
@@ -42,7 +54,7 @@ void FixRateSender::OnIncomingQuicCongestionFeedbackFrame(
// Silently ignore invalid messages in release mode.
}
-void FixRateSender::OnIncomingAck(
+void FixRateSender::OnPacketAcked(
QuicPacketSequenceNumber /*acked_sequence_number*/,
QuicByteCount bytes_acked,
QuicTime::Delta rtt) {
@@ -56,32 +68,35 @@ void FixRateSender::OnIncomingAck(
latest_rtt_ = rtt;
}
-void FixRateSender::OnIncomingLoss(QuicTime /*ack_receive_time*/) {
+void FixRateSender::OnPacketLost(QuicPacketSequenceNumber /*sequence_number*/,
+ QuicTime /*ack_receive_time*/) {
// Ignore losses for fix rate sender.
}
-bool FixRateSender::SentPacket(
+bool FixRateSender::OnPacketSent(
QuicTime sent_time,
QuicPacketSequenceNumber /*sequence_number*/,
QuicByteCount bytes,
- Retransmission is_retransmission,
+ TransmissionType transmission_type,
HasRetransmittableData /*has_retransmittable_data*/) {
fix_rate_leaky_bucket_.Add(sent_time, bytes);
- paced_sender_.SentPacket(sent_time, bytes);
- if (is_retransmission == NOT_RETRANSMISSION) {
+ paced_sender_.OnPacketSent(sent_time, bytes);
+ if (transmission_type == NOT_RETRANSMISSION) {
data_in_flight_ += bytes;
}
return true;
}
-void FixRateSender::AbandoningPacket(
+void FixRateSender::OnRetransmissionTimeout() { }
+
+void FixRateSender::OnPacketAbandoned(
QuicPacketSequenceNumber /*sequence_number*/,
QuicByteCount /*abandoned_bytes*/) {
}
QuicTime::Delta FixRateSender::TimeUntilSend(
QuicTime now,
- Retransmission /*is_retransmission*/,
+ TransmissionType /* transmission_type */,
HasRetransmittableData /*has_retransmittable_data*/,
IsHandshake /*handshake*/) {
if (CongestionWindow() > fix_rate_leaky_bucket_.BytesPending(now)) {
@@ -103,22 +118,26 @@ QuicByteCount FixRateSender::CongestionWindow() {
QuicByteCount window_size_bytes = bitrate_.ToBytesPerPeriod(
QuicTime::Delta::FromMicroseconds(kWindowSizeUs));
// Make sure window size is not less than a packet.
- return std::max(kMaxPacketSize, window_size_bytes);
+ return std::max(kDefaultMaxPacketSize, window_size_bytes);
}
-QuicBandwidth FixRateSender::BandwidthEstimate() {
+QuicBandwidth FixRateSender::BandwidthEstimate() const {
return bitrate_;
}
-QuicTime::Delta FixRateSender::SmoothedRtt() {
+QuicTime::Delta FixRateSender::SmoothedRtt() const {
// TODO(satyamshekhar): Calculate and return smoothed rtt.
return latest_rtt_;
}
-QuicTime::Delta FixRateSender::RetransmissionDelay() {
+QuicTime::Delta FixRateSender::RetransmissionDelay() const {
// TODO(pwestin): Calculate and return retransmission delay.
// Use 2 * the latest RTT for now.
return latest_rtt_.Add(latest_rtt_);
}
+QuicByteCount FixRateSender::GetCongestionWindow() const {
+ return 0;
+}
+
} // namespace net
diff --git a/chromium/net/quic/congestion_control/fix_rate_sender.h b/chromium/net/quic/congestion_control/fix_rate_sender.h
index 781deade1c0..d3d48c7e3da 100644
--- a/chromium/net/quic/congestion_control/fix_rate_sender.h
+++ b/chromium/net/quic/congestion_control/fix_rate_sender.h
@@ -24,36 +24,42 @@ class NET_EXPORT_PRIVATE FixRateSender : public SendAlgorithmInterface {
virtual ~FixRateSender();
// Start implementation of SendAlgorithmInterface.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
- virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
+ virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) OVERRIDE;
- virtual void OnIncomingLoss(QuicTime ack_receive_time) OVERRIDE;
- virtual bool SentPacket(
+ virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
+ QuicTime ack_receive_time) OVERRIDE;
+ virtual bool OnPacketSent(
QuicTime sent_time,
- QuicPacketSequenceNumber equence_number,
+ QuicPacketSequenceNumber sequence_number,
QuicByteCount bytes,
- Retransmission is_retransmission,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) OVERRIDE;
- virtual void AbandoningPacket(QuicPacketSequenceNumber sequence_number,
- QuicByteCount abandoned_bytes) OVERRIDE;
+ virtual void OnRetransmissionTimeout() OVERRIDE;
+ virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
+ QuicByteCount abandoned_bytes) OVERRIDE;
virtual QuicTime::Delta TimeUntilSend(
QuicTime now,
- Retransmission is_retransmission,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data,
IsHandshake handshake) OVERRIDE;
- virtual QuicBandwidth BandwidthEstimate() OVERRIDE;
- virtual QuicTime::Delta SmoothedRtt() OVERRIDE;
- virtual QuicTime::Delta RetransmissionDelay() OVERRIDE;
+ virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
+ virtual QuicTime::Delta SmoothedRtt() const OVERRIDE;
+ virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
// End implementation of SendAlgorithmInterface.
private:
QuicByteCount CongestionWindow();
QuicBandwidth bitrate_;
+ QuicByteCount max_segment_size_;
LeakyBucket fix_rate_leaky_bucket_;
PacedSender paced_sender_;
QuicByteCount data_in_flight_;
diff --git a/chromium/net/quic/congestion_control/fix_rate_test.cc b/chromium/net/quic/congestion_control/fix_rate_test.cc
index e316f6517a7..752d37fe641 100644
--- a/chromium/net/quic/congestion_control/fix_rate_test.cc
+++ b/chromium/net/quic/congestion_control/fix_rate_test.cc
@@ -63,14 +63,14 @@ TEST_F(FixRateTest, SenderAPI) {
EXPECT_EQ(300000, sender_->BandwidthEstimate().ToBytesPerSecond());
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- sender_->SentPacket(clock_.Now(), 1, kMaxPacketSize, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ sender_->OnPacketSent(clock_.Now(), 1, kDefaultMaxPacketSize,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- sender_->SentPacket(clock_.Now(), 2, kMaxPacketSize, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- sender_->SentPacket(clock_.Now(), 3, 600, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ sender_->OnPacketSent(clock_.Now(), 2, kDefaultMaxPacketSize,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ sender_->OnPacketSent(clock_.Now(), 3, 600, NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(QuicTime::Delta::FromMilliseconds(10),
sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
@@ -78,9 +78,9 @@ TEST_F(FixRateTest, SenderAPI) {
EXPECT_EQ(QuicTime::Delta::Infinite(), sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(8));
- sender_->OnIncomingAck(1, kMaxPacketSize, rtt_);
- sender_->OnIncomingAck(2, kMaxPacketSize, rtt_);
- sender_->OnIncomingAck(3, 600, rtt_);
+ sender_->OnPacketAcked(1, kDefaultMaxPacketSize, rtt_);
+ sender_->OnPacketAcked(2, kDefaultMaxPacketSize, rtt_);
+ sender_->OnPacketAcked(3, 600, rtt_);
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
}
@@ -100,18 +100,18 @@ TEST_F(FixRateTest, FixRatePacing) {
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
NOT_HANDSHAKE).IsZero());
- sender_->SentPacket(clock_.Now(), sequence_number++, packet_size,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ sender_->OnPacketSent(clock_.Now(), sequence_number++, packet_size,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
NOT_HANDSHAKE).IsZero());
- sender_->SentPacket(clock_.Now(), sequence_number++, packet_size,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ sender_->OnPacketSent(clock_.Now(), sequence_number++, packet_size,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
QuicTime::Delta advance_time = sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
clock_.AdvanceTime(advance_time);
- sender_->OnIncomingAck(sequence_number - 1, packet_size, rtt_);
- sender_->OnIncomingAck(sequence_number - 2, packet_size, rtt_);
+ sender_->OnPacketAcked(sequence_number - 1, packet_size, rtt_);
+ sender_->OnPacketAcked(sequence_number - 2, packet_size, rtt_);
acc_advance_time = acc_advance_time.Add(advance_time);
}
EXPECT_EQ(num_packets * packet_size * 1000000 / bitrate.ToBytesPerSecond(),
diff --git a/chromium/net/quic/congestion_control/hybrid_slow_start.cc b/chromium/net/quic/congestion_control/hybrid_slow_start.cc
index eee96ad5bb3..0edb10e86ea 100644
--- a/chromium/net/quic/congestion_control/hybrid_slow_start.cc
+++ b/chromium/net/quic/congestion_control/hybrid_slow_start.cc
@@ -4,6 +4,8 @@
#include "net/quic/congestion_control/hybrid_slow_start.h"
+#include <algorithm>
+
namespace net {
// Note(pwestin): the magic clamping numbers come from the original code in
@@ -32,7 +34,7 @@ void HybridSlowStart::Restart() {
}
void HybridSlowStart::Reset(QuicPacketSequenceNumber end_sequence_number) {
- DLOG(INFO) << "Reset hybrid slow start @" << end_sequence_number;
+ DVLOG(1) << "Reset hybrid slow start @" << end_sequence_number;
round_start_ = last_time_ = clock_->ApproximateNow();
end_sequence_number_ = end_sequence_number;
current_rtt_ = QuicTime::Delta::Zero();
diff --git a/chromium/net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc b/chromium/net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc
index 0a15a74dffc..2438493cc0b 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc
+++ b/chromium/net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc
@@ -4,6 +4,8 @@
#include "net/quic/congestion_control/inter_arrival_bitrate_ramp_up.h"
+#include <algorithm>
+
#include "base/basictypes.h"
#include "base/logging.h"
#include "net/quic/congestion_control/cube_root.h"
@@ -56,7 +58,7 @@ void InterArrivalBitrateRampUp::Reset(QuicBandwidth new_rate,
new_rate.Subtract(available_channel_estimate_));
}
current_rate_ = new_rate;
- DLOG(INFO) << "Reset; time to origin point:" << time_to_origin_point_;
+ DVLOG(1) << "Reset; time to origin point:" << time_to_origin_point_;
}
void InterArrivalBitrateRampUp::UpdateChannelEstimate(
@@ -77,7 +79,7 @@ void InterArrivalBitrateRampUp::UpdateChannelEstimate(
channel_estimate_ = channel_estimate;
halfway_point_ = available_channel_estimate_.Add(
(channel_estimate_.Subtract(available_channel_estimate_).Scale(0.5f)));
- DLOG(INFO) << "UpdateChannelEstimate; first usable value:"
+ DVLOG(1) << "UpdateChannelEstimate; first usable value:"
<< channel_estimate.ToKBitsPerSecond() << " Kbits/s";
return;
}
@@ -95,7 +97,7 @@ void InterArrivalBitrateRampUp::UpdateChannelEstimate(
time_to_origin_point_ =
CalcuateTimeToOriginPoint(channel_estimate_.Subtract(current_rate_));
- DLOG(INFO) << "UpdateChannelEstimate; time to origin point:"
+ DVLOG(1) << "UpdateChannelEstimate; time to origin point:"
<< time_to_origin_point_;
}
@@ -117,7 +119,7 @@ QuicBandwidth InterArrivalBitrateRampUp::GetNewBitrate(
// Don't go up in bitrate when we are not sending.
// We need to update the epoch to reflect this state.
epoch_ = epoch_.Add(time_from_last_update);
- DLOG(INFO) << "Don't increase; our sent bitrate is:"
+ DVLOG(1) << "Don't increase; our sent bitrate is:"
<< sent_bitrate.ToKBitsPerSecond() << " Kbits/s"
<< " current target rate is:"
<< current_rate_.ToKBitsPerSecond() << " Kbits/s";
@@ -154,7 +156,7 @@ QuicBandwidth InterArrivalBitrateRampUp::GetNewBitrate(
time_to_origin_point_ =
CalcuateTimeToOriginPoint(channel_estimate_.Subtract(current_rate));
}
- DLOG(INFO) << "Passed the halfway point; time to origin point:"
+ DVLOG(1) << "Passed the halfway point; time to origin point:"
<< time_to_origin_point_;
}
current_rate_ = current_rate;
diff --git a/chromium/net/quic/congestion_control/inter_arrival_overuse_detector.cc b/chromium/net/quic/congestion_control/inter_arrival_overuse_detector.cc
index ea1c3afebfa..5e500b371bc 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_overuse_detector.cc
+++ b/chromium/net/quic/congestion_control/inter_arrival_overuse_detector.cc
@@ -7,6 +7,8 @@
#include <math.h>
#include <stdlib.h>
+#include <algorithm>
+
// Initial noise variance, equal to a standard deviation of 1 millisecond.
static const float kInitialVarianceNoise = 1000000.0;
@@ -63,7 +65,7 @@ void InterArrivalOveruseDetector::OnAcknowledgedPacket(
// This is an old packet and should be ignored. Note that we are called
// with a full 64 bit sequence number, even if the wire format may only
// convey some low-order bits of that number.
- DLOG(INFO) << "Skip old packet";
+ DVLOG(1) << "Skip old packet";
return;
}
@@ -154,7 +156,7 @@ void InterArrivalOveruseDetector::DetectDrift(int64 sigma_delta) {
if (delta_overuse_counter_ > 0 &&
accumulated_deltas_.ToMicroseconds() > kThresholdAccumulatedDeltasUs) {
if (delta_estimate_ != kBandwidthDraining) {
- DLOG(INFO) << "Bandwidth estimate drift: Draining buffer(s) "
+ DVLOG(1) << "Bandwidth estimate drift: Draining buffer(s) "
<< accumulated_deltas_.ToMilliseconds() << " ms";
delta_estimate_ = kBandwidthDraining;
}
@@ -165,7 +167,7 @@ void InterArrivalOveruseDetector::DetectDrift(int64 sigma_delta) {
(sigma_delta * kDetectDriftStandardDeviation >
abs(accumulated_deltas_.ToMicroseconds()))) {
if (delta_estimate_ != kBandwidthSteady) {
- DLOG(INFO) << "Bandwidth estimate drift: Steady"
+ DVLOG(1) << "Bandwidth estimate drift: Steady"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta
<< " offset:" << send_receive_offset_.ToMicroseconds()
@@ -181,7 +183,7 @@ void InterArrivalOveruseDetector::DetectDrift(int64 sigma_delta) {
if (accumulated_deltas_.ToMicroseconds() > 0) {
if (delta_estimate_ != kBandwidthOverUsing) {
++delta_overuse_counter_;
- DLOG(INFO) << "Bandwidth estimate drift: Over using"
+ DVLOG(1) << "Bandwidth estimate drift: Over using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta
<< " offset:" << send_receive_offset_.ToMicroseconds()
@@ -192,7 +194,7 @@ void InterArrivalOveruseDetector::DetectDrift(int64 sigma_delta) {
} else {
if (delta_estimate_ != kBandwidthUnderUsing) {
--delta_overuse_counter_;
- DLOG(INFO) << "Bandwidth estimate drift: Under using"
+ DVLOG(1) << "Bandwidth estimate drift: Under using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta
<< " offset:" << send_receive_offset_.ToMicroseconds()
@@ -217,14 +219,14 @@ void InterArrivalOveruseDetector::DetectSlope(int64 sigma_delta) {
}
if (slope_overuse_counter_ > 0 && delta_mean_ > 0) {
if (slope_estimate_ != kBandwidthDraining) {
- DLOG(INFO) << "Bandwidth estimate slope: Draining buffer(s)";
+ DVLOG(1) << "Bandwidth estimate slope: Draining buffer(s)";
}
slope_estimate_ = kBandwidthDraining;
return;
}
if (sigma_delta > abs(delta_mean_) * kDetectSlopeFactor) {
if (slope_estimate_ != kBandwidthSteady) {
- DLOG(INFO) << "Bandwidth estimate slope: Steady"
+ DVLOG(1) << "Bandwidth estimate slope: Steady"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta;
slope_overuse_counter_ = 0;
@@ -235,7 +237,7 @@ void InterArrivalOveruseDetector::DetectSlope(int64 sigma_delta) {
if (delta_mean_ > 0) {
if (slope_estimate_ != kBandwidthOverUsing) {
++slope_overuse_counter_;
- DLOG(INFO) << "Bandwidth estimate slope: Over using"
+ DVLOG(1) << "Bandwidth estimate slope: Over using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta;
slope_estimate_ = kBandwidthOverUsing;
@@ -243,7 +245,7 @@ void InterArrivalOveruseDetector::DetectSlope(int64 sigma_delta) {
} else {
if (slope_estimate_ != kBandwidthUnderUsing) {
--slope_overuse_counter_;
- DLOG(INFO) << "Bandwidth estimate slope: Under using"
+ DVLOG(1) << "Bandwidth estimate slope: Under using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta;
slope_estimate_ = kBandwidthUnderUsing;
diff --git a/chromium/net/quic/congestion_control/inter_arrival_probe.cc b/chromium/net/quic/congestion_control/inter_arrival_probe.cc
index 6d4c07315d0..6d3af3208fe 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_probe.cc
+++ b/chromium/net/quic/congestion_control/inter_arrival_probe.cc
@@ -16,8 +16,9 @@ const float kUncertainScaleFactor = 0.5; // TODO(pwestin): revisit this factor.
namespace net {
-InterArrivalProbe::InterArrivalProbe()
- : estimate_available_(false),
+InterArrivalProbe::InterArrivalProbe(QuicByteCount max_segment_size)
+ : max_segment_size_(max_segment_size),
+ estimate_available_(false),
available_channel_estimate_(QuicBandwidth::Zero()),
unacked_data_(0) {
}
@@ -25,6 +26,10 @@ InterArrivalProbe::InterArrivalProbe()
InterArrivalProbe::~InterArrivalProbe() {
}
+void InterArrivalProbe::set_max_segment_size(QuicByteCount max_segment_size) {
+ max_segment_size_ = max_segment_size;
+}
+
bool InterArrivalProbe::GetEstimate(QuicBandwidth* available_channel_estimate) {
if (!estimate_available_) {
return false;
@@ -33,7 +38,7 @@ bool InterArrivalProbe::GetEstimate(QuicBandwidth* available_channel_estimate) {
return true;
}
-void InterArrivalProbe::OnSentPacket(QuicByteCount bytes) {
+void InterArrivalProbe::OnPacketSent(QuicByteCount bytes) {
if (!estimate_available_) {
unacked_data_ += bytes;
}
@@ -50,7 +55,7 @@ QuicByteCount InterArrivalProbe::GetAvailableCongestionWindow() {
if (estimate_available_) {
return 0;
}
- return (kProbeSizePackets * kMaxPacketSize) - unacked_data_;
+ return (kProbeSizePackets * max_segment_size_) - unacked_data_;
}
void InterArrivalProbe::OnIncomingFeedback(
@@ -109,7 +114,7 @@ void InterArrivalProbe::OnIncomingFeedback(
}
estimate_available_ = true;
available_channel_estimator_.reset(NULL);
- DLOG(INFO) << "Probe estimate:"
+ DVLOG(1) << "Probe estimate:"
<< available_channel_estimate_.ToKBitsPerSecond()
<< " Kbits/s";
}
diff --git a/chromium/net/quic/congestion_control/inter_arrival_probe.h b/chromium/net/quic/congestion_control/inter_arrival_probe.h
index 5788a68a926..0cba7eec8db 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_probe.h
+++ b/chromium/net/quic/congestion_control/inter_arrival_probe.h
@@ -17,11 +17,13 @@ namespace net {
class NET_EXPORT_PRIVATE InterArrivalProbe {
public:
- InterArrivalProbe();
+ explicit InterArrivalProbe(QuicByteCount max_segment_size);
~InterArrivalProbe();
+ void set_max_segment_size(QuicByteCount max_segment_size);
+
// Call every time a packet is sent to the network.
- void OnSentPacket(QuicByteCount bytes);
+ void OnPacketSent(QuicByteCount bytes);
// Call once for each sent packet that we receive an acknowledgement from
// the peer for.
@@ -45,6 +47,7 @@ class NET_EXPORT_PRIVATE InterArrivalProbe {
bool GetEstimate(QuicBandwidth* available_channel_estimate);
private:
+ QuicByteCount max_segment_size_;
scoped_ptr<AvailableChannelEstimator> available_channel_estimator_;
QuicPacketSequenceNumber first_sequence_number_;
bool estimate_available_;
diff --git a/chromium/net/quic/congestion_control/inter_arrival_probe_test.cc b/chromium/net/quic/congestion_control/inter_arrival_probe_test.cc
index 18b97d33090..d242a6caf4e 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_probe_test.cc
+++ b/chromium/net/quic/congestion_control/inter_arrival_probe_test.cc
@@ -13,7 +13,9 @@ namespace test {
class InterArrivalProbeTest : public ::testing::Test {
protected:
- InterArrivalProbeTest() : start_(QuicTime::Zero()) {
+ InterArrivalProbeTest()
+ : probe_(kDefaultMaxPacketSize),
+ start_(QuicTime::Zero()) {
}
InterArrivalProbe probe_;
@@ -22,19 +24,20 @@ class InterArrivalProbeTest : public ::testing::Test {
TEST_F(InterArrivalProbeTest, CongestionWindow) {
for (size_t i = 0; i < 10; i++) {
- probe_.OnSentPacket(kMaxPacketSize);
- EXPECT_EQ((9 - i) * kMaxPacketSize, probe_.GetAvailableCongestionWindow());
+ probe_.OnPacketSent(kDefaultMaxPacketSize);
+ EXPECT_EQ((9 - i) * kDefaultMaxPacketSize,
+ probe_.GetAvailableCongestionWindow());
}
- probe_.OnAcknowledgedPacket(kMaxPacketSize);
- EXPECT_EQ(kMaxPacketSize, probe_.GetAvailableCongestionWindow());
+ probe_.OnAcknowledgedPacket(kDefaultMaxPacketSize);
+ EXPECT_EQ(kDefaultMaxPacketSize, probe_.GetAvailableCongestionWindow());
- probe_.OnSentPacket(kMaxPacketSize);
+ probe_.OnPacketSent(kDefaultMaxPacketSize);
EXPECT_EQ(0u, probe_.GetAvailableCongestionWindow());
}
TEST_F(InterArrivalProbeTest, Estimate) {
QuicPacketSequenceNumber sequence_number = 1;
- QuicByteCount bytes_sent = kMaxPacketSize;
+ QuicByteCount bytes_sent = kDefaultMaxPacketSize;
QuicTime time_received = start_.Add(QuicTime::Delta::FromMilliseconds(10));
QuicTime time_sent = start_.Add(QuicTime::Delta::FromMilliseconds(1));
QuicBandwidth available_channel_estimate = QuicBandwidth::Zero();
@@ -50,13 +53,13 @@ TEST_F(InterArrivalProbeTest, Estimate) {
time_received = time_received.Add(QuicTime::Delta::FromMilliseconds(10));
}
EXPECT_TRUE(probe_.GetEstimate(&available_channel_estimate));
- EXPECT_EQ(kMaxPacketSize * 100,
+ EXPECT_EQ(kDefaultMaxPacketSize * 100,
static_cast<uint64>(available_channel_estimate.ToBytesPerSecond()));
}
TEST_F(InterArrivalProbeTest, EstimateWithLoss) {
QuicPacketSequenceNumber sequence_number = 1;
- QuicByteCount bytes_sent = kMaxPacketSize;
+ QuicByteCount bytes_sent = kDefaultMaxPacketSize;
QuicTime time_received = start_.Add(QuicTime::Delta::FromMilliseconds(10));
QuicTime time_sent = start_.Add(QuicTime::Delta::FromMilliseconds(1));
QuicBandwidth available_channel_estimate = QuicBandwidth::Zero();
@@ -73,7 +76,7 @@ TEST_F(InterArrivalProbeTest, EstimateWithLoss) {
time_received = time_received.Add(QuicTime::Delta::FromMilliseconds(10));
}
EXPECT_TRUE(probe_.GetEstimate(&available_channel_estimate));
- EXPECT_EQ(kMaxPacketSize * 50,
+ EXPECT_EQ(kDefaultMaxPacketSize * 50,
static_cast<uint64>(available_channel_estimate.ToBytesPerSecond()));
}
diff --git a/chromium/net/quic/congestion_control/inter_arrival_sender.cc b/chromium/net/quic/congestion_control/inter_arrival_sender.cc
index 5640a731ae9..632a41612be 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_sender.cc
+++ b/chromium/net/quic/congestion_control/inter_arrival_sender.cc
@@ -24,15 +24,16 @@ static const int kMinBitrateSmoothingPeriodMs = 500;
InterArrivalSender::InterArrivalSender(const QuicClock* clock)
: probing_(true),
+ max_segment_size_(kDefaultMaxPacketSize),
current_bandwidth_(QuicBandwidth::Zero()),
smoothed_rtt_(QuicTime::Delta::Zero()),
channel_estimator_(new ChannelEstimator()),
bitrate_ramp_up_(new InterArrivalBitrateRampUp(clock)),
overuse_detector_(new InterArrivalOveruseDetector()),
- probe_(new InterArrivalProbe()),
+ probe_(new InterArrivalProbe(max_segment_size_)),
state_machine_(new InterArrivalStateMachine(clock)),
paced_sender_(new PacedSender(QuicBandwidth::FromKBytesPerSecond(
- kProbeBitrateKBytesPerSecond))),
+ kProbeBitrateKBytesPerSecond), max_segment_size_)),
accumulated_number_of_lost_packets_(0),
bandwidth_usage_state_(kBandwidthSteady),
back_down_time_(QuicTime::Zero()),
@@ -43,6 +44,16 @@ InterArrivalSender::InterArrivalSender(const QuicClock* clock)
InterArrivalSender::~InterArrivalSender() {
}
+void InterArrivalSender::SetFromConfig(const QuicConfig& config,
+ bool is_server) {
+}
+
+void InterArrivalSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ max_segment_size_ = max_packet_size;
+ paced_sender_->set_max_segment_size(max_segment_size_);
+ probe_->set_max_segment_size(max_segment_size_);
+}
+
// TODO(pwestin): this is really inefficient (4% CPU on the GFE loadtest).
// static
QuicBandwidth InterArrivalSender::CalculateSentBandwidth(
@@ -62,11 +73,11 @@ QuicBandwidth InterArrivalSender::CalculateSentBandwidth(
QuicTime::Delta max_diff = QuicTime::Delta::Zero();
for (; history_rit != sent_packets_map.rend(); ++history_rit) {
QuicTime::Delta diff =
- feedback_receive_time.Subtract(history_rit->second->SendTimestamp());
+ feedback_receive_time.Subtract(history_rit->second->send_timestamp());
if (diff > kBitrateSmoothingPeriod) {
break;
}
- sum_bytes_sent += history_rit->second->BytesSent();
+ sum_bytes_sent += history_rit->second->bytes_sent();
max_diff = diff;
}
if (max_diff < kMinBitrateSmoothingPeriod) {
@@ -98,13 +109,13 @@ void InterArrivalSender::OnIncomingQuicCongestionFeedbackFrame(
SentPacketsMap::const_iterator sent_it = sent_packets.find(sequence_number);
if (sent_it == sent_packets.end()) {
// Too old data; ignore and move forward.
- DLOG(INFO) << "Too old feedback move forward, sequence_number:"
+ DVLOG(1) << "Too old feedback move forward, sequence_number:"
<< sequence_number;
continue;
}
QuicTime time_received = received_it->second;
- QuicTime time_sent = sent_it->second->SendTimestamp();
- QuicByteCount bytes_sent = sent_it->second->BytesSent();
+ QuicTime time_sent = sent_it->second->send_timestamp();
+ QuicByteCount bytes_sent = sent_it->second->bytes_sent();
channel_estimator_->OnAcknowledgedPacket(
sequence_number, bytes_sent, time_sent, time_received);
@@ -118,7 +129,7 @@ void InterArrivalSender::OnIncomingQuicCongestionFeedbackFrame(
// No more sent packets; hence this must be the last.
last_of_send_time = true;
} else {
- if (time_sent != next_sent_it->second->SendTimestamp()) {
+ if (time_sent != next_sent_it->second->send_timestamp()) {
// Next sent packet have a different send time.
last_of_send_time = true;
}
@@ -189,7 +200,7 @@ bool InterArrivalSender::ProbingPhase(QuicTime feedback_receive_time) {
current_bandwidth_ = new_rate;
paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, new_rate);
- DLOG(INFO) << "Probe result; new rate:"
+ DVLOG(1) << "Probe result; new rate:"
<< new_rate.ToKBitsPerSecond() << " Kbits/s "
<< " available estimate:"
<< available_channel_estimate.ToKBitsPerSecond() << " Kbits/s "
@@ -198,7 +209,7 @@ bool InterArrivalSender::ProbingPhase(QuicTime feedback_receive_time) {
return false;
}
-void InterArrivalSender::OnIncomingAck(
+void InterArrivalSender::OnPacketAcked(
QuicPacketSequenceNumber /*acked_sequence_number*/,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) {
@@ -223,7 +234,9 @@ void InterArrivalSender::OnIncomingAck(
state_machine_->set_rtt(smoothed_rtt_);
}
-void InterArrivalSender::OnIncomingLoss(QuicTime ack_receive_time) {
+void InterArrivalSender::OnPacketLost(
+ QuicPacketSequenceNumber /*sequence_number*/,
+ QuicTime ack_receive_time) {
// Packet loss was reported.
if (!probing_) {
if (!state_machine_->PacketLossEvent()) {
@@ -235,20 +248,24 @@ void InterArrivalSender::OnIncomingLoss(QuicTime ack_receive_time) {
}
}
-bool InterArrivalSender::SentPacket(
+bool InterArrivalSender::OnPacketSent(
QuicTime sent_time,
QuicPacketSequenceNumber sequence_number,
QuicByteCount bytes,
- Retransmission /*is_retransmit*/,
+ TransmissionType /*transmission_type*/,
HasRetransmittableData /*has_retransmittable_data*/) {
if (probing_) {
- probe_->OnSentPacket(bytes);
+ probe_->OnPacketSent(bytes);
}
- paced_sender_->SentPacket(sent_time, bytes);
+ paced_sender_->OnPacketSent(sent_time, bytes);
return true;
}
-void InterArrivalSender::AbandoningPacket(
+void InterArrivalSender::OnRetransmissionTimeout() {
+ // TODO(ianswett): Decrease the available bandwidth.
+}
+
+void InterArrivalSender::OnPacketAbandoned(
QuicPacketSequenceNumber /*sequence_number*/,
QuicByteCount abandoned_bytes) {
// TODO(pwestin): use for out outer_congestion_window_ logic.
@@ -259,7 +276,7 @@ void InterArrivalSender::AbandoningPacket(
QuicTime::Delta InterArrivalSender::TimeUntilSend(
QuicTime now,
- Retransmission /*retransmit*/,
+ TransmissionType /*transmission_type*/,
HasRetransmittableData has_retransmittable_data,
IsHandshake /*handshake*/) {
// TODO(pwestin): implement outer_congestion_window_ logic.
@@ -307,23 +324,27 @@ void InterArrivalSender::EstimateDelayBandwidth(QuicTime feedback_receive_time,
bandwidth_usage_state_ = new_bandwidth_usage_state;
}
-QuicBandwidth InterArrivalSender::BandwidthEstimate() {
+QuicBandwidth InterArrivalSender::BandwidthEstimate() const {
return current_bandwidth_;
}
-QuicTime::Delta InterArrivalSender::SmoothedRtt() {
+QuicTime::Delta InterArrivalSender::SmoothedRtt() const {
if (smoothed_rtt_.IsZero()) {
return QuicTime::Delta::FromMilliseconds(kInitialRttMs);
}
return smoothed_rtt_;
}
-QuicTime::Delta InterArrivalSender::RetransmissionDelay() {
+QuicTime::Delta InterArrivalSender::RetransmissionDelay() const {
// TODO(pwestin): Calculate and return retransmission delay.
// Use 2 * the smoothed RTT for now.
return smoothed_rtt_.Add(smoothed_rtt_);
}
+QuicByteCount InterArrivalSender::GetCongestionWindow() const {
+ return 0;
+}
+
void InterArrivalSender::EstimateNewBandwidth(QuicTime feedback_receive_time,
QuicBandwidth sent_bandwidth) {
QuicBandwidth new_bandwidth = bitrate_ramp_up_->GetNewBitrate(sent_bandwidth);
@@ -342,7 +363,7 @@ void InterArrivalSender::EstimateNewBandwidth(QuicTime feedback_receive_time,
}
paced_sender_->UpdateBandwidthEstimate(feedback_receive_time,
current_bandwidth_);
- DLOG(INFO) << "New bandwidth estimate in steady state:"
+ DVLOG(1) << "New bandwidth estimate in steady state:"
<< current_bandwidth_.ToKBitsPerSecond()
<< " Kbits/s";
}
@@ -354,12 +375,12 @@ void InterArrivalSender::EstimateNewBandwidthAfterDraining(
if (current_bandwidth_ > back_down_bandwidth_) {
// Do nothing, our current bandwidth is higher than our bandwidth at the
// previous back down.
- DLOG(INFO) << "Current bandwidth estimate is higher than before draining";
+ DVLOG(1) << "Current bandwidth estimate is higher than before draining";
return;
}
if (estimated_congestion_delay >= back_down_congestion_delay_) {
// Do nothing, our estimated delay have increased.
- DLOG(INFO) << "Current delay estimate is higher than before draining";
+ DVLOG(1) << "Current delay estimate is higher than before draining";
return;
}
DCHECK(back_down_time_.IsInitialized());
@@ -389,7 +410,7 @@ void InterArrivalSender::EstimateNewBandwidthAfterDraining(
new_estimate = std::max(current_bandwidth_,
current_bandwidth_.Add(draining_rate).Scale(
1.0f - kMinBitrateReduction));
- DLOG(INFO) << "Draining calculation; current rate:"
+ DVLOG(1) << "Draining calculation; current rate:"
<< current_bandwidth_.ToKBitsPerSecond() << " Kbits/s "
<< "draining rate:"
<< draining_rate.ToKBitsPerSecond() << " Kbits/s "
@@ -425,7 +446,7 @@ void InterArrivalSender::EstimateNewBandwidthAfterDraining(
state_machine_->IncreaseBitrateDecision();
paced_sender_->UpdateBandwidthEstimate(feedback_receive_time, new_estimate);
current_bandwidth_ = new_estimate;
- DLOG(INFO) << "New bandwidth estimate after draining:"
+ DVLOG(1) << "New bandwidth estimate after draining:"
<< new_estimate.ToKBitsPerSecond() << " Kbits/s";
}
@@ -452,12 +473,12 @@ void InterArrivalSender::EstimateBandwidthAfterDelayEvent(
// While in delay sensing mode send at least one packet per RTT.
QuicBandwidth min_delay_bitrate =
- QuicBandwidth::FromBytesAndTimeDelta(kMaxPacketSize, SmoothedRtt());
+ QuicBandwidth::FromBytesAndTimeDelta(max_segment_size_, SmoothedRtt());
new_target_bitrate = std::max(new_target_bitrate, min_delay_bitrate);
ResetCurrentBandwidth(feedback_receive_time, new_target_bitrate);
- DLOG(INFO) << "New bandwidth estimate after delay event:"
+ DVLOG(1) << "New bandwidth estimate after delay event:"
<< current_bandwidth_.ToKBitsPerSecond()
<< " Kbits/s min delay bitrate:"
<< min_delay_bitrate.ToKBitsPerSecond()
@@ -470,7 +491,7 @@ void InterArrivalSender::EstimateBandwidthAfterLossEvent(
QuicTime feedback_receive_time) {
ResetCurrentBandwidth(feedback_receive_time,
current_bandwidth_.Scale(kPacketLossBitrateReduction));
- DLOG(INFO) << "New bandwidth estimate after loss event:"
+ DVLOG(1) << "New bandwidth estimate after loss event:"
<< current_bandwidth_.ToKBitsPerSecond()
<< " Kbits/s";
}
diff --git a/chromium/net/quic/congestion_control/inter_arrival_sender.h b/chromium/net/quic/congestion_control/inter_arrival_sender.h
index 2c455cc9d13..fabc7b65e34 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_sender.h
+++ b/chromium/net/quic/congestion_control/inter_arrival_sender.h
@@ -32,36 +32,35 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface {
QuicTime feedback_receive_time);
// Start implementation of SendAlgorithmInterface.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
-
- virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
+ virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) OVERRIDE;
-
- virtual void OnIncomingLoss(QuicTime ack_receive_time) OVERRIDE;
-
- virtual bool SentPacket(
+ virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
+ QuicTime ack_receive_time) OVERRIDE;
+ virtual bool OnPacketSent(
QuicTime sent_time,
QuicPacketSequenceNumber sequence_number,
QuicByteCount bytes,
- Retransmission is_retransmit,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) OVERRIDE;
-
- virtual void AbandoningPacket(QuicPacketSequenceNumber sequence_number,
- QuicByteCount abandoned_bytes) OVERRIDE;
-
+ virtual void OnRetransmissionTimeout() OVERRIDE;
+ virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
+ QuicByteCount abandoned_bytes) OVERRIDE;
virtual QuicTime::Delta TimeUntilSend(
QuicTime now,
- Retransmission is_retransmission,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data,
IsHandshake handshake) OVERRIDE;
-
- virtual QuicBandwidth BandwidthEstimate() OVERRIDE;
- virtual QuicTime::Delta SmoothedRtt() OVERRIDE;
- virtual QuicTime::Delta RetransmissionDelay() OVERRIDE;
+ virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
+ virtual QuicTime::Delta SmoothedRtt() const OVERRIDE;
+ virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
// End implementation of SendAlgorithmInterface.
private:
@@ -81,6 +80,7 @@ class NET_EXPORT_PRIVATE InterArrivalSender : public SendAlgorithmInterface {
bool ProbingPhase(QuicTime feedback_receive_time);
bool probing_; // Are we currently in the probing phase?
+ QuicByteCount max_segment_size_;
QuicBandwidth current_bandwidth_;
QuicTime::Delta smoothed_rtt_;
scoped_ptr<ChannelEstimator> channel_estimator_;
diff --git a/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc b/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc
index 7392b1a3a67..fe8dd3cf29f 100644
--- a/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc
+++ b/chromium/net/quic/congestion_control/inter_arrival_sender_test.cc
@@ -2,13 +2,16 @@
// 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/inter_arrival_sender.h"
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
-#include "net/quic/congestion_control/inter_arrival_sender.h"
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using std::pair;
+
namespace net {
namespace test {
@@ -35,13 +38,13 @@ class InterArrivalSenderTest : public ::testing::Test {
void SendAvailableCongestionWindow() {
while (sender_.TimeUntilSend(send_clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero()) {
- QuicByteCount bytes_in_packet = kMaxPacketSize;
+ QuicByteCount bytes_in_packet = kDefaultMaxPacketSize;
sent_packets_[sequence_number_] =
new class SendAlgorithmInterface::SentPacket(
- bytes_in_packet, send_clock_.Now());
+ bytes_in_packet, send_clock_.Now(), HAS_RETRANSMITTABLE_DATA);
- sender_.SentPacket(send_clock_.Now(), sequence_number_, bytes_in_packet,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ sender_.OnPacketSent(send_clock_.Now(), sequence_number_, bytes_in_packet,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
sequence_number_++;
}
EXPECT_FALSE(sender_.TimeUntilSend(send_clock_.Now(),
@@ -50,7 +53,8 @@ class InterArrivalSenderTest : public ::testing::Test {
void AckNPackets(int n) {
for (int i = 0; i < n; ++i) {
- sender_.OnIncomingAck(acked_sequence_number_++, kMaxPacketSize, rtt_);
+ sender_.OnPacketAcked(
+ acked_sequence_number_++, kDefaultMaxPacketSize, rtt_);
}
}
@@ -61,14 +65,14 @@ class InterArrivalSenderTest : public ::testing::Test {
receive_clock_.AdvanceTime(spike_time);
QuicTime receive_time = receive_clock_.ApproximateNow();
feedback.inter_arrival.received_packet_times.insert(
- std::pair<QuicPacketSequenceNumber, QuicTime>(
+ pair<QuicPacketSequenceNumber, QuicTime>(
feedback_sequence_number_, receive_time));
feedback_sequence_number_++;
// We need to send feedback for 2 packets since they where sent at the
// same time.
feedback.inter_arrival.received_packet_times.insert(
- std::pair<QuicPacketSequenceNumber, QuicTime>(
+ pair<QuicPacketSequenceNumber, QuicTime>(
feedback_sequence_number_, receive_time));
feedback_sequence_number_++;
@@ -90,7 +94,7 @@ class InterArrivalSenderTest : public ::testing::Test {
}
QuicTime receive_time = receive_clock_.ApproximateNow();
feedback.inter_arrival.received_packet_times.insert(
- std::pair<QuicPacketSequenceNumber, QuicTime>(
+ pair<QuicPacketSequenceNumber, QuicTime>(
feedback_sequence_number_, receive_time));
feedback_sequence_number_++;
}
@@ -145,7 +149,7 @@ TEST_F(InterArrivalSenderTest, ProbeFollowedByFullRampUpCycle) {
// We should now have our probe rate.
QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(41);
- int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond /
+ int64 probe_rate = kDefaultMaxPacketSize * 9 * kNumMicrosPerSecond /
acc_arrival_time.ToMicroseconds();
EXPECT_NEAR(0.7f * probe_rate,
sender_.BandwidthEstimate().ToBytesPerSecond(), 1000);
@@ -257,7 +261,7 @@ TEST_F(InterArrivalSenderTest, ProbeFollowedByFullRampUpCycle) {
sender_.BandwidthEstimate().ToBytesPerSecond(), 2000);
EXPECT_NEAR(SenderDeltaSinceStart().ToMilliseconds(), 3400, 100);
- int64 max_rate = kMaxPacketSize * kNumMicrosPerSecond /
+ int64 max_rate = kDefaultMaxPacketSize * kNumMicrosPerSecond /
one_ms_.ToMicroseconds();
int64 halfway_rate = probe_rate + (max_rate - probe_rate) / 2;
@@ -323,7 +327,7 @@ TEST_F(InterArrivalSenderTest, DelaySpikeFollowedBySlowDrain) {
// We should now have our probe rate.
QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(41);
- int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond /
+ int64 probe_rate = kDefaultMaxPacketSize * 9 * kNumMicrosPerSecond /
acc_arrival_time.ToMicroseconds();
EXPECT_NEAR(0.7f * probe_rate,
sender_.BandwidthEstimate().ToBytesPerSecond(), 1000);
@@ -420,7 +424,7 @@ TEST_F(InterArrivalSenderTest, DelaySpikeFollowedByImmediateDrain) {
// We should now have our probe rate.
QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(41);
- int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond /
+ int64 probe_rate = kDefaultMaxPacketSize * 9 * kNumMicrosPerSecond /
acc_arrival_time.ToMicroseconds();
EXPECT_NEAR(0.7f * probe_rate,
sender_.BandwidthEstimate().ToBytesPerSecond(), 1000);
@@ -524,7 +528,7 @@ TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) {
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
QuicTime::Delta acc_arrival_time = QuicTime::Delta::FromMilliseconds(81);
- int64 probe_rate = kMaxPacketSize * 9 * kNumMicrosPerSecond /
+ int64 probe_rate = kDefaultMaxPacketSize * 9 * kNumMicrosPerSecond /
acc_arrival_time.ToMicroseconds();
EXPECT_NEAR(0.7f * probe_rate,
sender_.BandwidthEstimate().ToBytesPerSecond(), 1000);
@@ -536,8 +540,8 @@ TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) {
send_clock_.AdvanceTime(time_until_send);
EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- sender_.OnIncomingLoss(send_clock_.Now());
- sender_.OnIncomingAck(acked_sequence_number_, kMaxPacketSize, rtt_);
+ sender_.OnPacketLost(acked_sequence_number_ - 1, send_clock_.Now());
+ sender_.OnPacketAcked(acked_sequence_number_, kDefaultMaxPacketSize, rtt_);
acked_sequence_number_ += 2; // Create a loss by not acking both packets.
SendFeedbackMessageNPackets(2, nine_ms_, nine_ms_);
}
@@ -551,8 +555,8 @@ TEST_F(InterArrivalSenderTest, MinBitrateDueToLoss) {
send_clock_.AdvanceTime(time_until_send);
EXPECT_TRUE(sender_.TimeUntilSend(send_clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- sender_.OnIncomingLoss(send_clock_.Now());
- sender_.OnIncomingAck(acked_sequence_number_, kMaxPacketSize, rtt_);
+ sender_.OnPacketLost(acked_sequence_number_ - 1, send_clock_.Now());
+ sender_.OnPacketAcked(acked_sequence_number_, kDefaultMaxPacketSize, rtt_);
acked_sequence_number_ += 2; // Create a loss by not acking both packets.
SendFeedbackMessageNPackets(2, nine_ms_, nine_ms_);
diff --git a/chromium/net/quic/congestion_control/paced_sender.cc b/chromium/net/quic/congestion_control/paced_sender.cc
index dd116a80955..9a5cc448962 100644
--- a/chromium/net/quic/congestion_control/paced_sender.cc
+++ b/chromium/net/quic/congestion_control/paced_sender.cc
@@ -4,6 +4,8 @@
#include "net/quic/congestion_control/paced_sender.h"
+#include <algorithm>
+
#include "net/quic/quic_protocol.h"
namespace net {
@@ -14,9 +16,14 @@ const int64 kMinPacketBurstSize = 2;
// AvailableCongestionWindow.
const int64 kMaxSchedulingDelayUs = 2000;
-PacedSender::PacedSender(QuicBandwidth estimate)
+PacedSender::PacedSender(QuicBandwidth estimate, QuicByteCount max_segment_size)
: leaky_bucket_(estimate),
- pace_(estimate) {
+ pace_(estimate),
+ max_segment_size_(kDefaultMaxPacketSize) {
+}
+
+void PacedSender::set_max_segment_size(QuicByteCount max_segment_size) {
+ max_segment_size_ = max_segment_size;
}
void PacedSender::UpdateBandwidthEstimate(QuicTime now,
@@ -25,7 +32,7 @@ void PacedSender::UpdateBandwidthEstimate(QuicTime now,
pace_ = estimate;
}
-void PacedSender::SentPacket(QuicTime now, QuicByteCount bytes) {
+void PacedSender::OnPacketSent(QuicTime now, QuicByteCount bytes) {
leaky_bucket_.Add(now, bytes);
}
@@ -37,7 +44,7 @@ QuicTime::Delta PacedSender::TimeUntilSend(QuicTime now,
// Pace the data.
QuicByteCount pacing_window = pace_.ToBytesPerPeriod(
QuicTime::Delta::FromMicroseconds(kMaxSchedulingDelayUs));
- QuicByteCount min_window_size = kMinPacketBurstSize * kMaxPacketSize;
+ QuicByteCount min_window_size = kMinPacketBurstSize * max_segment_size_;
pacing_window = std::max(pacing_window, min_window_size);
if (pacing_window > leaky_bucket_.BytesPending(now)) {
diff --git a/chromium/net/quic/congestion_control/paced_sender.h b/chromium/net/quic/congestion_control/paced_sender.h
index 5f61b76f0ab..6d7c42919d0 100644
--- a/chromium/net/quic/congestion_control/paced_sender.h
+++ b/chromium/net/quic/congestion_control/paced_sender.h
@@ -17,13 +17,15 @@ namespace net {
class NET_EXPORT_PRIVATE PacedSender {
public:
- explicit PacedSender(QuicBandwidth bandwidth_estimate);
+ PacedSender(QuicBandwidth bandwidth_estimate, QuicByteCount max_segment_size);
+
+ void set_max_segment_size(QuicByteCount max_segment_size);
// The estimated bandidth from the congestion algorithm changed.
void UpdateBandwidthEstimate(QuicTime now, QuicBandwidth bandwidth_estimate);
// A packet of size bytes was sent.
- void SentPacket(QuicTime now, QuicByteCount bytes);
+ void OnPacketSent(QuicTime now, QuicByteCount bytes);
// Return time until we can send based on the pacing.
QuicTime::Delta TimeUntilSend(QuicTime now, QuicTime::Delta time_until_send);
@@ -32,6 +34,7 @@ class NET_EXPORT_PRIVATE PacedSender {
// Helper object to track the rate data can leave the buffer for pacing.
LeakyBucket leaky_bucket_;
QuicBandwidth pace_;
+ QuicByteCount max_segment_size_;
DISALLOW_COPY_AND_ASSIGN(PacedSender);
};
diff --git a/chromium/net/quic/congestion_control/paced_sender_test.cc b/chromium/net/quic/congestion_control/paced_sender_test.cc
index cc9297f8af3..fa42c2ce579 100644
--- a/chromium/net/quic/congestion_control/paced_sender_test.cc
+++ b/chromium/net/quic/congestion_control/paced_sender_test.cc
@@ -20,7 +20,8 @@ class PacedSenderTest : public ::testing::Test {
PacedSenderTest()
: zero_time_(QuicTime::Delta::Zero()),
paced_sender_(new PacedSender(
- QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS))) {
+ QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS),
+ kDefaultMaxPacketSize)) {
}
const QuicTime::Delta zero_time_;
@@ -32,10 +33,10 @@ TEST_F(PacedSenderTest, Basic) {
paced_sender_->UpdateBandwidthEstimate(clock_.Now(),
QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS * 10));
EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
- paced_sender_->SentPacket(clock_.Now(), kMaxPacketSize);
+ paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
- paced_sender_->SentPacket(clock_.Now(), kMaxPacketSize);
- EXPECT_EQ(static_cast<int64>(kMaxPacketSize * 2),
+ paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
+ EXPECT_EQ(static_cast<int64>(kDefaultMaxPacketSize * 2),
paced_sender_->TimeUntilSend(
clock_.Now(), zero_time_).ToMicroseconds());
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(24));
@@ -46,10 +47,10 @@ TEST_F(PacedSenderTest, LowRate) {
paced_sender_->UpdateBandwidthEstimate(clock_.Now(),
QuicBandwidth::FromKBytesPerSecond(kHundredKBytesPerS));
EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
- paced_sender_->SentPacket(clock_.Now(), kMaxPacketSize);
+ paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
- paced_sender_->SentPacket(clock_.Now(), kMaxPacketSize);
- EXPECT_EQ(static_cast<int64>(kMaxPacketSize * 20),
+ paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
+ EXPECT_EQ(static_cast<int64>(kDefaultMaxPacketSize * 20),
paced_sender_->TimeUntilSend(
clock_.Now(), zero_time_).ToMicroseconds());
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(24));
@@ -62,11 +63,11 @@ TEST_F(PacedSenderTest, HighRate) {
paced_sender_->UpdateBandwidthEstimate(clock_.Now(), bandwidth_estimate);
EXPECT_TRUE(paced_sender_->TimeUntilSend(clock_.Now(), zero_time_).IsZero());
for (int i = 0; i < 16; ++i) {
- paced_sender_->SentPacket(clock_.Now(), kMaxPacketSize);
+ paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
EXPECT_TRUE(paced_sender_->TimeUntilSend(
clock_.Now(), zero_time_).IsZero());
}
- paced_sender_->SentPacket(clock_.Now(), kMaxPacketSize);
+ paced_sender_->OnPacketSent(clock_.Now(), kDefaultMaxPacketSize);
EXPECT_EQ(2040, paced_sender_->TimeUntilSend(
clock_.Now(), zero_time_).ToMicroseconds());
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(20400));
diff --git a/chromium/net/quic/congestion_control/pacing_sender.cc b/chromium/net/quic/congestion_control/pacing_sender.cc
new file mode 100644
index 00000000000..a20e7522750
--- /dev/null
+++ b/chromium/net/quic/congestion_control/pacing_sender.cc
@@ -0,0 +1,138 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/pacing_sender.h"
+
+namespace net {
+
+PacingSender::PacingSender(SendAlgorithmInterface* sender,
+ QuicTime::Delta alarm_granularity)
+ : sender_(sender),
+ alarm_granularity_(alarm_granularity),
+ next_packet_send_time_(QuicTime::Zero()),
+ was_last_send_delayed_(false),
+ max_segment_size_(kDefaultMaxPacketSize) {
+}
+
+PacingSender::~PacingSender() {}
+
+void PacingSender::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ max_segment_size_ = max_packet_size;
+ sender_->SetMaxPacketSize(max_packet_size);
+}
+
+void PacingSender::SetFromConfig(const QuicConfig& config, bool is_server) {
+ sender_->SetFromConfig(config, is_server);
+}
+
+void PacingSender::OnIncomingQuicCongestionFeedbackFrame(
+ const QuicCongestionFeedbackFrame& feedback,
+ QuicTime feedback_receive_time,
+ const SendAlgorithmInterface::SentPacketsMap& sent_packets) {
+ sender_->OnIncomingQuicCongestionFeedbackFrame(
+ feedback, feedback_receive_time, sent_packets);
+}
+
+void PacingSender::OnPacketAcked(
+ QuicPacketSequenceNumber acked_sequence_number,
+ QuicByteCount acked_bytes,
+ QuicTime::Delta rtt) {
+ sender_->OnPacketAcked(acked_sequence_number, acked_bytes, rtt);
+}
+
+void PacingSender::OnPacketLost(QuicPacketSequenceNumber sequence_number,
+ QuicTime ack_receive_time) {
+ sender_->OnPacketLost(sequence_number, ack_receive_time);
+}
+
+bool PacingSender::OnPacketSent(
+ QuicTime sent_time,
+ QuicPacketSequenceNumber sequence_number,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData has_retransmittable_data) {
+ // Only pace data packets.
+ if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) {
+ // The next packet should be sent as soon as the current packets has
+ // been transferred. We pace at twice the rate of the underlying
+ // sender's bandwidth estimate to help ensure that pacing doesn't become
+ // a bottleneck.
+ const float kPacingAggression = 2;
+ QuicTime::Delta delay =
+ BandwidthEstimate().Scale(kPacingAggression).TransferTime(bytes);
+ next_packet_send_time_ = next_packet_send_time_.Add(delay);
+ }
+ return sender_->OnPacketSent(sent_time, sequence_number, bytes,
+ transmission_type, has_retransmittable_data);
+}
+
+void PacingSender::OnRetransmissionTimeout() {
+ sender_->OnRetransmissionTimeout();
+}
+
+void PacingSender::OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
+ QuicByteCount abandoned_bytes) {
+ sender_->OnPacketAbandoned(sequence_number, abandoned_bytes);
+}
+
+QuicTime::Delta PacingSender::TimeUntilSend(
+ QuicTime now,
+ TransmissionType transmission_type,
+ HasRetransmittableData has_retransmittable_data,
+ IsHandshake handshake) {
+ QuicTime::Delta time_until_send =
+ sender_->TimeUntilSend(now, transmission_type,
+ has_retransmittable_data, handshake);
+ if (!time_until_send.IsZero()) {
+ DCHECK(time_until_send.IsInfinite());
+ // The underlying sender prevents sending.
+ 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 (!was_last_send_delayed_ &&
+ (!next_packet_send_time_.IsInitialized() ||
+ now > next_packet_send_time_.Add(alarm_granularity_))) {
+ // An alarm did not go off late, instead the application is "slow"
+ // delivering data. In this case, we restrict the amount of lost time
+ // that we can make up for.
+ next_packet_send_time_ = now.Subtract(alarm_granularity_);
+ }
+
+ // If the end of the epoch is far enough in the future, delay the send.
+ if (next_packet_send_time_ > now.Add(alarm_granularity_)) {
+ was_last_send_delayed_ = true;
+ DVLOG(1) << "Delaying packet: "
+ << next_packet_send_time_.Subtract(now).ToMicroseconds();
+ return next_packet_send_time_.Subtract(now);
+ }
+
+ // Sent it immediately. The epoch end will be adjusted in OnPacketSent.
+ was_last_send_delayed_ = false;
+ DVLOG(1) << "Sending packet now";
+ return QuicTime::Delta::Zero();
+}
+
+QuicBandwidth PacingSender::BandwidthEstimate() const {
+ return sender_->BandwidthEstimate();
+}
+
+QuicTime::Delta PacingSender::SmoothedRtt() const {
+ return sender_->SmoothedRtt();
+}
+
+QuicTime::Delta PacingSender::RetransmissionDelay() const {
+ return sender_->RetransmissionDelay();
+}
+
+QuicByteCount PacingSender::GetCongestionWindow() const {
+ return sender_->GetCongestionWindow();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/congestion_control/pacing_sender.h b/chromium/net/quic/congestion_control/pacing_sender.h
new file mode 100644
index 00000000000..92970b93ce9
--- /dev/null
+++ b/chromium/net/quic/congestion_control/pacing_sender.h
@@ -0,0 +1,77 @@
+// 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.
+//
+// A send algorithm which adds pacing on top of an another send algorithm.
+// It uses the underlying sender's bandwidth estimate to determine the
+// pacing rate to be used. It also takes into consideration the expected
+// resolution of the underlying alarm mechanism to ensure that alarms are
+// not set too aggressively, and to smooth out variations.
+
+#ifndef NET_QUIC_CONGESTION_CONTROL_PACING_SENDER_H_
+#define NET_QUIC_CONGESTION_CONTROL_PACING_SENDER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/quic_bandwidth.h"
+#include "net/quic/quic_clock.h"
+#include "net/quic/quic_config.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+class NET_EXPORT_PRIVATE PacingSender : public SendAlgorithmInterface {
+ public:
+ PacingSender(SendAlgorithmInterface* sender,
+ QuicTime::Delta alarm_granularity);
+ virtual ~PacingSender();
+
+ // SendAlgorithmInterface methods.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
+ virtual void OnIncomingQuicCongestionFeedbackFrame(
+ const QuicCongestionFeedbackFrame& feedback,
+ QuicTime feedback_receive_time,
+ const SendAlgorithmInterface::SentPacketsMap& sent_packets) OVERRIDE;
+ virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
+ QuicByteCount acked_bytes,
+ QuicTime::Delta rtt) OVERRIDE;
+ virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
+ QuicTime ack_receive_time) OVERRIDE;
+ virtual bool OnPacketSent(QuicTime sent_time,
+ QuicPacketSequenceNumber sequence_number,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData is_retransmittable) OVERRIDE;
+ virtual void OnRetransmissionTimeout() OVERRIDE;
+ virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
+ QuicByteCount abandoned_bytes) OVERRIDE;
+ virtual QuicTime::Delta TimeUntilSend(
+ QuicTime now,
+ TransmissionType transmission_type,
+ HasRetransmittableData has_retransmittable_data,
+ IsHandshake handshake) OVERRIDE;
+ virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
+ virtual QuicTime::Delta SmoothedRtt() const OVERRIDE;
+ virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
+
+ private:
+ QuicTime::Delta GetTransferTime(QuicByteCount bytes);
+
+ scoped_ptr<SendAlgorithmInterface> sender_; // Underlying sender.
+ QuicTime::Delta alarm_granularity_;
+ QuicTime next_packet_send_time_; // When can the next packet be sent.
+ bool was_last_send_delayed_; // True when the last send was delayed.
+ QuicByteCount max_segment_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PacingSender);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CONGESTION_CONTROL_PACING_SENDER_H_
diff --git a/chromium/net/quic/congestion_control/pacing_sender_test.cc b/chromium/net/quic/congestion_control/pacing_sender_test.cc
new file mode 100644
index 00000000000..dfc78b84ece
--- /dev/null
+++ b/chromium/net/quic/congestion_control/pacing_sender_test.cc
@@ -0,0 +1,168 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/congestion_control/pacing_sender.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::StrictMock;
+
+namespace net {
+namespace test {
+
+class PacingSenderTest : public ::testing::Test {
+ protected:
+ PacingSenderTest()
+ : zero_time_(QuicTime::Delta::Zero()),
+ infinite_time_(QuicTime::Delta::Infinite()),
+ sequence_number_(1),
+ mock_sender_(new StrictMock<MockSendAlgorithm>()),
+ pacing_sender_(new PacingSender(mock_sender_,
+ QuicTime::Delta::FromMilliseconds(1))) {
+ // Pick arbitrary time.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(9));
+ }
+
+ virtual ~PacingSenderTest() {}
+
+ void CheckPacketIsSentImmediately() {
+ // In order for the packet to be sendable, the underlying sender must
+ // permit it to be sent immediately.
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE))
+ .WillOnce(Return(zero_time_));
+ // Verify that the packet can be sent immediately.
+ EXPECT_EQ(zero_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE));
+
+ // Actually send the packet.
+ EXPECT_CALL(*mock_sender_,
+ OnPacketSent(clock_.Now(), sequence_number_, kMaxPacketSize,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA));
+ pacing_sender_->OnPacketSent(clock_.Now(), sequence_number_++,
+ kMaxPacketSize, NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
+ }
+
+ void CheckAckIsSentImmediately() {
+ // In order for the ack to be sendable, the underlying sender must
+ // permit it to be sent immediately.
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE))
+ .WillOnce(Return(zero_time_));
+ // Verify that the ACK can be sent immediately.
+ EXPECT_EQ(zero_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE));
+
+ // Actually send the packet.
+ EXPECT_CALL(*mock_sender_,
+ OnPacketSent(clock_.Now(), sequence_number_, kMaxPacketSize,
+ NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA));
+ pacing_sender_->OnPacketSent(clock_.Now(), sequence_number_++,
+ kMaxPacketSize, NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA);
+ }
+
+ void CheckPacketIsDelayed(QuicTime::Delta delay) {
+ // In order for the packet to be sendable, the underlying sender must
+ // permit it to be sent immediately.
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE))
+ .WillOnce(Return(zero_time_));
+ // Verify that the packet is delayed.
+ EXPECT_EQ(delay.ToMicroseconds(),
+ pacing_sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE).ToMicroseconds());
+ }
+
+ const QuicTime::Delta zero_time_;
+ const QuicTime::Delta infinite_time_;
+ MockClock clock_;
+ QuicPacketSequenceNumber sequence_number_;
+ StrictMock<MockSendAlgorithm>* mock_sender_;
+ scoped_ptr<PacingSender> pacing_sender_;
+};
+
+TEST_F(PacingSenderTest, NoSend) {
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE))
+ .WillOnce(Return(infinite_time_));
+ EXPECT_EQ(infinite_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE));
+}
+
+TEST_F(PacingSenderTest, SendNow) {
+ EXPECT_CALL(*mock_sender_, TimeUntilSend(clock_.Now(),
+ NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE))
+ .WillOnce(Return(zero_time_));
+ EXPECT_EQ(zero_time_,
+ pacing_sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA,
+ NOT_HANDSHAKE));
+}
+
+TEST_F(PacingSenderTest, VariousSending) {
+ // Configure bandwith of 1 packet per 2 ms, for which the pacing rate
+ // will be 1 packet per 1 ms.
+ EXPECT_CALL(*mock_sender_, BandwidthEstimate())
+ .WillRepeatedly(Return(QuicBandwidth::FromBytesAndTimeDelta(
+ kMaxPacketSize, QuicTime::Delta::FromMilliseconds(2))));
+
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+
+ // The first packet was a "make up", then we sent two packets "into the
+ // future", so the delay should be 2.
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+ // Wake up on time.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+ CheckAckIsSentImmediately();
+
+ // Wake up late.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(4));
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsSentImmediately();
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+ // Wake up too early.
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+
+ // Wake up early, but after enough time has passed to permit a send.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+ CheckPacketIsSentImmediately();
+ CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/congestion_control/quic_congestion_control_test.cc b/chromium/net/quic/congestion_control/quic_congestion_control_test.cc
deleted file mode 100644
index 457538f4552..00000000000
--- a/chromium/net/quic/congestion_control/quic_congestion_control_test.cc
+++ /dev/null
@@ -1,140 +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.
-
-// Test of the full congestion control chain.
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/quic/congestion_control/quic_congestion_manager.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/test_tools/mock_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using std::max;
-
-namespace net {
-namespace test {
-
-class QuicCongestionManagerPeer : public QuicCongestionManager {
- public:
- explicit QuicCongestionManagerPeer(const QuicClock* clock,
- CongestionFeedbackType congestion_type)
- : QuicCongestionManager(clock, congestion_type) {
- }
- using QuicCongestionManager::BandwidthEstimate;
-};
-
-class QuicCongestionControlTest : public ::testing::Test {
- protected:
- QuicCongestionControlTest()
- : start_(clock_.ApproximateNow()) {
- }
-
- void SetUpCongestionType(CongestionFeedbackType congestion_type) {
- manager_.reset(new QuicCongestionManagerPeer(&clock_, congestion_type));
- }
-
- MockClock clock_;
- QuicTime start_;
- scoped_ptr<QuicCongestionManagerPeer> manager_;
-};
-
-TEST_F(QuicCongestionControlTest, FixedRateSenderAPI) {
- SetUpCongestionType(kFixRate);
- QuicCongestionFeedbackFrame congestion_feedback;
- congestion_feedback.type = kFixRate;
- congestion_feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(30);
- manager_->OnIncomingQuicCongestionFeedbackFrame(congestion_feedback,
- clock_.Now());
- EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(1, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(40),
- manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(35));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- EXPECT_EQ(QuicTime::Delta::Infinite(),
- manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE));
-}
-
-TEST_F(QuicCongestionControlTest, FixedRatePacing) {
- SetUpCongestionType(kFixRate);
- QuicAckFrame ack;
- ack.received_info.largest_observed = 0;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
-
- QuicCongestionFeedbackFrame feedback;
- feedback.type = kFixRate;
- feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(100);
- manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
-
- QuicTime acc_advance_time(QuicTime::Zero());
- for (QuicPacketSequenceNumber i = 1; i <= 100; ++i) {
- EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(i, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- QuicTime::Delta advance_time = manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
- clock_.AdvanceTime(advance_time);
- acc_advance_time = acc_advance_time.Add(advance_time);
- // Ack the packet we sent.
- ack.received_info.largest_observed = max(
- i, ack.received_info.largest_observed);
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- }
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1200),
- acc_advance_time.Subtract(start_));
-}
-
-TEST_F(QuicCongestionControlTest, Pacing) {
- SetUpCongestionType(kFixRate);
- QuicAckFrame ack;
- ack.received_info.largest_observed = 0;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
-
- QuicCongestionFeedbackFrame feedback;
- feedback.type = kFixRate;
- // Test a high bitrate (8Mbit/s) to trigger pacing.
- feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(1000);
- manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
-
- QuicTime acc_advance_time(QuicTime::Zero());
- for (QuicPacketSequenceNumber i = 1; i <= 100;) {
- EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(i++, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- EXPECT_TRUE(manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(i++, clock_.Now(), kMaxPacketSize, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- QuicTime::Delta advance_time = manager_->TimeUntilSend(clock_.Now(),
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
- clock_.AdvanceTime(advance_time);
- acc_advance_time = acc_advance_time.Add(advance_time);
- // Ack the packets we sent.
- ack.received_info.largest_observed = max(
- i - 2, ack.received_info.largest_observed);
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- ack.received_info.largest_observed = max(
- i - 1, ack.received_info.largest_observed);
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- }
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(120),
- acc_advance_time.Subtract(start_));
-}
-
-// TODO(pwestin): add TCP tests.
-
-// TODO(pwestin): add InterArrival tests.
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/quic_congestion_manager.cc b/chromium/net/quic/congestion_control/quic_congestion_manager.cc
deleted file mode 100644
index ec519db7c93..00000000000
--- a/chromium/net/quic/congestion_control/quic_congestion_manager.cc
+++ /dev/null
@@ -1,234 +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/quic_congestion_manager.h"
-
-#include <algorithm>
-#include <map>
-
-#include "base/stl_util.h"
-#include "net/quic/congestion_control/receive_algorithm_interface.h"
-#include "net/quic/congestion_control/send_algorithm_interface.h"
-
-namespace {
-static const int kBitrateSmoothingPeriodMs = 1000;
-static const int kHistoryPeriodMs = 5000;
-
-static const int kDefaultRetransmissionTimeMs = 500;
-// TCP RFC calls for 1 second RTO however Linux differs from this default and
-// define the minimum RTO to 200ms, we will use the same until we have data to
-// support a higher or lower value.
-static const int kMinRetransmissionTimeMs = 200;
-static const int kMaxRetransmissionTimeMs = 60000;
-static const size_t kMaxRetransmissions = 10;
-static const size_t kTailDropWindowSize = 5;
-static const size_t kTailDropMaxRetransmissions = 4;
-
-COMPILE_ASSERT(kHistoryPeriodMs >= kBitrateSmoothingPeriodMs,
- history_must_be_longer_or_equal_to_the_smoothing_period);
-} // namespace
-
-using std::map;
-using std::min;
-
-namespace net {
-
-QuicCongestionManager::QuicCongestionManager(
- const QuicClock* clock,
- CongestionFeedbackType type)
- : clock_(clock),
- receive_algorithm_(ReceiveAlgorithmInterface::Create(clock, type)),
- send_algorithm_(SendAlgorithmInterface::Create(clock, type)),
- largest_missing_(0),
- current_rtt_(QuicTime::Delta::Infinite()) {
-}
-
-QuicCongestionManager::~QuicCongestionManager() {
- STLDeleteValues(&packet_history_map_);
-}
-
-void QuicCongestionManager::SentPacket(
- QuicPacketSequenceNumber sequence_number,
- QuicTime sent_time,
- QuicByteCount bytes,
- Retransmission retransmission,
- HasRetransmittableData has_retransmittable_data) {
- DCHECK(!ContainsKey(pending_packets_, sequence_number));
-
- if (send_algorithm_->SentPacket(sent_time, sequence_number, bytes,
- retransmission, has_retransmittable_data)) {
- packet_history_map_[sequence_number] =
- new class SendAlgorithmInterface::SentPacket(bytes, sent_time);
- pending_packets_[sequence_number] = bytes;
- CleanupPacketHistory();
- }
-}
-
-// Called when a packet is timed out.
-void QuicCongestionManager::AbandoningPacket(
- QuicPacketSequenceNumber sequence_number) {
- PendingPacketsMap::iterator it = pending_packets_.find(sequence_number);
- if (it != pending_packets_.end()) {
- // Shouldn't this report loss as well? (decrease cgst window).
- send_algorithm_->AbandoningPacket(sequence_number, it->second);
- pending_packets_.erase(it);
- }
-}
-
-void QuicCongestionManager::OnIncomingQuicCongestionFeedbackFrame(
- const QuicCongestionFeedbackFrame& frame, QuicTime feedback_receive_time) {
- send_algorithm_->OnIncomingQuicCongestionFeedbackFrame(
- frame, feedback_receive_time, packet_history_map_);
-}
-
-void QuicCongestionManager::OnIncomingAckFrame(const QuicAckFrame& frame,
- QuicTime ack_receive_time) {
- // We calculate the RTT based on the highest ACKed sequence number, the lower
- // sequence numbers will include the ACK aggregation delay.
- SendAlgorithmInterface::SentPacketsMap::iterator history_it =
- packet_history_map_.find(frame.received_info.largest_observed);
- // TODO(satyamshekhar): largest_observed might be missing.
- if (history_it != packet_history_map_.end() &&
- !frame.received_info.delta_time_largest_observed.IsInfinite()) {
- QuicTime::Delta send_delta = ack_receive_time.Subtract(
- history_it->second->SendTimestamp());
- if (send_delta > frame.received_info.delta_time_largest_observed) {
- current_rtt_ = send_delta.Subtract(
- frame.received_info.delta_time_largest_observed);
- }
- }
- // We want to.
- // * Get all packets lower(including) than largest_observed
- // from pending_packets_.
- // * Remove all missing packets.
- // * Send each ACK in the list to send_algorithm_.
- PendingPacketsMap::iterator it, it_upper;
- it = pending_packets_.begin();
- it_upper = pending_packets_.upper_bound(frame.received_info.largest_observed);
-
- bool new_packet_loss_reported = false;
- while (it != it_upper) {
- QuicPacketSequenceNumber sequence_number = it->first;
- if (!IsAwaitingPacket(frame.received_info, sequence_number)) {
- // Not missing, hence implicitly acked.
- send_algorithm_->OnIncomingAck(sequence_number, it->second, current_rtt_);
- pending_packets_.erase(it++); // Must be incremented post to work.
- } else {
- if (sequence_number > largest_missing_) {
- // We have a new loss reported.
- new_packet_loss_reported = true;
- largest_missing_ = sequence_number;
- }
- ++it;
- }
- }
- if (new_packet_loss_reported) {
- send_algorithm_->OnIncomingLoss(ack_receive_time);
- }
-}
-
-QuicTime::Delta QuicCongestionManager::TimeUntilSend(
- QuicTime now,
- Retransmission retransmission,
- HasRetransmittableData retransmittable,
- IsHandshake handshake) {
- return send_algorithm_->TimeUntilSend(now, retransmission, retransmittable,
- handshake);
-}
-
-bool QuicCongestionManager::GenerateCongestionFeedback(
- QuicCongestionFeedbackFrame* feedback) {
- return receive_algorithm_->GenerateCongestionFeedback(feedback);
-}
-
-void QuicCongestionManager::RecordIncomingPacket(
- QuicByteCount bytes,
- QuicPacketSequenceNumber sequence_number,
- QuicTime timestamp,
- bool revived) {
- receive_algorithm_->RecordIncomingPacket(bytes, sequence_number, timestamp,
- revived);
-}
-
-const QuicTime::Delta QuicCongestionManager::rtt() {
- return current_rtt_;
-}
-
-const QuicTime::Delta QuicCongestionManager::DefaultRetransmissionTime() {
- return QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs);
-}
-
-// Ensures that the Delayed Ack timer is always set to a value lesser
-// than the retransmission timer's minimum value (MinRTO). We want the
-// delayed ack to get back to the QUIC peer before the sender's
-// retransmission timer triggers. Since we do not know the
-// reverse-path one-way delay, we assume equal delays for forward and
-// reverse paths, and ensure that the timer is set to less than half
-// of the MinRTO.
-// There may be a value in making this delay adaptive with the help of
-// the sender and a signaling mechanism -- if the sender uses a
-// different MinRTO, we may get spurious retransmissions. May not have
-// any benefits, but if the delayed ack becomes a significant source
-// of (likely, tail) latency, then consider such a mechanism.
-
-const QuicTime::Delta QuicCongestionManager::DelayedAckTime() {
- return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
-}
-
-const QuicTime::Delta QuicCongestionManager::GetRetransmissionDelay(
- size_t unacked_packets_count,
- size_t number_retransmissions) {
- QuicTime::Delta retransmission_delay = send_algorithm_->RetransmissionDelay();
- if (retransmission_delay.IsZero()) {
- // We are in the initial state, use default timeout values.
- if (unacked_packets_count <= kTailDropWindowSize) {
- if (number_retransmissions <= kTailDropMaxRetransmissions) {
- return QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs);
- }
- number_retransmissions -= kTailDropMaxRetransmissions;
- }
- retransmission_delay =
- QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs);
- }
- // Calcluate exponential back off.
- retransmission_delay = QuicTime::Delta::FromMilliseconds(
- retransmission_delay.ToMilliseconds() * static_cast<size_t>(
- (1 << min<size_t>(number_retransmissions, kMaxRetransmissions))));
-
- // TODO(rch): This code should move to |send_algorithm_|.
- if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) {
- return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs);
- }
- if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) {
- return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs);
- }
- return retransmission_delay;
-}
-
-const QuicTime::Delta QuicCongestionManager::SmoothedRtt() {
- return send_algorithm_->SmoothedRtt();
-}
-
-QuicBandwidth QuicCongestionManager::BandwidthEstimate() {
- return send_algorithm_->BandwidthEstimate();
-}
-
-void QuicCongestionManager::CleanupPacketHistory() {
- const QuicTime::Delta kHistoryPeriod =
- QuicTime::Delta::FromMilliseconds(kHistoryPeriodMs);
- QuicTime now = clock_->ApproximateNow();
-
- SendAlgorithmInterface::SentPacketsMap::iterator history_it =
- packet_history_map_.begin();
- for (; history_it != packet_history_map_.end(); ++history_it) {
- if (now.Subtract(history_it->second->SendTimestamp()) <= kHistoryPeriod) {
- return;
- }
- delete history_it->second;
- packet_history_map_.erase(history_it);
- history_it = packet_history_map_.begin();
- }
-}
-
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/quic_congestion_manager.h b/chromium/net/quic/congestion_control/quic_congestion_manager.h
deleted file mode 100644
index 66303439ba4..00000000000
--- a/chromium/net/quic/congestion_control/quic_congestion_manager.h
+++ /dev/null
@@ -1,121 +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.
-//
-// This is the interface from the QuicConnection into the QUIC
-// congestion control code. It wraps the SendAlgorithmInterface and
-// ReceiveAlgorithmInterface and provides a single interface
-// for consumers.
-
-#ifndef NET_QUIC_CONGESTION_CONTROL_QUIC_CONGESTION_MANAGER_H_
-#define NET_QUIC_CONGESTION_CONTROL_QUIC_CONGESTION_MANAGER_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/quic_bandwidth.h"
-#include "net/quic/quic_protocol.h"
-
-namespace net {
-
-namespace test {
-class QuicConnectionPeer;
-class QuicCongestionManagerPeer;
-} // namespace test
-
-class QuicClock;
-class ReceiveAlgorithmInterface;
-
-class NET_EXPORT_PRIVATE QuicCongestionManager {
- public:
- QuicCongestionManager(const QuicClock* clock,
- CongestionFeedbackType congestion_type);
- virtual ~QuicCongestionManager();
-
- // Called when we have received an ack frame from peer.
- virtual void OnIncomingAckFrame(const QuicAckFrame& frame,
- QuicTime ack_receive_time);
-
- // Called when a congestion feedback frame is received from peer.
- virtual void OnIncomingQuicCongestionFeedbackFrame(
- const QuicCongestionFeedbackFrame& frame,
- QuicTime feedback_receive_time);
-
- // Called when we have sent bytes to the peer. This informs the manager both
- // the number of bytes sent and if they were retransmitted.
- virtual void SentPacket(QuicPacketSequenceNumber sequence_number,
- QuicTime sent_time,
- QuicByteCount bytes,
- Retransmission retransmission,
- HasRetransmittableData has_retransmittable_data);
-
- // Called when a packet is timed out.
- virtual void AbandoningPacket(QuicPacketSequenceNumber sequence_number);
-
- // Calculate the time until we can send the next packet to the wire.
- // Note 1: When kUnknownWaitTime is returned, there is no need to poll
- // TimeUntilSend again until we receive an OnIncomingAckFrame event.
- // Note 2: Send algorithms may or may not use |retransmit| in their
- // calculations.
- virtual QuicTime::Delta TimeUntilSend(QuicTime now,
- Retransmission retransmission,
- HasRetransmittableData retransmittable,
- IsHandshake handshake);
-
- // Should be called before sending an ACK packet, to decide if we need
- // to attach a QuicCongestionFeedbackFrame block.
- // Returns false if no QuicCongestionFeedbackFrame block is needed.
- // Otherwise fills in feedback and returns true.
- virtual bool GenerateCongestionFeedback(
- QuicCongestionFeedbackFrame* feedback);
-
- // Should be called for each incoming packet.
- // bytes: the packet size in bytes including Quic Headers.
- // sequence_number: the unique sequence number from the QUIC packet header.
- // timestamp: the arrival time of the packet.
- // revived: true if the packet was lost and then recovered with help of a
- // FEC packet.
- virtual void RecordIncomingPacket(QuicByteCount bytes,
- QuicPacketSequenceNumber sequence_number,
- QuicTime timestamp,
- bool revived);
-
- const QuicTime::Delta DefaultRetransmissionTime();
-
- // Returns amount of time for delayed ack timer.
- const QuicTime::Delta DelayedAckTime();
-
- const QuicTime::Delta GetRetransmissionDelay(
- size_t unacked_packets_count,
- size_t number_retransmissions);
-
- // Returns the estimated smoothed RTT calculated by the congestion algorithm.
- const QuicTime::Delta SmoothedRtt();
-
- // Returns the estimated bandwidth calculated by the congestion algorithm.
- QuicBandwidth BandwidthEstimate();
-
- private:
- friend class test::QuicConnectionPeer;
- friend class test::QuicCongestionManagerPeer;
- typedef std::map<QuicPacketSequenceNumber, size_t> PendingPacketsMap;
-
- // Get the current(last) rtt. Infinite is returned if invalid.
- const QuicTime::Delta rtt();
-
- void CleanupPacketHistory();
-
- const QuicClock* clock_;
- scoped_ptr<ReceiveAlgorithmInterface> receive_algorithm_;
- scoped_ptr<SendAlgorithmInterface> send_algorithm_;
- SendAlgorithmInterface::SentPacketsMap packet_history_map_;
- PendingPacketsMap pending_packets_;
- QuicPacketSequenceNumber largest_missing_;
- QuicTime::Delta current_rtt_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicCongestionManager);
-};
-
-} // namespace net
-
-#endif // NET_QUIC_CONGESTION_CONTROL_QUIC_CONGESTION_MANAGER_H_
diff --git a/chromium/net/quic/congestion_control/quic_congestion_manager_test.cc b/chromium/net/quic/congestion_control/quic_congestion_manager_test.cc
deleted file mode 100644
index 80460f552b6..00000000000
--- a/chromium/net/quic/congestion_control/quic_congestion_manager_test.cc
+++ /dev/null
@@ -1,247 +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.
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/quic/congestion_control/inter_arrival_sender.h"
-#include "net/quic/congestion_control/quic_congestion_manager.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/test_tools/mock_clock.h"
-#include "net/quic/test_tools/quic_test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::_;
-using testing::StrictMock;
-using testing::Return;
-
-namespace net {
-namespace test {
-
-class QuicCongestionManagerPeer : public QuicCongestionManager {
- public:
- explicit QuicCongestionManagerPeer(const QuicClock* clock,
- CongestionFeedbackType congestion_type)
- : QuicCongestionManager(clock, congestion_type) {
- }
- void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
- this->send_algorithm_.reset(send_algorithm);
- }
-
- using QuicCongestionManager::rtt;
- const SendAlgorithmInterface::SentPacketsMap& packet_history_map() {
- return packet_history_map_;
- }
- private:
- DISALLOW_COPY_AND_ASSIGN(QuicCongestionManagerPeer);
-};
-
-class QuicCongestionManagerTest : public ::testing::Test {
- protected:
- void SetUpCongestionType(CongestionFeedbackType congestion_type) {
- manager_.reset(new QuicCongestionManagerPeer(&clock_, congestion_type));
- }
-
- static const HasRetransmittableData kIgnored = HAS_RETRANSMITTABLE_DATA;
-
- MockClock clock_;
- scoped_ptr<QuicCongestionManagerPeer> manager_;
-};
-
-TEST_F(QuicCongestionManagerTest, Bandwidth) {
- SetUpCongestionType(kFixRate);
- QuicAckFrame ack;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
-
- QuicCongestionFeedbackFrame feedback;
- feedback.type = kFixRate;
- feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(100);
- manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
-
- for (int i = 1; i <= 100; ++i) {
- QuicTime::Delta advance_time = manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE);
- clock_.AdvanceTime(advance_time);
- EXPECT_TRUE(manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(i, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- // Ack the packet we sent.
- ack.received_info.largest_observed = i;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- }
- EXPECT_EQ(100, manager_->BandwidthEstimate().ToKBytesPerSecond());
- EXPECT_NEAR(100,
- InterArrivalSender::CalculateSentBandwidth(
- manager_->packet_history_map(),
- clock_.Now()).ToKBytesPerSecond(),
- 4);
-}
-
-TEST_F(QuicCongestionManagerTest, BandwidthWith1SecondGap) {
- SetUpCongestionType(kFixRate);
- QuicAckFrame ack;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
-
- QuicCongestionFeedbackFrame feedback;
- feedback.type = kFixRate;
- feedback.fix_rate.bitrate = QuicBandwidth::FromKBytesPerSecond(100);
- manager_->OnIncomingQuicCongestionFeedbackFrame(feedback, clock_.Now());
-
- for (QuicPacketSequenceNumber sequence_number = 1; sequence_number <= 100;
- ++sequence_number) {
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
- EXPECT_TRUE(manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(sequence_number, clock_.Now(), 1000,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
- // Ack the packet we sent.
- ack.received_info.largest_observed = sequence_number;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- }
- EXPECT_EQ(100000, manager_->BandwidthEstimate().ToBytesPerSecond());
- EXPECT_NEAR(100000,
- InterArrivalSender::CalculateSentBandwidth(
- manager_->packet_history_map(),
- clock_.Now()).ToBytesPerSecond(),
- 2000);
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(500));
- EXPECT_NEAR(50000,
- InterArrivalSender::CalculateSentBandwidth(
- manager_->packet_history_map(),
- clock_.Now()).ToBytesPerSecond(),
- 1000);
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(501));
- EXPECT_NEAR(100000, manager_->BandwidthEstimate().ToBytesPerSecond(), 2000);
- EXPECT_TRUE(InterArrivalSender::CalculateSentBandwidth(
- manager_->packet_history_map(),
- clock_.Now()).IsZero());
- for (int i = 1; i <= 150; ++i) {
- EXPECT_TRUE(manager_->TimeUntilSend(
- clock_.Now(), NOT_RETRANSMISSION, kIgnored, NOT_HANDSHAKE).IsZero());
- manager_->SentPacket(i + 100, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
- // Ack the packet we sent.
- ack.received_info.largest_observed = i + 100;
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- }
- EXPECT_EQ(100, manager_->BandwidthEstimate().ToKBytesPerSecond());
- EXPECT_NEAR(100,
- InterArrivalSender::CalculateSentBandwidth(
- manager_->packet_history_map(),
- clock_.Now()).ToKBytesPerSecond(),
- 2);
-}
-
-TEST_F(QuicCongestionManagerTest, Rtt) {
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
-
- QuicPacketSequenceNumber sequence_number = 1;
- QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(15);
-
- EXPECT_CALL(*send_algorithm, SentPacket(_, _, _, _, _))
- .Times(1).WillOnce(Return(true));
- EXPECT_CALL(*send_algorithm,
- OnIncomingAck(sequence_number, _, expected_rtt)).Times(1);
-
- manager_->SentPacket(sequence_number, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
-
- QuicAckFrame ack;
- ack.received_info.largest_observed = sequence_number;
- ack.received_info.delta_time_largest_observed =
- QuicTime::Delta::FromMilliseconds(5);
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- EXPECT_EQ(manager_->rtt(), expected_rtt);
-}
-
-TEST_F(QuicCongestionManagerTest, RttWithInvalidDelta) {
- // Expect that the RTT is infinite since the delta_time_largest_observed is
- // larger than the local time elapsed aka invalid.
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
-
- QuicPacketSequenceNumber sequence_number = 1;
- QuicTime::Delta expected_rtt = QuicTime::Delta::Infinite();
-
- EXPECT_CALL(*send_algorithm, SentPacket(_, _, _, _, _))
- .Times(1).WillOnce(Return(true));
- EXPECT_CALL(*send_algorithm,
- OnIncomingAck(sequence_number, _, expected_rtt)).Times(1);
-
- manager_->SentPacket(sequence_number, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
-
- QuicAckFrame ack;
- ack.received_info.largest_observed = sequence_number;
- ack.received_info.delta_time_largest_observed =
- QuicTime::Delta::FromMilliseconds(11);
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- EXPECT_EQ(manager_->rtt(), expected_rtt);
-}
-
-TEST_F(QuicCongestionManagerTest, RttInfiniteDelta) {
- // Expect that the RTT is infinite since the delta_time_largest_observed is
- // infinite aka invalid.
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
-
- QuicPacketSequenceNumber sequence_number = 1;
- QuicTime::Delta expected_rtt = QuicTime::Delta::Infinite();
-
- EXPECT_CALL(*send_algorithm, SentPacket(_, _, _, _, _))
- .Times(1).WillOnce(Return(true));
- EXPECT_CALL(*send_algorithm,
- OnIncomingAck(sequence_number, _, expected_rtt)).Times(1);
-
- manager_->SentPacket(sequence_number, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
-
- QuicAckFrame ack;
- ack.received_info.largest_observed = sequence_number;
- ack.received_info.delta_time_largest_observed = QuicTime::Delta::Infinite();
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- EXPECT_EQ(manager_->rtt(), expected_rtt);
-}
-
-TEST_F(QuicCongestionManagerTest, RttZeroDelta) {
- // Expect that the RTT is the time between send and receive since the
- // delta_time_largest_observed is zero.
- SetUpCongestionType(kFixRate);
-
- MockSendAlgorithm* send_algorithm = new StrictMock<MockSendAlgorithm>;
- manager_->SetSendAlgorithm(send_algorithm);
-
- QuicPacketSequenceNumber sequence_number = 1;
- QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
-
- EXPECT_CALL(*send_algorithm, SentPacket(_, _, _, _, _))
- .Times(1).WillOnce(Return(true));
- EXPECT_CALL(*send_algorithm, OnIncomingAck(sequence_number, _, expected_rtt))
- .Times(1);
-
- manager_->SentPacket(sequence_number, clock_.Now(), 1000, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
- clock_.AdvanceTime(expected_rtt);
-
- QuicAckFrame ack;
- ack.received_info.largest_observed = sequence_number;
- ack.received_info.delta_time_largest_observed = QuicTime::Delta::Zero();
- manager_->OnIncomingAckFrame(ack, clock_.Now());
- EXPECT_EQ(manager_->rtt(), expected_rtt);
-}
-
-} // namespace test
-} // namespace net
diff --git a/chromium/net/quic/congestion_control/receive_algorithm_interface.cc b/chromium/net/quic/congestion_control/receive_algorithm_interface.cc
index e8dacf0725b..a49f64f160a 100644
--- a/chromium/net/quic/congestion_control/receive_algorithm_interface.cc
+++ b/chromium/net/quic/congestion_control/receive_algorithm_interface.cc
@@ -11,7 +11,6 @@ namespace net {
// Factory for receive side congestion control algorithm.
ReceiveAlgorithmInterface* ReceiveAlgorithmInterface::Create(
- const QuicClock* clock,
CongestionFeedbackType type) {
switch (type) {
case kTCP:
diff --git a/chromium/net/quic/congestion_control/receive_algorithm_interface.h b/chromium/net/quic/congestion_control/receive_algorithm_interface.h
index e2bae4bb793..17e7793749a 100644
--- a/chromium/net/quic/congestion_control/receive_algorithm_interface.h
+++ b/chromium/net/quic/congestion_control/receive_algorithm_interface.h
@@ -17,8 +17,7 @@ namespace net {
class NET_EXPORT_PRIVATE ReceiveAlgorithmInterface {
public:
- static ReceiveAlgorithmInterface* Create(const QuicClock* clock,
- CongestionFeedbackType type);
+ static ReceiveAlgorithmInterface* Create(CongestionFeedbackType type);
virtual ~ReceiveAlgorithmInterface() {}
diff --git a/chromium/net/quic/congestion_control/send_algorithm_interface.cc b/chromium/net/quic/congestion_control/send_algorithm_interface.cc
index 90399e7d05b..493d84e88ef 100644
--- a/chromium/net/quic/congestion_control/send_algorithm_interface.cc
+++ b/chromium/net/quic/congestion_control/send_algorithm_interface.cc
@@ -4,17 +4,13 @@
#include "net/quic/congestion_control/send_algorithm_interface.h"
-#include "net/quic/congestion_control/cubic.h"
#include "net/quic/congestion_control/fix_rate_sender.h"
#include "net/quic/congestion_control/tcp_cubic_sender.h"
+#include "net/quic/quic_protocol.h"
namespace net {
const bool kUseReno = false;
-// TODO(ianswett): Increase the max congestion window once the RTO logic is
-// improved, particularly in cases when RTT is larger than the RTO. b/10075719
-// Maximum number of outstanding packets for tcp.
-const QuicTcpCongestionWindow kMaxTcpCongestionWindow = 100;
// Factory for send side congestion control algorithm.
SendAlgorithmInterface* SendAlgorithmInterface::Create(
diff --git a/chromium/net/quic/congestion_control/send_algorithm_interface.h b/chromium/net/quic/congestion_control/send_algorithm_interface.h
index c29f22545d0..87a5f9c03fc 100644
--- a/chromium/net/quic/congestion_control/send_algorithm_interface.h
+++ b/chromium/net/quic/congestion_control/send_algorithm_interface.h
@@ -7,12 +7,14 @@
#ifndef NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
#define NET_QUIC_CONGESTION_CONTROL_SEND_ALGORITHM_INTERFACE_H_
+#include <algorithm>
#include <map>
#include "base/basictypes.h"
#include "net/base/net_export.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_clock.h"
+#include "net/quic/quic_config.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
@@ -22,16 +24,30 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
public:
class SentPacket {
public:
- SentPacket(QuicByteCount bytes, QuicTime timestamp)
+ SentPacket(QuicByteCount bytes,
+ QuicTime timestamp,
+ HasRetransmittableData has_retransmittable_data)
: bytes_sent_(bytes),
- send_timestamp_(timestamp) {
+ send_timestamp_(timestamp),
+ has_retransmittable_data_(has_retransmittable_data),
+ nack_count_(0) {
+ }
+ QuicByteCount bytes_sent() const { return bytes_sent_; }
+ const QuicTime& send_timestamp() const { return send_timestamp_; }
+ HasRetransmittableData has_retransmittable_data() const {
+ return has_retransmittable_data_;
+ }
+ size_t nack_count() const { return nack_count_; }
+
+ void Nack(size_t min_nacks) {
+ nack_count_ = std::max(min_nacks, nack_count_ + 1);
}
- QuicByteCount BytesSent() { return bytes_sent_; }
- QuicTime& SendTimestamp() { return send_timestamp_; }
private:
QuicByteCount bytes_sent_;
QuicTime send_timestamp_;
+ HasRetransmittableData has_retransmittable_data_;
+ size_t nack_count_;
};
typedef std::map<QuicPacketSequenceNumber, SentPacket*> SentPacketsMap;
@@ -41,6 +57,11 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
virtual ~SendAlgorithmInterface() {}
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) = 0;
+
+ // Sets the maximum size of packets that will be sent.
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) = 0;
+
// Called when we receive congestion feedback from remote peer.
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
@@ -48,45 +69,56 @@ class NET_EXPORT_PRIVATE SendAlgorithmInterface {
const SentPacketsMap& sent_packets) = 0;
// Called for each received ACK, with sequence number from remote peer.
- virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
+ virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) = 0;
- virtual void OnIncomingLoss(QuicTime ack_receive_time) = 0;
+ // Indicates a loss event of one packet. |sequence_number| is the
+ // sequence number of the lost packet.
+ virtual void OnPacketLost(QuicPacketSequenceNumber sequence_number,
+ QuicTime ack_receive_time) = 0;
// Inform that we sent x bytes to the wire, and if that was a retransmission.
// Returns true if the packet should be tracked by the congestion manager,
// false otherwise. This is used by implementations such as tcp_cubic_sender
// that do not count outgoing ACK packets against the congestion window.
// Note: this function must be called for every packet sent to the wire.
- virtual bool SentPacket(QuicTime sent_time,
- QuicPacketSequenceNumber sequence_number,
- QuicByteCount bytes,
- Retransmission is_retransmission,
- HasRetransmittableData is_retransmittable) = 0;
+ virtual bool OnPacketSent(QuicTime sent_time,
+ QuicPacketSequenceNumber sequence_number,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData is_retransmittable) = 0;
+
+ // Called when the retransmission timeout fires.
+ virtual void OnRetransmissionTimeout() = 0;
// Called when a packet is timed out.
- virtual void AbandoningPacket(QuicPacketSequenceNumber sequence_number,
+ virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes) = 0;
// Calculate the time until we can send the next packet.
virtual QuicTime::Delta TimeUntilSend(
QuicTime now,
- Retransmission is_retransmission,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data,
IsHandshake handshake) = 0;
// What's the current estimated bandwidth in bytes per second.
// Returns 0 when it does not have an estimate.
- virtual QuicBandwidth BandwidthEstimate() = 0;
+ virtual QuicBandwidth BandwidthEstimate() const = 0;
// TODO(satyamshekhar): Monitor MinRtt.
- virtual QuicTime::Delta SmoothedRtt() = 0;
+ virtual QuicTime::Delta SmoothedRtt() const = 0;
// Get the send algorithm specific retransmission delay, called RTO in TCP,
// Note 1: the caller is responsible for sanity checking this value.
// Note 2: this will return zero if we don't have enough data for an estimate.
- virtual QuicTime::Delta RetransmissionDelay() = 0;
+ virtual QuicTime::Delta RetransmissionDelay() const = 0;
+
+ // Returns the size of the current congestion window in bytes. Note, this is
+ // not the *available* window. Some send algorithms may not use a congestion
+ // window and will return 0.
+ virtual QuicByteCount GetCongestionWindow() const = 0;
};
} // namespace net
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender.cc
index 52c910e8592..50fc3937b99 100644
--- a/chromium/net/quic/congestion_control/tcp_cubic_sender.cc
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender.cc
@@ -4,15 +4,25 @@
#include "net/quic/congestion_control/tcp_cubic_sender.h"
+#include <algorithm>
+
+#include "base/metrics/histogram.h"
+
+using std::max;
+
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 QuicTcpCongestionWindow kMinimumCongestionWindow = 2;
const int64 kHybridStartLowWindow = 16;
-const QuicByteCount kMaxSegmentSize = kMaxPacketSize;
+const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
const QuicByteCount kDefaultReceiveWindow = 64000;
const int64 kInitialCongestionWindow = 10;
const int kMaxBurstLength = 3;
+// Constants used for RTT calculation.
const int kInitialRttMs = 60; // At a typical RTT 60 ms.
const float kAlpha = 0.125f;
const float kOneMinusAlpha = (1 - kAlpha);
@@ -28,11 +38,14 @@ TcpCubicSender::TcpCubicSender(
cubic_(clock),
reno_(reno),
congestion_window_count_(0),
- receiver_congestion_window_(kDefaultReceiveWindow),
+ receive_window_(kDefaultReceiveWindow),
last_received_accumulated_number_of_lost_packets_(0),
bytes_in_flight_(0),
update_end_sequence_number_(true),
end_sequence_number_(0),
+ largest_sent_sequence_number_(0),
+ largest_acked_sequence_number_(0),
+ largest_sent_at_last_cutback_(0),
congestion_window_(kInitialCongestionWindow),
slowstart_threshold_(max_tcp_congestion_window),
max_tcp_congestion_window_(max_tcp_congestion_window),
@@ -42,6 +55,17 @@ TcpCubicSender::TcpCubicSender(
}
TcpCubicSender::~TcpCubicSender() {
+ UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
+}
+
+void TcpCubicSender::SetMaxPacketSize(QuicByteCount /*max_packet_size*/) {
+}
+
+void TcpCubicSender::SetFromConfig(const QuicConfig& config, bool is_server) {
+ if (is_server) {
+ // Set the initial window size.
+ congestion_window_ = config.server_initial_congestion_window();
+ }
}
void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame(
@@ -56,26 +80,39 @@ void TcpCubicSender::OnIncomingQuicCongestionFeedbackFrame(
last_received_accumulated_number_of_lost_packets_ =
feedback.tcp.accumulated_number_of_lost_packets;
if (recovered_lost_packets > 0) {
- OnIncomingLoss(feedback_receive_time);
+ // Assume the loss could be as late as the last acked packet.
+ OnPacketLost(largest_acked_sequence_number_, feedback_receive_time);
}
}
- receiver_congestion_window_ = feedback.tcp.receive_window;
+ receive_window_ = feedback.tcp.receive_window;
}
-void TcpCubicSender::OnIncomingAck(
- QuicPacketSequenceNumber acked_sequence_number, QuicByteCount acked_bytes,
+void TcpCubicSender::OnPacketAcked(
+ QuicPacketSequenceNumber acked_sequence_number,
+ QuicByteCount acked_bytes,
QuicTime::Delta rtt) {
DCHECK_GE(bytes_in_flight_, acked_bytes);
bytes_in_flight_ -= acked_bytes;
+ largest_acked_sequence_number_ = max(acked_sequence_number,
+ largest_acked_sequence_number_);
CongestionAvoidance(acked_sequence_number);
AckAccounting(rtt);
if (end_sequence_number_ == acked_sequence_number) {
- DLOG(INFO) << "Start update end sequence number @" << acked_sequence_number;
+ DVLOG(1) << "Start update end sequence number @" << acked_sequence_number;
update_end_sequence_number_ = true;
}
}
-void TcpCubicSender::OnIncomingLoss(QuicTime /*ack_receive_time*/) {
+void TcpCubicSender::OnPacketLost(QuicPacketSequenceNumber sequence_number,
+ QuicTime /*ack_receive_time*/) {
+ // 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 (sequence_number <= largest_sent_at_last_cutback_) {
+ DVLOG(1) << "Ignoring loss for largest_missing:" << sequence_number
+ << " because it was sent prior to the last CWND cutback.";
+ return;
+ }
+
// In a normal TCP we would need to know the lowest missing packet to detect
// if we receive 3 missing packets. Here we get a missing packet for which we
// enter TCP Fast Retransmit immediately.
@@ -87,92 +124,99 @@ void TcpCubicSender::OnIncomingLoss(QuicTime /*ack_receive_time*/) {
cubic_.CongestionWindowAfterPacketLoss(congestion_window_);
slowstart_threshold_ = congestion_window_;
}
- // Sanity, make sure that we don't end up with an empty window.
- if (congestion_window_ == 0) {
- congestion_window_ = 1;
+ // Enforce TCP's minimimum congestion window of 2*MSS.
+ if (congestion_window_ < kMinimumCongestionWindow) {
+ congestion_window_ = kMinimumCongestionWindow;
}
- DLOG(INFO) << "Incoming loss; congestion window:" << congestion_window_;
+ largest_sent_at_last_cutback_ = largest_sent_sequence_number_;
+ DVLOG(1) << "Incoming loss; congestion window:" << congestion_window_;
}
-bool TcpCubicSender::SentPacket(QuicTime /*sent_time*/,
- QuicPacketSequenceNumber sequence_number,
- QuicByteCount bytes,
- Retransmission is_retransmission,
- HasRetransmittableData is_retransmittable) {
+bool TcpCubicSender::OnPacketSent(QuicTime /*sent_time*/,
+ QuicPacketSequenceNumber sequence_number,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData is_retransmittable) {
// Only update bytes_in_flight_ for data packets.
if (is_retransmittable != HAS_RETRANSMITTABLE_DATA) {
return false;
}
bytes_in_flight_ += bytes;
- if (is_retransmission == NOT_RETRANSMISSION && update_end_sequence_number_) {
+ if (largest_sent_sequence_number_ < sequence_number) {
+ // TODO(rch): Ensure that packets are really sent in order.
+ // DCHECK_LT(largest_sent_sequence_number_, sequence_number);
+ largest_sent_sequence_number_ = sequence_number;
+ }
+ if (transmission_type == NOT_RETRANSMISSION && update_end_sequence_number_) {
end_sequence_number_ = sequence_number;
- if (AvailableCongestionWindow() == 0) {
+ if (AvailableSendWindow() == 0) {
update_end_sequence_number_ = false;
- DLOG(INFO) << "Stop update end sequence number @" << sequence_number;
+ DVLOG(1) << "Stop update end sequence number @" << sequence_number;
}
}
return true;
}
-void TcpCubicSender::AbandoningPacket(QuicPacketSequenceNumber sequence_number,
- QuicByteCount abandoned_bytes) {
+void TcpCubicSender::OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
+ QuicByteCount abandoned_bytes) {
DCHECK_GE(bytes_in_flight_, abandoned_bytes);
bytes_in_flight_ -= abandoned_bytes;
}
QuicTime::Delta TcpCubicSender::TimeUntilSend(
- QuicTime now,
- Retransmission is_retransmission,
+ QuicTime /* now */,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data,
IsHandshake handshake) {
- if (is_retransmission == IS_RETRANSMISSION ||
+ if (transmission_type == NACK_RETRANSMISSION ||
has_retransmittable_data == NO_RETRANSMITTABLE_DATA ||
handshake == IS_HANDSHAKE) {
- // For TCP we can always send a retransmission, or an ACK immediately.
+ // For TCP we can always send an ACK immediately.
// We also immediately send any handshake packet (CHLO, etc.). We provide
- // this special dispensation for handshake messages in QUIC, although the
+ // this special dispensation for handshake messages in QUIC, although the
// concept is not present in TCP.
return QuicTime::Delta::Zero();
}
- if (AvailableCongestionWindow() == 0) {
+ if (AvailableSendWindow() == 0) {
return QuicTime::Delta::Infinite();
}
return QuicTime::Delta::Zero();
}
-QuicByteCount TcpCubicSender::AvailableCongestionWindow() {
- if (bytes_in_flight_ > CongestionWindow()) {
+QuicByteCount TcpCubicSender::AvailableSendWindow() {
+ if (bytes_in_flight_ > SendWindow()) {
return 0;
}
- return CongestionWindow() - bytes_in_flight_;
+ return SendWindow() - bytes_in_flight_;
}
-QuicByteCount TcpCubicSender::CongestionWindow() {
- // What's the current congestion window in bytes.
- return std::min(receiver_congestion_window_,
- congestion_window_ * kMaxSegmentSize);
+QuicByteCount TcpCubicSender::SendWindow() {
+ // What's the current send window in bytes.
+ return std::min(receive_window_, GetCongestionWindow());
}
-QuicBandwidth TcpCubicSender::BandwidthEstimate() {
- // TODO(pwestin): make a long term estimate, based on RTT and loss rate? or
- // instantaneous estimate?
- // Throughput ~= (1/RTT)*sqrt(3/2p)
- return QuicBandwidth::Zero();
+QuicBandwidth TcpCubicSender::BandwidthEstimate() const {
+ return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(),
+ SmoothedRtt());
}
-QuicTime::Delta TcpCubicSender::SmoothedRtt() {
+QuicTime::Delta TcpCubicSender::SmoothedRtt() const {
if (smoothed_rtt_.IsZero()) {
return QuicTime::Delta::FromMilliseconds(kInitialRttMs);
}
return smoothed_rtt_;
}
-QuicTime::Delta TcpCubicSender::RetransmissionDelay() {
+QuicTime::Delta TcpCubicSender::RetransmissionDelay() const {
return QuicTime::Delta::FromMicroseconds(
smoothed_rtt_.ToMicroseconds() + 4 * mean_deviation_.ToMicroseconds());
}
+QuicByteCount TcpCubicSender::GetCongestionWindow() const {
+ return congestion_window_ * kMaxSegmentSize;
+}
+
void TcpCubicSender::Reset() {
delay_min_ = QuicTime::Delta::Zero();
hybrid_slow_start_.Restart();
@@ -189,7 +233,7 @@ bool TcpCubicSender::IsCwndLimited() const {
return left <= tcp_max_burst;
}
-// Called when we receive and ack. Normal TCP tracks how many packets one ack
+// 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::CongestionAvoidance(QuicPacketSequenceNumber ack) {
if (!IsCwndLimited()) {
@@ -207,7 +251,7 @@ void TcpCubicSender::CongestionAvoidance(QuicPacketSequenceNumber ack) {
// TCP slow start, exponential growth, increase by one for each ACK.
congestion_window_++;
}
- DLOG(INFO) << "Slow start; congestion window:" << congestion_window_;
+ DVLOG(1) << "Slow start; congestion window:" << congestion_window_;
} else {
if (congestion_window_ < max_tcp_congestion_window_) {
if (reno_) {
@@ -218,25 +262,26 @@ void TcpCubicSender::CongestionAvoidance(QuicPacketSequenceNumber ack) {
} else {
congestion_window_count_++;
}
- DLOG(INFO) << "Reno; congestion window:" << congestion_window_;
+ DVLOG(1) << "Reno; congestion window:" << congestion_window_;
} else {
congestion_window_ = std::min(
max_tcp_congestion_window_,
cubic_.CongestionWindowAfterAck(congestion_window_, delay_min_));
- DLOG(INFO) << "Cubic; congestion window:" << congestion_window_;
+ DVLOG(1) << "Cubic; congestion window:" << congestion_window_;
}
}
}
}
-// TODO(pwestin): what is the timout value?
-void TcpCubicSender::OnTimeOut() {
+void TcpCubicSender::OnRetransmissionTimeout() {
cubic_.Reset();
- congestion_window_ = 1;
+ congestion_window_ = kMinimumCongestionWindow;
}
void TcpCubicSender::AckAccounting(QuicTime::Delta rtt) {
if (rtt.IsInfinite() || rtt.IsZero()) {
+ DVLOG(1) << "Ignoring rtt, because it's "
+ << (rtt.IsZero() ? "Zero" : "Infinite");
return;
}
// RTT can't be negative.
@@ -261,7 +306,8 @@ void TcpCubicSender::AckAccounting(QuicTime::Delta rtt) {
smoothed_rtt_ = QuicTime::Delta::FromMicroseconds(
kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() +
kAlpha * rtt.ToMicroseconds());
- DLOG(INFO) << "Cubic; mean_deviation_:" << mean_deviation_.ToMicroseconds();
+ DVLOG(1) << "Cubic; smoothed_rtt_:" << smoothed_rtt_.ToMicroseconds()
+ << " mean_deviation_:" << mean_deviation_.ToMicroseconds();
}
// Hybrid start triggers when cwnd is larger than some threshold.
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender.h b/chromium/net/quic/congestion_control/tcp_cubic_sender.h
index db829c29bba..f026fd56b3f 100644
--- a/chromium/net/quic/congestion_control/tcp_cubic_sender.h
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender.h
@@ -20,6 +20,9 @@
namespace net {
+// Default maximum packet size used in Linux TCP implementations.
+const QuicByteCount kDefaultTCPMSS = 1460;
+
namespace test {
class TcpCubicSenderPeer;
} // namespace test
@@ -33,37 +36,41 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
virtual ~TcpCubicSender();
// Start implementation of SendAlgorithmInterface.
+ virtual void SetFromConfig(const QuicConfig& config, bool is_server) OVERRIDE;
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size) OVERRIDE;
virtual void OnIncomingQuicCongestionFeedbackFrame(
const QuicCongestionFeedbackFrame& feedback,
QuicTime feedback_receive_time,
const SentPacketsMap& sent_packets) OVERRIDE;
- virtual void OnIncomingAck(QuicPacketSequenceNumber acked_sequence_number,
+ virtual void OnPacketAcked(QuicPacketSequenceNumber acked_sequence_number,
QuicByteCount acked_bytes,
QuicTime::Delta rtt) OVERRIDE;
- virtual void OnIncomingLoss(QuicTime ack_receive_time) OVERRIDE;
- virtual bool SentPacket(
- QuicTime sent_time,
- QuicPacketSequenceNumber sequence_number,
- QuicByteCount bytes,
- Retransmission is_retransmission,
- HasRetransmittableData is_retransmittable) OVERRIDE;
- virtual void AbandoningPacket(QuicPacketSequenceNumber sequence_number,
- QuicByteCount abandoned_bytes) OVERRIDE;
+ virtual void OnPacketLost(QuicPacketSequenceNumber largest_loss,
+ QuicTime ack_receive_time) OVERRIDE;
+ virtual bool OnPacketSent(QuicTime sent_time,
+ QuicPacketSequenceNumber sequence_number,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData is_retransmittable) OVERRIDE;
+ virtual void OnRetransmissionTimeout() OVERRIDE;
+ virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number,
+ QuicByteCount abandoned_bytes) OVERRIDE;
virtual QuicTime::Delta TimeUntilSend(
QuicTime now,
- Retransmission is_retransmission,
+ TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data,
IsHandshake handshake) OVERRIDE;
- virtual QuicBandwidth BandwidthEstimate() OVERRIDE;
- virtual QuicTime::Delta SmoothedRtt() OVERRIDE;
- virtual QuicTime::Delta RetransmissionDelay() OVERRIDE;
+ virtual QuicBandwidth BandwidthEstimate() const OVERRIDE;
+ virtual QuicTime::Delta SmoothedRtt() const OVERRIDE;
+ virtual QuicTime::Delta RetransmissionDelay() const OVERRIDE;
+ virtual QuicByteCount GetCongestionWindow() const OVERRIDE;
// End implementation of SendAlgorithmInterface.
private:
friend class test::TcpCubicSenderPeer;
- QuicByteCount AvailableCongestionWindow();
- QuicByteCount CongestionWindow();
+ QuicByteCount AvailableSendWindow();
+ QuicByteCount SendWindow();
void Reset();
void AckAccounting(QuicTime::Delta rtt);
void CongestionAvoidance(QuicPacketSequenceNumber ack);
@@ -80,7 +87,7 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
int64 congestion_window_count_;
// Receiver side advertised window.
- QuicByteCount receiver_congestion_window_;
+ QuicByteCount receive_window_;
// Receiver side advertised packet loss.
int last_received_accumulated_number_of_lost_packets_;
@@ -92,6 +99,15 @@ class NET_EXPORT_PRIVATE TcpCubicSender : public SendAlgorithmInterface {
bool update_end_sequence_number_;
QuicPacketSequenceNumber end_sequence_number_;
+ // Track the largest packet that has been sent.
+ QuicPacketSequenceNumber largest_sent_sequence_number_;
+
+ // Track the largest packet that has been acked.
+ QuicPacketSequenceNumber largest_acked_sequence_number_;
+
+ // Track the largest sequence number outstanding when a CWND cutback occurs.
+ QuicPacketSequenceNumber largest_sent_at_last_cutback_;
+
// Congestion window in packets.
QuicTcpCongestionWindow congestion_window_;
diff --git a/chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc b/chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc
index c7046fcb2f7..20dd6a6d316 100644
--- a/chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc
+++ b/chromium/net/quic/congestion_control/tcp_cubic_sender_test.cc
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "net/quic/congestion_control/tcp_cubic_sender.h"
+
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "net/quic/congestion_control/tcp_cubic_sender.h"
#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/test_tools/mock_clock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -12,7 +13,8 @@
namespace net {
namespace test {
-const uint32 kDefaultWindowTCP = 10 * kMaxPacketSize;
+const uint32 kDefaultWindowTCP = 10 * kDefaultTCPMSS;
+
// TODO(ianswett): Remove 10000 once b/10075719 is fixed.
const QuicTcpCongestionWindow kDefaultMaxCongestionWindowTCP = 10000;
@@ -23,8 +25,13 @@ class TcpCubicSenderPeer : public TcpCubicSender {
QuicTcpCongestionWindow max_tcp_congestion_window)
: TcpCubicSender(clock, reno, max_tcp_congestion_window) {
}
- using TcpCubicSender::AvailableCongestionWindow;
- using TcpCubicSender::CongestionWindow;
+
+ QuicTcpCongestionWindow congestion_window() {
+ return congestion_window_;
+ }
+
+ using TcpCubicSender::AvailableSendWindow;
+ using TcpCubicSender::SendWindow;
using TcpCubicSender::AckAccounting;
};
@@ -40,12 +47,12 @@ class TcpCubicSenderTest : public ::testing::Test {
acked_sequence_number_(0) {
}
- void SendAvailableCongestionWindow() {
- QuicByteCount bytes_to_send = sender_->AvailableCongestionWindow();
+ void SendAvailableSendWindow() {
+ QuicByteCount bytes_to_send = sender_->AvailableSendWindow();
while (bytes_to_send > 0) {
- QuicByteCount bytes_in_packet = std::min(kMaxPacketSize, bytes_to_send);
- sender_->SentPacket(clock_.Now(), sequence_number_++, bytes_in_packet,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ QuicByteCount bytes_in_packet = std::min(kDefaultTCPMSS, bytes_to_send);
+ sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
bytes_to_send -= bytes_in_packet;
if (bytes_to_send > 0) {
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
@@ -57,7 +64,7 @@ class TcpCubicSenderTest : public ::testing::Test {
void AckNPackets(int n) {
for (int i = 0; i < n; ++i) {
acked_sequence_number_++;
- sender_->OnIncomingAck(acked_sequence_number_, kMaxPacketSize, rtt_);
+ sender_->OnPacketAcked(acked_sequence_number_, kDefaultTCPMSS, rtt_);
}
clock_.AdvanceTime(one_ms_); // 1 millisecond.
}
@@ -75,8 +82,8 @@ class TcpCubicSenderTest : public ::testing::Test {
TEST_F(TcpCubicSenderTest, SimpleSender) {
QuicCongestionFeedbackFrame feedback;
// At startup make sure we are at the default.
- EXPECT_EQ(kDefaultWindowTCP,
- sender_->AvailableCongestionWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// At startup make sure we can send.
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
@@ -88,11 +95,12 @@ TEST_F(TcpCubicSenderTest, SimpleSender) {
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
// And that window is un-affected.
- EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableCongestionWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->AvailableSendWindow());
+ EXPECT_EQ(kDefaultWindowTCP, sender_->GetCongestionWindow());
// A retransmit should always return 0.
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
- IS_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
+ NACK_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
}
TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
@@ -110,12 +118,12 @@ TEST_F(TcpCubicSenderTest, ExponentialSlowStart) {
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
for (int n = 0; n < kNumberOfAck; ++n) {
- // Send our full congestion window.
- SendAvailableCongestionWindow();
+ // Send our full send window.
+ SendAvailableSendWindow();
AckNPackets(2);
}
- QuicByteCount bytes_to_send = sender_->CongestionWindow();
- EXPECT_EQ(kDefaultWindowTCP + kMaxPacketSize * 2 * kNumberOfAck,
+ QuicByteCount bytes_to_send = sender_->SendWindow();
+ EXPECT_EQ(kDefaultWindowTCP + kDefaultTCPMSS * 2 * kNumberOfAck,
bytes_to_send);
}
@@ -139,31 +147,32 @@ TEST_F(TcpCubicSenderTest, SlowStartAckTrain) {
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
for (int n = 0; n < kNumberOfAck; ++n) {
- // Send our full congestion window.
- SendAvailableCongestionWindow();
+ // Send our full send window.
+ SendAvailableSendWindow();
AckNPackets(2);
}
- QuicByteCount expected_congestion_window =
- kDefaultWindowTCP + (kMaxPacketSize * 2 * kNumberOfAck);
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ QuicByteCount expected_send_window =
+ kDefaultWindowTCP + (kDefaultTCPMSS * 2 * kNumberOfAck);
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
+ EXPECT_EQ(expected_send_window, sender_->GetCongestionWindow());
// We should now have fallen out of slow start.
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(2);
- expected_congestion_window += kMaxPacketSize;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ expected_send_window += kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
// Testing Reno phase.
// We should need 141(65*2+1+10) ACK:ed packets before increasing window by
// one.
for (int m = 0; m < 70; ++m) {
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(2);
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
}
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(2);
- expected_congestion_window += kMaxPacketSize;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ expected_send_window += kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
}
TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
@@ -182,16 +191,16 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
for (int i = 0; i < kNumberOfAck; ++i) {
- // Send our full congestion window.
- SendAvailableCongestionWindow();
+ // Send our full send window.
+ SendAvailableSendWindow();
AckNPackets(2);
}
- SendAvailableCongestionWindow();
- QuicByteCount expected_congestion_window = kDefaultWindowTCP +
- (kMaxPacketSize * 2 * kNumberOfAck);
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ SendAvailableSendWindow();
+ QuicByteCount expected_send_window = kDefaultWindowTCP +
+ (kDefaultTCPMSS * 2 * kNumberOfAck);
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
- sender_->OnIncomingLoss(clock_.Now());
+ sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
// Make sure that we should not send right now.
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(), NOT_RETRANSMISSION,
@@ -199,32 +208,40 @@ TEST_F(TcpCubicSenderTest, SlowStartPacketLoss) {
// We should now have fallen out of slow start.
// We expect window to be cut in half.
- expected_congestion_window /= 2;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ expected_send_window /= 2;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
// Testing Reno phase.
// We need to ack half of the pending packet before we can send again.
- int number_of_packets_in_window = expected_congestion_window / kMaxPacketSize;
+ int number_of_packets_in_window = expected_send_window / kDefaultTCPMSS;
AckNPackets(number_of_packets_in_window);
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
- EXPECT_EQ(0u, sender_->AvailableCongestionWindow());
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
+ EXPECT_EQ(0u, sender_->AvailableSendWindow());
AckNPackets(1);
- expected_congestion_window += kMaxPacketSize;
+ expected_send_window += kDefaultTCPMSS;
number_of_packets_in_window++;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
// We should need number_of_packets_in_window ACK:ed packets before
// increasing window by one.
for (int k = 0; k < number_of_packets_in_window; ++k) {
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(1);
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
}
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(1);
- expected_congestion_window += kMaxPacketSize;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ expected_send_window += kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
+}
+
+TEST_F(TcpCubicSenderTest, RTOCongestionWindow) {
+ EXPECT_EQ(kDefaultWindowTCP, sender_->SendWindow());
+
+ // Expect the window to decrease to the minimum once the RTO fires.
+ sender_->OnRetransmissionTimeout();
+ EXPECT_EQ(2 * kDefaultTCPMSS, sender_->SendWindow());
}
TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
@@ -254,9 +271,13 @@ TEST_F(TcpCubicSenderTest, RetransmissionDelay) {
EXPECT_NEAR(expected_delay.ToMilliseconds(),
sender_->RetransmissionDelay().ToMilliseconds(),
1);
+ EXPECT_EQ(static_cast<int64>(
+ sender_->GetCongestionWindow() * kNumMicrosPerSecond /
+ sender_->SmoothedRtt().ToMicroseconds()),
+ sender_->BandwidthEstimate().ToBytesPerSecond());
}
-TEST_F(TcpCubicSenderTest, SlowStartMaxCongestionWindow) {
+TEST_F(TcpCubicSenderTest, SlowStartMaxSendWindow) {
const QuicTcpCongestionWindow kMaxCongestionWindowTCP = 50;
const int kNumberOfAck = 100;
sender_.reset(
@@ -275,13 +296,13 @@ TEST_F(TcpCubicSenderTest, SlowStartMaxCongestionWindow) {
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
for (int i = 0; i < kNumberOfAck; ++i) {
- // Send our full congestion window.
- SendAvailableCongestionWindow();
+ // Send our full send window.
+ SendAvailableSendWindow();
AckNPackets(2);
}
- QuicByteCount expected_congestion_window =
- kMaxCongestionWindowTCP * kMaxPacketSize;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ QuicByteCount expected_send_window =
+ kMaxCongestionWindowTCP * kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
}
TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
@@ -302,20 +323,20 @@ TEST_F(TcpCubicSenderTest, TcpRenoMaxCongestionWindow) {
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(2);
// Make sure we fall out of slow start.
- sender_->OnIncomingLoss(clock_.Now());
+ sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
for (int i = 0; i < kNumberOfAck; ++i) {
- // Send our full congestion window.
- SendAvailableCongestionWindow();
+ // Send our full send window.
+ SendAvailableSendWindow();
AckNPackets(2);
}
- QuicByteCount expected_congestion_window =
- kMaxCongestionWindowTCP * kMaxPacketSize;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ QuicByteCount expected_send_window =
+ kMaxCongestionWindowTCP * kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
}
TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
@@ -336,37 +357,64 @@ TEST_F(TcpCubicSenderTest, TcpCubicMaxCongestionWindow) {
EXPECT_TRUE(sender_->TimeUntilSend(clock_.Now(),
NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE).IsZero());
- SendAvailableCongestionWindow();
+ SendAvailableSendWindow();
AckNPackets(2);
// Make sure we fall out of slow start.
- sender_->OnIncomingLoss(clock_.Now());
+ sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
for (int i = 0; i < kNumberOfAck; ++i) {
- // Send our full congestion window.
- SendAvailableCongestionWindow();
+ // Send our full send window.
+ SendAvailableSendWindow();
AckNPackets(2);
}
- QuicByteCount expected_congestion_window =
- kMaxCongestionWindowTCP * kMaxPacketSize;
- EXPECT_EQ(expected_congestion_window, sender_->CongestionWindow());
+ QuicByteCount expected_send_window =
+ kMaxCongestionWindowTCP * kDefaultTCPMSS;
+ EXPECT_EQ(expected_send_window, sender_->SendWindow());
+}
+
+TEST_F(TcpCubicSenderTest, MultipleLossesInOneWindow) {
+ SendAvailableSendWindow();
+ const QuicByteCount initial_window = sender_->GetCongestionWindow();
+ sender_->OnPacketLost(acked_sequence_number_ + 1, clock_.Now());
+ const QuicByteCount post_loss_window = sender_->GetCongestionWindow();
+ EXPECT_GT(initial_window, post_loss_window);
+ sender_->OnPacketLost(acked_sequence_number_ + 3, clock_.Now());
+ EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
+ sender_->OnPacketLost(sequence_number_ - 1, clock_.Now());
+ EXPECT_EQ(post_loss_window, sender_->GetCongestionWindow());
+
+ // Lose a later packet and ensure the window decreases.
+ sender_->OnPacketLost(sequence_number_, clock_.Now());
+ EXPECT_GT(post_loss_window, sender_->GetCongestionWindow());
}
-TEST_F(TcpCubicSenderTest, CongestionWindowNotAffectedByAcks) {
- QuicByteCount congestion_window = sender_->AvailableCongestionWindow();
+TEST_F(TcpCubicSenderTest, SendWindowNotAffectedByAcks) {
+ QuicByteCount send_window = sender_->AvailableSendWindow();
// Send a packet with no retransmittable data, and ensure that the congestion
// window doesn't change.
- QuicByteCount bytes_in_packet = std::min(kMaxPacketSize, congestion_window);
- sender_->SentPacket(clock_.Now(), sequence_number_++, bytes_in_packet,
- NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
- EXPECT_EQ(congestion_window, sender_->AvailableCongestionWindow());
+ QuicByteCount bytes_in_packet = std::min(kDefaultTCPMSS, send_window);
+ sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
+ NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
+ EXPECT_EQ(send_window, sender_->AvailableSendWindow());
// Send a data packet with retransmittable data, and ensure that the
// congestion window has shrunk.
- sender_->SentPacket(clock_.Now(), sequence_number_++, bytes_in_packet,
- NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
- EXPECT_GT(congestion_window, sender_->AvailableCongestionWindow());
+ sender_->OnPacketSent(clock_.Now(), sequence_number_++, bytes_in_packet,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ EXPECT_GT(send_window, sender_->AvailableSendWindow());
+}
+
+TEST_F(TcpCubicSenderTest, ConfigureMaxInitialWindow) {
+ QuicTcpCongestionWindow congestion_window = sender_->congestion_window();
+ QuicConfig config;
+ config.set_server_initial_congestion_window(2 * congestion_window,
+ 2 * congestion_window);
+ EXPECT_EQ(2 * congestion_window, config.server_initial_congestion_window());
+
+ sender_->SetFromConfig(config, true);
+ EXPECT_EQ(2 * congestion_window, sender_->congestion_window());
}
} // namespace test
diff --git a/chromium/net/quic/congestion_control/tcp_receiver.cc b/chromium/net/quic/congestion_control/tcp_receiver.cc
index 465e40f194a..ecff130b003 100644
--- a/chromium/net/quic/congestion_control/tcp_receiver.cc
+++ b/chromium/net/quic/congestion_control/tcp_receiver.cc
@@ -7,8 +7,9 @@
namespace net {
+// static
// Originally 64K bytes for TCP, setting it to 256K to support higher bitrates.
-const QuicByteCount kReceiveWindowTCP = 256000;
+const QuicByteCount TcpReceiver::kReceiveWindowTCP = 256000;
TcpReceiver::TcpReceiver()
: accumulated_number_of_recoverd_lost_packets_(0),
diff --git a/chromium/net/quic/congestion_control/tcp_receiver.h b/chromium/net/quic/congestion_control/tcp_receiver.h
index 695ffbbac41..99cf93c4933 100644
--- a/chromium/net/quic/congestion_control/tcp_receiver.h
+++ b/chromium/net/quic/congestion_control/tcp_receiver.h
@@ -20,6 +20,9 @@ class NET_EXPORT_PRIVATE TcpReceiver : public ReceiveAlgorithmInterface {
public:
TcpReceiver();
+ // Size of the (currently fixed) receive window.
+ static const QuicByteCount kReceiveWindowTCP;
+
// Start implementation of SendAlgorithmInterface.
virtual bool GenerateCongestionFeedback(
QuicCongestionFeedbackFrame* feedback) OVERRIDE;
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 5dc12c8f9c9..aba610f25df 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter.h
@@ -60,6 +60,8 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Decrypter : public QuicDecrypter {
unsigned char nonce_prefix_[4];
#if defined(USE_OPENSSL)
+ // TODO(rtenneti): when Chromium's version of OpenSSL has EVP_AEAD_CTX, merge
+ // internal CL 53267501.
ScopedEVPCipherCtx ctx_;
#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 e3fc1b6f0ae..e0b42378021 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
@@ -104,7 +104,6 @@ CK_MECHANISM_TYPE GcmSupportChecker::aes_key_mechanism_ = CKM_AES_GCM;
base::LazyInstance<GcmSupportChecker>::Leaky g_gcm_support_checker =
LAZY_INSTANCE_INITIALIZER;
-const size_t kKeySize = 16;
const size_t kNoncePrefixSize = 4;
const size_t kAESNonceSize = 12;
@@ -143,7 +142,7 @@ SECStatus My_Decrypt(PK11SymKey* key,
DCHECK_EQ(gcm_params->ulTagBits,
static_cast<CK_ULONG>(Aes128Gcm12Decrypter::kAuthTagSize * 8));
if (gcm_params->ulIvLen != 12u) {
- DLOG(INFO) << "ulIvLen is not equal to 12";
+ DVLOG(1) << "ulIvLen is not equal to 12";
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
@@ -155,20 +154,20 @@ SECStatus My_Decrypt(PK11SymKey* key,
crypto::ScopedPK11Context ctx(PK11_CreateContextBySymKey(
CKM_AES_ECB, CKA_ENCRYPT, key, &my_param));
if (!ctx) {
- DLOG(INFO) << "PK11_CreateContextBySymKey failed";
+ DVLOG(1) << "PK11_CreateContextBySymKey failed";
return SECFailure;
}
int output_len;
if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key),
ghash_key, sizeof(ghash_key)) != SECSuccess) {
- DLOG(INFO) << "PK11_CipherOp failed";
+ DVLOG(1) << "PK11_CipherOp failed";
return SECFailure;
}
PK11_Finalize(ctx.get());
if (output_len != sizeof(ghash_key)) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -189,7 +188,7 @@ SECStatus My_Decrypt(PK11SymKey* key,
ctx.reset(PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key,
&my_param));
if (!ctx) {
- DLOG(INFO) << "PK11_CreateContextBySymKey failed";
+ DVLOG(1) << "PK11_CreateContextBySymKey failed";
return SECFailure;
}
@@ -197,11 +196,11 @@ SECStatus My_Decrypt(PK11SymKey* key,
unsigned char tag_mask[16] = {0};
if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask),
tag_mask, sizeof(tag_mask)) != SECSuccess) {
- DLOG(INFO) << "PK11_CipherOp failed";
+ DVLOG(1) << "PK11_CipherOp failed";
return SECFailure;
}
if (output_len != sizeof(tag_mask)) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -217,7 +216,7 @@ SECStatus My_Decrypt(PK11SymKey* key,
if (PK11_CipherOp(ctx.get(), out, &output_len, max_len,
const_cast<unsigned char*>(enc),
enc_len - Aes128Gcm12Decrypter::kAuthTagSize) != SECSuccess) {
- DLOG(INFO) << "PK11_CipherOp failed";
+ DVLOG(1) << "PK11_CipherOp failed";
return SECFailure;
}
@@ -225,7 +224,7 @@ SECStatus My_Decrypt(PK11SymKey* key,
if (static_cast<unsigned int>(output_len) !=
enc_len - Aes128Gcm12Decrypter::kAuthTagSize) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -315,7 +314,7 @@ bool Aes128Gcm12Decrypter::Decrypt(StringPiece nonce,
PK11_FreeSlot(slot);
slot = NULL;
if (!aes_key) {
- DLOG(INFO) << "PK11_ImportSymKey failed";
+ DVLOG(1) << "PK11_ImportSymKey failed";
return false;
}
@@ -334,18 +333,15 @@ bool Aes128Gcm12Decrypter::Decrypt(StringPiece nonce,
param.len = sizeof(gcm_params);
unsigned int output_len;
- // If an incorrect authentication tag causes a decryption failure, the NSS
- // error is SEC_ERROR_BAD_DATA (-8190).
if (My_Decrypt(aes_key.get(), CKM_AES_GCM, &param,
output, &output_len, ciphertext.length(),
reinterpret_cast<const unsigned char*>(ciphertext.data()),
ciphertext.length()) != SECSuccess) {
- DLOG(INFO) << "My_Decrypt failed: NSS error " << PORT_GetError();
return false;
}
if (output_len != plaintext_size) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
return false;
}
*output_length = output_len;
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc
index cbc7a8426d3..56317fdd3c4 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc
@@ -12,14 +12,9 @@ using base::StringPiece;
namespace net {
-namespace {
-
-const size_t kKeySize = 16;
const size_t kNoncePrefixSize = 4;
const size_t kAESNonceSize = 12;
-} // namespace
-
Aes128Gcm12Decrypter::Aes128Gcm12Decrypter() {}
Aes128Gcm12Decrypter::~Aes128Gcm12Decrypter() {}
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 cea6a6e5b6c..dd37085894c 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
@@ -245,47 +245,6 @@ const TestVector* const test_group_array[] = {
test_group_5,
};
-// Returns true if |ch| is a lowercase hexadecimal digit.
-bool IsHexDigit(char ch) {
- return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f');
-}
-
-// Converts a lowercase hexadecimal digit to its integer value.
-int HexDigitToInt(char ch) {
- if ('0' <= ch && ch <= '9') {
- return ch - '0';
- }
- return ch - 'a' + 10;
-}
-
-// |in| is a string consisting of lowercase hexadecimal digits, where
-// every two digits represent one byte. |out| is a buffer of size |max_len|.
-// Converts |in| to bytes and stores the bytes in the |out| buffer. The
-// number of bytes converted is returned in |*out_len|. Returns true on
-// success, false on failure.
-bool DecodeHexString(const char* in,
- char* out,
- size_t* out_len,
- size_t max_len) {
- if (!in) {
- *out_len = (size_t)-1;
- return true;
- }
- *out_len = 0;
- while (*in != '\0') {
- if (!IsHexDigit(*in) || !IsHexDigit(*(in + 1))) {
- return false;
- }
- if (*out_len >= max_len) {
- return false;
- }
- out[*out_len] = HexDigitToInt(*in) * 16 + HexDigitToInt(*(in + 1));
- (*out_len)++;
- in += 2;
- }
- return true;
-}
-
} // namespace
namespace net {
@@ -314,70 +273,64 @@ TEST(Aes128Gcm12DecrypterTest, Decrypt) {
return;
}
- char key[1024];
- size_t key_len;
- char iv[1024];
- size_t iv_len;
- char ct[1024];
- size_t ct_len;
- char aad[1024];
- size_t aad_len;
- char tag[1024];
- size_t tag_len;
- char pt[1024];
- size_t pt_len;
+ string key;
+ string iv;
+ string ct;
+ string aad;
+ string tag;
+ string pt;
for (size_t i = 0; i < arraysize(test_group_array); i++) {
SCOPED_TRACE(i);
const TestVector* test_vector = test_group_array[i];
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vector[j].key != NULL; j++) {
+ // If not present then decryption is expected to fail.
+ bool has_pt = test_vector[j].pt;
+
// Decode the test vector.
- ASSERT_TRUE(
- DecodeHexString(test_vector[j].key, key, &key_len, sizeof(key)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len, sizeof(iv)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len, sizeof(ct)));
- ASSERT_TRUE(
- DecodeHexString(test_vector[j].aad, aad, &aad_len, sizeof(aad)));
- ASSERT_TRUE(
- DecodeHexString(test_vector[j].tag, tag, &tag_len, sizeof(tag)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len, sizeof(pt)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].key, &key));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].iv, &iv));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].ct, &ct));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].aad, &aad));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].tag, &tag));
+ if (has_pt)
+ ASSERT_TRUE(DecodeHexString(test_vector[j].pt, &pt));
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
- EXPECT_EQ(test_info.key_len, key_len * 8);
- EXPECT_EQ(test_info.iv_len, iv_len * 8);
- EXPECT_EQ(test_info.pt_len, ct_len * 8);
- EXPECT_EQ(test_info.aad_len, aad_len * 8);
- EXPECT_EQ(test_info.tag_len, tag_len * 8);
- if (pt_len != static_cast<size_t>(-1)) {
- EXPECT_EQ(test_info.pt_len, pt_len * 8);
- }
+ EXPECT_EQ(test_info.key_len, key.size() * 8);
+ EXPECT_EQ(test_info.iv_len, iv.size() * 8);
+ EXPECT_EQ(test_info.pt_len, pt.size() * 8);
+ EXPECT_EQ(test_info.aad_len, aad.size() * 8);
+ EXPECT_EQ(test_info.tag_len, tag.size() * 8);
+ if (has_pt)
+ EXPECT_EQ(test_info.pt_len, pt.size() * 8);
// The test vectors have 16 byte authenticators but this code only uses
// the first 12.
ASSERT_LE(static_cast<size_t>(Aes128Gcm12Decrypter::kAuthTagSize),
- tag_len);
- tag_len = Aes128Gcm12Decrypter::kAuthTagSize;
+ tag.size());
+ string ciphertext =
+ ct + tag.substr(0, Aes128Gcm12Decrypter::kAuthTagSize);
Aes128Gcm12Decrypter decrypter;
- ASSERT_TRUE(decrypter.SetKey(StringPiece(key, key_len)));
- string ciphertext(ct, ct_len);
- ciphertext.append(tag, tag_len);
+ ASSERT_TRUE(decrypter.SetKey(key));
+
scoped_ptr<QuicData> decrypted(DecryptWithNonce(
- &decrypter, StringPiece(iv, iv_len),
+ &decrypter, iv,
// OpenSSL fails if NULL is set as the AAD, as opposed to a
// zero-length, non-NULL pointer.
- StringPiece(aad_len ? aad : NULL, aad_len), ciphertext));
+ aad.size() ? aad : StringPiece(), ciphertext));
if (!decrypted.get()) {
- EXPECT_EQ((size_t)-1, pt_len);
+ EXPECT_FALSE(has_pt);
continue;
}
- ASSERT_NE((size_t)-1, pt_len);
+ EXPECT_TRUE(has_pt);
- ASSERT_EQ(pt_len, decrypted->length());
+ ASSERT_EQ(pt.size(), decrypted->length());
test::CompareCharArraysWithHexError("plaintext", decrypted->data(),
- pt_len, pt, pt_len);
+ pt.size(), pt.data(), pt.size());
}
}
}
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter.h b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter.h
index ca9a2b1fca6..a2d1dc9a088 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter.h
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter.h
@@ -36,9 +36,6 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Encrypter : public QuicEncrypter {
Aes128Gcm12Encrypter();
virtual ~Aes128Gcm12Encrypter();
- // Returns true if the underlying crypto library supports AES GCM.
- static bool IsSupported();
-
// QuicEncrypter implementation
virtual bool SetKey(base::StringPiece key) OVERRIDE;
virtual bool SetNoncePrefix(base::StringPiece nonce_prefix) OVERRIDE;
@@ -63,6 +60,8 @@ class NET_EXPORT_PRIVATE Aes128Gcm12Encrypter : public QuicEncrypter {
unsigned char nonce_prefix_[4];
#if defined(USE_OPENSSL)
+ // TODO(rtenneti): when Chromium's version of OpenSSL has EVP_AEAD_CTX, merge
+ // internal CL 53267501.
ScopedEVPCipherCtx ctx_;
#endif
};
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
index ae6adab462b..2cd072af461 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_nss.cc
@@ -138,7 +138,7 @@ SECStatus My_Encrypt(PK11SymKey* key,
DCHECK_EQ(param->len, sizeof(CK_GCM_PARAMS));
if (max_len < static_cast<unsigned int>(Aes128Gcm12Encrypter::kAuthTagSize)) {
- DLOG(INFO) << "max_len is less than kAuthTagSize";
+ DVLOG(1) << "max_len is less than kAuthTagSize";
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
@@ -149,7 +149,7 @@ SECStatus My_Encrypt(PK11SymKey* key,
DCHECK_EQ(gcm_params->ulTagBits,
static_cast<CK_ULONG>(Aes128Gcm12Encrypter::kAuthTagSize * 8));
if (gcm_params->ulIvLen != 12u) {
- DLOG(INFO) << "ulIvLen is not equal to 12";
+ DVLOG(1) << "ulIvLen is not equal to 12";
PORT_SetError(SEC_ERROR_INPUT_LEN);
return SECFailure;
}
@@ -161,20 +161,20 @@ SECStatus My_Encrypt(PK11SymKey* key,
crypto::ScopedPK11Context ctx(PK11_CreateContextBySymKey(
CKM_AES_ECB, CKA_ENCRYPT, key, &my_param));
if (!ctx) {
- DLOG(INFO) << "PK11_CreateContextBySymKey failed";
+ DVLOG(1) << "PK11_CreateContextBySymKey failed";
return SECFailure;
}
int output_len;
if (PK11_CipherOp(ctx.get(), ghash_key, &output_len, sizeof(ghash_key),
ghash_key, sizeof(ghash_key)) != SECSuccess) {
- DLOG(INFO) << "PK11_CipherOp failed";
+ DVLOG(1) << "PK11_CipherOp failed";
return SECFailure;
}
PK11_Finalize(ctx.get());
if (output_len != sizeof(ghash_key)) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -195,7 +195,7 @@ SECStatus My_Encrypt(PK11SymKey* key,
ctx.reset(PK11_CreateContextBySymKey(CKM_AES_CTR, CKA_ENCRYPT, key,
&my_param));
if (!ctx) {
- DLOG(INFO) << "PK11_CreateContextBySymKey failed";
+ DVLOG(1) << "PK11_CreateContextBySymKey failed";
return SECFailure;
}
@@ -203,11 +203,11 @@ SECStatus My_Encrypt(PK11SymKey* key,
unsigned char tag_mask[16] = {0};
if (PK11_CipherOp(ctx.get(), tag_mask, &output_len, sizeof(tag_mask),
tag_mask, sizeof(tag_mask)) != SECSuccess) {
- DLOG(INFO) << "PK11_CipherOp failed";
+ DVLOG(1) << "PK11_CipherOp failed";
return SECFailure;
}
if (output_len != sizeof(tag_mask)) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -217,21 +217,21 @@ SECStatus My_Encrypt(PK11SymKey* key,
// https://bugzilla.mozilla.org/show_bug.cgi?id=808218).
if (PK11_CipherOp(ctx.get(), out, &output_len, max_len,
const_cast<unsigned char*>(data), data_len) != SECSuccess) {
- DLOG(INFO) << "PK11_CipherOp failed";
+ DVLOG(1) << "PK11_CipherOp failed";
return SECFailure;
}
PK11_Finalize(ctx.get());
if (static_cast<unsigned int>(output_len) != data_len) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if ((max_len - Aes128Gcm12Encrypter::kAuthTagSize) <
static_cast<unsigned int>(output_len)) {
- DLOG(INFO) << "(max_len - kAuthTagSize) is less than output_len";
+ DVLOG(1) << "(max_len - kAuthTagSize) is less than output_len";
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
@@ -256,14 +256,6 @@ Aes128Gcm12Encrypter::Aes128Gcm12Encrypter() {
Aes128Gcm12Encrypter::~Aes128Gcm12Encrypter() {}
-// static
-bool Aes128Gcm12Encrypter::IsSupported() {
- // NSS 3.15 supports CKM_AES_GCM directly.
- // NSS 3.14 supports CKM_AES_CTR, which can be used to emulate CKM_AES_GCM.
- // Versions earlier than NSS 3.14 are not supported.
- return NSS_VersionCheck("3.14") != PR_FALSE;
-}
-
bool Aes128Gcm12Encrypter::SetKey(StringPiece key) {
DCHECK_EQ(key.size(), sizeof(key_));
if (key.size() != sizeof(key_)) {
@@ -308,7 +300,7 @@ bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce,
PK11_FreeSlot(slot);
slot = NULL;
if (!aes_key) {
- DLOG(INFO) << "PK11_ImportSymKey failed";
+ DVLOG(1) << "PK11_ImportSymKey failed";
return false;
}
@@ -331,12 +323,12 @@ bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce,
output, &output_len, ciphertext_size,
reinterpret_cast<const unsigned char*>(plaintext.data()),
plaintext.size()) != SECSuccess) {
- DLOG(INFO) << "My_Encrypt failed";
+ DVLOG(1) << "My_Encrypt failed";
return false;
}
if (output_len != ciphertext_size) {
- DLOG(INFO) << "Wrong output length";
+ DVLOG(1) << "Wrong output length";
return false;
}
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc
index 166fd55cb7c..394971a7382 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc
@@ -4,6 +4,7 @@
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
+#include <openssl/err.h>
#include <openssl/evp.h>
#include <string.h>
@@ -19,15 +20,24 @@ const size_t kKeySize = 16;
const size_t kNoncePrefixSize = 4;
const size_t kAESNonceSize = 12;
+void ClearOpenSslErrors() {
+#ifdef NDEBUG
+ while (ERR_get_error()) {}
+#else
+ while (long error = ERR_get_error()) {
+ char buf[120];
+ ERR_error_string_n(error, buf, arraysize(buf));
+ DLOG(ERROR) << "OpenSSL error: " << buf;
+ }
+#endif
+}
+
} // namespace
Aes128Gcm12Encrypter::Aes128Gcm12Encrypter() {}
Aes128Gcm12Encrypter::~Aes128Gcm12Encrypter() {}
-// static
-bool Aes128Gcm12Encrypter::IsSupported() { return true; }
-
bool Aes128Gcm12Encrypter::SetKey(StringPiece key) {
DCHECK_EQ(key.size(), sizeof(key_));
if (key.size() != sizeof(key_)) {
@@ -38,12 +48,14 @@ bool Aes128Gcm12Encrypter::SetKey(StringPiece key) {
// Set the cipher type and the key.
if (EVP_EncryptInit_ex(ctx_.get(), EVP_aes_128_gcm(), NULL, key_,
NULL) == 0) {
+ ClearOpenSslErrors();
return false;
}
// Set the IV (nonce) length.
if (EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_GCM_SET_IVLEN, kAESNonceSize,
NULL) == 0) {
+ ClearOpenSslErrors();
return false;
}
@@ -72,6 +84,7 @@ bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce,
if (EVP_EncryptInit_ex(
ctx_.get(), NULL, NULL, NULL,
reinterpret_cast<const unsigned char*>(nonce.data())) == 0) {
+ ClearOpenSslErrors();
return false;
}
@@ -85,6 +98,7 @@ bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce,
ctx_.get(), NULL, &unused_len,
reinterpret_cast<const unsigned char*>(associated_data.data()),
associated_data.size()) == 0) {
+ ClearOpenSslErrors();
return false;
}
}
@@ -94,17 +108,20 @@ bool Aes128Gcm12Encrypter::Encrypt(StringPiece nonce,
ctx_.get(), output, &len,
reinterpret_cast<const unsigned char*>(plaintext.data()),
plaintext.size()) == 0) {
+ ClearOpenSslErrors();
return false;
}
output += len;
if (EVP_EncryptFinal_ex(ctx_.get(), output, &len) == 0) {
+ ClearOpenSslErrors();
return false;
}
output += len;
if (EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_GCM_GET_TAG, kAuthTagSize,
output) == 0) {
+ ClearOpenSslErrors();
return false;
}
diff --git a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc
index 0c9928bc570..bfbf93cd716 100644
--- a/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc
+++ b/chromium/net/quic/crypto/aes_128_gcm_12_encrypter_test.cc
@@ -201,43 +201,6 @@ const TestVector* const test_group_array[] = {
test_group_5,
};
-// Returns true if |ch| is a lowercase hexadecimal digit.
-bool IsHexDigit(char ch) {
- return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f');
-}
-
-// Converts a lowercase hexadecimal digit to its integer value.
-int HexDigitToInt(char ch) {
- if ('0' <= ch && ch <= '9') {
- return ch - '0';
- }
- return ch - 'a' + 10;
-}
-
-// |in| is a string consisting of lowercase hexadecimal digits, where
-// every two digits represent one byte. |out| is a buffer of size |max_len|.
-// Converts |in| to bytes and stores the bytes in the |out| buffer. The
-// number of bytes converted is returned in |*out_len|. Returns true on
-// success, false on failure.
-bool DecodeHexString(const char* in,
- char* out,
- size_t* out_len,
- size_t max_len) {
- *out_len = 0;
- while (*in != '\0') {
- if (!IsHexDigit(*in) || !IsHexDigit(*(in + 1))) {
- return false;
- }
- if (*out_len >= max_len) {
- return false;
- }
- out[*out_len] = HexDigitToInt(*in) * 16 + HexDigitToInt(*(in + 1));
- (*out_len)++;
- in += 2;
- }
- return true;
-}
-
} // namespace
namespace net {
@@ -261,23 +224,12 @@ QuicData* EncryptWithNonce(Aes128Gcm12Encrypter* encrypter,
}
TEST(Aes128Gcm12EncrypterTest, Encrypt) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
- char key[1024];
- size_t key_len;
- char iv[1024];
- size_t iv_len;
- char pt[1024];
- size_t pt_len;
- char aad[1024];
- size_t aad_len;
- char ct[1024];
- size_t ct_len;
- char tag[1024];
- size_t tag_len;
+ string key;
+ string iv;
+ string pt;
+ string aad;
+ string ct;
+ string tag;
for (size_t i = 0; i < arraysize(test_group_array); i++) {
SCOPED_TRACE(i);
@@ -285,47 +237,44 @@ TEST(Aes128Gcm12EncrypterTest, Encrypt) {
const TestGroupInfo& test_info = test_group_info[i];
for (size_t j = 0; test_vector[j].key != NULL; j++) {
// Decode the test vector.
- ASSERT_TRUE(
- DecodeHexString(test_vector[j].key, key, &key_len, sizeof(key)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].iv, iv, &iv_len, sizeof(iv)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].pt, pt, &pt_len, sizeof(pt)));
- ASSERT_TRUE(
- DecodeHexString(test_vector[j].aad, aad, &aad_len, sizeof(aad)));
- ASSERT_TRUE(DecodeHexString(test_vector[j].ct, ct, &ct_len, sizeof(ct)));
- ASSERT_TRUE(
- DecodeHexString(test_vector[j].tag, tag, &tag_len, sizeof(tag)));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].key, &key));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].iv, &iv));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].pt, &pt));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].aad, &aad));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].ct, &ct));
+ ASSERT_TRUE(DecodeHexString(test_vector[j].tag, &tag));
// The test vector's lengths should look sane. Note that the lengths
// in |test_info| are in bits.
- EXPECT_EQ(test_info.key_len, key_len * 8);
- EXPECT_EQ(test_info.iv_len, iv_len * 8);
- EXPECT_EQ(test_info.pt_len, pt_len * 8);
- EXPECT_EQ(test_info.aad_len, aad_len * 8);
- EXPECT_EQ(test_info.pt_len, ct_len * 8);
- EXPECT_EQ(test_info.tag_len, tag_len * 8);
+ EXPECT_EQ(test_info.key_len, key.size() * 8);
+ EXPECT_EQ(test_info.iv_len, iv.size() * 8);
+ EXPECT_EQ(test_info.pt_len, pt.size() * 8);
+ EXPECT_EQ(test_info.aad_len, aad.size() * 8);
+ EXPECT_EQ(test_info.pt_len, ct.size() * 8);
+ EXPECT_EQ(test_info.tag_len, tag.size() * 8);
Aes128Gcm12Encrypter encrypter;
- ASSERT_TRUE(encrypter.SetKey(StringPiece(key, key_len)));
+ ASSERT_TRUE(encrypter.SetKey(key));
scoped_ptr<QuicData> encrypted(EncryptWithNonce(
- &encrypter, StringPiece(iv, iv_len),
+ &encrypter, iv,
// OpenSSL fails if NULL is set as the AAD, as opposed to a
// zero-length, non-NULL pointer. This deliberately tests that we
// handle this case.
- StringPiece(aad_len ? aad : NULL, aad_len), StringPiece(pt, pt_len)));
+ aad.size() ? aad : StringPiece(), pt));
ASSERT_TRUE(encrypted.get());
// The test vectors have 16 byte authenticators but this code only uses
// the first 12.
ASSERT_LE(static_cast<size_t>(Aes128Gcm12Encrypter::kAuthTagSize),
- tag_len);
- tag_len = Aes128Gcm12Encrypter::kAuthTagSize;
+ tag.size());
+ size_t tag_len = Aes128Gcm12Encrypter::kAuthTagSize;
- ASSERT_EQ(ct_len + tag_len, encrypted->length());
+ ASSERT_EQ(ct.size() + tag_len, encrypted->length());
test::CompareCharArraysWithHexError("ciphertext", encrypted->data(),
- ct_len, ct, ct_len);
+ ct.size(), ct.data(), ct.size());
test::CompareCharArraysWithHexError(
- "authentication tag", encrypted->data() + ct_len, tag_len, tag,
- tag_len);
+ "authentication tag", encrypted->data() + ct.size(), tag_len,
+ tag.data(), tag_len);
}
}
}
diff --git a/chromium/net/quic/crypto/channel_id_test.cc b/chromium/net/quic/crypto/channel_id_test.cc
index d29bfced059..48319ec334b 100644
--- a/chromium/net/quic/crypto/channel_id_test.cc
+++ b/chromium/net/quic/crypto/channel_id_test.cc
@@ -5,6 +5,7 @@
#include "net/quic/crypto/channel_id.h"
#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -185,85 +186,36 @@ const TestVector test_vector[] = {
{ NULL }
};
-// Returns true if |ch| is a lowercase hexadecimal digit.
-bool IsHexDigit(char ch) {
- return ('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'f');
-}
-
-// Converts a lowercase hexadecimal digit to its integer value.
-int HexDigitToInt(char ch) {
- if ('0' <= ch && ch <= '9') {
- return ch - '0';
- }
- return ch - 'a' + 10;
-}
-
-// |in| is a string consisting of lowercase hexadecimal digits, where
-// every two digits represent one byte. |out| is a buffer of size |max_len|.
-// Converts |in| to bytes and stores the bytes in the |out| buffer. The
-// number of bytes converted is returned in |*out_len|. Returns true on
-// success, false on failure.
-bool DecodeHexString(const char* in,
- char* out,
- size_t* out_len,
- size_t max_len) {
- if (!in) {
- *out_len = (size_t)-1;
- return true;
- }
- *out_len = 0;
- while (*in != '\0') {
- if (!IsHexDigit(*in) || !IsHexDigit(*(in + 1))) {
- return false;
- }
- if (*out_len >= max_len) {
- return false;
- }
- out[*out_len] = HexDigitToInt(*in) * 16 + HexDigitToInt(*(in + 1));
- (*out_len)++;
- in += 2;
- }
- return true;
-}
-
} // namespace
// A known answer test for ChannelIDVerifier.
TEST(ChannelIDTest, VerifyKnownAnswerTest) {
- char msg[1024];
- size_t msg_len;
- char key[64];
- size_t qx_len;
- size_t qy_len;
- char signature[64];
- size_t r_len;
- size_t s_len;
+ string msg;
+ string qx;
+ string qy;
+ string r;
+ string s;
for (size_t i = 0; test_vector[i].msg != NULL; i++) {
SCOPED_TRACE(i);
// Decode the test vector.
- ASSERT_TRUE(
- DecodeHexString(test_vector[i].msg, msg, &msg_len, sizeof(msg)));
- ASSERT_TRUE(DecodeHexString(test_vector[i].qx, key, &qx_len, sizeof(key)));
- ASSERT_TRUE(DecodeHexString(test_vector[i].qy, key + qx_len, &qy_len,
- sizeof(key) - qx_len));
- ASSERT_TRUE(DecodeHexString(test_vector[i].r, signature, &r_len,
- sizeof(signature)));
- ASSERT_TRUE(DecodeHexString(test_vector[i].s, signature + r_len, &s_len,
- sizeof(signature) - r_len));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].msg, &msg));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].qx, &qx));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].qy, &qy));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].r, &r));
+ ASSERT_TRUE(DecodeHexString(test_vector[i].s, &s));
+
+ string key = qx + qy;
+ string signature = r + s;
// The test vector's lengths should look sane.
- EXPECT_EQ(sizeof(key) / 2, qx_len);
- EXPECT_EQ(sizeof(key) / 2, qy_len);
- EXPECT_EQ(sizeof(signature) / 2, r_len);
- EXPECT_EQ(sizeof(signature) / 2, s_len);
+ EXPECT_EQ(32u, qx.size());
+ EXPECT_EQ(32u, qy.size());
+ EXPECT_EQ(32u, r.size());
+ EXPECT_EQ(32u, s.size());
EXPECT_EQ(test_vector[i].result,
- ChannelIDVerifier::VerifyRaw(
- StringPiece(key, sizeof(key)),
- StringPiece(msg, msg_len),
- StringPiece(signature, sizeof(signature)),
- false));
+ ChannelIDVerifier::VerifyRaw(key, msg, signature, false));
}
}
diff --git a/chromium/net/quic/crypto/common_cert_set_test.cc b/chromium/net/quic/crypto/common_cert_set_test.cc
index 325d0b2c1f3..e15a10ef7ff 100644
--- a/chromium/net/quic/crypto/common_cert_set_test.cc
+++ b/chromium/net/quic/crypto/common_cert_set_test.cc
@@ -90,7 +90,7 @@ TEST(CommonCertSets, FindGIA) {
StringPiece gia_copy = sets->GetCert(hash, index);
EXPECT_FALSE(gia_copy.empty());
ASSERT_EQ(gia.size(), gia_copy.size());
- EXPECT_TRUE(0 == memcmp(gia.data(), gia_copy.data(), gia.size()));
+ EXPECT_EQ(0, memcmp(gia.data(), gia_copy.data(), gia.size()));
}
TEST(CommonCertSets, NonMatch) {
diff --git a/chromium/net/quic/crypto/crypto_handshake.cc b/chromium/net/quic/crypto/crypto_handshake.cc
index 51465b75c4b..056272e9c94 100644
--- a/chromium/net/quic/crypto/crypto_handshake.cc
+++ b/chromium/net/quic/crypto/crypto_handshake.cc
@@ -7,34 +7,22 @@
#include <ctype.h>
#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "crypto/secure_hash.h"
#include "net/base/net_util.h"
-#include "net/quic/crypto/cert_compressor.h"
-#include "net/quic/crypto/channel_id.h"
#include "net/quic/crypto/common_cert_set.h"
#include "net/quic/crypto/crypto_framer.h"
-#include "net/quic/crypto/crypto_utils.h"
-#include "net/quic/crypto/curve25519_key_exchange.h"
#include "net/quic/crypto/key_exchange.h"
-#include "net/quic/crypto/p256_key_exchange.h"
-#include "net/quic/crypto/proof_verifier.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
using base::StringPiece;
using base::StringPrintf;
-using std::map;
using std::string;
using std::vector;
@@ -261,8 +249,11 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
bool done = false;
switch (it->first) {
+ case kICSL:
+ case kIRTT:
case kKATO:
- case kVERS:
+ case kMSPC:
+ case kSWND:
// uint32 value
if (it->second.size() == 4) {
uint32 value;
@@ -271,10 +262,20 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
done = true;
}
break;
+ case kVERS:
+ // uint16 value
+ if (it->second.size() == 2) {
+ uint16 value;
+ memcpy(&value, it->second.data(), sizeof(value));
+ ret += base::UintToString(value);
+ done = true;
+ }
+ break;
case kKEXS:
case kAEAD:
case kCGST:
case kPDMD:
+ case kVER:
// tag lists
if (it->second.size() % sizeof(QuicTag) == 0) {
for (size_t j = 0; j < it->second.size(); j += sizeof(QuicTag)) {
@@ -283,7 +284,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (j > 0) {
ret += ",";
}
- ret += QuicUtils::TagToString(tag);
+ ret += "'" + QuicUtils::TagToString(tag) + "'";
}
done = true;
}
@@ -311,7 +312,7 @@ string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
if (!done) {
// If there's no specific format for this tag, or the value is invalid,
// then just use hex.
- ret += base::HexEncode(it->second.data(), it->second.size());
+ ret += "0x" + base::HexEncode(it->second.data(), it->second.size());
}
ret += "\n";
}
@@ -342,579 +343,9 @@ const char QuicCryptoConfig::kForwardSecureLabel[] =
"QUIC forward secure key expansion";
QuicCryptoConfig::QuicCryptoConfig()
- : version(0),
- common_cert_sets(CommonCertSets::GetInstanceQUIC()) {
+ : common_cert_sets(CommonCertSets::GetInstanceQUIC()) {
}
QuicCryptoConfig::~QuicCryptoConfig() {}
-QuicCryptoClientConfig::QuicCryptoClientConfig() {}
-
-QuicCryptoClientConfig::~QuicCryptoClientConfig() {
- STLDeleteValues(&cached_states_);
-}
-
-QuicCryptoClientConfig::CachedState::CachedState()
- : server_config_valid_(false),
- generation_counter_(0) {}
-
-QuicCryptoClientConfig::CachedState::~CachedState() {}
-
-bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const {
- if (server_config_.empty() || !server_config_valid_) {
- return false;
- }
-
- const CryptoHandshakeMessage* scfg = GetServerConfig();
- if (!scfg) {
- // Should be impossible short of cache corruption.
- DCHECK(false);
- return false;
- }
-
- uint64 expiry_seconds;
- if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR ||
- now.ToUNIXSeconds() >= expiry_seconds) {
- return false;
- }
-
- return true;
-}
-
-const CryptoHandshakeMessage*
-QuicCryptoClientConfig::CachedState::GetServerConfig() const {
- if (server_config_.empty()) {
- return NULL;
- }
-
- if (!scfg_.get()) {
- scfg_.reset(CryptoFramer::ParseMessage(server_config_));
- DCHECK(scfg_.get());
- }
- return scfg_.get();
-}
-
-QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig(
- StringPiece server_config, QuicWallTime now, string* error_details) {
- const bool matches_existing = server_config == server_config_;
-
- // Even if the new server config matches the existing one, we still wish to
- // reject it if it has expired.
- scoped_ptr<CryptoHandshakeMessage> new_scfg_storage;
- const CryptoHandshakeMessage* new_scfg;
-
- if (!matches_existing) {
- new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config));
- new_scfg = new_scfg_storage.get();
- } else {
- new_scfg = GetServerConfig();
- }
-
- if (!new_scfg) {
- *error_details = "SCFG invalid";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- uint64 expiry_seconds;
- if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
- *error_details = "SCFG missing EXPY";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- if (now.ToUNIXSeconds() >= expiry_seconds) {
- *error_details = "SCFG has expired";
- return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
- }
-
- if (!matches_existing) {
- server_config_ = server_config.as_string();
- SetProofInvalid();
- scfg_.reset(new_scfg_storage.release());
- }
- return QUIC_NO_ERROR;
-}
-
-void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
- server_config_.clear();
- scfg_.reset();
- SetProofInvalid();
-}
-
-void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
- StringPiece signature) {
- bool has_changed =
- signature != server_config_sig_ || certs_.size() != certs.size();
-
- if (!has_changed) {
- for (size_t i = 0; i < certs_.size(); i++) {
- if (certs_[i] != certs[i]) {
- has_changed = true;
- break;
- }
- }
- }
-
- if (!has_changed) {
- return;
- }
-
- // If the proof has changed then it needs to be revalidated.
- SetProofInvalid();
- certs_ = certs;
- server_config_sig_ = signature.as_string();
-}
-
-void QuicCryptoClientConfig::CachedState::ClearProof() {
- SetProofInvalid();
- certs_.clear();
- server_config_sig_.clear();
-}
-
-void QuicCryptoClientConfig::CachedState::SetProofValid() {
- server_config_valid_ = true;
-}
-
-void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
- server_config_valid_ = false;
- ++generation_counter_;
-}
-
-const string& QuicCryptoClientConfig::CachedState::server_config() const {
- return server_config_;
-}
-
-const string&
-QuicCryptoClientConfig::CachedState::source_address_token() const {
- return source_address_token_;
-}
-
-const vector<string>& QuicCryptoClientConfig::CachedState::certs() const {
- return certs_;
-}
-
-const string& QuicCryptoClientConfig::CachedState::signature() const {
- return server_config_sig_;
-}
-
-bool QuicCryptoClientConfig::CachedState::proof_valid() const {
- return server_config_valid_;
-}
-
-uint64 QuicCryptoClientConfig::CachedState::generation_counter() const {
- return generation_counter_;
-}
-
-const ProofVerifyDetails*
-QuicCryptoClientConfig::CachedState::proof_verify_details() const {
- return proof_verify_details_.get();
-}
-
-void QuicCryptoClientConfig::CachedState::set_source_address_token(
- StringPiece token) {
- source_address_token_ = token.as_string();
-}
-
-void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
- ProofVerifyDetails* details) {
- proof_verify_details_.reset(details);
-}
-
-void QuicCryptoClientConfig::SetDefaults() {
- // Version must be 0.
- // TODO(agl): this version stuff is obsolete now.
- version = QuicCryptoConfig::CONFIG_VERSION;
-
- // Key exchange methods.
- kexs.resize(2);
- kexs[0] = kC255;
- kexs[1] = kP256;
-
- // Authenticated encryption algorithms.
- aead.resize(1);
- aead[0] = kAESG;
-}
-
-QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
- const string& server_hostname) {
- map<string, CachedState*>::const_iterator it =
- cached_states_.find(server_hostname);
- if (it != cached_states_.end()) {
- return it->second;
- }
-
- CachedState* cached = new CachedState;
- cached_states_.insert(make_pair(server_hostname, cached));
- return cached;
-}
-
-void QuicCryptoClientConfig::FillInchoateClientHello(
- const string& server_hostname,
- const CachedState* cached,
- QuicCryptoNegotiatedParameters* out_params,
- CryptoHandshakeMessage* out) const {
- out->set_tag(kCHLO);
- out->set_minimum_size(kClientHelloMinimumSize);
-
- // Server name indication. We only send SNI if it's a valid domain name, as
- // per the spec.
- if (CryptoUtils::IsValidSNI(server_hostname)) {
- out->SetStringPiece(kSNI, server_hostname);
- }
- out->SetValue(kVERS, version);
-
- if (!cached->source_address_token().empty()) {
- out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
- }
-
- if (proof_verifier_.get()) {
- // Don't request ECDSA proofs on platforms that do not support ECDSA
- // certificates.
- bool disableECDSA = false;
-#if defined(OS_WIN)
- if (base::win::GetVersion() < base::win::VERSION_VISTA)
- disableECDSA = true;
-#endif
- if (disableECDSA) {
- out->SetTaglist(kPDMD, kX59R, 0);
- } else {
- out->SetTaglist(kPDMD, kX509, 0);
- }
-
- if (!cached->proof_valid()) {
- // If we are expecting a certificate chain, double the size of the client
- // hello so that the response from the server can be larger - hopefully
- // including the whole certificate chain.
- out->set_minimum_size(kClientHelloMinimumSize * 2);
- }
- }
-
- if (common_cert_sets) {
- out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes());
- }
-
- const vector<string>& certs = cached->certs();
- // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
- // client config is being used for multiple connections, another connection
- // doesn't update the cached certificates and cause us to be unable to
- // process the server's compressed certificate chain.
- out_params->cached_certs = certs;
- if (!certs.empty()) {
- vector<uint64> hashes;
- hashes.reserve(certs.size());
- for (vector<string>::const_iterator i = certs.begin();
- i != certs.end(); ++i) {
- hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
- }
- out->SetVector(kCCRT, hashes);
- }
-}
-
-QuicErrorCode QuicCryptoClientConfig::FillClientHello(
- const string& server_hostname,
- QuicGuid guid,
- const CachedState* cached,
- QuicWallTime now,
- QuicRandom* rand,
- QuicCryptoNegotiatedParameters* out_params,
- CryptoHandshakeMessage* out,
- string* error_details) const {
- DCHECK(error_details != NULL);
-
- FillInchoateClientHello(server_hostname, cached, out_params, out);
-
- const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
- if (!scfg) {
- // This should never happen as our caller should have checked
- // cached->IsComplete() before calling this function.
- *error_details = "Handshake not ready";
- return QUIC_CRYPTO_INTERNAL_ERROR;
- }
-
- StringPiece scid;
- if (!scfg->GetStringPiece(kSCID, &scid)) {
- *error_details = "SCFG missing SCID";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
- out->SetStringPiece(kSCID, scid);
-
- const QuicTag* their_aeads;
- const QuicTag* their_key_exchanges;
- size_t num_their_aeads, num_their_key_exchanges;
- if (scfg->GetTaglist(kAEAD, &their_aeads,
- &num_their_aeads) != QUIC_NO_ERROR ||
- scfg->GetTaglist(kKEXS, &their_key_exchanges,
- &num_their_key_exchanges) != QUIC_NO_ERROR) {
- *error_details = "Missing AEAD or KEXS";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- size_t key_exchange_index;
- if (!QuicUtils::FindMutualTag(
- aead, their_aeads, num_their_aeads, QuicUtils::PEER_PRIORITY,
- &out_params->aead, NULL) ||
- !QuicUtils::FindMutualTag(
- kexs, their_key_exchanges, num_their_key_exchanges,
- QuicUtils::PEER_PRIORITY, &out_params->key_exchange,
- &key_exchange_index)) {
- *error_details = "Unsupported AEAD or KEXS";
- return QUIC_CRYPTO_NO_SUPPORT;
- }
- out->SetTaglist(kAEAD, out_params->aead, 0);
- out->SetTaglist(kKEXS, out_params->key_exchange, 0);
-
- StringPiece public_value;
- if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
- QUIC_NO_ERROR) {
- *error_details = "Missing public value";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- StringPiece orbit;
- if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
- *error_details = "SCFG missing OBIT";
- return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
- }
-
- CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
- out->SetStringPiece(kNONC, out_params->client_nonce);
- if (!out_params->server_nonce.empty()) {
- out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
- }
-
- switch (out_params->key_exchange) {
- case kC255:
- out_params->client_key_exchange.reset(Curve25519KeyExchange::New(
- Curve25519KeyExchange::NewPrivateKey(rand)));
- break;
- case kP256:
- out_params->client_key_exchange.reset(P256KeyExchange::New(
- P256KeyExchange::NewPrivateKey()));
- break;
- default:
- DCHECK(false);
- *error_details = "Configured to support an unknown key exchange";
- return QUIC_CRYPTO_INTERNAL_ERROR;
- }
-
- if (!out_params->client_key_exchange->CalculateSharedKey(
- public_value, &out_params->initial_premaster_secret)) {
- *error_details = "Key exchange failure";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
- out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
-
- bool do_channel_id = false;
- if (channel_id_signer_.get()) {
- const QuicTag* their_proof_demands;
- size_t num_their_proof_demands;
- if (scfg->GetTaglist(kPDMD, &their_proof_demands,
- &num_their_proof_demands) == QUIC_NO_ERROR) {
- for (size_t i = 0; i < num_their_proof_demands; i++) {
- if (their_proof_demands[i] == kCHID) {
- do_channel_id = true;
- break;
- }
- }
- }
- }
-
- if (do_channel_id) {
- // In order to calculate the encryption key for the CETV block we need to
- // serialise the client hello as it currently is (i.e. without the CETV
- // block). For this, the client hello is serialized without padding.
- const size_t orig_min_size = out->minimum_size();
- out->set_minimum_size(0);
-
- CryptoHandshakeMessage cetv;
- cetv.set_tag(kCETV);
-
- string hkdf_input;
- const QuicData& client_hello_serialized = out->GetSerialized();
- hkdf_input.append(QuicCryptoConfig::kCETVLabel,
- strlen(QuicCryptoConfig::kCETVLabel) + 1);
- hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
- hkdf_input.append(client_hello_serialized.data(),
- client_hello_serialized.length());
- hkdf_input.append(cached->server_config());
-
- string key, signature;
- if (!channel_id_signer_->Sign(server_hostname, hkdf_input,
- &key, &signature)) {
- *error_details = "Channel ID signature failed";
- return QUIC_INTERNAL_ERROR;
- }
-
- cetv.SetStringPiece(kCIDK, key);
- cetv.SetStringPiece(kCIDS, signature);
-
- CrypterPair crypters;
- CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
- out_params->aead, out_params->client_nonce,
- out_params->server_nonce, hkdf_input,
- CryptoUtils::CLIENT, &crypters);
-
- const QuicData& cetv_plaintext = cetv.GetSerialized();
- scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket(
- 0 /* sequence number */,
- StringPiece() /* associated data */,
- cetv_plaintext.AsStringPiece()));
- if (!cetv_ciphertext.get()) {
- *error_details = "Packet encryption failed";
- return QUIC_ENCRYPTION_FAILURE;
- }
-
- out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece());
- out->MarkDirty();
-
- out->set_minimum_size(orig_min_size);
- }
-
- out_params->hkdf_input_suffix.clear();
- out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid),
- sizeof(guid));
- const QuicData& client_hello_serialized = out->GetSerialized();
- out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
- client_hello_serialized.length());
- out_params->hkdf_input_suffix.append(cached->server_config());
-
- string hkdf_input;
- const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
- hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
- hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
- hkdf_input.append(out_params->hkdf_input_suffix);
-
- CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
- out_params->aead, out_params->client_nonce,
- out_params->server_nonce, hkdf_input,
- CryptoUtils::CLIENT, &out_params->initial_crypters);
-
- return QUIC_NO_ERROR;
-}
-
-QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
- const CryptoHandshakeMessage& rej,
- QuicWallTime now,
- CachedState* cached,
- QuicCryptoNegotiatedParameters* out_params,
- string* error_details) {
- DCHECK(error_details != NULL);
-
- if (rej.tag() != kREJ) {
- *error_details = "Message is not REJ";
- return QUIC_CRYPTO_INTERNAL_ERROR;
- }
-
- StringPiece scfg;
- if (!rej.GetStringPiece(kSCFG, &scfg)) {
- *error_details = "Missing SCFG";
- return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
- }
-
- QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details);
- if (error != QUIC_NO_ERROR) {
- return error;
- }
-
- StringPiece token;
- if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) {
- cached->set_source_address_token(token);
- }
-
- StringPiece nonce;
- if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
- out_params->server_nonce = nonce.as_string();
- }
-
- StringPiece proof, cert_bytes;
- bool has_proof = rej.GetStringPiece(kPROF, &proof);
- bool has_cert = rej.GetStringPiece(kCertificateTag, &cert_bytes);
- if (has_proof && has_cert) {
- vector<string> certs;
- if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
- common_cert_sets, &certs)) {
- *error_details = "Certificate data invalid";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- cached->SetProof(certs, proof);
- } else {
- cached->ClearProof();
- if (has_proof && !has_cert) {
- *error_details = "Certificate missing";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- if (!has_proof && has_cert) {
- *error_details = "Proof missing";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
- }
-
- return QUIC_NO_ERROR;
-}
-
-QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
- const CryptoHandshakeMessage& server_hello,
- QuicGuid guid,
- CachedState* cached,
- QuicCryptoNegotiatedParameters* out_params,
- string* error_details) {
- DCHECK(error_details != NULL);
-
- if (server_hello.tag() != kSHLO) {
- *error_details = "Bad tag";
- return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
- }
-
- // Learn about updated source address tokens.
- StringPiece token;
- if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) {
- cached->set_source_address_token(token);
- }
-
- // TODO(agl):
- // learn about updated SCFGs.
-
- StringPiece public_value;
- if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
- *error_details = "server hello missing forward secure public value";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- if (!out_params->client_key_exchange->CalculateSharedKey(
- public_value, &out_params->forward_secure_premaster_secret)) {
- *error_details = "Key exchange failure";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
- }
-
- string hkdf_input;
- const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
- hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
- hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
- hkdf_input.append(out_params->hkdf_input_suffix);
-
- CryptoUtils::DeriveKeys(
- out_params->forward_secure_premaster_secret, out_params->aead,
- out_params->client_nonce, out_params->server_nonce, hkdf_input,
- CryptoUtils::CLIENT, &out_params->forward_secure_crypters);
-
- return QUIC_NO_ERROR;
-}
-
-ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
- return proof_verifier_.get();
-}
-
-void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
- proof_verifier_.reset(verifier);
-}
-
-ChannelIDSigner* QuicCryptoClientConfig::channel_id_signer() const {
- return channel_id_signer_.get();
-}
-
-void QuicCryptoClientConfig::SetChannelIDSigner(ChannelIDSigner* signer) {
- channel_id_signer_.reset(signer);
-}
-
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_handshake.h b/chromium/net/quic/crypto/crypto_handshake.h
index cec393f7c77..962e13336ef 100644
--- a/chromium/net/quic/crypto/crypto_handshake.h
+++ b/chromium/net/quic/crypto/crypto_handshake.h
@@ -188,12 +188,6 @@ struct NET_EXPORT_PRIVATE QuicCryptoNegotiatedParameters {
// QuicCryptoConfig contains common configuration between clients and servers.
class NET_EXPORT_PRIVATE QuicCryptoConfig {
public:
- enum {
- // CONFIG_VERSION is the one (and, for the moment, only) version number that
- // we implement.
- CONFIG_VERSION = 0,
- };
-
// kInitialLabel is a constant that is used when deriving the initial
// (non-forward secure) keys for the connection in order to tie the resulting
// key to this protocol.
@@ -211,8 +205,6 @@ class NET_EXPORT_PRIVATE QuicCryptoConfig {
QuicCryptoConfig();
~QuicCryptoConfig();
- // Protocol version
- uint16 version;
// Key exchange methods. The following two members' values correspond by
// index.
QuicTagVector kexs;
@@ -225,176 +217,6 @@ class NET_EXPORT_PRIVATE QuicCryptoConfig {
DISALLOW_COPY_AND_ASSIGN(QuicCryptoConfig);
};
-// QuicCryptoClientConfig contains crypto-related configuration settings for a
-// client. Note that this object isn't thread-safe. It's designed to be used on
-// a single thread at a time.
-class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
- public:
- // A CachedState contains the information that the client needs in order to
- // perform a 0-RTT handshake with a server. This information can be reused
- // over several connections to the same server.
- class CachedState {
- public:
- CachedState();
- ~CachedState();
-
- // IsComplete returns true if this object contains enough information to
- // perform a handshake with the server. |now| is used to judge whether any
- // cached server config has expired.
- bool IsComplete(QuicWallTime now) const;
-
- // GetServerConfig returns the parsed contents of |server_config|, or NULL
- // if |server_config| is empty. The return value is owned by this object
- // and is destroyed when this object is.
- const CryptoHandshakeMessage* GetServerConfig() const;
-
- // SetServerConfig checks that |server_config| parses correctly and stores
- // it in |server_config_|. |now| is used to judge whether |server_config|
- // has expired.
- QuicErrorCode SetServerConfig(base::StringPiece server_config,
- QuicWallTime now,
- std::string* error_details);
-
- // InvalidateServerConfig clears the cached server config (if any).
- void InvalidateServerConfig();
-
- // SetProof stores a certificate chain and signature.
- void SetProof(const std::vector<std::string>& certs,
- base::StringPiece signature);
-
- // Clears the certificate chain and signature and invalidates the proof.
- void ClearProof();
-
- // SetProofValid records that the certificate chain and signature have been
- // validated and that it's safe to assume that the server is legitimate.
- // (Note: this does not check the chain or signature.)
- void SetProofValid();
-
- // If the server config or the proof has changed then it needs to be
- // revalidated. Helper function to keep server_config_valid_ and
- // generation_counter_ in sync.
- void SetProofInvalid();
-
- const std::string& server_config() const;
- const std::string& source_address_token() const;
- const std::vector<std::string>& certs() const;
- const std::string& signature() const;
- bool proof_valid() const;
- uint64 generation_counter() const;
- const ProofVerifyDetails* proof_verify_details() const;
-
- void set_source_address_token(base::StringPiece token);
-
- // SetProofVerifyDetails takes ownership of |details|.
- void SetProofVerifyDetails(ProofVerifyDetails* details);
-
- private:
- std::string server_config_id_; // An opaque id from the server.
- std::string server_config_; // A serialized handshake message.
- std::string source_address_token_; // An opaque proof of IP ownership.
- std::vector<std::string> certs_; // A list of certificates in leaf-first
- // order.
- 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
- // validated.
- // Generation counter associated with the |server_config_|, |certs_| and
- // |server_config_sig_| combination. It is incremented whenever we set
- // server_config_valid_ to false.
- uint64 generation_counter_;
-
- scoped_ptr<ProofVerifyDetails> proof_verify_details_;
-
- // scfg contains the cached, parsed value of |server_config|.
- mutable scoped_ptr<CryptoHandshakeMessage> scfg_;
- };
-
- QuicCryptoClientConfig();
- ~QuicCryptoClientConfig();
-
- // Sets the members to reasonable, default values.
- void SetDefaults();
-
- // LookupOrCreate returns a CachedState for the given hostname. If no such
- // CachedState currently exists, it will be created and cached.
- CachedState* LookupOrCreate(const std::string& server_hostname);
-
- // FillInchoateClientHello sets |out| to be a CHLO message that elicits a
- // source-address token or SCFG from a server. If |cached| is non-NULL, the
- // source-address token will be taken from it. |out_params| is used in order
- // to store the cached certs that were sent as hints to the server in
- // |out_params->cached_certs|.
- void FillInchoateClientHello(const std::string& server_hostname,
- const CachedState* cached,
- QuicCryptoNegotiatedParameters* out_params,
- CryptoHandshakeMessage* out) const;
-
- // FillClientHello sets |out| to be a CHLO message based on the configuration
- // of this object. This object must have cached enough information about
- // |server_hostname| in order to perform a handshake. This can be checked
- // with the |IsComplete| member of |CachedState|.
- //
- // |clock| and |rand| are used to generate the nonce and |out_params| is
- // filled with the results of the handshake that the server is expected to
- // accept.
- QuicErrorCode FillClientHello(const std::string& server_hostname,
- QuicGuid guid,
- const CachedState* cached,
- QuicWallTime now,
- QuicRandom* rand,
- QuicCryptoNegotiatedParameters* out_params,
- CryptoHandshakeMessage* out,
- std::string* error_details) const;
-
- // ProcessRejection processes a REJ message from a server and updates the
- // cached information about that server. After this, |IsComplete| may return
- // true for that server's CachedState. If the rejection message contains
- // state about a future handshake (i.e. an nonce value from the server), then
- // it will be saved in |out_params|. |now| is used to judge whether the
- // server config in the rejection message has expired.
- QuicErrorCode ProcessRejection(const CryptoHandshakeMessage& rej,
- QuicWallTime now,
- CachedState* cached,
- QuicCryptoNegotiatedParameters* out_params,
- std::string* error_details);
-
- // ProcessServerHello processes the message in |server_hello|, updates the
- // cached information about that server, writes the negotiated parameters to
- // |out_params| and returns QUIC_NO_ERROR. If |server_hello| is unacceptable
- // then it puts an error message in |error_details| and returns an error
- // code.
- QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello,
- QuicGuid guid,
- CachedState* cached,
- QuicCryptoNegotiatedParameters* out_params,
- std::string* error_details);
-
- ProofVerifier* proof_verifier() const;
-
- // SetProofVerifier takes ownership of a |ProofVerifier| that clients are
- // free to use in order to verify certificate chains from servers. If a
- // ProofVerifier is set then the client will request a certificate chain from
- // the server.
- void SetProofVerifier(ProofVerifier* verifier);
-
- ChannelIDSigner* channel_id_signer() const;
-
- // SetChannelIDSigner sets a ChannelIDSigner that will be called when the
- // server supports channel IDs to sign a message proving possession of the
- // given ChannelID. This object takes ownership of |signer|.
- void SetChannelIDSigner(ChannelIDSigner* signer);
-
- private:
- // cached_states_ maps from the server hostname to the cached information
- // about that server.
- std::map<std::string, CachedState*> cached_states_;
-
- scoped_ptr<ProofVerifier> proof_verifier_;
- scoped_ptr<ChannelIDSigner> channel_id_signer_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientConfig);
-};
-
} // namespace net
#endif // NET_QUIC_CRYPTO_CRYPTO_HANDSHAKE_H_
diff --git a/chromium/net/quic/crypto/crypto_protocol.h b/chromium/net/quic/crypto/crypto_protocol.h
index 4580fce4bb4..1971b58c543 100644
--- a/chromium/net/quic/crypto/crypto_protocol.h
+++ b/chromium/net/quic/crypto/crypto_protocol.h
@@ -40,11 +40,12 @@ const QuicTag kP256 = TAG('P', '2', '5', '6'); // ECDH, Curve P-256
const QuicTag kC255 = TAG('C', '2', '5', '5'); // ECDH, Curve25519
// AEAD algorithms
-const QuicTag kNULL = TAG('N', 'U', 'L', 'L'); // null algorithm
+const QuicTag kNULL = TAG('N', 'U', 'L', 'N'); // null algorithm
const QuicTag kAESG = TAG('A', 'E', 'S', 'G'); // AES128 + GCM-12
// Congestion control feedback types
const QuicTag kQBIC = TAG('Q', 'B', 'I', 'C'); // TCP cubic
+const QuicTag kPACE = TAG('P', 'A', 'C', 'E'); // Paced TCP cubic
const QuicTag kINAR = TAG('I', 'N', 'A', 'R'); // Inter arrival
// Proof types (i.e. certificate types)
@@ -57,7 +58,9 @@ const QuicTag kX59R = TAG('X', '5', '9', 'R'); // X.509 certificate, RSA keys
const QuicTag kCHID = TAG('C', 'H', 'I', 'D'); // Channel ID.
// Client hello tags
-const QuicTag kVERS = TAG('V', 'E', 'R', 'S'); // Version
+// TODO(rch): Remove once we remove QUIC_VERSION_12.
+const QuicTag kVERS = TAG('V', 'E', 'R', 'S'); // Version (obsolete)
+const QuicTag kVER = TAG('V', 'E', 'R', '\0'); // Version (new)
const QuicTag kNONC = TAG('N', 'O', 'N', 'C'); // The client's nonce
const QuicTag kKEXS = TAG('K', 'E', 'X', 'S'); // Key exchange methods
const QuicTag kAEAD = TAG('A', 'E', 'A', 'D'); // Authenticated
@@ -68,6 +71,9 @@ const QuicTag kICSL = TAG('I', 'C', 'S', 'L'); // Idle connection state
// lifetime
const QuicTag kKATO = TAG('K', 'A', 'T', 'O'); // Keepalive timeout
const QuicTag kMSPC = TAG('M', 'S', 'P', 'C'); // Max streams per connection.
+const QuicTag kIRTT = TAG('I', 'R', 'T', 'T'); // Estimated initial RTT in us.
+const QuicTag kSWND = TAG('S', 'W', 'N', 'D'); // Server's Initial congestion
+ // window.
const QuicTag kSNI = TAG('S', 'N', 'I', '\0'); // Server name
// indication
const QuicTag kPUBS = TAG('P', 'U', 'B', 'S'); // Public key values
@@ -123,7 +129,17 @@ const char kProofSignatureLabel[] = "QUIC server config signature";
// will have PAD tags added in order to ensure this minimum is met and client
// hellos smaller than this will be an error. This minimum size reduces the
// amplification factor of any mirror DoS attack.
-const size_t kClientHelloMinimumSize = 512;
+//
+// A client may pad an inchoate client hello to a size larger than
+// kClientHelloMinimumSize to make it more likely to receive a complete
+// rejection message.
+const size_t kClientHelloMinimumSize = 1024;
+
+// kClientHelloMinimumSizeOld is the previous value of kClientHelloMinimumSize.
+// To support old clients, the server only enforces this size.
+// TODO(wtc): Replace it with kClientHelloMinimumSize when we drop support for
+// QUIC_VERSION_12 clients.
+const size_t kClientHelloMinimumSizeOld = 512;
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_server_test.cc b/chromium/net/quic/crypto/crypto_server_test.cc
index b2cdf820c34..4eec2a86a28 100644
--- a/chromium/net/quic/crypto/crypto_server_test.cc
+++ b/chromium/net/quic/crypto/crypto_server_test.cc
@@ -3,11 +3,15 @@
// found in the LICENSE file.
#include "base/strings/string_number_conversions.h"
-#include "net/quic/crypto/crypto_server_config.h"
+#include "crypto/secure_hash.h"
#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_random.h"
+#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/delayed_verify_strike_register_client.h"
#include "net/quic/test_tools/mock_clock.h"
+#include "net/quic/test_tools/mock_random.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -24,12 +28,13 @@ class CryptoServerTest : public ::testing::Test {
addr_(ParseIPLiteralToNumber("192.0.2.33", &ip_) ?
ip_ : IPAddressNumber(), 1) {
config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
+ supported_versions_ = QuicSupportedVersions();
}
virtual void SetUp() {
scoped_ptr<CryptoHandshakeMessage> msg(
config_.AddDefaultConfig(rand_, &clock_,
- QuicCryptoServerConfig::ConfigOptions()));
+ config_options_));
StringPiece orbit;
CHECK(msg->GetStringPiece(kORBT, &orbit));
@@ -69,29 +74,85 @@ class CryptoServerTest : public ::testing::Test {
scid_hex_ = "#" + base::HexEncode(scid.data(), scid.size());
}
+ // Helper used to accept the result of ValidateClientHello and pass
+ // it on to ProcessClientHello.
+ class ValidateCallback : public ValidateClientHelloResultCallback {
+ public:
+ ValidateCallback(CryptoServerTest* test,
+ bool should_succeed,
+ const char* error_substr,
+ bool* called)
+ : test_(test),
+ should_succeed_(should_succeed),
+ error_substr_(error_substr),
+ called_(called) {
+ *called_ = false;
+ }
+
+ virtual void RunImpl(const CryptoHandshakeMessage& client_hello,
+ const Result& result) OVERRIDE {
+ ASSERT_FALSE(*called_);
+ test_->ProcessValidationResult(
+ client_hello, result, should_succeed_, error_substr_);
+ *called_ = true;
+ }
+
+ private:
+ CryptoServerTest* test_;
+ bool should_succeed_;
+ const char* error_substr_;
+ bool* called_;
+ };
+
void ShouldSucceed(const CryptoHandshakeMessage& message) {
- string error_details;
- QuicErrorCode error = config_.ProcessClientHello(
- message, 1 /* GUID */, addr_, &clock_,
- rand_, &params_, &out_, &error_details);
+ bool called = false;
+ ShouldSucceed(message, &called);
+ EXPECT_TRUE(called);
+ }
- ASSERT_EQ(error, QUIC_NO_ERROR)
- << "Message failed with error " << error_details << ": "
- << message.DebugString();
+ void ShouldSucceed(const CryptoHandshakeMessage& message,
+ bool* called) {
+ config_.ValidateClientHello(
+ message, addr_, &clock_,
+ new ValidateCallback(this, true, "", called));
}
void ShouldFailMentioning(const char* error_substr,
const CryptoHandshakeMessage& message) {
- string error_details;
- QuicErrorCode error = config_.ProcessClientHello(
- message, 1 /* GUID */, addr_, &clock_,
- rand_, &params_, &out_, &error_details);
+ bool called = false;
+ ShouldFailMentioning(error_substr, message, &called);
+ EXPECT_TRUE(called);
+ }
- ASSERT_NE(error, QUIC_NO_ERROR)
- << "Message didn't fail: " << message.DebugString();
+ void ShouldFailMentioning(const char* error_substr,
+ const CryptoHandshakeMessage& message,
+ bool* called) {
+ config_.ValidateClientHello(
+ message, addr_, &clock_,
+ new ValidateCallback(this, false, error_substr, called));
+ }
- EXPECT_TRUE(error_details.find(error_substr) != string::npos)
- << error_substr << " not in " << error_details;
+ void ProcessValidationResult(const CryptoHandshakeMessage& message,
+ const ValidateCallback::Result& result,
+ bool should_succeed,
+ const char* error_substr) {
+ string error_details;
+ QuicErrorCode error = config_.ProcessClientHello(
+ result, 1 /* GUID */, addr_,
+ supported_versions_.front(), supported_versions_, &clock_, rand_,
+ &params_, &out_, &error_details);
+
+ if (should_succeed) {
+ ASSERT_EQ(error, QUIC_NO_ERROR)
+ << "Message failed with error " << error_details << ": "
+ << message.DebugString();
+ } else {
+ ASSERT_NE(error, QUIC_NO_ERROR)
+ << "Message didn't fail: " << message.DebugString();
+
+ EXPECT_TRUE(error_details.find(error_substr) != string::npos)
+ << error_substr << " not in " << error_details;
+ }
}
CryptoHandshakeMessage InchoateClientHello(const char* message_tag, ...) {
@@ -118,7 +179,9 @@ class CryptoServerTest : public ::testing::Test {
protected:
QuicRandom* const rand_;
MockClock clock_;
+ QuicVersionVector supported_versions_;
QuicCryptoServerConfig config_;
+ QuicCryptoServerConfig::ConfigOptions config_options_;
QuicCryptoNegotiatedParameters params_;
CryptoHandshakeMessage out_;
IPAddressNumber ip_;
@@ -211,6 +274,22 @@ TEST_F(CryptoServerTest, BadClientNonce) {
}
}
+TEST_F(CryptoServerTest, DowngradeAttack) {
+ if (supported_versions_.size() == 1) {
+ // No downgrade attack is possible if the server only supports one version.
+ return;
+ }
+ // Set the client's preferred version to a supported version that
+ // is not the "current" version (supported_versions_.front()).
+ string client_version = QuicUtils::TagToString(
+ QuicVersionToQuicTag(supported_versions_.back()));
+
+ ShouldFailMentioning("Downgrade", InchoateClientHello(
+ "CHLO",
+ "VER\0", client_version.data(),
+ NULL));
+}
+
TEST_F(CryptoServerTest, ReplayProtection) {
// This tests that disabling replay protection works.
CryptoHandshakeMessage msg = CryptoTestUtils::Message(
@@ -237,6 +316,83 @@ TEST_F(CryptoServerTest, ReplayProtection) {
ShouldSucceed(msg);
// The message should accepted twice when replay protection is off.
ASSERT_EQ(kSHLO, out_.tag());
+ const QuicTag* versions;
+ size_t num_versions;
+ out_.GetTaglist(kVER, &versions, &num_versions);
+ ASSERT_EQ(QuicSupportedVersions().size(), num_versions);
+ for (size_t i = 0; i < num_versions; ++i) {
+ EXPECT_EQ(QuicVersionToQuicTag(QuicSupportedVersions()[i]), versions[i]);
+ }
+}
+
+TEST(CryptoServerConfigGenerationTest, Determinism) {
+ // Test that using a deterministic PRNG causes the server-config to be
+ // deterministic.
+
+ MockRandom rand_a, rand_b;
+ const QuicCryptoServerConfig::ConfigOptions options;
+ MockClock clock;
+
+ QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
+ QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
+ scoped_ptr<CryptoHandshakeMessage> scfg_a(
+ a.AddDefaultConfig(&rand_a, &clock, options));
+ scoped_ptr<CryptoHandshakeMessage> scfg_b(
+ b.AddDefaultConfig(&rand_b, &clock, options));
+
+ ASSERT_EQ(scfg_a->DebugString(), scfg_b->DebugString());
+}
+
+TEST(CryptoServerConfigGenerationTest, SCIDVaries) {
+ // This test ensures that the server config ID varies for different server
+ // configs.
+
+ MockRandom rand_a, rand_b;
+ const QuicCryptoServerConfig::ConfigOptions options;
+ MockClock clock;
+
+ QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
+ rand_b.ChangeValue();
+ QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
+ scoped_ptr<CryptoHandshakeMessage> scfg_a(
+ a.AddDefaultConfig(&rand_a, &clock, options));
+ scoped_ptr<CryptoHandshakeMessage> scfg_b(
+ b.AddDefaultConfig(&rand_b, &clock, options));
+
+ StringPiece scid_a, scid_b;
+ EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a));
+ EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b));
+
+ EXPECT_NE(scid_a, scid_b);
+}
+
+
+TEST(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
+ MockRandom rand_a;
+ const QuicCryptoServerConfig::ConfigOptions options;
+ MockClock clock;
+
+ QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
+ scoped_ptr<CryptoHandshakeMessage> scfg(
+ a.AddDefaultConfig(&rand_a, &clock, options));
+
+ StringPiece scid;
+ EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
+ // Need to take a copy of |scid| has we're about to call |Erase|.
+ const string scid_str(scid.as_string());
+
+ scfg->Erase(kSCID);
+ scfg->MarkDirty();
+ const QuicData& serialized(scfg->GetSerialized());
+
+ scoped_ptr<crypto::SecureHash> hash(
+ crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ hash->Update(serialized.data(), serialized.length());
+ uint8 digest[16];
+ hash->Finish(digest, sizeof(digest));
+
+ ASSERT_EQ(scid.size(), sizeof(digest));
+ EXPECT_TRUE(0 == memcmp(digest, scid_str.data(), sizeof(digest)));
}
class CryptoServerTestNoConfig : public CryptoServerTest {
@@ -252,5 +408,70 @@ TEST_F(CryptoServerTestNoConfig, DontCrash) {
NULL));
}
+class AsyncStrikeServerVerificationTest : public CryptoServerTest {
+ protected:
+ AsyncStrikeServerVerificationTest() {
+ }
+
+ virtual void SetUp() {
+ const string kOrbit = "12345678";
+ config_options_.orbit = kOrbit;
+ strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
+ 10000, // strike_register_max_entries
+ static_cast<uint32>(clock_.WallNow().ToUNIXSeconds()),
+ 60, // strike_register_window_secs
+ reinterpret_cast<const uint8 *>(kOrbit.data()),
+ StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
+ config_.SetStrikeRegisterClient(strike_register_client_);
+ CryptoServerTest::SetUp();
+ strike_register_client_->StartDelayingVerification();
+ }
+
+ DelayedVerifyStrikeRegisterClient* strike_register_client_;
+};
+
+TEST_F(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
+ // This tests async validation with a strike register works.
+ 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(),
+ "$padding", static_cast<int>(kClientHelloMinimumSize),
+ NULL);
+
+ // Clear the message tag.
+ out_.set_tag(0);
+
+ bool called = false;
+ ShouldSucceed(msg, &called);
+ // The verification request was queued.
+ ASSERT_FALSE(called);
+ EXPECT_EQ(0u, out_.tag());
+ EXPECT_EQ(1, strike_register_client_->PendingVerifications());
+
+ // Continue processing the verification request.
+ strike_register_client_->RunPendingVerifications();
+ ASSERT_TRUE(called);
+ EXPECT_EQ(0, strike_register_client_->PendingVerifications());
+ // The message should be accepted now.
+ EXPECT_EQ(kSHLO, out_.tag());
+
+ // Rejected if replayed.
+ ShouldSucceed(msg, &called);
+ // The verification request was queued.
+ ASSERT_FALSE(called);
+ EXPECT_EQ(1, strike_register_client_->PendingVerifications());
+
+ strike_register_client_->RunPendingVerifications();
+ ASSERT_TRUE(called);
+ EXPECT_EQ(0, strike_register_client_->PendingVerifications());
+ // The message should be rejected now.
+ EXPECT_EQ(kREJ, out_.tag());
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_utils.cc b/chromium/net/quic/crypto/crypto_utils.cc
index 469e582268f..eec8a9d05a2 100644
--- a/chromium/net/quic/crypto/crypto_utils.cc
+++ b/chromium/net/quic/crypto/crypto_utils.cc
@@ -77,7 +77,7 @@ string CryptoUtils::NormalizeHostname(const char* hostname) {
}
// static
-void CryptoUtils::DeriveKeys(StringPiece premaster_secret,
+bool CryptoUtils::DeriveKeys(StringPiece premaster_secret,
QuicTag aead,
StringPiece client_nonce,
StringPiece server_nonce,
@@ -99,16 +99,22 @@ void CryptoUtils::DeriveKeys(StringPiece premaster_secret,
crypto::HKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes,
nonce_prefix_bytes);
if (perspective == SERVER) {
- out->encrypter->SetKey(hkdf.server_write_key());
- out->encrypter->SetNoncePrefix(hkdf.server_write_iv());
- out->decrypter->SetKey(hkdf.client_write_key());
- out->decrypter->SetNoncePrefix(hkdf.client_write_iv());
+ if (!out->encrypter->SetKey(hkdf.server_write_key()) ||
+ !out->encrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+ !out->decrypter->SetKey(hkdf.client_write_key()) ||
+ !out->decrypter->SetNoncePrefix(hkdf.client_write_iv())) {
+ return false;
+ }
} else {
- out->encrypter->SetKey(hkdf.client_write_key());
- out->encrypter->SetNoncePrefix(hkdf.client_write_iv());
- out->decrypter->SetKey(hkdf.server_write_key());
- out->decrypter->SetNoncePrefix(hkdf.server_write_iv());
+ if (!out->encrypter->SetKey(hkdf.client_write_key()) ||
+ !out->encrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+ !out->decrypter->SetKey(hkdf.server_write_key()) ||
+ !out->decrypter->SetNoncePrefix(hkdf.server_write_iv())) {
+ return false;
+ }
}
+
+ return true;
}
} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_utils.h b/chromium/net/quic/crypto/crypto_utils.h
index 6dfce2a58e3..147e41436f8 100644
--- a/chromium/net/quic/crypto/crypto_utils.h
+++ b/chromium/net/quic/crypto/crypto_utils.h
@@ -55,7 +55,7 @@ class NET_EXPORT_PRIVATE CryptoUtils {
// controls whether the server's keys are assigned to |encrypter| or
// |decrypter|. |server_nonce| is optional and, if non-empty, is mixed into
// the key derivation.
- static void DeriveKeys(base::StringPiece premaster_secret,
+ static bool DeriveKeys(base::StringPiece premaster_secret,
QuicTag aead,
base::StringPiece client_nonce,
base::StringPiece server_nonce,
diff --git a/chromium/net/quic/crypto/local_strike_register_client.cc b/chromium/net/quic/crypto/local_strike_register_client.cc
new file mode 100644
index 00000000000..c3751450397
--- /dev/null
+++ b/chromium/net/quic/crypto/local_strike_register_client.cc
@@ -0,0 +1,46 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/crypto/local_strike_register_client.h"
+
+#include "net/quic/crypto/crypto_protocol.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+
+LocalStrikeRegisterClient::LocalStrikeRegisterClient(
+ unsigned max_entries,
+ uint32 current_time_external,
+ uint32 window_secs,
+ const uint8 orbit[8],
+ StrikeRegister::StartupType startup)
+ : strike_register_(max_entries, current_time_external, window_secs,
+ orbit, startup) {
+}
+
+string LocalStrikeRegisterClient::orbit() {
+ base::AutoLock lock(m_);
+ return string(reinterpret_cast<const char*>(strike_register_.orbit()),
+ kOrbitSize);
+}
+
+void LocalStrikeRegisterClient::VerifyNonceIsValidAndUnique(
+ StringPiece nonce, QuicWallTime now, ResultCallback* cb) {
+ bool nonce_is_valid_and_unique;
+ if (nonce.length() != kNonceSize) {
+ nonce_is_valid_and_unique = false;
+ } else {
+ base::AutoLock lock(m_);
+ nonce_is_valid_and_unique = strike_register_.Insert(
+ reinterpret_cast<const uint8*>(nonce.data()),
+ static_cast<uint32>(now.ToUNIXSeconds()));
+ }
+
+ // m_ must not be held when the ResultCallback runs.
+ cb->Run(nonce_is_valid_and_unique);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/crypto/local_strike_register_client.h b/chromium/net/quic/crypto/local_strike_register_client.h
new file mode 100644
index 00000000000..37020b7b420
--- /dev/null
+++ b/chromium/net/quic/crypto/local_strike_register_client.h
@@ -0,0 +1,42 @@
+// 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_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
+#define NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
+
+#include "base/strings/string_piece.h"
+#include "base/synchronization/lock.h"
+#include "net/base/net_export.h"
+#include "net/quic/crypto/strike_register.h"
+#include "net/quic/crypto/strike_register_client.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+// StrikeRegisterClient implementation that wraps a local in-memory
+// strike register.
+class NET_EXPORT_PRIVATE LocalStrikeRegisterClient
+ : public StrikeRegisterClient {
+ public:
+ LocalStrikeRegisterClient(unsigned max_entries,
+ uint32 current_time_external,
+ uint32 window_secs,
+ const uint8 orbit[8],
+ StrikeRegister::StartupType startup);
+
+ virtual std::string orbit() OVERRIDE;
+ virtual void VerifyNonceIsValidAndUnique(base::StringPiece nonce,
+ QuicWallTime now,
+ ResultCallback* cb) OVERRIDE;
+
+ private:
+ base::Lock m_;
+ StrikeRegister strike_register_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalStrikeRegisterClient);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CRYPTO_LOCAL_STRIKE_REGISTER_CLIENT_H_
diff --git a/chromium/net/quic/crypto/local_strike_register_client_test.cc b/chromium/net/quic/crypto/local_strike_register_client_test.cc
new file mode 100644
index 00000000000..0227e92c6dc
--- /dev/null
+++ b/chromium/net/quic/crypto/local_strike_register_client_test.cc
@@ -0,0 +1,119 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/crypto/local_strike_register_client.h"
+
+#include <memory>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "base/sys_byteorder.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/quic_time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::StringPiece;
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+class RecordResultCallback : public StrikeRegisterClient::ResultCallback {
+ public:
+ // RecordResultCallback stores the argument to RunImpl in
+ // |*saved_value| and sets |*called| to true. The callback is self
+ // deleting.
+ RecordResultCallback(bool* called, bool* saved_value)
+ : called_(called), saved_value_(saved_value) {
+ *called_ = false;
+ }
+
+ protected:
+ virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE {
+ *called_ = true;
+ *saved_value_ = nonce_is_valid_and_unique;
+ }
+
+ private:
+ bool* called_;
+ bool* saved_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(RecordResultCallback);
+};
+
+const uint8 kOrbit[] = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0";
+const uint32 kCurrentTimeExternalSecs = 12345678;
+size_t kMaxEntries = 100;
+uint32 kWindowSecs = 60;
+
+class LocalStrikeRegisterClientTest : public ::testing::Test {
+ protected:
+ LocalStrikeRegisterClientTest() {
+ }
+
+ virtual void SetUp() {
+ strike_register_.reset(new LocalStrikeRegisterClient(
+ kMaxEntries, kCurrentTimeExternalSecs, kWindowSecs, kOrbit,
+ net::StrikeRegister::NO_STARTUP_PERIOD_NEEDED));
+ }
+
+ scoped_ptr<LocalStrikeRegisterClient> strike_register_;
+};
+
+TEST_F(LocalStrikeRegisterClientTest, CheckOrbit) {
+ EXPECT_EQ(StringPiece(reinterpret_cast<const char*>(kOrbit), kOrbitSize),
+ strike_register_->orbit());
+}
+
+TEST_F(LocalStrikeRegisterClientTest, IncorrectNonceLength) {
+ string valid_nonce;
+ uint32 norder = htonl(kCurrentTimeExternalSecs);
+ valid_nonce.assign(reinterpret_cast<const char*>(&norder), sizeof(norder));
+ valid_nonce.append(strike_register_->orbit());
+ valid_nonce.append(string(20, '\x17')); // 20 'random' bytes.
+
+ {
+ // Validation fails if you remove a byte from the nonce.
+ bool called;
+ bool is_valid;
+ string short_nonce = valid_nonce.substr(0, valid_nonce.length() - 1);
+ strike_register_->VerifyNonceIsValidAndUnique(
+ short_nonce,
+ QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
+ new RecordResultCallback(&called, &is_valid));
+ EXPECT_TRUE(called);
+ EXPECT_FALSE(is_valid);
+ }
+
+ {
+ // Validation fails if you add a byte to the nonce.
+ bool called;
+ bool is_valid;
+ string long_nonce(valid_nonce);
+ long_nonce.append("a");
+ strike_register_->VerifyNonceIsValidAndUnique(
+ long_nonce,
+ QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
+ new RecordResultCallback(&called, &is_valid));
+ EXPECT_TRUE(called);
+ EXPECT_FALSE(is_valid);
+ }
+
+ {
+ // Verify that the base nonce validates was valid.
+ bool called;
+ bool is_valid;
+ strike_register_->VerifyNonceIsValidAndUnique(
+ valid_nonce,
+ QuicWallTime::FromUNIXSeconds(kCurrentTimeExternalSecs),
+ new RecordResultCallback(&called, &is_valid));
+ EXPECT_TRUE(called);
+ EXPECT_TRUE(is_valid);
+ }
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/crypto/null_decrypter.cc b/chromium/net/quic/crypto/null_decrypter.cc
index 7bda75fe80d..c58e7b07c0b 100644
--- a/chromium/net/quic/crypto/null_decrypter.cc
+++ b/chromium/net/quic/crypto/null_decrypter.cc
@@ -11,6 +11,8 @@ using std::string;
namespace net {
+NullDecrypter::NullDecrypter() {}
+
bool NullDecrypter::SetKey(StringPiece key) { return key.empty(); }
bool NullDecrypter::SetNoncePrefix(StringPiece nonce_prefix) {
@@ -25,7 +27,7 @@ bool NullDecrypter::Decrypt(StringPiece /*nonce*/,
QuicDataReader reader(ciphertext.data(), ciphertext.length());
uint128 hash;
- if (!reader.ReadUInt128(&hash)) {
+ if (!ReadHash(&reader, &hash)) {
return false;
}
@@ -34,8 +36,7 @@ bool NullDecrypter::Decrypt(StringPiece /*nonce*/,
// TODO(rch): avoid buffer copy here
string buffer = associated_data.as_string();
plaintext.AppendToString(&buffer);
-
- if (hash != QuicUtils::FNV1a_128_Hash(buffer.data(), buffer.length())) {
+ if (hash != ComputeHash(buffer)) {
return false;
}
memcpy(output, plaintext.data(), plaintext.length());
@@ -51,7 +52,7 @@ QuicData* NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/,
QuicDataReader reader(ciphertext.data(), ciphertext.length());
uint128 hash;
- if (!reader.ReadUInt128(&hash)) {
+ if (!ReadHash(&reader, &hash)) {
return NULL;
}
@@ -61,7 +62,7 @@ QuicData* NullDecrypter::DecryptPacket(QuicPacketSequenceNumber /*seq_number*/,
string buffer = associated_data.as_string();
plaintext.AppendToString(&buffer);
- if (hash != QuicUtils::FNV1a_128_Hash(buffer.data(), buffer.length())) {
+ if (hash != ComputeHash(buffer)) {
return NULL;
}
return new QuicData(plaintext.data(), plaintext.length());
@@ -71,4 +72,25 @@ StringPiece NullDecrypter::GetKey() const { return StringPiece(); }
StringPiece NullDecrypter::GetNoncePrefix() const { return StringPiece(); }
+bool NullDecrypter::ReadHash(QuicDataReader* reader, uint128* hash) {
+ uint64 lo;
+ uint32 hi;
+ if (!reader->ReadUInt64(&lo) ||
+ !reader->ReadUInt32(&hi)) {
+ return false;
+ }
+ *hash = hi;
+ *hash <<= 64;
+ *hash += lo;
+ return true;
+}
+
+uint128 NullDecrypter::ComputeHash(const string& data) const {
+ uint128 correct_hash = QuicUtils::FNV1a_128_Hash(data.data(), data.length());
+ uint128 mask(GG_UINT64_C(0x0), GG_UINT64_C(0xffffffff));
+ mask <<= 96;
+ correct_hash &= ~mask;
+ return correct_hash;
+}
+
} // namespace net
diff --git a/chromium/net/quic/crypto/null_decrypter.h b/chromium/net/quic/crypto/null_decrypter.h
index 01beb2d7110..e85e1247582 100644
--- a/chromium/net/quic/crypto/null_decrypter.h
+++ b/chromium/net/quic/crypto/null_decrypter.h
@@ -11,11 +11,14 @@
namespace net {
+class QuicDataReader;
+
// A NullDecrypter is a QuicDecrypter used before a crypto negotiation
// has occurred. It does not actually decrypt the payload, but does
// verify a hash (fnv128) over both the payload and associated data.
class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
public:
+ NullDecrypter();
virtual ~NullDecrypter() {}
// QuicDecrypter implementation
@@ -31,6 +34,10 @@ class NET_EXPORT_PRIVATE NullDecrypter : public QuicDecrypter {
base::StringPiece ciphertext) OVERRIDE;
virtual base::StringPiece GetKey() const OVERRIDE;
virtual base::StringPiece GetNoncePrefix() const OVERRIDE;
+
+ private:
+ bool ReadHash(QuicDataReader* reader, uint128* hash);
+ uint128 ComputeHash(const std::string& data) const;
};
} // namespace net
diff --git a/chromium/net/quic/crypto/null_decrypter_test.cc b/chromium/net/quic/crypto/null_decrypter_test.cc
index e9b9647d202..173ecdeac65 100644
--- a/chromium/net/quic/crypto/null_decrypter_test.cc
+++ b/chromium/net/quic/crypto/null_decrypter_test.cc
@@ -10,55 +10,58 @@ using base::StringPiece;
namespace net {
namespace test {
-TEST(NullDecrypterTest, Decrypt) {
+class NullDecrypterTest : public ::testing::TestWithParam<bool> {
+};
+
+TEST_F(NullDecrypterTest, Decrypt) {
unsigned char expected[] = {
// fnv hash
0xa0, 0x6f, 0x44, 0x8a,
0x44, 0xf8, 0x18, 0x3b,
0x47, 0x91, 0xb2, 0x13,
- 0x6b, 0x09, 0xbb, 0xae,
// payload
'g', 'o', 'o', 'd',
'b', 'y', 'e', '!',
};
+ const char* data = reinterpret_cast<const char*>(expected);
+ size_t len = arraysize(expected);
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(decrypter.DecryptPacket(
- 0, "hello world!", StringPiece(reinterpret_cast<const char*>(expected),
- arraysize(expected))));
+ scoped_ptr<QuicData> decrypted(
+ decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len)));
ASSERT_TRUE(decrypted.get());
EXPECT_EQ("goodbye!", decrypted->AsStringPiece());
}
-TEST(NullDecrypterTest, BadHash) {
+TEST_F(NullDecrypterTest, BadHash) {
unsigned char expected[] = {
// fnv hash
0x46, 0x11, 0xea, 0x5f,
0xcf, 0x1d, 0x66, 0x5b,
0xba, 0xf0, 0xbc, 0xfd,
- 0x88, 0x79, 0xca, 0x37,
// payload
'g', 'o', 'o', 'd',
'b', 'y', 'e', '!',
};
+ const char* data = reinterpret_cast<const char*>(expected);
+ size_t len = arraysize(expected);
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(decrypter.DecryptPacket(
- 0, "hello world!", StringPiece(reinterpret_cast<const char*>(expected),
- arraysize(expected))));
+ scoped_ptr<QuicData> decrypted(
+ decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len)));
ASSERT_FALSE(decrypted.get());
}
-TEST(NullDecrypterTest, ShortInput) {
+TEST_F(NullDecrypterTest, ShortInput) {
unsigned char expected[] = {
// fnv hash (truncated)
0x46, 0x11, 0xea, 0x5f,
0xcf, 0x1d, 0x66, 0x5b,
- 0xba, 0xf0, 0xbc, 0xfd,
- 0x88, 0x79, 0xca,
+ 0xba, 0xf0, 0xbc,
};
+ const char* data = reinterpret_cast<const char*>(expected);
+ size_t len = arraysize(expected);
NullDecrypter decrypter;
- scoped_ptr<QuicData> decrypted(decrypter.DecryptPacket(
- 0, "hello world!", StringPiece(reinterpret_cast<const char*>(expected),
- arraysize(expected))));
+ scoped_ptr<QuicData> decrypted(
+ decrypter.DecryptPacket(0, "hello world!", StringPiece(data, len)));
ASSERT_FALSE(decrypted.get());
}
diff --git a/chromium/net/quic/crypto/null_encrypter.cc b/chromium/net/quic/crypto/null_encrypter.cc
index a0a680d9c71..5f1a85b114a 100644
--- a/chromium/net/quic/crypto/null_encrypter.cc
+++ b/chromium/net/quic/crypto/null_encrypter.cc
@@ -11,7 +11,9 @@ using std::string;
namespace net {
-const size_t kHashSize = 16; // size of uint128 serialized
+const size_t kHashSizeShort = 12; // size of uint128 serialized short
+
+NullEncrypter::NullEncrypter() {}
bool NullEncrypter::SetKey(StringPiece key) { return key.empty(); }
@@ -27,8 +29,8 @@ bool NullEncrypter::Encrypt(
string buffer = associated_data.as_string();
plaintext.AppendToString(&buffer);
uint128 hash = QuicUtils::FNV1a_128_Hash(buffer.data(), buffer.length());
- QuicUtils::SerializeUint128(hash, output);
- memcpy(output + sizeof(hash), plaintext.data(), plaintext.size());
+ QuicUtils::SerializeUint128Short(hash, output);
+ memcpy(output + GetHashLength(), plaintext.data(), plaintext.size());
return true;
}
@@ -36,7 +38,7 @@ QuicData* NullEncrypter::EncryptPacket(
QuicPacketSequenceNumber /*sequence_number*/,
StringPiece associated_data,
StringPiece plaintext) {
- const size_t len = plaintext.size() + sizeof(uint128);
+ const size_t len = plaintext.size() + GetHashLength();
uint8* buffer = new uint8[len];
Encrypt(StringPiece(), associated_data, plaintext, buffer);
return new QuicData(reinterpret_cast<char*>(buffer), len, true);
@@ -47,15 +49,19 @@ size_t NullEncrypter::GetKeySize() const { return 0; }
size_t NullEncrypter::GetNoncePrefixSize() const { return 0; }
size_t NullEncrypter::GetMaxPlaintextSize(size_t ciphertext_size) const {
- return ciphertext_size - kHashSize;
+ return ciphertext_size - GetHashLength();
}
size_t NullEncrypter::GetCiphertextSize(size_t plaintext_size) const {
- return plaintext_size + kHashSize;
+ return plaintext_size + GetHashLength();
}
StringPiece NullEncrypter::GetKey() const { return StringPiece(); }
StringPiece NullEncrypter::GetNoncePrefix() const { return StringPiece(); }
+size_t NullEncrypter::GetHashLength() const {
+ return kHashSizeShort;
+}
+
} // namespace net
diff --git a/chromium/net/quic/crypto/null_encrypter.h b/chromium/net/quic/crypto/null_encrypter.h
index ed05e1faaa0..44e6f5555e6 100644
--- a/chromium/net/quic/crypto/null_encrypter.h
+++ b/chromium/net/quic/crypto/null_encrypter.h
@@ -16,6 +16,7 @@ namespace net {
// generate a MAC (fnv128) over both the payload and associated data.
class NET_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
public:
+ NullEncrypter();
virtual ~NullEncrypter() {}
// QuicEncrypter implementation
@@ -34,6 +35,9 @@ class NET_EXPORT_PRIVATE NullEncrypter : public QuicEncrypter {
virtual size_t GetCiphertextSize(size_t plaintext_size) const OVERRIDE;
virtual base::StringPiece GetKey() const OVERRIDE;
virtual base::StringPiece GetNoncePrefix() const OVERRIDE;
+
+ private:
+ size_t GetHashLength() const;
};
} // namespace net
diff --git a/chromium/net/quic/crypto/null_encrypter_test.cc b/chromium/net/quic/crypto/null_encrypter_test.cc
index 4c00f918177..4f4dae754a7 100644
--- a/chromium/net/quic/crypto/null_encrypter_test.cc
+++ b/chromium/net/quic/crypto/null_encrypter_test.cc
@@ -10,13 +10,15 @@ using base::StringPiece;
namespace net {
namespace test {
-TEST(NullEncrypterTest, Encrypt) {
+class NullEncrypterTest : public ::testing::TestWithParam<bool> {
+};
+
+TEST_F(NullEncrypterTest, Encrypt) {
unsigned char expected[] = {
// fnv hash
0xa0, 0x6f, 0x44, 0x8a,
0x44, 0xf8, 0x18, 0x3b,
0x47, 0x91, 0xb2, 0x13,
- 0x6b, 0x09, 0xbb, 0xae,
// payload
'g', 'o', 'o', 'd',
'b', 'y', 'e', '!',
@@ -27,21 +29,22 @@ TEST(NullEncrypterTest, Encrypt) {
ASSERT_TRUE(encrypted.get());
test::CompareCharArraysWithHexError(
"encrypted data", encrypted->data(), encrypted->length(),
- reinterpret_cast<const char*>(expected), arraysize(expected));
+ reinterpret_cast<const char*>(expected),
+ arraysize(expected));
}
-TEST(NullEncrypterTest, GetMaxPlaintextSize) {
+TEST_F(NullEncrypterTest, GetMaxPlaintextSize) {
NullEncrypter encrypter;
- EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1016));
- EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(116));
- EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(26));
+ EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012));
+ EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112));
+ EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22));
}
-TEST(NullEncrypterTest, GetCiphertextSize) {
+TEST_F(NullEncrypterTest, GetCiphertextSize) {
NullEncrypter encrypter;
- EXPECT_EQ(1016u, encrypter.GetCiphertextSize(1000));
- EXPECT_EQ(116u, encrypter.GetCiphertextSize(100));
- EXPECT_EQ(26u, encrypter.GetCiphertextSize(10));
+ EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000));
+ EXPECT_EQ(112u, encrypter.GetCiphertextSize(100));
+ EXPECT_EQ(22u, encrypter.GetCiphertextSize(10));
}
} // namespace test
diff --git a/chromium/net/quic/crypto/p256_key_exchange_nss.cc b/chromium/net/quic/crypto/p256_key_exchange_nss.cc
index dede5ba7b21..6e60f5df8e6 100644
--- a/chromium/net/quic/crypto/p256_key_exchange_nss.cc
+++ b/chromium/net/quic/crypto/p256_key_exchange_nss.cc
@@ -40,7 +40,7 @@ P256KeyExchange::~P256KeyExchange() {
// static
P256KeyExchange* P256KeyExchange::New(StringPiece key) {
if (key.size() < 2) {
- DLOG(INFO) << "Key pair is too small.";
+ DVLOG(1) << "Key pair is too small.";
return NULL;
}
@@ -49,14 +49,14 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
(static_cast<size_t>(data[1]) << 8);
key.remove_prefix(2);
if (key.size() < size) {
- DLOG(INFO) << "Key pair does not contain key material.";
+ DVLOG(1) << "Key pair does not contain key material.";
return NULL;
}
StringPiece private_piece(key.data(), size);
key.remove_prefix(size);
if (key.empty()) {
- DLOG(INFO) << "Key pair does not contain public key.";
+ DVLOG(1) << "Key pair does not contain public key.";
return NULL;
}
@@ -70,7 +70,7 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
StringPieceToVector(public_piece)));
if (!key_pair.get()) {
- DLOG(INFO) << "Can't decrypt private key.";
+ DVLOG(1) << "Can't decrypt private key.";
return NULL;
}
@@ -80,14 +80,14 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
public_key->u.ec.publicValue.len != kUncompressedP256PointBytes ||
!public_key->u.ec.publicValue.data ||
public_key->u.ec.publicValue.data[0] != kUncompressedECPointForm) {
- DLOG(INFO) << "Key is invalid.";
+ DVLOG(1) << "Key is invalid.";
return NULL;
}
// Ensure that the key is using the correct curve, i.e., NIST P-256.
const SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
if (!oid_data) {
- DLOG(INFO) << "Can't get P-256's OID.";
+ DVLOG(1) << "Can't get P-256's OID.";
return NULL;
}
@@ -97,7 +97,7 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
public_key->u.ec.DEREncodedParams.data[1] != oid_data->oid.len ||
memcmp(public_key->u.ec.DEREncodedParams.data + 2,
oid_data->oid.data, oid_data->oid.len) != 0) {
- DLOG(INFO) << "Key is invalid.";
+ DVLOG(1) << "Key is invalid.";
}
return new P256KeyExchange(key_pair.release(),
@@ -109,7 +109,7 @@ string P256KeyExchange::NewPrivateKey() {
scoped_ptr<crypto::ECPrivateKey> key_pair(crypto::ECPrivateKey::Create());
if (!key_pair.get()) {
- DLOG(INFO) << "Can't generate new key pair.";
+ DVLOG(1) << "Can't generate new key pair.";
return string();
}
@@ -117,7 +117,7 @@ string P256KeyExchange::NewPrivateKey() {
if (!key_pair->ExportEncryptedPrivateKey(kExportPassword,
1 /* iteration */,
&private_key)) {
- DLOG(INFO) << "Can't export private key.";
+ DVLOG(1) << "Can't export private key.";
return string();
}
@@ -126,7 +126,7 @@ string P256KeyExchange::NewPrivateKey() {
// store the public key.
vector<uint8> public_key;
if (!key_pair->ExportPublicKey(&public_key)) {
- DLOG(INFO) << "Can't export public key.";
+ DVLOG(1) << "Can't export public key.";
return string();
}
@@ -159,7 +159,7 @@ bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes ||
peer_public_value[0] != kUncompressedECPointForm) {
- DLOG(INFO) << "Peer public value is invalid.";
+ DVLOG(1) << "Peer public value is invalid.";
return false;
}
@@ -203,18 +203,18 @@ bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
NULL));
if (!premaster_secret.get()) {
- DLOG(INFO) << "Can't derive ECDH shared key.";
+ DVLOG(1) << "Can't derive ECDH shared key.";
return false;
}
if (PK11_ExtractKeyValue(premaster_secret.get()) != SECSuccess) {
- DLOG(INFO) << "Can't extract raw ECDH shared key.";
+ DVLOG(1) << "Can't extract raw ECDH shared key.";
return false;
}
SECItem* key_data = PK11_GetKeyData(premaster_secret.get());
if (!key_data || !key_data->data || key_data->len != kP256FieldBytes) {
- DLOG(INFO) << "ECDH shared key is invalid.";
+ DVLOG(1) << "ECDH shared key is invalid.";
return false;
}
diff --git a/chromium/net/quic/crypto/p256_key_exchange_openssl.cc b/chromium/net/quic/crypto/p256_key_exchange_openssl.cc
index 6eaa981a86d..197df6a1b91 100644
--- a/chromium/net/quic/crypto/p256_key_exchange_openssl.cc
+++ b/chromium/net/quic/crypto/p256_key_exchange_openssl.cc
@@ -25,7 +25,7 @@ P256KeyExchange::~P256KeyExchange() {}
// static
P256KeyExchange* P256KeyExchange::New(StringPiece key) {
if (key.empty()) {
- DLOG(INFO) << "Private key is empty";
+ DVLOG(1) << "Private key is empty";
return NULL;
}
@@ -33,7 +33,7 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> private_key(
d2i_ECPrivateKey(NULL, &keyp, key.size()));
if (!private_key.get() || !EC_KEY_check_key(private_key.get())) {
- DLOG(INFO) << "Private key is invalid.";
+ DVLOG(1) << "Private key is invalid.";
return NULL;
}
@@ -42,7 +42,7 @@ P256KeyExchange* P256KeyExchange::New(StringPiece key) {
EC_KEY_get0_public_key(private_key.get()),
POINT_CONVERSION_UNCOMPRESSED, public_key,
sizeof(public_key), NULL) != sizeof(public_key)) {
- DLOG(INFO) << "Can't get public key.";
+ DVLOG(1) << "Can't get public key.";
return NULL;
}
@@ -54,19 +54,19 @@ string P256KeyExchange::NewPrivateKey() {
crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> key(
EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
if (!key.get() || !EC_KEY_generate_key(key.get())) {
- DLOG(INFO) << "Can't generate a new private key.";
+ DVLOG(1) << "Can't generate a new private key.";
return string();
}
int key_len = i2d_ECPrivateKey(key.get(), NULL);
if (key_len <= 0) {
- DLOG(INFO) << "Can't convert private key to string";
+ DVLOG(1) << "Can't convert private key to string";
return string();
}
scoped_ptr<uint8[]> private_key(new uint8[key_len]);
uint8* keyp = private_key.get();
if (!i2d_ECPrivateKey(key.get(), &keyp)) {
- DLOG(INFO) << "Can't convert private key to string.";
+ DVLOG(1) << "Can't convert private key to string.";
return string();
}
return string(reinterpret_cast<char*>(private_key.get()), key_len);
@@ -81,7 +81,7 @@ KeyExchange* P256KeyExchange::NewKeyPair(QuicRandom* /*rand*/) const {
bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
string* out_result) const {
if (peer_public_value.size() != kUncompressedP256PointBytes) {
- DLOG(INFO) << "Peer public value is invalid";
+ DVLOG(1) << "Peer public value is invalid";
return false;
}
@@ -93,14 +93,14 @@ bool P256KeyExchange::CalculateSharedKey(const StringPiece& peer_public_value,
point.get(),
reinterpret_cast<const uint8*>(peer_public_value.data()),
peer_public_value.size(), NULL)) {
- DLOG(INFO) << "Can't convert peer public value to curve point.";
+ DVLOG(1) << "Can't convert peer public value to curve point.";
return false;
}
uint8 result[kP256FieldBytes];
if (ECDH_compute_key(result, sizeof(result), point.get(), private_key_.get(),
NULL) != sizeof(result)) {
- DLOG(INFO) << "Can't compute ECDH shared key.";
+ DVLOG(1) << "Can't compute ECDH shared key.";
return false;
}
diff --git a/chromium/net/quic/crypto/proof_test.cc b/chromium/net/quic/crypto/proof_test.cc
index e4e661a298c..cc9e0992c1a 100644
--- a/chromium/net/quic/crypto/proof_test.cc
+++ b/chromium/net/quic/crypto/proof_test.cc
@@ -173,49 +173,76 @@ TEST(ProofTest, VerifyRSAKnownAnswerTest) {
// and dumping the bytes of the |signature| output of ProofSource::GetProof().
// sLen = special value -2 used by OpenSSL.
static const unsigned char signature_data_0[] = {
- 0x9e, 0xe6, 0x74, 0x3b, 0x8f, 0xb8, 0x66, 0x77, 0x57, 0x09,
- 0x8a, 0x04, 0xe9, 0xf0, 0x7c, 0x91, 0xa9, 0x5c, 0xe9, 0xdf,
- 0x12, 0x4d, 0x23, 0x82, 0x8c, 0x29, 0x72, 0x7f, 0xc2, 0x20,
- 0xa7, 0xb3, 0xe5, 0xbc, 0xcf, 0x3c, 0x0d, 0x8f, 0xae, 0x46,
- 0x6a, 0xb9, 0xee, 0x0c, 0xe1, 0x13, 0x21, 0xc0, 0x7e, 0x45,
- 0x24, 0x24, 0x4b, 0x72, 0x43, 0x5e, 0xc4, 0x0d, 0xdf, 0x6c,
- 0xd8, 0xaa, 0x35, 0x97, 0x05, 0x40, 0x76, 0xd3, 0x2c, 0xee,
- 0x82, 0x16, 0x6a, 0x43, 0xf9, 0xa2, 0xd0, 0x41, 0x3c, 0xed,
- 0x3f, 0x40, 0x10, 0x95, 0xc7, 0xa9, 0x1f, 0x04, 0xdb, 0xd5,
- 0x98, 0x9f, 0xe2, 0xbf, 0x77, 0x3d, 0xc9, 0x9a, 0xaf, 0xf7,
- 0xef, 0x63, 0x0b, 0x7d, 0xc8, 0x37, 0xda, 0x37, 0x23, 0x88,
- 0x78, 0xc8, 0x8b, 0xf5, 0xb9, 0x36, 0x5d, 0x72, 0x1f, 0xfc,
- 0x14, 0xff, 0xa7, 0x81, 0x27, 0x49, 0xae, 0xe1,
+ 0x31, 0xd5, 0xfb, 0x40, 0x30, 0x75, 0xd2, 0x7d, 0x61, 0xf9, 0xd7, 0x54,
+ 0x30, 0x06, 0xaf, 0x54, 0x0d, 0xb0, 0x0a, 0xda, 0x63, 0xca, 0x7e, 0x9e,
+ 0xce, 0xba, 0x10, 0x05, 0x1b, 0xa6, 0x7f, 0xef, 0x2b, 0xa3, 0xff, 0x3c,
+ 0xbb, 0x9a, 0xe4, 0xbf, 0xb8, 0x0c, 0xc1, 0xbd, 0xed, 0xc2, 0x90, 0x68,
+ 0xeb, 0x45, 0x48, 0xea, 0x3c, 0x95, 0xf8, 0xa2, 0xb9, 0xe7, 0x62, 0x29,
+ 0x00, 0xc3, 0x18, 0xb4, 0x16, 0x6f, 0x5e, 0xb0, 0xc1, 0x26, 0xc0, 0x4b,
+ 0x84, 0xf5, 0x97, 0xfc, 0x17, 0xf9, 0x1c, 0x43, 0xb8, 0xf2, 0x3f, 0x38,
+ 0x32, 0xad, 0x36, 0x52, 0x2c, 0x26, 0x92, 0x7a, 0xea, 0x2c, 0xa2, 0xf4,
+ 0x28, 0x2f, 0x19, 0x4d, 0x1f, 0x11, 0x46, 0x82, 0xd0, 0xc4, 0x86, 0x56,
+ 0x5c, 0x97, 0x9e, 0xc6, 0x37, 0x8e, 0xaf, 0x9d, 0x69, 0xe9, 0x4f, 0x5a,
+ 0x6d, 0x70, 0x75, 0xc7, 0x41, 0x95, 0x68, 0x53, 0x94, 0xca, 0x31, 0x63,
+ 0x61, 0x9f, 0xb8, 0x8c, 0x3b, 0x75, 0x36, 0x8b, 0x69, 0xa2, 0x35, 0xc0,
+ 0x4b, 0x77, 0x55, 0x08, 0xc2, 0xb4, 0x56, 0xd2, 0x81, 0xce, 0x9e, 0x25,
+ 0xdb, 0x50, 0x74, 0xb3, 0x8a, 0xd9, 0x20, 0x42, 0x3f, 0x85, 0x2d, 0xaa,
+ 0xfd, 0x66, 0xfa, 0xd6, 0x95, 0x55, 0x6b, 0x63, 0x63, 0x04, 0xf8, 0x6c,
+ 0x3e, 0x08, 0x22, 0x39, 0xb9, 0x9a, 0xe0, 0xd7, 0x01, 0xff, 0xeb, 0x8a,
+ 0xb9, 0xe2, 0x34, 0xa5, 0xa0, 0x51, 0xe9, 0xbe, 0x15, 0x12, 0xbf, 0xbe,
+ 0x64, 0x3d, 0x3f, 0x98, 0xce, 0xc1, 0xa6, 0x33, 0x32, 0xd3, 0x5c, 0xa8,
+ 0x39, 0x93, 0xdc, 0x1c, 0xb9, 0xab, 0x3c, 0x80, 0x62, 0xb3, 0x76, 0x21,
+ 0xdf, 0x47, 0x1e, 0xa9, 0x0e, 0x5e, 0x8a, 0xbe, 0x66, 0x5b, 0x7c, 0x21,
+ 0xfa, 0x78, 0x2d, 0xd1, 0x1d, 0x5c, 0x35, 0x8a, 0x34, 0xb2, 0x1a, 0xc2,
+ 0xc4, 0x4b, 0x53, 0x54,
};
static const unsigned char signature_data_1[] = {
- 0x5e, 0xc2, 0xab, 0x6b, 0x16, 0xe6, 0x55, 0xf3, 0x16, 0x46,
- 0x35, 0xdc, 0xcc, 0xde, 0xd0, 0xbd, 0x6c, 0x66, 0xb2, 0x3d,
- 0xd3, 0x14, 0x78, 0xed, 0x47, 0x55, 0xfb, 0xdb, 0xe1, 0x7d,
- 0xbf, 0x31, 0xf6, 0xf4, 0x10, 0x4c, 0x8d, 0x22, 0x17, 0xaa,
- 0xe1, 0x85, 0xc7, 0x96, 0x4c, 0x42, 0xfb, 0xf4, 0x63, 0x53,
- 0x8a, 0x79, 0x01, 0x63, 0x48, 0xa8, 0x3a, 0xbc, 0xc9, 0xd2,
- 0xf5, 0xec, 0xe9, 0x09, 0x71, 0xaf, 0xce, 0x34, 0x56, 0xe5,
- 0x00, 0xbe, 0xee, 0x3c, 0x1c, 0xc4, 0xa0, 0x07, 0xd5, 0x77,
- 0xb8, 0x83, 0x57, 0x7d, 0x1a, 0xc9, 0xd0, 0xc0, 0x59, 0x9a,
- 0x88, 0x19, 0x3f, 0xb9, 0xf0, 0x45, 0x37, 0xc3, 0x00, 0x8b,
- 0xb3, 0x89, 0xf4, 0x89, 0x07, 0xa9, 0xc3, 0x26, 0xbf, 0x81,
- 0xaf, 0x6b, 0x47, 0xbc, 0x16, 0x55, 0x37, 0x0a, 0xbe, 0x0e,
- 0xc5, 0x75, 0x3f, 0x3d, 0x8e, 0xe8, 0x44, 0xe3,
+ 0x01, 0x7b, 0x52, 0x35, 0xe3, 0x51, 0xdd, 0xf1, 0x67, 0x8d, 0x31, 0x5e,
+ 0xa3, 0x75, 0x1f, 0x68, 0x6c, 0xdd, 0x41, 0x7a, 0x18, 0x25, 0xe0, 0x12,
+ 0x6e, 0x84, 0x46, 0x5e, 0xb2, 0x98, 0xd7, 0x84, 0xe1, 0x62, 0xe0, 0xc1,
+ 0xc4, 0xd7, 0x4f, 0x4f, 0x80, 0xc1, 0x92, 0xd6, 0x02, 0xaf, 0xca, 0x28,
+ 0x9f, 0xe0, 0xf3, 0x74, 0xd7, 0xf1, 0x44, 0x67, 0x59, 0x27, 0xc8, 0xc2,
+ 0x8b, 0xd4, 0xe5, 0x4a, 0x07, 0xfd, 0x00, 0xd6, 0x8a, 0xbf, 0x8b, 0xcd,
+ 0x6a, 0xe0, 0x1d, 0xf6, 0x4b, 0x68, 0x0f, 0xcf, 0xb9, 0xd0, 0xa1, 0xbc,
+ 0x2e, 0xcf, 0x7c, 0x03, 0x47, 0x11, 0xe4, 0x4c, 0xbc, 0x1b, 0x6b, 0xa5,
+ 0x2a, 0x82, 0x86, 0xa4, 0x7f, 0x1d, 0x85, 0x64, 0x21, 0x10, 0xd2, 0xb2,
+ 0xa0, 0x31, 0xa2, 0x78, 0xe6, 0xf2, 0xea, 0x96, 0x38, 0x8c, 0x9a, 0xe1,
+ 0x01, 0xab, 0x8e, 0x95, 0x66, 0xc8, 0xe5, 0xcc, 0x80, 0xa3, 0xbd, 0x16,
+ 0xa7, 0x79, 0x19, 0x39, 0x61, 0x3d, 0xff, 0x37, 0xca, 0x9f, 0x97, 0x05,
+ 0xc7, 0xcb, 0xf0, 0xea, 0xaf, 0x64, 0x07, 0xc0, 0xed, 0x2a, 0x98, 0xa4,
+ 0xaf, 0x04, 0x6f, 0xf2, 0xc9, 0xb2, 0x73, 0x9a, 0x56, 0x85, 0x43, 0x64,
+ 0x5f, 0xaa, 0xb7, 0xff, 0x31, 0x4c, 0x2e, 0x6c, 0x17, 0xcf, 0xe5, 0xbe,
+ 0x7f, 0x7e, 0xad, 0xf5, 0x6f, 0x84, 0x50, 0x20, 0x29, 0xb3, 0x57, 0xe7,
+ 0xb1, 0xdc, 0x2c, 0x95, 0x48, 0xfe, 0xb0, 0xc1, 0x92, 0xda, 0xc5, 0x58,
+ 0x95, 0xb0, 0x1a, 0x3a, 0x05, 0x71, 0x3c, 0x6d, 0x20, 0x01, 0x4c, 0xa9,
+ 0xe4, 0x38, 0x08, 0x65, 0xb4, 0xbd, 0x86, 0x76, 0xbd, 0xad, 0x25, 0x06,
+ 0x74, 0x0b, 0xca, 0x95, 0x27, 0x0c, 0x13, 0x08, 0x7e, 0x30, 0xcf, 0xf6,
+ 0xb5, 0xc1, 0x2a, 0x08, 0xfc, 0x4b, 0xc6, 0xb5, 0x2f, 0x23, 0x27, 0x32,
+ 0x89, 0xdb, 0x0e, 0x4a,
};
static const unsigned char signature_data_2[] = {
- 0x8e, 0x5c, 0x78, 0x63, 0x74, 0x99, 0x2e, 0x96, 0xc0, 0x14,
- 0x8d, 0xb5, 0x13, 0x74, 0xa3, 0xa4, 0xe0, 0x43, 0x3e, 0x85,
- 0xba, 0x8f, 0x3c, 0x5e, 0x14, 0x64, 0x0e, 0x5e, 0xff, 0x89,
- 0x88, 0x8a, 0x65, 0xe2, 0xa2, 0x79, 0xe4, 0xe9, 0x3a, 0x7f,
- 0xf6, 0x9d, 0x3d, 0xe2, 0xb0, 0x8a, 0x35, 0x55, 0xed, 0x21,
- 0xee, 0x20, 0xd8, 0x8a, 0x60, 0x47, 0xca, 0x52, 0x54, 0x91,
- 0x99, 0x69, 0x8d, 0x16, 0x34, 0x69, 0xe1, 0x46, 0x56, 0x67,
- 0x5f, 0x50, 0xf0, 0x94, 0xe7, 0x8b, 0xf2, 0x6a, 0x73, 0x0f,
- 0x30, 0x30, 0xde, 0x59, 0xdc, 0xc7, 0xfe, 0xb6, 0x83, 0xe1,
- 0x86, 0x1d, 0x88, 0xd3, 0x2f, 0x2f, 0x74, 0x68, 0xbd, 0x6c,
- 0xd1, 0x46, 0x76, 0x06, 0xa9, 0xd4, 0x03, 0x3f, 0xda, 0x7d,
- 0xa7, 0xff, 0x48, 0xe4, 0xb4, 0x42, 0x06, 0xac, 0x19, 0x12,
- 0xe6, 0x05, 0xae, 0xbe, 0x29, 0x94, 0x8f, 0x99,
+ 0x6d, 0x7d, 0x22, 0x8c, 0x85, 0xc4, 0x8a, 0x80, 0x05, 0xe4, 0x3c, 0xaf,
+ 0x10, 0x3b, 0xe3, 0x51, 0xb1, 0x86, 0x52, 0x63, 0xb6, 0x17, 0x33, 0xbd,
+ 0x1b, 0x1e, 0xc4, 0x50, 0x10, 0xfc, 0xcc, 0xea, 0x6b, 0x11, 0xeb, 0x6d,
+ 0x5e, 0x00, 0xe7, 0xf3, 0x67, 0x99, 0x74, 0x53, 0x12, 0x8f, 0xe4, 0x3e,
+ 0x20, 0x17, 0x8e, 0x83, 0xe6, 0xdc, 0x83, 0x91, 0x0e, 0xf3, 0x69, 0x22,
+ 0x95, 0x14, 0xdf, 0xc1, 0xda, 0xb5, 0xdb, 0x6a, 0x1a, 0xb4, 0x4f, 0x26,
+ 0xd0, 0x32, 0x1d, 0x73, 0x95, 0x1f, 0x39, 0x1d, 0x00, 0xcb, 0xc3, 0x92,
+ 0x49, 0x53, 0xcb, 0x5c, 0x36, 0x70, 0x19, 0xd9, 0x64, 0x36, 0xda, 0xfb,
+ 0x20, 0xe5, 0x47, 0xd9, 0x08, 0xc6, 0x5a, 0x9e, 0x87, 0x1a, 0xdb, 0x11,
+ 0x7b, 0x17, 0xfc, 0x53, 0x7b, 0xc1, 0xa0, 0xc0, 0x33, 0xcf, 0x96, 0xba,
+ 0x03, 0x79, 0x8e, 0xc6, 0x05, 0xd2, 0xb7, 0xa2, 0xe2, 0xc1, 0x67, 0xb7,
+ 0x6a, 0xeb, 0xb1, 0x40, 0xbb, 0x7d, 0x57, 0xcb, 0xc2, 0x60, 0x9f, 0xf1,
+ 0x72, 0xe5, 0xad, 0xce, 0x95, 0x45, 0x7c, 0xbc, 0x75, 0x81, 0x45, 0x19,
+ 0xe1, 0xa7, 0x2f, 0x05, 0x52, 0xeb, 0xed, 0xdd, 0x19, 0xd9, 0x1a, 0xc9,
+ 0x5a, 0x06, 0x8e, 0x29, 0x54, 0xb5, 0x4f, 0x80, 0xaa, 0x36, 0x36, 0xc0,
+ 0xff, 0x64, 0xac, 0xe8, 0x0f, 0x99, 0x35, 0x5e, 0xc6, 0x72, 0x1f, 0x8c,
+ 0xc4, 0x2b, 0x7d, 0xc1, 0xfb, 0xf0, 0x12, 0x61, 0xb1, 0x18, 0x65, 0xdd,
+ 0xc2, 0x38, 0x92, 0xba, 0x84, 0xf8, 0xc8, 0x5e, 0x17, 0x63, 0xe0, 0x9c,
+ 0x2c, 0xe6, 0x70, 0x71, 0xdc, 0xe5, 0xc1, 0xea, 0xb3, 0x9a, 0xb6, 0x91,
+ 0xdc, 0xc5, 0x56, 0x84, 0x8a, 0x31, 0x31, 0x23, 0x61, 0x94, 0x7e, 0x01,
+ 0x22, 0x49, 0xf3, 0xcb, 0x0e, 0x31, 0x03, 0x04, 0x1b, 0x14, 0x43, 0x7c,
+ 0xad, 0x42, 0xe5, 0x55,
};
scoped_ptr<ProofVerifier> verifier(
@@ -223,7 +250,6 @@ TEST(ProofTest, VerifyRSAKnownAnswerTest) {
const string server_config = "server config bytes";
const string hostname = "test.example.com";
- string error_details;
CertVerifyResult cert_verify_result;
vector<string> certs(2);
@@ -278,33 +304,28 @@ TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
// (modified to use ECDSA for signing proofs) and dumping the bytes of the
// |signature| output of ProofSource::GetProof().
static const unsigned char signature_data_0[] = {
- 0x30, 0x45, 0x02, 0x20, 0x15, 0xb7, 0x9f, 0xe3, 0xd9, 0x7a,
- 0x3c, 0x3b, 0x18, 0xb0, 0xdb, 0x60, 0x23, 0x56, 0xa0, 0x06,
- 0x4e, 0x70, 0xa3, 0xf7, 0x4b, 0xe5, 0x0d, 0x69, 0xf0, 0x35,
- 0x8c, 0xae, 0xb5, 0x54, 0x32, 0xe9, 0x02, 0x21, 0x00, 0xf7,
- 0xe3, 0x06, 0x99, 0x16, 0x56, 0x7e, 0xab, 0x33, 0x53, 0x0d,
- 0xde, 0xbe, 0xef, 0x6d, 0xb0, 0xc7, 0xa6, 0x63, 0xaf, 0x8d,
- 0xab, 0x34, 0xa9, 0xc0, 0x63, 0x88, 0x47, 0x17, 0x4c, 0x4c,
- 0x04,
+ 0x30, 0x45, 0x02, 0x21, 0x00, 0x89, 0xc4, 0x7d, 0x08, 0xd1, 0x49, 0x19,
+ 0x6c, 0xd1, 0x7c, 0xb9, 0x25, 0xe0, 0xe3, 0xbd, 0x6a, 0x5c, 0xd7, 0xaa,
+ 0x0c, 0xdc, 0x4f, 0x8e, 0xeb, 0xde, 0xbf, 0x32, 0xf8, 0xd1, 0x84, 0x95,
+ 0x97, 0x02, 0x20, 0x29, 0x3d, 0x49, 0x22, 0x73, 0xed, 0x8b, 0xde, 0x3d,
+ 0xc2, 0xa4, 0x20, 0xcc, 0xe7, 0xc8, 0x2a, 0x85, 0x20, 0x9b, 0x5b, 0xda,
+ 0xcd, 0x58, 0x23, 0xbe, 0x89, 0x73, 0x31, 0x87, 0x51, 0xd1, 0x01,
};
static const unsigned char signature_data_1[] = {
- 0x30, 0x44, 0x02, 0x20, 0x69, 0x60, 0x55, 0xbb, 0x11, 0x93,
- 0x6a, 0xdc, 0x9b, 0x61, 0x2c, 0x60, 0x19, 0xbc, 0x15, 0x55,
- 0xcf, 0xf2, 0x8e, 0x2e, 0x27, 0x0b, 0x69, 0xef, 0x33, 0x25,
- 0x1e, 0x5d, 0x8c, 0x00, 0x11, 0xef, 0x02, 0x20, 0x0c, 0x26,
- 0xfe, 0x0b, 0x06, 0x8f, 0xe8, 0xe2, 0x02, 0x63, 0xe5, 0x43,
- 0x0d, 0xc9, 0x80, 0x4d, 0xe9, 0x6f, 0x6e, 0x18, 0xdb, 0xb0,
- 0x04, 0x2a, 0x45, 0x37, 0x1a, 0x60, 0x0e, 0xc6, 0xc4, 0x8f,
+ 0x30, 0x46, 0x02, 0x21, 0x00, 0xec, 0xdf, 0x69, 0xc8, 0x24, 0x59, 0x93,
+ 0xda, 0x49, 0xee, 0x37, 0x28, 0xaf, 0xeb, 0x0e, 0x2f, 0x80, 0x17, 0x4b,
+ 0x3b, 0xf6, 0x54, 0xcd, 0x3b, 0x86, 0xc5, 0x98, 0x0d, 0xff, 0xc6, 0xb1,
+ 0xe7, 0x02, 0x21, 0x00, 0xe1, 0x36, 0x8c, 0xc0, 0xf4, 0x50, 0x5f, 0xba,
+ 0xfb, 0xe2, 0xff, 0x1d, 0x5d, 0x64, 0xe4, 0x07, 0xbb, 0x5a, 0x4b, 0x19,
+ 0xb6, 0x39, 0x7a, 0xc4, 0x12, 0xc6, 0xe5, 0x42, 0xc8, 0x78, 0x33, 0xcd,
};
static const unsigned char signature_data_2[] = {
- 0x30, 0x45, 0x02, 0x21, 0x00, 0xd5, 0x43, 0x36, 0x60, 0x50,
- 0xce, 0xe0, 0x00, 0x51, 0x02, 0x84, 0x95, 0x51, 0x47, 0xaf,
- 0xe4, 0xf9, 0xe1, 0x23, 0xae, 0x21, 0xb4, 0x98, 0xd1, 0xa3,
- 0x5f, 0x3b, 0xf3, 0x6a, 0x65, 0x44, 0x6b, 0x02, 0x20, 0x30,
- 0x7e, 0xb4, 0xea, 0xf0, 0xda, 0xdb, 0xbd, 0x38, 0xb9, 0x7a,
- 0x5d, 0x12, 0x04, 0x0e, 0xc2, 0xf0, 0xb1, 0x0e, 0x25, 0xf8,
- 0x0a, 0x27, 0xa3, 0x16, 0x94, 0xac, 0x1e, 0xb8, 0x6e, 0x00,
- 0x05,
+ 0x30, 0x45, 0x02, 0x20, 0x09, 0x51, 0xe9, 0xde, 0xdb, 0x01, 0xfd, 0xb4,
+ 0xd8, 0x20, 0xbb, 0xad, 0x41, 0xe3, 0xaa, 0xe7, 0xa3, 0xc3, 0x32, 0x10,
+ 0x9d, 0xfa, 0x37, 0xce, 0x17, 0xd1, 0x29, 0xf9, 0xd4, 0x1d, 0x0d, 0x19,
+ 0x02, 0x21, 0x00, 0xc6, 0x20, 0xd4, 0x28, 0xf9, 0x70, 0xb5, 0xb4, 0xff,
+ 0x4a, 0x35, 0xba, 0xa0, 0xf2, 0x8e, 0x00, 0xf7, 0xcb, 0x43, 0xaf, 0x2d,
+ 0x1f, 0xce, 0x92, 0x05, 0xca, 0x29, 0xfe, 0xd2, 0x8f, 0xd9, 0x31,
};
scoped_ptr<ProofVerifier> verifier(
@@ -312,7 +333,6 @@ TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
const string server_config = "server config bytes";
const string hostname = "test.example.com";
- string error_details;
CertVerifyResult cert_verify_result;
vector<string> certs(2);
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium.cc b/chromium/net/quic/crypto/proof_verifier_chromium.cc
index 8c4796204ec..68ad25ca12d 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium.cc
+++ b/chromium/net/quic/crypto/proof_verifier_chromium.cc
@@ -248,7 +248,7 @@ bool ProofVerifierChromium::VerifySignature(const string& signed_data,
return false;
}
- DLOG(INFO) << "VerifyFinal success";
+ DVLOG(1) << "VerifyFinal success";
return true;
}
diff --git a/chromium/net/quic/crypto/quic_crypto_client_config.cc b/chromium/net/quic/crypto/quic_crypto_client_config.cc
new file mode 100644
index 00000000000..a3eeeb62d22
--- /dev/null
+++ b/chromium/net/quic/crypto/quic_crypto_client_config.cc
@@ -0,0 +1,650 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/crypto/quic_crypto_client_config.h"
+
+#include "base/stl_util.h"
+#include "net/quic/crypto/cert_compressor.h"
+#include "net/quic/crypto/channel_id.h"
+#include "net/quic/crypto/common_cert_set.h"
+#include "net/quic/crypto/crypto_framer.h"
+#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/crypto/curve25519_key_exchange.h"
+#include "net/quic/crypto/key_exchange.h"
+#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/quic_utils.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+using base::StringPiece;
+using std::map;
+using std::string;
+using std::vector;
+
+namespace net {
+
+QuicCryptoClientConfig::QuicCryptoClientConfig() {}
+
+QuicCryptoClientConfig::~QuicCryptoClientConfig() {
+ STLDeleteValues(&cached_states_);
+}
+
+QuicCryptoClientConfig::CachedState::CachedState()
+ : server_config_valid_(false),
+ generation_counter_(0) {}
+
+QuicCryptoClientConfig::CachedState::~CachedState() {}
+
+bool QuicCryptoClientConfig::CachedState::IsComplete(QuicWallTime now) const {
+ if (server_config_.empty() || !server_config_valid_) {
+ return false;
+ }
+
+ const CryptoHandshakeMessage* scfg = GetServerConfig();
+ if (!scfg) {
+ // Should be impossible short of cache corruption.
+ DCHECK(false);
+ return false;
+ }
+
+ uint64 expiry_seconds;
+ if (scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR ||
+ now.ToUNIXSeconds() >= expiry_seconds) {
+ return false;
+ }
+
+ return true;
+}
+
+const CryptoHandshakeMessage*
+QuicCryptoClientConfig::CachedState::GetServerConfig() const {
+ if (server_config_.empty()) {
+ return NULL;
+ }
+
+ if (!scfg_.get()) {
+ scfg_.reset(CryptoFramer::ParseMessage(server_config_));
+ DCHECK(scfg_.get());
+ }
+ return scfg_.get();
+}
+
+QuicErrorCode QuicCryptoClientConfig::CachedState::SetServerConfig(
+ StringPiece server_config, QuicWallTime now, string* error_details) {
+ const bool matches_existing = server_config == server_config_;
+
+ // Even if the new server config matches the existing one, we still wish to
+ // reject it if it has expired.
+ scoped_ptr<CryptoHandshakeMessage> new_scfg_storage;
+ const CryptoHandshakeMessage* new_scfg;
+
+ if (!matches_existing) {
+ new_scfg_storage.reset(CryptoFramer::ParseMessage(server_config));
+ new_scfg = new_scfg_storage.get();
+ } else {
+ new_scfg = GetServerConfig();
+ }
+
+ if (!new_scfg) {
+ *error_details = "SCFG invalid";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ uint64 expiry_seconds;
+ if (new_scfg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
+ *error_details = "SCFG missing EXPY";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ if (now.ToUNIXSeconds() >= expiry_seconds) {
+ *error_details = "SCFG has expired";
+ return QUIC_CRYPTO_SERVER_CONFIG_EXPIRED;
+ }
+
+ if (!matches_existing) {
+ server_config_ = server_config.as_string();
+ SetProofInvalid();
+ scfg_.reset(new_scfg_storage.release());
+ }
+ return QUIC_NO_ERROR;
+}
+
+void QuicCryptoClientConfig::CachedState::InvalidateServerConfig() {
+ server_config_.clear();
+ scfg_.reset();
+ SetProofInvalid();
+}
+
+void QuicCryptoClientConfig::CachedState::SetProof(const vector<string>& certs,
+ StringPiece signature) {
+ bool has_changed =
+ signature != server_config_sig_ || certs_.size() != certs.size();
+
+ if (!has_changed) {
+ for (size_t i = 0; i < certs_.size(); i++) {
+ if (certs_[i] != certs[i]) {
+ has_changed = true;
+ break;
+ }
+ }
+ }
+
+ if (!has_changed) {
+ return;
+ }
+
+ // If the proof has changed then it needs to be revalidated.
+ SetProofInvalid();
+ certs_ = certs;
+ server_config_sig_ = signature.as_string();
+}
+
+void QuicCryptoClientConfig::CachedState::ClearProof() {
+ SetProofInvalid();
+ certs_.clear();
+ server_config_sig_.clear();
+}
+
+void QuicCryptoClientConfig::CachedState::SetProofValid() {
+ server_config_valid_ = true;
+}
+
+void QuicCryptoClientConfig::CachedState::SetProofInvalid() {
+ server_config_valid_ = false;
+ ++generation_counter_;
+}
+
+const string& QuicCryptoClientConfig::CachedState::server_config() const {
+ return server_config_;
+}
+
+const string&
+QuicCryptoClientConfig::CachedState::source_address_token() const {
+ return source_address_token_;
+}
+
+const vector<string>& QuicCryptoClientConfig::CachedState::certs() const {
+ return certs_;
+}
+
+const string& QuicCryptoClientConfig::CachedState::signature() const {
+ return server_config_sig_;
+}
+
+bool QuicCryptoClientConfig::CachedState::proof_valid() const {
+ return server_config_valid_;
+}
+
+uint64 QuicCryptoClientConfig::CachedState::generation_counter() const {
+ return generation_counter_;
+}
+
+const ProofVerifyDetails*
+QuicCryptoClientConfig::CachedState::proof_verify_details() const {
+ return proof_verify_details_.get();
+}
+
+void QuicCryptoClientConfig::CachedState::set_source_address_token(
+ StringPiece token) {
+ source_address_token_ = token.as_string();
+}
+
+void QuicCryptoClientConfig::CachedState::SetProofVerifyDetails(
+ ProofVerifyDetails* details) {
+ proof_verify_details_.reset(details);
+}
+
+void QuicCryptoClientConfig::CachedState::InitializeFrom(
+ const QuicCryptoClientConfig::CachedState& other) {
+ DCHECK(server_config_.empty());
+ DCHECK(!server_config_valid_);
+ server_config_ = other.server_config_;
+ source_address_token_ = other.source_address_token_;
+ certs_ = other.certs_;
+ server_config_sig_ = other.server_config_sig_;
+ server_config_valid_ = other.server_config_valid_;
+}
+
+void QuicCryptoClientConfig::SetDefaults() {
+ // Key exchange methods.
+ kexs.resize(2);
+ kexs[0] = kC255;
+ kexs[1] = kP256;
+
+ // Authenticated encryption algorithms.
+ aead.resize(1);
+ aead[0] = kAESG;
+}
+
+QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
+ const string& server_hostname) {
+ map<string, CachedState*>::const_iterator it =
+ cached_states_.find(server_hostname);
+ if (it != cached_states_.end()) {
+ return it->second;
+ }
+
+ CachedState* cached = new CachedState;
+ cached_states_.insert(make_pair(server_hostname, cached));
+ return cached;
+}
+
+void QuicCryptoClientConfig::FillInchoateClientHello(
+ const string& server_hostname,
+ const QuicVersion preferred_version,
+ const CachedState* cached,
+ QuicCryptoNegotiatedParameters* out_params,
+ CryptoHandshakeMessage* out) const {
+ out->set_tag(kCHLO);
+ out->set_minimum_size(kClientHelloMinimumSize);
+
+ // Server name indication. We only send SNI if it's a valid domain name, as
+ // per the spec.
+ if (CryptoUtils::IsValidSNI(server_hostname)) {
+ out->SetStringPiece(kSNI, server_hostname);
+ }
+ // TODO(rch): Remove once we remove QUIC_VERSION_12.
+ out->SetValue(kVERS, static_cast<uint16>(0));
+ out->SetValue(kVER, QuicVersionToQuicTag(preferred_version));
+
+ if (!cached->source_address_token().empty()) {
+ out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
+ }
+
+ if (proof_verifier_.get()) {
+ // Don't request ECDSA proofs on platforms that do not support ECDSA
+ // certificates.
+ bool disableECDSA = false;
+#if defined(OS_WIN)
+ if (base::win::GetVersion() < base::win::VERSION_VISTA)
+ disableECDSA = true;
+#endif
+ if (disableECDSA) {
+ out->SetTaglist(kPDMD, kX59R, 0);
+ } else {
+ out->SetTaglist(kPDMD, kX509, 0);
+ }
+ }
+
+ if (common_cert_sets) {
+ out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes());
+ }
+
+ const vector<string>& certs = cached->certs();
+ // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
+ // client config is being used for multiple connections, another connection
+ // doesn't update the cached certificates and cause us to be unable to
+ // process the server's compressed certificate chain.
+ out_params->cached_certs = certs;
+ if (!certs.empty()) {
+ vector<uint64> hashes;
+ hashes.reserve(certs.size());
+ for (vector<string>::const_iterator i = certs.begin();
+ i != certs.end(); ++i) {
+ hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
+ }
+ out->SetVector(kCCRT, hashes);
+ }
+}
+
+QuicErrorCode QuicCryptoClientConfig::FillClientHello(
+ const string& server_hostname,
+ QuicGuid guid,
+ const QuicVersion preferred_version,
+ const CachedState* cached,
+ QuicWallTime now,
+ QuicRandom* rand,
+ QuicCryptoNegotiatedParameters* out_params,
+ CryptoHandshakeMessage* out,
+ string* error_details) const {
+ DCHECK(error_details != NULL);
+
+ FillInchoateClientHello(server_hostname, preferred_version, cached,
+ out_params, out);
+
+ const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
+ if (!scfg) {
+ // This should never happen as our caller should have checked
+ // cached->IsComplete() before calling this function.
+ *error_details = "Handshake not ready";
+ return QUIC_CRYPTO_INTERNAL_ERROR;
+ }
+
+ StringPiece scid;
+ if (!scfg->GetStringPiece(kSCID, &scid)) {
+ *error_details = "SCFG missing SCID";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+ out->SetStringPiece(kSCID, scid);
+
+ const QuicTag* their_aeads;
+ const QuicTag* their_key_exchanges;
+ size_t num_their_aeads, num_their_key_exchanges;
+ if (scfg->GetTaglist(kAEAD, &their_aeads,
+ &num_their_aeads) != QUIC_NO_ERROR ||
+ scfg->GetTaglist(kKEXS, &their_key_exchanges,
+ &num_their_key_exchanges) != QUIC_NO_ERROR) {
+ *error_details = "Missing AEAD or KEXS";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ size_t key_exchange_index;
+ if (!QuicUtils::FindMutualTag(
+ aead, their_aeads, num_their_aeads, QuicUtils::PEER_PRIORITY,
+ &out_params->aead, NULL) ||
+ !QuicUtils::FindMutualTag(
+ kexs, their_key_exchanges, num_their_key_exchanges,
+ QuicUtils::PEER_PRIORITY, &out_params->key_exchange,
+ &key_exchange_index)) {
+ *error_details = "Unsupported AEAD or KEXS";
+ return QUIC_CRYPTO_NO_SUPPORT;
+ }
+ out->SetTaglist(kAEAD, out_params->aead, 0);
+ out->SetTaglist(kKEXS, out_params->key_exchange, 0);
+
+ StringPiece public_value;
+ if (scfg->GetNthValue24(kPUBS, key_exchange_index, &public_value) !=
+ QUIC_NO_ERROR) {
+ *error_details = "Missing public value";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ StringPiece orbit;
+ if (!scfg->GetStringPiece(kORBT, &orbit) || orbit.size() != kOrbitSize) {
+ *error_details = "SCFG missing OBIT";
+ return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
+ }
+
+ CryptoUtils::GenerateNonce(now, rand, orbit, &out_params->client_nonce);
+ out->SetStringPiece(kNONC, out_params->client_nonce);
+ if (!out_params->server_nonce.empty()) {
+ out->SetStringPiece(kServerNonceTag, out_params->server_nonce);
+ }
+
+ switch (out_params->key_exchange) {
+ case kC255:
+ out_params->client_key_exchange.reset(Curve25519KeyExchange::New(
+ Curve25519KeyExchange::NewPrivateKey(rand)));
+ break;
+ case kP256:
+ out_params->client_key_exchange.reset(P256KeyExchange::New(
+ P256KeyExchange::NewPrivateKey()));
+ break;
+ default:
+ DCHECK(false);
+ *error_details = "Configured to support an unknown key exchange";
+ return QUIC_CRYPTO_INTERNAL_ERROR;
+ }
+
+ if (!out_params->client_key_exchange->CalculateSharedKey(
+ public_value, &out_params->initial_premaster_secret)) {
+ *error_details = "Key exchange failure";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+ out->SetStringPiece(kPUBS, out_params->client_key_exchange->public_value());
+
+ bool do_channel_id = false;
+ if (channel_id_signer_.get()) {
+ const QuicTag* their_proof_demands;
+ size_t num_their_proof_demands;
+ if (scfg->GetTaglist(kPDMD, &their_proof_demands,
+ &num_their_proof_demands) == QUIC_NO_ERROR) {
+ for (size_t i = 0; i < num_their_proof_demands; i++) {
+ if (their_proof_demands[i] == kCHID) {
+ do_channel_id = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (do_channel_id) {
+ // In order to calculate the encryption key for the CETV block we need to
+ // serialise the client hello as it currently is (i.e. without the CETV
+ // block). For this, the client hello is serialized without padding.
+ const size_t orig_min_size = out->minimum_size();
+ out->set_minimum_size(0);
+
+ CryptoHandshakeMessage cetv;
+ cetv.set_tag(kCETV);
+
+ string hkdf_input;
+ const QuicData& client_hello_serialized = out->GetSerialized();
+ hkdf_input.append(QuicCryptoConfig::kCETVLabel,
+ strlen(QuicCryptoConfig::kCETVLabel) + 1);
+ hkdf_input.append(reinterpret_cast<char*>(&guid), sizeof(guid));
+ hkdf_input.append(client_hello_serialized.data(),
+ client_hello_serialized.length());
+ hkdf_input.append(cached->server_config());
+
+ string key, signature;
+ if (!channel_id_signer_->Sign(server_hostname, hkdf_input,
+ &key, &signature)) {
+ *error_details = "Channel ID signature failed";
+ return QUIC_INVALID_CHANNEL_ID_SIGNATURE;
+ }
+
+ cetv.SetStringPiece(kCIDK, key);
+ cetv.SetStringPiece(kCIDS, signature);
+
+ CrypterPair crypters;
+ if (!CryptoUtils::DeriveKeys(out_params->initial_premaster_secret,
+ out_params->aead, out_params->client_nonce,
+ out_params->server_nonce, hkdf_input,
+ CryptoUtils::CLIENT, &crypters)) {
+ *error_details = "Symmetric key setup failed";
+ return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
+ }
+
+ const QuicData& cetv_plaintext = cetv.GetSerialized();
+ scoped_ptr<QuicData> cetv_ciphertext(crypters.encrypter->EncryptPacket(
+ 0 /* sequence number */,
+ StringPiece() /* associated data */,
+ cetv_plaintext.AsStringPiece()));
+ if (!cetv_ciphertext.get()) {
+ *error_details = "Packet encryption failed";
+ return QUIC_ENCRYPTION_FAILURE;
+ }
+
+ out->SetStringPiece(kCETV, cetv_ciphertext->AsStringPiece());
+ out->MarkDirty();
+
+ out->set_minimum_size(orig_min_size);
+ }
+
+ out_params->hkdf_input_suffix.clear();
+ out_params->hkdf_input_suffix.append(reinterpret_cast<char*>(&guid),
+ sizeof(guid));
+ const QuicData& client_hello_serialized = out->GetSerialized();
+ out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
+ client_hello_serialized.length());
+ out_params->hkdf_input_suffix.append(cached->server_config());
+
+ string hkdf_input;
+ const size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
+ hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
+ 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,
+ CryptoUtils::CLIENT, &out_params->initial_crypters)) {
+ *error_details = "Symmetric key setup failed";
+ return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
+ }
+
+ return QUIC_NO_ERROR;
+}
+
+QuicErrorCode QuicCryptoClientConfig::ProcessRejection(
+ const CryptoHandshakeMessage& rej,
+ QuicWallTime now,
+ CachedState* cached,
+ QuicCryptoNegotiatedParameters* out_params,
+ string* error_details) {
+ DCHECK(error_details != NULL);
+
+ if (rej.tag() != kREJ) {
+ *error_details = "Message is not REJ";
+ return QUIC_CRYPTO_INTERNAL_ERROR;
+ }
+
+ StringPiece scfg;
+ if (!rej.GetStringPiece(kSCFG, &scfg)) {
+ *error_details = "Missing SCFG";
+ return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
+ }
+
+ QuicErrorCode error = cached->SetServerConfig(scfg, now, error_details);
+ if (error != QUIC_NO_ERROR) {
+ return error;
+ }
+
+ StringPiece token;
+ if (rej.GetStringPiece(kSourceAddressTokenTag, &token)) {
+ cached->set_source_address_token(token);
+ }
+
+ StringPiece nonce;
+ if (rej.GetStringPiece(kServerNonceTag, &nonce)) {
+ out_params->server_nonce = nonce.as_string();
+ }
+
+ StringPiece proof, cert_bytes;
+ bool has_proof = rej.GetStringPiece(kPROF, &proof);
+ bool has_cert = rej.GetStringPiece(kCertificateTag, &cert_bytes);
+ if (has_proof && has_cert) {
+ vector<string> certs;
+ if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
+ common_cert_sets, &certs)) {
+ *error_details = "Certificate data invalid";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ cached->SetProof(certs, proof);
+ } else {
+ cached->ClearProof();
+ if (has_proof && !has_cert) {
+ *error_details = "Certificate missing";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ if (!has_proof && has_cert) {
+ *error_details = "Proof missing";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+ }
+
+ return QUIC_NO_ERROR;
+}
+
+QuicErrorCode QuicCryptoClientConfig::ProcessServerHello(
+ const CryptoHandshakeMessage& server_hello,
+ QuicGuid guid,
+ const QuicVersionVector& negotiated_versions,
+ CachedState* cached,
+ QuicCryptoNegotiatedParameters* out_params,
+ string* error_details) {
+ DCHECK(error_details != NULL);
+
+ if (server_hello.tag() != kSHLO) {
+ *error_details = "Bad tag";
+ return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
+ }
+
+ const QuicTag* supported_version_tags;
+ size_t num_supported_versions;
+ // TODO(rch): Once QUIC_VERSION_12 is removed, then make it a failure
+ // if the server does not have a version list.
+ if (server_hello.GetTaglist(kVER, &supported_version_tags,
+ &num_supported_versions) == QUIC_NO_ERROR) {
+ if (!negotiated_versions.empty()) {
+ bool mismatch = num_supported_versions != negotiated_versions.size();
+ for (size_t i = 0; i < num_supported_versions && !mismatch; ++i) {
+ mismatch = QuicTagToQuicVersion(supported_version_tags[i]) !=
+ negotiated_versions[i];
+ }
+ // The server sent a list of supported versions, and the connection
+ // reports that there was a version negotiation during the handshake.
+ // Ensure that these two lists are identical.
+ if (mismatch) {
+ *error_details = "Downgrade attack detected";
+ return QUIC_VERSION_NEGOTIATION_MISMATCH;
+ }
+ }
+ }
+
+ // Learn about updated source address tokens.
+ StringPiece token;
+ if (server_hello.GetStringPiece(kSourceAddressTokenTag, &token)) {
+ cached->set_source_address_token(token);
+ }
+
+ // TODO(agl):
+ // learn about updated SCFGs.
+
+ StringPiece public_value;
+ if (!server_hello.GetStringPiece(kPUBS, &public_value)) {
+ *error_details = "server hello missing forward secure public value";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ if (!out_params->client_key_exchange->CalculateSharedKey(
+ public_value, &out_params->forward_secure_premaster_secret)) {
+ *error_details = "Key exchange failure";
+ return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ }
+
+ string hkdf_input;
+ const size_t label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
+ hkdf_input.reserve(label_len + out_params->hkdf_input_suffix.size());
+ hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel, label_len);
+ hkdf_input.append(out_params->hkdf_input_suffix);
+
+ if (!CryptoUtils::DeriveKeys(
+ out_params->forward_secure_premaster_secret, out_params->aead,
+ out_params->client_nonce, out_params->server_nonce, hkdf_input,
+ CryptoUtils::CLIENT, &out_params->forward_secure_crypters)) {
+ *error_details = "Symmetric key setup failed";
+ return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
+ }
+
+ return QUIC_NO_ERROR;
+}
+
+ProofVerifier* QuicCryptoClientConfig::proof_verifier() const {
+ return proof_verifier_.get();
+}
+
+void QuicCryptoClientConfig::SetProofVerifier(ProofVerifier* verifier) {
+ proof_verifier_.reset(verifier);
+}
+
+ChannelIDSigner* QuicCryptoClientConfig::channel_id_signer() const {
+ return channel_id_signer_.get();
+}
+
+void QuicCryptoClientConfig::SetChannelIDSigner(ChannelIDSigner* signer) {
+ channel_id_signer_.reset(signer);
+}
+
+void QuicCryptoClientConfig::InitializeFrom(
+ const std::string& server_hostname,
+ const std::string& canonical_server_hostname,
+ QuicCryptoClientConfig* canonical_crypto_config) {
+ CachedState* canonical_cached =
+ canonical_crypto_config->LookupOrCreate(canonical_server_hostname);
+ if (!canonical_cached->proof_valid()) {
+ return;
+ }
+ CachedState* cached = LookupOrCreate(server_hostname);
+ cached->InitializeFrom(*canonical_cached);
+}
+
+} // namespace net
diff --git a/chromium/net/quic/crypto/quic_crypto_client_config.h b/chromium/net/quic/crypto/quic_crypto_client_config.h
new file mode 100644
index 00000000000..30f4cf6f09e
--- /dev/null
+++ b/chromium/net/quic/crypto/quic_crypto_client_config.h
@@ -0,0 +1,218 @@
+// 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_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
+#define NET_QUIC_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+// QuicCryptoClientConfig contains crypto-related configuration settings for a
+// client. Note that this object isn't thread-safe. It's designed to be used on
+// a single thread at a time.
+class NET_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
+ public:
+ // A CachedState contains the information that the client needs in order to
+ // perform a 0-RTT handshake with a server. This information can be reused
+ // over several connections to the same server.
+ class NET_EXPORT_PRIVATE CachedState {
+ public:
+ CachedState();
+ ~CachedState();
+
+ // IsComplete returns true if this object contains enough information to
+ // perform a handshake with the server. |now| is used to judge whether any
+ // cached server config has expired.
+ bool IsComplete(QuicWallTime now) const;
+
+ // GetServerConfig returns the parsed contents of |server_config|, or NULL
+ // if |server_config| is empty. The return value is owned by this object
+ // and is destroyed when this object is.
+ const CryptoHandshakeMessage* GetServerConfig() const;
+
+ // SetServerConfig checks that |server_config| parses correctly and stores
+ // it in |server_config_|. |now| is used to judge whether |server_config|
+ // has expired.
+ QuicErrorCode SetServerConfig(base::StringPiece server_config,
+ QuicWallTime now,
+ std::string* error_details);
+
+ // InvalidateServerConfig clears the cached server config (if any).
+ void InvalidateServerConfig();
+
+ // SetProof stores a certificate chain and signature.
+ void SetProof(const std::vector<std::string>& certs,
+ base::StringPiece signature);
+
+ // Clears the certificate chain and signature and invalidates the proof.
+ void ClearProof();
+
+ // SetProofValid records that the certificate chain and signature have been
+ // validated and that it's safe to assume that the server is legitimate.
+ // (Note: this does not check the chain or signature.)
+ void SetProofValid();
+
+ // If the server config or the proof has changed then it needs to be
+ // revalidated. Helper function to keep server_config_valid_ and
+ // generation_counter_ in sync.
+ void SetProofInvalid();
+
+ const std::string& server_config() const;
+ const std::string& source_address_token() const;
+ const std::vector<std::string>& certs() const;
+ const std::string& signature() const;
+ bool proof_valid() const;
+ uint64 generation_counter() const;
+ const ProofVerifyDetails* proof_verify_details() const;
+
+ void set_source_address_token(base::StringPiece token);
+
+ // 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.
+ void InitializeFrom(const CachedState& other);
+
+ private:
+ std::string server_config_id_; // An opaque id from the server.
+ std::string server_config_; // A serialized handshake message.
+ std::string source_address_token_; // An opaque proof of IP ownership.
+ std::vector<std::string> certs_; // A list of certificates in leaf-first
+ // order.
+ 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
+ // validated.
+ // Generation counter associated with the |server_config_|, |certs_| and
+ // |server_config_sig_| combination. It is incremented whenever we set
+ // server_config_valid_ to false.
+ uint64 generation_counter_;
+
+ scoped_ptr<ProofVerifyDetails> proof_verify_details_;
+
+ // scfg contains the cached, parsed value of |server_config|.
+ mutable scoped_ptr<CryptoHandshakeMessage> scfg_;
+
+ DISALLOW_COPY_AND_ASSIGN(CachedState);
+ };
+
+ QuicCryptoClientConfig();
+ ~QuicCryptoClientConfig();
+
+ // Sets the members to reasonable, default values.
+ void SetDefaults();
+
+ // LookupOrCreate returns a CachedState for the given hostname. If no such
+ // CachedState currently exists, it will be created and cached.
+ CachedState* LookupOrCreate(const std::string& server_hostname);
+
+ // FillInchoateClientHello sets |out| to be a CHLO message that elicits a
+ // source-address token or SCFG from a server. If |cached| is non-NULL, the
+ // source-address token will be taken from it. |out_params| is used in order
+ // to store the cached certs that were sent as hints to the server in
+ // |out_params->cached_certs|. |preferred_version| is the version of the QUIC
+ // protocol that this client chose to use initially. This allows the server to
+ // detect downgrade attacks.
+ void FillInchoateClientHello(const std::string& server_hostname,
+ const QuicVersion preferred_version,
+ const CachedState* cached,
+ QuicCryptoNegotiatedParameters* out_params,
+ CryptoHandshakeMessage* out) const;
+
+ // FillClientHello sets |out| to be a CHLO message based on the configuration
+ // of this object. This object must have cached enough information about
+ // |server_hostname| in order to perform a handshake. This can be checked
+ // with the |IsComplete| member of |CachedState|.
+ //
+ // |clock| and |rand| are used to generate the nonce and |out_params| is
+ // filled with the results of the handshake that the server is expected to
+ // accept. |preferred_version| is the version of the QUIC protocol that this
+ // client chose to use initially. This allows the server to detect downgrade
+ // attacks.
+ QuicErrorCode FillClientHello(const std::string& server_hostname,
+ QuicGuid guid,
+ const QuicVersion preferred_version,
+ const CachedState* cached,
+ QuicWallTime now,
+ QuicRandom* rand,
+ QuicCryptoNegotiatedParameters* out_params,
+ CryptoHandshakeMessage* out,
+ std::string* error_details) const;
+
+ // ProcessRejection processes a REJ message from a server and updates the
+ // cached information about that server. After this, |IsComplete| may return
+ // true for that server's CachedState. If the rejection message contains
+ // state about a future handshake (i.e. an nonce value from the server), then
+ // it will be saved in |out_params|. |now| is used to judge whether the
+ // server config in the rejection message has expired.
+ QuicErrorCode ProcessRejection(const CryptoHandshakeMessage& rej,
+ QuicWallTime now,
+ CachedState* cached,
+ QuicCryptoNegotiatedParameters* out_params,
+ std::string* error_details);
+
+ // ProcessServerHello processes the message in |server_hello|, updates the
+ // cached information about that server, writes the negotiated parameters to
+ // |out_params| and returns QUIC_NO_ERROR. If |server_hello| is unacceptable
+ // then it puts an error message in |error_details| and returns an error
+ // code. |negotiated_versions| contains the list of version, if any, that were
+ // present in a version negotiation packet previously recevied from the
+ // server. The contents of this list will be compared against the list of
+ // versions provided in the VER tag of the server hello.
+ QuicErrorCode ProcessServerHello(const CryptoHandshakeMessage& server_hello,
+ QuicGuid guid,
+ const QuicVersionVector& negotiated_versions,
+ CachedState* cached,
+ QuicCryptoNegotiatedParameters* out_params,
+ std::string* error_details);
+
+ ProofVerifier* proof_verifier() const;
+
+ // SetProofVerifier takes ownership of a |ProofVerifier| that clients are
+ // free to use in order to verify certificate chains from servers. If a
+ // ProofVerifier is set then the client will request a certificate chain from
+ // the server.
+ void SetProofVerifier(ProofVerifier* verifier);
+
+ ChannelIDSigner* channel_id_signer() const;
+
+ // SetChannelIDSigner sets a ChannelIDSigner that will be called when the
+ // server supports channel IDs to sign a message proving possession of the
+ // given ChannelID. This object takes ownership of |signer|.
+ void SetChannelIDSigner(ChannelIDSigner* signer);
+
+ // Initialize the CachedState from |canonical_crypto_config| for the
+ // |canonical_server_hostname| as the initial CachedState for
+ // |server_hostname|. We will copy config data only if
+ // |canonical_crypto_config| has valid proof.
+ void InitializeFrom(const std::string& server_hostname,
+ const std::string& canonical_server_hostname,
+ QuicCryptoClientConfig* canonical_crypto_config);
+
+ private:
+ // cached_states_ maps from the server hostname to the cached information
+ // about that server.
+ std::map<std::string, CachedState*> cached_states_;
+
+ scoped_ptr<ProofVerifier> proof_verifier_;
+ scoped_ptr<ChannelIDSigner> channel_id_signer_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientConfig);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_CLIENT_CONFIG_H_
diff --git a/chromium/net/quic/crypto/quic_crypto_client_config_test.cc b/chromium/net/quic/crypto/quic_crypto_client_config_test.cc
new file mode 100644
index 00000000000..2893372dd1a
--- /dev/null
+++ b/chromium/net/quic/crypto/quic_crypto_client_config_test.cc
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/crypto/quic_crypto_client_config.h"
+
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+
+TEST(QuicCryptoClientConfigTest, InchoateChlo) {
+ QuicCryptoClientConfig::CachedState state;
+ QuicCryptoClientConfig config;
+ QuicCryptoNegotiatedParameters params;
+ CryptoHandshakeMessage msg;
+ config.FillInchoateClientHello("www.google.com", QuicVersionMax(), &state,
+ &params, &msg);
+
+ QuicTag cver;
+ EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kVER, &cver));
+ EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
+
+ // TODO(rch): Remove once we remove QUIC_VERSION_12.
+ uint16 vers;
+ EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint16(kVERS, &vers));
+ EXPECT_EQ(0u, vers);
+}
+
+TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
+ QuicVersionVector supported_versions = QuicSupportedVersions();
+ if (supported_versions.size() == 1) {
+ // No downgrade attack is possible if the client only supports one version.
+ return;
+ }
+ QuicTagVector supported_version_tags;
+ for (size_t i = supported_versions.size(); i > 0; --i) {
+ supported_version_tags.push_back(
+ QuicVersionToQuicTag(supported_versions[i - 1]));
+ }
+ CryptoHandshakeMessage msg;
+ msg.set_tag(kSHLO);
+ msg.SetVector(kVER, supported_version_tags);
+
+ QuicCryptoClientConfig::CachedState cached;
+ QuicCryptoNegotiatedParameters out_params;
+ string error;
+ QuicCryptoClientConfig config;
+ EXPECT_EQ(QUIC_VERSION_NEGOTIATION_MISMATCH,
+ config.ProcessServerHello(msg, 0, supported_versions,
+ &cached, &out_params, &error));
+ EXPECT_EQ("Downgrade attack detected", error);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/crypto/crypto_server_config.cc b/chromium/net/quic/crypto/quic_crypto_server_config.cc
index 89cea42862d..31651dbf633 100644
--- a/chromium/net/quic/crypto/crypto_server_config.cc
+++ b/chromium/net/quic/crypto/quic_crypto_server_config.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include <stdlib.h>
#include <algorithm>
@@ -22,6 +22,7 @@
#include "net/quic/crypto/curve25519_key_exchange.h"
#include "net/quic/crypto/ephemeral_key_source.h"
#include "net/quic/crypto/key_exchange.h"
+#include "net/quic/crypto/local_strike_register_client.h"
#include "net/quic/crypto/p256_key_exchange.h"
#include "net/quic/crypto/proof_source.h"
#include "net/quic/crypto/quic_decrypter.h"
@@ -29,6 +30,7 @@
#include "net/quic/crypto/quic_random.h"
#include "net/quic/crypto/source_address_token.h"
#include "net/quic/crypto/strike_register.h"
+#include "net/quic/crypto/strike_register_client.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
@@ -41,12 +43,126 @@ using std::vector;
namespace net {
+// ClientHelloInfo contains information about a client hello message that is
+// only kept for as long as it's being processed.
+struct ClientHelloInfo {
+ ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now)
+ : client_ip(in_client_ip),
+ now(in_now),
+ valid_source_address_token(false),
+ client_nonce_well_formed(false),
+ unique(false) {}
+
+ // Inputs to EvaluateClientHello.
+ const IPEndPoint client_ip;
+ const QuicWallTime now;
+
+ // Outputs from EvaluateClientHello.
+ bool valid_source_address_token;
+ bool client_nonce_well_formed;
+ bool unique;
+ StringPiece sni;
+ StringPiece client_nonce;
+ StringPiece server_nonce;
+};
+
+struct ValidateClientHelloResultCallback::Result {
+ Result(const CryptoHandshakeMessage& in_client_hello,
+ IPEndPoint in_client_ip,
+ QuicWallTime in_now)
+ : client_hello(in_client_hello),
+ info(in_client_ip, in_now),
+ error_code(QUIC_NO_ERROR) {
+ }
+
+ CryptoHandshakeMessage client_hello;
+ ClientHelloInfo info;
+ QuicErrorCode error_code;
+ string error_details;
+};
+
+class ValidateClientHelloHelper {
+ public:
+ ValidateClientHelloHelper(ValidateClientHelloResultCallback::Result* result,
+ ValidateClientHelloResultCallback* done_cb)
+ : result_(result), done_cb_(done_cb) {
+ }
+
+ ~ValidateClientHelloHelper() {
+ if (done_cb_ != NULL) {
+ LOG(DFATAL) <<
+ "Deleting ValidateClientHelloHelper with a pending callback.";
+ }
+ }
+
+ void ValidationComplete(QuicErrorCode error_code, const char* error_details) {
+ result_->error_code = error_code;
+ result_->error_details = error_details;
+ done_cb_->Run(result_);
+ DetachCallback();
+ }
+
+ void StartedAsyncCallback() {
+ DetachCallback();
+ }
+
+ private:
+ void DetachCallback() {
+ if (done_cb_ == NULL) {
+ LOG(DFATAL) << "Callback already detached.";
+ }
+ done_cb_ = NULL;
+ }
+
+ ValidateClientHelloResultCallback::Result* result_;
+ ValidateClientHelloResultCallback* done_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloHelper);
+};
+
+class VerifyNonceIsValidAndUniqueCallback
+ : public StrikeRegisterClient::ResultCallback {
+ public:
+ VerifyNonceIsValidAndUniqueCallback(
+ ValidateClientHelloResultCallback::Result* result,
+ ValidateClientHelloResultCallback* done_cb)
+ : result_(result), done_cb_(done_cb) {
+ }
+
+ protected:
+ virtual void RunImpl(bool nonce_is_valid_and_unique) OVERRIDE {
+ DVLOG(1) << "Using client nonce, unique: " << nonce_is_valid_and_unique;
+ result_->info.unique = nonce_is_valid_and_unique;
+ done_cb_->Run(result_);
+ }
+
+ private:
+ ValidateClientHelloResultCallback::Result* result_;
+ ValidateClientHelloResultCallback* done_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(VerifyNonceIsValidAndUniqueCallback);
+};
+
// static
const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";
+
+ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {
+}
+
+ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {
+}
+
+void ValidateClientHelloResultCallback::Run(const Result* result) {
+ RunImpl(result->client_hello, *result);
+ delete result;
+ delete this;
+}
+
QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
: expiry_time(QuicWallTime::Zero()),
- channel_id_enabled(false) { }
+ channel_id_enabled(false),
+ p256(false) {}
QuicCryptoServerConfig::QuicCryptoServerConfig(
StringPiece source_address_token_secret,
@@ -55,7 +171,6 @@ QuicCryptoServerConfig::QuicCryptoServerConfig(
configs_lock_(),
primary_config_(NULL),
next_config_promotion_time_(QuicWallTime::Zero()),
- strike_register_lock_(),
server_nonce_strike_register_lock_(),
strike_register_no_startup_period_(false),
strike_register_max_entries_(1 << 10),
@@ -97,10 +212,6 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
Curve25519KeyExchange::New(curve25519_private_key));
StringPiece curve25519_public_value = curve25519->public_value();
- const string p256_private_key = P256KeyExchange::NewPrivateKey();
- scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
- StringPiece p256_public_value = p256->public_value();
-
string encoded_public_values;
// First three bytes encode the length of the public value.
encoded_public_values.push_back(curve25519_public_value.size());
@@ -108,15 +219,28 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
encoded_public_values.push_back(curve25519_public_value.size() >> 16);
encoded_public_values.append(curve25519_public_value.data(),
curve25519_public_value.size());
- encoded_public_values.push_back(p256_public_value.size());
- encoded_public_values.push_back(p256_public_value.size() >> 8);
- encoded_public_values.push_back(p256_public_value.size() >> 16);
- encoded_public_values.append(p256_public_value.data(),
- p256_public_value.size());
+
+ string p256_private_key;
+ if (options.p256) {
+ p256_private_key = P256KeyExchange::NewPrivateKey();
+ scoped_ptr<P256KeyExchange> p256(P256KeyExchange::New(p256_private_key));
+ StringPiece p256_public_value = p256->public_value();
+
+ encoded_public_values.push_back(p256_public_value.size());
+ encoded_public_values.push_back(p256_public_value.size() >> 8);
+ encoded_public_values.push_back(p256_public_value.size() >> 16);
+ encoded_public_values.append(p256_public_value.data(),
+ p256_public_value.size());
+ }
msg.set_tag(kSCFG);
- msg.SetTaglist(kKEXS, kC255, kP256, 0);
+ if (options.p256) {
+ msg.SetTaglist(kKEXS, kC255, kP256, 0);
+ } else {
+ msg.SetTaglist(kKEXS, kC255, 0);
+ }
msg.SetTaglist(kAEAD, kAESG, 0);
+ // TODO(rch): Remove once we remove QUIC_VERSION_12.
msg.SetValue(kVERS, static_cast<uint16>(0));
msg.SetStringPiece(kPUBS, encoded_public_values);
@@ -130,14 +254,6 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
}
- if (options.id.empty()) {
- char scid_bytes[16];
- rand->RandBytes(scid_bytes, sizeof(scid_bytes));
- msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
- } else {
- msg.SetStringPiece(kSCID, options.id);
- }
-
char orbit_bytes[kOrbitSize];
if (options.orbit.size() == sizeof(orbit_bytes)) {
memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
@@ -151,6 +267,24 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
msg.SetTaglist(kPDMD, kCHID, 0);
}
+ if (options.id.empty()) {
+ // We need to ensure that the SCID changes whenever the server config does
+ // thus we make it a hash of the rest of the server config.
+ scoped_ptr<QuicData> serialized(
+ CryptoFramer::ConstructHandshakeMessage(msg));
+ scoped_ptr<SecureHash> hash(SecureHash::Create(SecureHash::SHA256));
+ hash->Update(serialized->data(), serialized->length());
+
+ char scid_bytes[16];
+ hash->Finish(scid_bytes, sizeof(scid_bytes));
+ msg.SetStringPiece(kSCID, StringPiece(scid_bytes, sizeof(scid_bytes)));
+ } else {
+ msg.SetStringPiece(kSCID, options.id);
+ }
+ // Don't put new tags below this point. The SCID generation should hash over
+ // everything but itself and so extra tags should be added prior to the
+ // preceeding if block.
+
scoped_ptr<QuicData> serialized(CryptoFramer::ConstructHandshakeMessage(msg));
scoped_ptr<QuicServerConfigProtobuf> config(new QuicServerConfigProtobuf);
@@ -158,9 +292,12 @@ QuicServerConfigProtobuf* QuicCryptoServerConfig::DefaultConfig(
QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
curve25519_key->set_tag(kC255);
curve25519_key->set_private_key(curve25519_private_key);
- QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
- p256_key->set_tag(kP256);
- p256_key->set_private_key(p256_private_key);
+
+ if (options.p256) {
+ QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
+ p256_key->set_tag(kP256);
+ p256_key->set_private_key(p256_private_key);
+ }
return config.release();
}
@@ -281,33 +418,46 @@ bool QuicCryptoServerConfig::SetConfigs(
return ok;
}
-// ClientHelloInfo contains information about a client hello message that is
-// only kept for as long as it's being processed.
-struct ClientHelloInfo {
- ClientHelloInfo(const IPEndPoint& in_client_ip, QuicWallTime in_now)
- : client_ip(in_client_ip),
- now(in_now),
- valid_source_address_token(false),
- client_nonce_well_formed(false),
- unique(false) {}
+void QuicCryptoServerConfig::ValidateClientHello(
+ const CryptoHandshakeMessage& client_hello,
+ IPEndPoint client_ip,
+ const QuicClock* clock,
+ ValidateClientHelloResultCallback* done_cb) const {
+ const QuicWallTime now(clock->WallNow());
+ ValidateClientHelloResultCallback::Result* result =
+ new ValidateClientHelloResultCallback::Result(
+ client_hello, client_ip, now);
- // Inputs to EvaluateClientHello.
- const IPEndPoint client_ip;
- const QuicWallTime now;
+ uint8 primary_orbit[kOrbitSize];
+ {
+ base::AutoLock locked(configs_lock_);
- // Outputs from EvaluateClientHello.
- bool valid_source_address_token;
- bool client_nonce_well_formed;
- bool unique;
- StringPiece sni;
- StringPiece client_nonce;
- StringPiece server_nonce;
-};
+ if (!primary_config_) {
+ result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
+ result->error_details = "No configurations loaded";
+ } else {
+ if (!next_config_promotion_time_.IsZero() &&
+ next_config_promotion_time_.IsAfter(now)) {
+ SelectNewPrimaryConfig(now);
+ }
+
+ memcpy(primary_orbit, primary_config_->orbit, sizeof(primary_orbit));
+ }
+ }
+
+ if (result->error_code == QUIC_NO_ERROR) {
+ EvaluateClientHello(primary_orbit, result, done_cb);
+ } else {
+ done_cb->Run(result);
+ }
+}
QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
- const CryptoHandshakeMessage& client_hello,
+ const ValidateClientHelloResultCallback::Result& validate_chlo_result,
QuicGuid guid,
- const IPEndPoint& client_ip,
+ IPEndPoint client_ip,
+ QuicVersion version,
+ const QuicVersionVector& supported_versions,
const QuicClock* clock,
QuicRandom* rand,
QuicCryptoNegotiatedParameters *params,
@@ -315,6 +465,31 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
string* error_details) const {
DCHECK(error_details);
+ const CryptoHandshakeMessage& client_hello =
+ validate_chlo_result.client_hello;
+ const ClientHelloInfo& info = validate_chlo_result.info;
+
+ // If the client's preferred version is not the version we are currently
+ // speaking, then the client went through a version negotiation. In this
+ // case, we need to make sure that we actually do not support this version
+ // and that it wasn't a downgrade attack.
+ QuicTag client_version_tag;
+ // TODO(rch): Make this check mandatory when we remove QUIC_VERSION_12.
+ if (client_hello.GetUint32(kVER, &client_version_tag) == QUIC_NO_ERROR) {
+ QuicVersion client_version = QuicTagToQuicVersion(client_version_tag);
+ if (client_version != version) {
+ // Just because client_version is a valid version enum doesn't mean that
+ // this server actually supports that version, so we check to see if
+ // it's actually in the supported versions list.
+ for (size_t i = 0; i < supported_versions.size(); ++i) {
+ if (client_version == supported_versions[i]) {
+ *error_details = "Downgrade attack detected";
+ return QUIC_VERSION_NEGOTIATION_MISMATCH;
+ }
+ }
+ }
+ }
+
StringPiece requested_scid;
client_hello.GetStringPiece(kSCID, &requested_scid);
const QuicWallTime now(clock->WallNow());
@@ -347,11 +522,9 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
}
}
- ClientHelloInfo info(client_ip, now);
- QuicErrorCode error = EvaluateClientHello(
- client_hello, primary_config->orbit, &info, error_details);
- if (error != QUIC_NO_ERROR) {
- return error;
+ if (validate_chlo_result.error_code != QUIC_NO_ERROR) {
+ *error_details = validate_chlo_result.error_details;
+ return validate_chlo_result.error_code;
}
out->Clear();
@@ -436,9 +609,12 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
hkdf_input.append(requested_config->serialized);
CrypterPair crypters;
- CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
- info.client_nonce, info.server_nonce, hkdf_input,
- CryptoUtils::SERVER, &crypters);
+ if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
+ info.client_nonce, info.server_nonce,
+ hkdf_input, CryptoUtils::SERVER, &crypters)) {
+ *error_details = "Symmetric key setup failed";
+ return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
+ }
scoped_ptr<QuicData> cetv_plaintext(crypters.decrypter->DecryptPacket(
0 /* sequence number */, StringPiece() /* associated data */,
@@ -473,9 +649,13 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
hkdf_input.append(hkdf_suffix);
- CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
- info.client_nonce, info.server_nonce, hkdf_input,
- CryptoUtils::SERVER, &params->initial_crypters);
+ if (!CryptoUtils::DeriveKeys(params->initial_premaster_secret, params->aead,
+ info.client_nonce, info.server_nonce, hkdf_input,
+ CryptoUtils::SERVER,
+ &params->initial_crypters)) {
+ *error_details = "Symmetric key setup failed";
+ return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
+ }
string forward_secure_public_value;
if (ephemeral_key_source_.get()) {
@@ -502,12 +682,21 @@ QuicErrorCode QuicCryptoServerConfig::ProcessClientHello(
label_len);
forward_secure_hkdf_input.append(hkdf_suffix);
- CryptoUtils::DeriveKeys(params->forward_secure_premaster_secret, params->aead,
- info.client_nonce, info.server_nonce,
- forward_secure_hkdf_input, CryptoUtils::SERVER,
- &params->forward_secure_crypters);
+ if (!CryptoUtils::DeriveKeys(
+ params->forward_secure_premaster_secret, params->aead,
+ info.client_nonce, info.server_nonce, forward_secure_hkdf_input,
+ CryptoUtils::SERVER, &params->forward_secure_crypters)) {
+ *error_details = "Symmetric key setup failed";
+ return QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED;
+ }
out->set_tag(kSHLO);
+ QuicTagVector supported_version_tags;
+ for (size_t i = 0; i < supported_versions.size(); ++i) {
+ supported_version_tags.push_back
+ (QuicVersionToQuicTag(supported_versions[i]));
+ }
+ out->SetVector(kVER, supported_version_tags);
out->SetStringPiece(kSourceAddressTokenTag,
NewSourceAddressToken(client_ip, rand, info.now));
out->SetStringPiece(kPUBS, forward_secure_public_value);
@@ -541,7 +730,7 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
configs.push_back(it->second);
}
- if (configs.size() == 0) {
+ if (configs.empty()) {
// Tests don't set |primary_time_|. For that case we promote the first
// Config and leave it as primary forever.
if (!primary_config_.get() && first_config.get()) {
@@ -599,70 +788,84 @@ void QuicCryptoServerConfig::SelectNewPrimaryConfig(
next_config_promotion_time_ = QuicWallTime::Zero();
}
-QuicErrorCode QuicCryptoServerConfig::EvaluateClientHello(
- const CryptoHandshakeMessage& client_hello,
- const uint8* orbit,
- ClientHelloInfo* info,
- string* error_details) const {
- if (client_hello.size() < kClientHelloMinimumSize) {
- *error_details = "Client hello too small";
- return QUIC_CRYPTO_INVALID_VALUE_LENGTH;
- }
+void QuicCryptoServerConfig::EvaluateClientHello(
+ const uint8* primary_orbit,
+ ValidateClientHelloResultCallback::Result* client_hello_state,
+ ValidateClientHelloResultCallback* done_cb) const {
+ ValidateClientHelloHelper helper(client_hello_state, done_cb);
- StringPiece srct;
- if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
- ValidateSourceAddressToken(srct, info->client_ip, info->now)) {
- info->valid_source_address_token = true;
+ const CryptoHandshakeMessage& client_hello =
+ client_hello_state->client_hello;
+ ClientHelloInfo* info = &(client_hello_state->info);
+
+ if (client_hello.size() < kClientHelloMinimumSizeOld) {
+ helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
+ "Client hello too small");
+ return;
}
if (client_hello.GetStringPiece(kSNI, &info->sni) &&
!CryptoUtils::IsValidSNI(info->sni)) {
- *error_details = "Invalid SNI name";
- return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
+ helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
+ "Invalid SNI name");
+ return;
}
- // The client nonce is used first to try and establish uniqueness.
- bool unique_by_strike_register = false;
+ StringPiece srct;
+ if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct) &&
+ ValidateSourceAddressToken(srct, info->client_ip, info->now)) {
+ info->valid_source_address_token = true;
+ } else {
+ // No valid source address token.
+ helper.ValidationComplete(QUIC_NO_ERROR, "");
+ return;
+ }
if (client_hello.GetStringPiece(kNONC, &info->client_nonce) &&
info->client_nonce.size() == kNonceSize) {
info->client_nonce_well_formed = true;
- if (replay_protection_) {
- base::AutoLock auto_lock(strike_register_lock_);
-
- if (strike_register_.get() == NULL) {
- strike_register_.reset(new StrikeRegister(
- strike_register_max_entries_,
- static_cast<uint32>(info->now.ToUNIXSeconds()),
- strike_register_window_secs_,
- orbit,
- strike_register_no_startup_period_ ?
- StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
- StrikeRegister::DENY_REQUESTS_AT_STARTUP));
- }
+ } else {
+ // Invalid client nonce.
+ DVLOG(1) << "Invalid client nonce.";
+ helper.ValidationComplete(QUIC_NO_ERROR, "");
+ return;
+ }
- unique_by_strike_register = strike_register_->Insert(
- reinterpret_cast<const uint8*>(info->client_nonce.data()),
- static_cast<uint32>(info->now.ToUNIXSeconds()));
- }
+ if (!replay_protection_) {
+ info->unique = true;
+ DVLOG(1) << "No replay protection.";
+ helper.ValidationComplete(QUIC_NO_ERROR, "");
+ return;
}
client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);
-
- // If the client nonce didn't establish uniqueness then an echoed server
- // nonce may.
- bool unique_by_server_nonce = false;
- if (replay_protection_ &&
- !unique_by_strike_register &&
- !info->server_nonce.empty()) {
- unique_by_server_nonce = ValidateServerNonce(info->server_nonce, info->now);
+ if (!info->server_nonce.empty()) {
+ // If the server nonce is present, use it to establish uniqueness.
+ info->unique = ValidateServerNonce(info->server_nonce, info->now);
+ DVLOG(1) << "Using server nonce, unique: " << info->unique;
+ helper.ValidationComplete(QUIC_NO_ERROR, "");
+ return;
}
- info->unique = !replay_protection_ ||
- unique_by_strike_register ||
- unique_by_server_nonce;
+ // Use the client nonce to establish uniqueness.
+ base::AutoLock locked(strike_register_client_lock_);
+
+ if (strike_register_client_.get() == NULL) {
+ strike_register_client_.reset(new LocalStrikeRegisterClient(
+ strike_register_max_entries_,
+ static_cast<uint32>(info->now.ToUNIXSeconds()),
+ strike_register_window_secs_,
+ primary_orbit,
+ strike_register_no_startup_period_ ?
+ StrikeRegister::NO_STARTUP_PERIOD_NEEDED :
+ StrikeRegister::DENY_REQUESTS_AT_STARTUP));
+ }
- return QUIC_NO_ERROR;
+ strike_register_client_->VerifyNonceIsValidAndUnique(
+ info->client_nonce,
+ info->now,
+ new VerifyNonceIsValidAndUniqueCallback(client_hello_state, done_cb));
+ helper.StartedAsyncCallback();
}
void QuicCryptoServerConfig::BuildRejection(
@@ -725,12 +928,22 @@ void QuicCryptoServerConfig::BuildRejection(
// kREJOverheadBytes is a very rough estimate of how much of a REJ
// message is taken up by things other than the certificates.
- const size_t kREJOverheadBytes = 112;
+ // STK: 56 bytes
+ // SNO: 56 bytes
+ // SCFG
+ // SCID: 16 bytes
+ // PUBS: 38 bytes
+ const size_t kREJOverheadBytes = 166;
+ // kMultiplier is the multiple of the CHLO message size that a REJ message
+ // must stay under when the client doesn't present a valid source-address
+ // token.
+ const size_t kMultiplier = 2;
// max_unverified_size is the number of bytes that the certificate chain
// and signature can consume before we will demand a valid source-address
// token.
- const size_t max_unverified_size = client_hello.size() - kREJOverheadBytes;
- COMPILE_ASSERT(kClientHelloMinimumSize >= kREJOverheadBytes,
+ const size_t max_unverified_size =
+ client_hello.size() * kMultiplier - kREJOverheadBytes;
+ COMPILE_ASSERT(kClientHelloMinimumSizeOld * kMultiplier >= kREJOverheadBytes,
overhead_calculation_may_underflow);
if (info.valid_source_address_token ||
signature.size() + compressed.size() < max_unverified_size) {
@@ -796,10 +1009,10 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
{
- base::AutoLock locked(strike_register_lock_);
- if (strike_register_.get()) {
- const uint8* orbit = strike_register_->orbit();
- if (0 != memcmp(orbit, config->orbit, kOrbitSize)) {
+ base::AutoLock locked(strike_register_client_lock_);
+ if (strike_register_client_.get()) {
+ const string& orbit = strike_register_client_->orbit();
+ if (0 != memcmp(orbit.data(), config->orbit, kOrbitSize)) {
LOG(WARNING)
<< "Server config has different orbit than current config. "
"Switching orbits at run-time is not supported.";
@@ -882,16 +1095,6 @@ QuicCryptoServerConfig::ParseConfigProtobuf(
config->key_exchanges.push_back(ka.release());
}
- if (msg->GetUint16(kVERS, &config->version) != QUIC_NO_ERROR) {
- LOG(WARNING) << "Server config message is missing version";
- return NULL;
- }
-
- if (config->version != QuicCryptoConfig::CONFIG_VERSION) {
- LOG(WARNING) << "Server config specifies an unsupported version";
- return NULL;
- }
-
return config;
}
@@ -904,27 +1107,34 @@ void QuicCryptoServerConfig::SetEphemeralKeySource(
ephemeral_key_source_.reset(ephemeral_key_source);
}
+void QuicCryptoServerConfig::SetStrikeRegisterClient(
+ StrikeRegisterClient* strike_register_client) {
+ base::AutoLock locker(strike_register_client_lock_);
+ DCHECK(!strike_register_client_.get());
+ strike_register_client_.reset(strike_register_client);
+}
+
void QuicCryptoServerConfig::set_replay_protection(bool on) {
replay_protection_ = on;
}
void QuicCryptoServerConfig::set_strike_register_no_startup_period() {
- base::AutoLock auto_lock(strike_register_lock_);
- DCHECK(!strike_register_.get());
+ base::AutoLock locker(strike_register_client_lock_);
+ DCHECK(!strike_register_client_.get());
strike_register_no_startup_period_ = true;
}
void QuicCryptoServerConfig::set_strike_register_max_entries(
uint32 max_entries) {
- base::AutoLock locker(strike_register_lock_);
- DCHECK(!strike_register_.get());
+ base::AutoLock locker(strike_register_client_lock_);
+ DCHECK(!strike_register_client_.get());
strike_register_max_entries_ = max_entries;
}
void QuicCryptoServerConfig::set_strike_register_window_secs(
uint32 window_secs) {
- base::AutoLock locker(strike_register_lock_);
- DCHECK(!strike_register_.get());
+ base::AutoLock locker(strike_register_client_lock_);
+ DCHECK(!strike_register_client_.get());
strike_register_window_secs_ = window_secs;
}
diff --git a/chromium/net/quic/crypto/crypto_server_config.h b/chromium/net/quic/crypto/quic_crypto_server_config.h
index 4255d228618..6d59bff6a9f 100644
--- a/chromium/net/quic/crypto/crypto_server_config.h
+++ b/chromium/net/quic/crypto/quic_crypto_server_config.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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_CRYPTO_CRYPTO_SERVER_CONFIG_H_
-#define NET_QUIC_CRYPTO_CRYPTO_SERVER_CONFIG_H_
+#ifndef NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
+#define NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
#include <map>
#include <string>
@@ -31,6 +31,7 @@ class QuicEncrypter;
class QuicRandom;
class QuicServerConfigProtobuf;
class StrikeRegister;
+class StrikeRegisterClient;
struct ClientHelloInfo;
@@ -38,6 +39,25 @@ namespace test {
class QuicCryptoServerConfigPeer;
} // namespace test
+// Callback used to accept the result of the |client_hello| validation step.
+class NET_EXPORT_PRIVATE ValidateClientHelloResultCallback {
+ public:
+ // Opaque token that holds information about the client_hello and
+ // its validity. Can be interpreted by calling ProcessClientHello.
+ struct Result;
+
+ ValidateClientHelloResultCallback();
+ virtual ~ValidateClientHelloResultCallback();
+ void Run(const Result* result);
+
+ protected:
+ virtual void RunImpl(const CryptoHandshakeMessage& client_hello,
+ const Result& result) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ValidateClientHelloResultCallback);
+};
+
// QuicCryptoServerConfig contains the crypto configuration of a QUIC server.
// Unlike a client, a QUIC server can have multiple configurations active in
// order to support clients resuming with a previous configuration.
@@ -61,6 +81,11 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// orbit contains the kOrbitSize bytes of the orbit value for the server
// config. If |orbit| is empty then a random orbit is generated.
std::string orbit;
+ // p256 determines whether a P-256 public key will be included in the
+ // server config. Note that this breaks deterministic server-config
+ // generation since P-256 key generation doesn't use the QuicRandom given
+ // to DefaultConfig().
+ bool p256;
};
// |source_address_token_secret|: secret key material used for encrypting and
@@ -109,16 +134,45 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
bool SetConfigs(const std::vector<QuicServerConfigProtobuf*>& protobufs,
QuicWallTime now);
+ // Checks |client_hello| for gross errors and determines whether it
+ // can be shown to be fresh (i.e. not a replay). The result of the
+ // validation step must be interpreted by calling
+ // QuicCryptoServerConfig::ProcessClientHello from the done_cb.
+ //
+ // ValidateClientHello may invoke the done_cb before unrolling the
+ // stack if it is able to assess the validity of the client_nonce
+ // without asynchronous operations.
+ //
+ // client_hello: the incoming client hello message.
+ // client_ip: the IP address of the client, which is used to generate and
+ // validate source-address tokens.
+ // clock: used to validate client nonces and ephemeral keys.
+ // done_cb: single-use callback that accepts an opaque
+ // ValidatedClientHelloMsg token that holds information about
+ // the client hello. The callback will always be called exactly
+ // once, either under the current call stack, or after the
+ // completion of an asynchronous operation.
+ void ValidateClientHello(
+ const CryptoHandshakeMessage& client_hello,
+ IPEndPoint client_ip,
+ const QuicClock* clock,
+ ValidateClientHelloResultCallback* done_cb) const;
+
// ProcessClientHello processes |client_hello| and decides whether to accept
// or reject the connection. If the connection is to be accepted, |out| is
// set to the contents of the ServerHello, |out_params| is completed and
// QUIC_NO_ERROR is returned. Otherwise |out| is set to be a REJ message and
// an error code is returned.
//
- // client_hello: the incoming client hello message.
+ // validate_chlo_result: Output from the asynchronous call to
+ // ValidateClientHello. Contains the client hello message and
+ // information about it.
// guid: the GUID for the connection, which is used in key derivation.
// client_ip: the IP address of the client, which is used to generate and
// validate source-address tokens.
+ // version: version of the QUIC protocol in use for this connection
+ // supported_versions: versions of the QUIC protocol that this server
+ // supports.
// clock: used to validate client nonces and ephemeral keys.
// rand: an entropy source
// params: the state of the handshake. This may be updated with a server
@@ -126,14 +180,17 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// contain the state of the connection.
// out: the resulting handshake message (either REJ or SHLO)
// error_details: used to store a string describing any error.
- QuicErrorCode ProcessClientHello(const CryptoHandshakeMessage& client_hello,
- QuicGuid guid,
- const IPEndPoint& client_ip,
- const QuicClock* clock,
- QuicRandom* rand,
- QuicCryptoNegotiatedParameters* params,
- CryptoHandshakeMessage* out,
- std::string* error_details) const;
+ QuicErrorCode ProcessClientHello(
+ const ValidateClientHelloResultCallback::Result& validate_chlo_result,
+ QuicGuid guid,
+ IPEndPoint client_ip,
+ QuicVersion version,
+ const QuicVersionVector& supported_versions,
+ const QuicClock* clock,
+ QuicRandom* rand,
+ QuicCryptoNegotiatedParameters* params,
+ CryptoHandshakeMessage* out,
+ std::string* error_details) const;
// SetProofSource installs |proof_source| as the ProofSource for handshakes.
// This object takes ownership of |proof_source|.
@@ -145,6 +202,11 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// per-connection.
void SetEphemeralKeySource(EphemeralKeySource* ephemeral_key_source);
+ // Install an externall created StrikeRegisterClient for use to
+ // interact with the strike register. This object takes ownership
+ // of the |strike_register_client|.
+ void SetStrikeRegisterClient(StrikeRegisterClient* strike_register_client);
+
// set_replay_protection controls whether replay protection is enabled. If
// replay protection is disabled then no strike registers are needed and
// frontends can share an orbit value without a shared strike-register.
@@ -255,11 +317,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// EvaluateClientHello checks |client_hello| for gross errors and determines
// whether it can be shown to be fresh (i.e. not a replay). The results are
// written to |info|.
- QuicErrorCode EvaluateClientHello(
- const CryptoHandshakeMessage& client_hello,
- const uint8* orbit,
- ClientHelloInfo* info,
- std::string* error_details) const;
+ void EvaluateClientHello(
+ const uint8* primary_orbit,
+ ValidateClientHelloResultCallback::Result* client_hello_state,
+ ValidateClientHelloResultCallback* done_cb) const;
// BuildRejection sets |out| to be a REJ message in reply to |client_hello|.
void BuildRejection(
@@ -317,10 +378,10 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
// active config will be promoted to primary.
mutable QuicWallTime next_config_promotion_time_;
- mutable base::Lock strike_register_lock_;
+ mutable base::Lock strike_register_client_lock_;
// strike_register_ contains a data structure that keeps track of previously
// observed client nonces in order to prevent replay attacks.
- mutable scoped_ptr<StrikeRegister> strike_register_;
+ mutable scoped_ptr<StrikeRegisterClient> strike_register_client_;
// source_address_token_boxer_ is used to protect the source-address tokens
// that are given to clients.
@@ -362,4 +423,4 @@ class NET_EXPORT_PRIVATE QuicCryptoServerConfig {
} // namespace net
-#endif // NET_QUIC_CRYPTO_CRYPTO_SERVER_CONFIG_H_
+#endif // NET_QUIC_CRYPTO_QUIC_CRYPTO_SERVER_CONFIG_H_
diff --git a/chromium/net/quic/crypto/crypto_handshake_test.cc b/chromium/net/quic/crypto/quic_crypto_server_config_test.cc
index 3ad50bb7f5a..fc8882cd85e 100644
--- a/chromium/net/quic/crypto/crypto_handshake_test.cc
+++ b/chromium/net/quic/crypto/quic_crypto_server_config_test.cc
@@ -1,14 +1,14 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include <stdarg.h>
#include "base/stl_util.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_server_config_protobuf.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_time.h"
@@ -155,11 +155,6 @@ TEST(QuicCryptoServerConfigTest, ServerConfig) {
}
TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
QuicRandom* rand = QuicRandom::GetInstance();
QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
IPAddressNumber ip;
diff --git a/chromium/net/quic/crypto/quic_random.cc b/chromium/net/quic/crypto/quic_random.cc
index c96f01a9139..73fce2ef2cf 100644
--- a/chromium/net/quic/crypto/quic_random.cc
+++ b/chromium/net/quic/crypto/quic_random.cc
@@ -19,7 +19,6 @@ class DefaultRandom : public QuicRandom {
// QuicRandom implementation
virtual void RandBytes(void* data, size_t len) OVERRIDE;
virtual uint64 RandUint64() OVERRIDE;
- virtual bool RandBool() OVERRIDE;
virtual void Reseed(const void* additional_entropy,
size_t entropy_len) OVERRIDE;
@@ -45,12 +44,6 @@ uint64 DefaultRandom::RandUint64() {
return value;
}
-bool DefaultRandom::RandBool() {
- char value;
- RandBytes(&value, sizeof(value));
- return (value & 1) == 1;
-}
-
void DefaultRandom::Reseed(const void* additional_entropy, size_t entropy_len) {
// No such function exists in crypto/random.h.
}
diff --git a/chromium/net/quic/crypto/quic_random.h b/chromium/net/quic/crypto/quic_random.h
index 68640c1695d..ac69b8567a9 100644
--- a/chromium/net/quic/crypto/quic_random.h
+++ b/chromium/net/quic/crypto/quic_random.h
@@ -27,9 +27,6 @@ class NET_EXPORT_PRIVATE QuicRandom {
// Returns a random number in the range [0, kuint64max].
virtual uint64 RandUint64() = 0;
- // Returns a random boolean value.
- virtual bool RandBool() = 0;
-
// Reseeds the random number generator with additional entropy input.
// NOTE: the constructor of a QuicRandom object is responsible for seeding
// itself with enough entropy input.
diff --git a/chromium/net/quic/crypto/quic_random_test.cc b/chromium/net/quic/crypto/quic_random_test.cc
index 425089a10e5..a76262572b1 100644
--- a/chromium/net/quic/crypto/quic_random_test.cc
+++ b/chromium/net/quic/crypto/quic_random_test.cc
@@ -14,11 +14,11 @@ TEST(QuicRandomTest, RandBytes) {
unsigned char buf2[16];
memset(buf1, 0xaf, sizeof(buf1));
memset(buf2, 0xaf, sizeof(buf2));
- ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) == 0);
+ ASSERT_EQ(0, memcmp(buf1, buf2, sizeof(buf1)));
QuicRandom* rng = QuicRandom::GetInstance();
rng->RandBytes(buf1, sizeof(buf1));
- EXPECT_FALSE(memcmp(buf1, buf2, sizeof(buf1)) == 0);
+ EXPECT_NE(0, memcmp(buf1, buf2, sizeof(buf1)));
}
TEST(QuicRandomTest, RandUint64) {
diff --git a/chromium/net/quic/crypto/strike_register_client.h b/chromium/net/quic/crypto/strike_register_client.h
new file mode 100644
index 00000000000..4a27bd7b85c
--- /dev/null
+++ b/chromium/net/quic/crypto/strike_register_client.h
@@ -0,0 +1,57 @@
+// 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_CRYPTO_STRIKE_REGISTER_CLIENT_H_
+#define NET_QUIC_CRYPTO_STRIKE_REGISTER_CLIENT_H_
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_time.h"
+
+namespace net {
+
+// Interface implemented by clients that talk to strike registers
+// implemented as local or remote services.
+class NET_EXPORT_PRIVATE StrikeRegisterClient {
+ public:
+ // Single use callback that will be invoked once the validation
+ // operation is complete.
+ class NET_EXPORT_PRIVATE ResultCallback {
+ public:
+ ResultCallback() {}
+ virtual ~ResultCallback() {}
+ void Run(bool nonce_is_valid_and_unique) {
+ RunImpl(nonce_is_valid_and_unique);
+ delete this;
+ }
+
+ protected:
+ virtual void RunImpl(bool nonce_is_valid_and_unique) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ResultCallback);
+ };
+
+ StrikeRegisterClient() {}
+ virtual ~StrikeRegisterClient() {}
+
+ // Returns the strike server orbit if known, else empty string.
+ virtual std::string orbit() = 0;
+ // Validate a nonce for freshness and uniqueness.
+ // Will invoke cb->Run(ValidateResponse::nonce_is_valid_and_unique())
+ // once the asynchronous operation is complete.
+ virtual void VerifyNonceIsValidAndUnique(
+ base::StringPiece nonce,
+ QuicWallTime now,
+ ResultCallback* cb) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StrikeRegisterClient);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_CRYPTO_STRIKE_REGISTER_CLIENT_H_
diff --git a/chromium/net/quic/iovector.cc b/chromium/net/quic/iovector.cc
new file mode 100644
index 00000000000..a6d2c617fc8
--- /dev/null
+++ b/chromium/net/quic/iovector.cc
@@ -0,0 +1,13 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/iovector.h"
+
+namespace net {
+
+IOVector::IOVector() {}
+
+IOVector::~IOVector() {}
+
+} // namespace net
diff --git a/chromium/net/quic/iovector.h b/chromium/net/quic/iovector.h
new file mode 100644
index 00000000000..74fcbef3087
--- /dev/null
+++ b/chromium/net/quic/iovector.h
@@ -0,0 +1,201 @@
+// 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_IOVECTOR_H_
+#define NET_QUIC_IOVECTOR_H_
+
+#include <stddef.h>
+#include <algorithm>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "net/base/iovec.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+// Calculate the total number of bytes in an array of iovec structures.
+inline size_t TotalIovecLength(const struct iovec* iov, size_t iovcnt) {
+ size_t length = 0;
+ if (iov != NULL) {
+ for (size_t i = 0; i < iovcnt; ++i) {
+ length += iov[i].iov_len;
+ }
+ }
+ return length;
+}
+
+// IOVector is a helper class that makes it easier to work with POSIX vector I/O
+// struct. It is a thin wrapper by design and thus has no virtual functions and
+// all inlined methods. This class makes no assumptions about the ordering of
+// the pointer values of the blocks appended, it simply counts bytes when asked
+// to consume bytes.
+//
+// IOVector is a bookkeeping object that collects a description of buffers to
+// be read or written together and in order. It does not take ownership of the
+// blocks appended.
+//
+// Because it is used for scatter-gather operations, the order in which the
+// buffer blocks are added to the IOVector is important to the client. The
+// intended usage pattern is:
+//
+// iovector.Append(p0, len0);
+// ...
+// iovector.Append(pn, lenn);
+// int bytes_written = writev(fd, iovector.iovec(), iovector.Size());
+// if (bytes_written > 0)
+// iovector.Consume(bytes_written);
+//
+// The sequence is the same for readv, except that Consume() in this case is
+// used to change the IOVector to only keep track of description of blocks of
+// memory not yet written to.
+//
+// IOVector does not have any method to change the iovec entries that it
+// accumulates. This is due to the block merging nature of Append(): we'd like
+// to avoid accidentally change an entry that is assembled by two or more
+// Append()'s by simply an index access.
+//
+
+class NET_EXPORT_PRIVATE IOVector {
+ public:
+ // Provide a default constructor so it'll never be inhibited by adding other
+ // constructors.
+ IOVector();
+ ~IOVector();
+
+ // Provides a way to convert system call-like iovec representation to
+ // IOVector.
+ void AppendIovec(const struct iovec* iov, size_t iovcnt) {
+ for (size_t i = 0; i < iovcnt; ++i)
+ Append(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
+ }
+
+ // Appends at most max_bytes from iovec to the IOVector.
+ size_t AppendIovecAtMostBytes(const struct iovec* iov,
+ size_t iovcnt,
+ size_t max_bytes) {
+ size_t bytes_appended = 0;
+ for (size_t i = 0; i < iovcnt && max_bytes > 0; ++i) {
+ const size_t length = std::min(max_bytes, iov[i].iov_len);
+ Append(static_cast<char*>(iov[i].iov_base), length);
+ max_bytes -= length;
+ bytes_appended += length;
+ }
+ return bytes_appended;
+ }
+
+ // Append another block to the IOVector. Since IOVector can be used for read
+ // and write, it always takes char*. Clients that writes will need to cast
+ // away the constant of the pointer before appending a block.
+ void Append(char* buffer, size_t length) {
+ if (buffer != NULL && length > 0) {
+ if (iovec_.size() > 0) {
+ struct iovec& last = iovec_.back();
+ // If the new block is contiguous with the last block, just extend.
+ if (static_cast<char*>(last.iov_base) + last.iov_len == buffer) {
+ last.iov_len += length;
+ return;
+ }
+ }
+ struct iovec tmp = {buffer, length};
+ iovec_.push_back(tmp);
+ }
+ }
+
+ // Same as Append, but doesn't do the tail merge optimization.
+ // Intended for testing.
+ void AppendNoCoalesce(char* buffer, size_t length) {
+ if (buffer != NULL && length > 0) {
+ struct iovec tmp = {buffer, length};
+ iovec_.push_back(tmp);
+ }
+ }
+
+ // Remove a number of bytes from the beginning of the IOVector. Since vector
+ // I/O operations always occur at the beginning of the block list, a method
+ // to remove bytes at the end is not provided.
+ // It returns the number of bytes actually consumed (it'll only be smaller
+ // than the requested number if the IOVector contains less data).
+ size_t Consume(size_t length) {
+ if (length == 0) return 0;
+
+ size_t bytes_to_consume = length;
+ std::vector<struct iovec>::iterator iter = iovec_.begin();
+ std::vector<struct iovec>::iterator end = iovec_.end();
+ for (; iter < end && bytes_to_consume >= iter->iov_len; ++iter) {
+ bytes_to_consume -= iter->iov_len;
+ }
+ iovec_.erase(iovec_.begin(), iter);
+ if (iovec_.size() > 0 && bytes_to_consume != 0) {
+ iovec_[0].iov_base =
+ static_cast<char*>(iovec_[0].iov_base) + bytes_to_consume;
+ iovec_[0].iov_len -= bytes_to_consume;
+ return length;
+ }
+ if (iovec_.size() == 0 && bytes_to_consume > 0) {
+ LOG(DFATAL) << "Attempting to consume " << bytes_to_consume
+ << " non-existent bytes.";
+ }
+ // At this point bytes_to_consume is the number of wanted bytes left over
+ // after walking through all the iovec entries.
+ return length - bytes_to_consume;
+ }
+
+ // TODO(joechan): If capacity is large, swap out for a blank one.
+ // Clears the IOVector object to contain no blocks.
+ void Clear() { iovec_.clear(); }
+
+ // Swap the guts of two IOVector.
+ void Swap(IOVector* other) { iovec_.swap(other->iovec_); }
+
+ // Returns the number of valid blocks in the IOVector (not the number of
+ // bytes).
+ size_t Size() const { return iovec_.size(); }
+
+ // Returns the total storage used by the IOVector in number of blocks (not
+ // the number of bytes).
+ size_t Capacity() const { return iovec_.capacity(); }
+
+ // Returns true if there are no blocks in the IOVector.
+ bool Empty() const { return iovec_.empty(); }
+
+ // Returns the pointer to the beginning of the iovec to be used for vector
+ // I/O operations. If the IOVector has no blocks appened, this function
+ // returns NULL.
+ struct iovec* iovec() { return !Empty() ? &iovec_[0] : NULL; }
+
+ // Const version.
+ const struct iovec* iovec() const { return !Empty() ? &iovec_[0] : NULL; }
+
+ // Returns a pointer to one past the last byte of the last block. If the
+ // IOVector is empty, NULL is returned.
+ const char* LastBlockEnd() const {
+ return iovec_.size() > 0 ?
+ static_cast<char *>(iovec_.back().iov_base) + iovec_.back().iov_len :
+ NULL;
+ }
+
+ // Returns the total number of bytes in the IOVector.
+ size_t TotalBufferSize() const { return TotalIovecLength(iovec(), Size()); }
+
+ void Resize(size_t count) {
+ iovec_.resize(count);
+ }
+
+ private:
+ std::vector<struct iovec> iovec_;
+
+ // IOVector has value-semantics; copy and assignment are allowed.
+ // This class does not explicitly define copy/move constructors or the
+ // assignment operator to preserve compiler-generated copy/move constructors
+ // and assignment operators. Note that since IOVector does not own the
+ // actual buffers that the struct iovecs point to, copies and assignments
+ // result in a shallow copy of the buffers; resulting IOVectors will point
+ // to the same copy of the underlying data.
+};
+
+} // namespace net
+
+#endif // NET_QUIC_IOVECTOR_H_
diff --git a/chromium/net/quic/iovector_test.cc b/chromium/net/quic/iovector_test.cc
new file mode 100644
index 00000000000..b25f29cced8
--- /dev/null
+++ b/chromium/net/quic/iovector_test.cc
@@ -0,0 +1,283 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/iovector.h"
+
+#include <string.h>
+
+#include "base/logging.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using std::string;
+
+namespace net {
+namespace test {
+namespace {
+
+const char* const test_data[] = {
+ "test string 1, a medium size one.",
+ "test string2",
+ "test string 3, a looooooooooooong loooooooooooooooong string"
+};
+
+TEST(IOVectorTest, CopyConstructor) {
+ IOVector iov1;
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ iov1.Append(const_cast<char*>(test_data[i]), strlen(test_data[i]));
+ }
+ IOVector iov2 = iov1;
+ EXPECT_EQ(iov2.Size(), iov1.Size());
+ for (size_t i = 0; i < iov2.Size(); ++i) {
+ EXPECT_TRUE(iov2.iovec()[i].iov_base == iov1.iovec()[i].iov_base);
+ EXPECT_EQ(iov2.iovec()[i].iov_len, iov1.iovec()[i].iov_len);
+ }
+ EXPECT_EQ(iov2.TotalBufferSize(), iov1.TotalBufferSize());
+}
+
+TEST(IOVectorTest, AssignmentOperator) {
+ IOVector iov1;
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ iov1.Append(const_cast<char*>(test_data[i]), strlen(test_data[i]));
+ }
+ IOVector iov2;
+ iov2.Append(const_cast<char*>("ephemeral string"), 16);
+ // The following assignment results in a shallow copy;
+ // both IOVectors point to the same underlying data.
+ iov2 = iov1;
+ EXPECT_EQ(iov2.Size(), iov1.Size());
+ for (size_t i = 0; i < iov2.Size(); ++i) {
+ EXPECT_TRUE(iov2.iovec()[i].iov_base == iov1.iovec()[i].iov_base);
+ EXPECT_EQ(iov2.iovec()[i].iov_len, iov1.iovec()[i].iov_len);
+ }
+ EXPECT_EQ(iov2.TotalBufferSize(), iov1.TotalBufferSize());
+}
+
+TEST(IOVectorTest, Append) {
+ IOVector iov;
+ int length = 0;
+ const struct iovec* iov2 = iov.iovec();
+
+ ASSERT_EQ(0u, iov.Size());
+ ASSERT_TRUE(iov2 == NULL);
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ const int str_len = strlen(test_data[i]);
+ const int append_len = str_len / 2;
+ // This should append a new block
+ iov.Append(const_cast<char*>(test_data[i]), append_len);
+ length += append_len;
+ ASSERT_EQ(i + 1, static_cast<size_t>(iov.Size()));
+ ASSERT_TRUE(iov.LastBlockEnd() == test_data[i] + append_len);
+ // This should just lengthen the existing block.
+ iov.Append(const_cast<char*>(test_data[i] + append_len),
+ str_len - append_len);
+ length += (str_len - append_len);
+ ASSERT_EQ(i + 1, static_cast<size_t>(iov.Size()));
+ ASSERT_TRUE(iov.LastBlockEnd() == test_data[i] + str_len);
+ }
+
+ iov2 = iov.iovec();
+ ASSERT_TRUE(iov2 != NULL);
+ for (size_t i = 0; i < iov.Size(); ++i) {
+ ASSERT_TRUE(test_data[i] == iov2[i].iov_base);
+ ASSERT_EQ(strlen(test_data[i]), iov2[i].iov_len);
+ }
+}
+
+TEST(IOVectorTest, AppendIovec) {
+ IOVector iov;
+ const struct iovec test_iov[] = {
+ {const_cast<char*>("foo"), 3},
+ {const_cast<char*>("bar"), 3},
+ {const_cast<char*>("buzzzz"), 6}
+ };
+ iov.AppendIovec(test_iov, ARRAYSIZE_UNSAFE(test_iov));
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_iov); ++i) {
+ EXPECT_EQ(test_iov[i].iov_base, iov.iovec()[i].iov_base);
+ EXPECT_EQ(test_iov[i].iov_len, iov.iovec()[i].iov_len);
+ }
+
+ // Test AppendIovecAtMostBytes.
+ iov.Clear();
+ // Stop in the middle of a block.
+ EXPECT_EQ(5u, iov.AppendIovecAtMostBytes(test_iov, ARRAYSIZE_UNSAFE(test_iov),
+ 5));
+ EXPECT_EQ(5u, iov.TotalBufferSize());
+ iov.Append(static_cast<char*>(test_iov[1].iov_base) + 2, 1);
+ // Make sure the boundary case, where max_bytes == size of block also works.
+ EXPECT_EQ(6u, iov.AppendIovecAtMostBytes(&test_iov[2], 1, 6));
+ ASSERT_LE(ARRAYSIZE_UNSAFE(test_iov), static_cast<size_t>(iov.Size()));
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_iov); ++i) {
+ EXPECT_EQ(test_iov[i].iov_base, iov.iovec()[i].iov_base);
+ EXPECT_EQ(test_iov[i].iov_len, iov.iovec()[i].iov_len);
+ }
+}
+
+TEST(IOVectorTest, ConsumeHalfBlocks) {
+ IOVector iov;
+ int length = 0;
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ const int str_len = strlen(test_data[i]);
+ iov.Append(const_cast<char*>(test_data[i]), str_len);
+ length += str_len;
+ }
+ const char* endp = iov.LastBlockEnd();
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ const struct iovec* iov2 = iov.iovec();
+ const size_t str_len = strlen(test_data[i]);
+ size_t tmp = str_len / 2;
+
+ ASSERT_TRUE(iov2 != NULL);
+ ASSERT_TRUE(iov2[0].iov_base == test_data[i]);
+ ASSERT_EQ(str_len, iov2[0].iov_len);
+
+ // Consume half of the first block.
+ size_t consumed = iov.Consume(tmp);
+ ASSERT_EQ(tmp, consumed);
+ ASSERT_EQ(ARRAYSIZE_UNSAFE(test_data) - i, static_cast<size_t>(iov.Size()));
+ iov2 = iov.iovec();
+ ASSERT_TRUE(iov2 != NULL);
+ ASSERT_TRUE(iov2[0].iov_base == test_data[i] + tmp);
+ ASSERT_EQ(iov2[0].iov_len, str_len - tmp);
+
+ // Consume the rest of the first block
+ consumed = iov.Consume(str_len - tmp);
+ ASSERT_EQ(str_len - tmp, consumed);
+ ASSERT_EQ(ARRAYSIZE_UNSAFE(test_data) - i - 1,
+ static_cast<size_t>(iov.Size()));
+ iov2 = iov.iovec();
+ if (iov.Size() > 0) {
+ ASSERT_TRUE(iov2 != NULL);
+ ASSERT_TRUE(iov.LastBlockEnd() == endp);
+ } else {
+ ASSERT_TRUE(iov2 == NULL);
+ ASSERT_TRUE(iov.LastBlockEnd() == NULL);
+ }
+ }
+}
+
+TEST(IOVectorTest, ConsumeTwoAndHalfBlocks) {
+ IOVector iov;
+ int length = 0;
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ const int str_len = strlen(test_data[i]);
+ iov.Append(const_cast<char*>(test_data[i]), str_len);
+ length += str_len;
+ }
+ const size_t last_len = strlen(test_data[ARRAYSIZE_UNSAFE(test_data) - 1]);
+ const size_t half_len = last_len / 2;
+
+ const char* endp = iov.LastBlockEnd();
+ size_t consumed = iov.Consume(length - half_len);
+ ASSERT_EQ(length - half_len, consumed);
+ const struct iovec* iov2 = iov.iovec();
+ ASSERT_TRUE(iov2 != NULL);
+ ASSERT_EQ(1u, iov.Size());
+ ASSERT_TRUE(iov2[0].iov_base ==
+ test_data[ARRAYSIZE_UNSAFE(test_data) - 1] + last_len - half_len);
+ ASSERT_EQ(half_len, iov2[0].iov_len);
+ ASSERT_TRUE(iov.LastBlockEnd() == endp);
+
+ consumed = iov.Consume(half_len);
+ ASSERT_EQ(half_len, consumed);
+ iov2 = iov.iovec();
+ ASSERT_EQ(0u, iov.Size());
+ ASSERT_TRUE(iov2 == NULL);
+ ASSERT_TRUE(iov.LastBlockEnd() == NULL);
+}
+
+TEST(IOVectorTest, ConsumeTooMuch) {
+ IOVector iov;
+ int length = 0;
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ const int str_len = strlen(test_data[i]);
+ iov.Append(const_cast<char*>(test_data[i]), str_len);
+ length += str_len;
+ }
+
+ int consumed = 0;
+ consumed = iov.Consume(length);
+ // TODO(rtenneti): enable when chromium supports EXPECT_DFATAL.
+ /*
+ EXPECT_DFATAL(
+ {consumed = iov.Consume(length + 1);},
+ "Attempting to consume 1 non-existent bytes.");
+ */
+ ASSERT_EQ(length, consumed);
+ const struct iovec* iov2 = iov.iovec();
+ ASSERT_EQ(0u, iov.Size());
+ ASSERT_TRUE(iov2 == NULL);
+ ASSERT_TRUE(iov.LastBlockEnd() == NULL);
+}
+
+TEST(IOVectorTest, Clear) {
+ IOVector iov;
+ int length = 0;
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ const int str_len = strlen(test_data[i]);
+ iov.Append(const_cast<char*>(test_data[i]), str_len);
+ length += str_len;
+ }
+ const struct iovec* iov2 = iov.iovec();
+ ASSERT_TRUE(iov2 != NULL);
+ ASSERT_EQ(ARRAYSIZE_UNSAFE(test_data), static_cast<size_t>(iov.Size()));
+
+ iov.Clear();
+ iov2 = iov.iovec();
+ ASSERT_EQ(0u, iov.Size());
+ ASSERT_TRUE(iov2 == NULL);
+}
+
+TEST(IOVectorTest, Capacity) {
+ IOVector iov;
+ // Note: IOVector merges adjacent Appends() into a single iov.
+ // Therefore, if we expect final size of iov to be 3, we must insure
+ // that the items we are appending are not adjacent. To achieve that
+ // we use use an array (a[1] provides a buffer between a[0] and b[0],
+ // and makes them non-adjacent).
+ char a[2], b[2], c[2];
+ iov.Append(&a[0], 1);
+ iov.Append(&b[0], 1);
+ iov.Append(&c[0], 1);
+ ASSERT_EQ(3u, iov.Size());
+ size_t capacity = iov.Capacity();
+ EXPECT_LE(iov.Size(), capacity);
+ iov.Consume(2);
+ // The capacity should not have changed.
+ EXPECT_EQ(capacity, iov.Capacity());
+}
+
+TEST(IOVectorTest, Swap) {
+ IOVector iov1, iov2;
+ // See IOVector merge comment above.
+ char a[2], b[2], c[2], d[2], e[2];
+ iov1.Append(&a[0], 1);
+ iov1.Append(&b[0], 1);
+
+ iov2.Append(&c[0], 1);
+ iov2.Append(&d[0], 1);
+ iov2.Append(&e[0], 1);
+ iov1.Swap(&iov2);
+
+ ASSERT_EQ(3u, iov1.Size());
+ EXPECT_EQ(&c[0], iov1.iovec()[0].iov_base);
+ EXPECT_EQ(1u, iov1.iovec()[0].iov_len);
+ EXPECT_EQ(&d[0], iov1.iovec()[1].iov_base);
+ EXPECT_EQ(1u, iov1.iovec()[1].iov_len);
+ EXPECT_EQ(&e[0], iov1.iovec()[2].iov_base);
+ EXPECT_EQ(1u, iov1.iovec()[2].iov_len);
+
+ ASSERT_EQ(2u, iov2.Size());
+ EXPECT_EQ(&a[0], iov2.iovec()[0].iov_base);
+ EXPECT_EQ(1u, iov2.iovec()[0].iov_len);
+ EXPECT_EQ(&b[0], iov2.iovec()[1].iov_base);
+ EXPECT_EQ(1u, iov2.iovec()[1].iov_len);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/port_suggester.cc b/chromium/net/quic/port_suggester.cc
new file mode 100644
index 00000000000..6b7940e83ef
--- /dev/null
+++ b/chromium/net/quic/port_suggester.cc
@@ -0,0 +1,49 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/port_suggester.h"
+
+#include "base/logging.h"
+#include "net/base/host_port_pair.h"
+
+namespace net {
+
+PortSuggester::PortSuggester(const HostPortPair& server, uint64 seed)
+ : call_count_(0),
+ previous_suggestion_(-1) {
+ unsigned char hash_bytes[base::kSHA1Length];
+ base::SHA1HashBytes(
+ reinterpret_cast<const unsigned char*>(server.host().data()),
+ server.host().length(), hash_bytes);
+ COMPILE_ASSERT(sizeof(seed_) < sizeof(hash_bytes), seed_larger_than_hash);
+ memcpy(&seed_, hash_bytes, sizeof(seed_));
+ seed_ ^= seed ^ server.port();
+}
+
+int PortSuggester::SuggestPort(int min, int max) {
+ // Sometimes our suggestion can't be used, so we ensure that if additional
+ // calls are made, then each call (probably) provides a new suggestion.
+ if (++call_count_ > 1) {
+ // Evolve the seed.
+ unsigned char hash_bytes[base::kSHA1Length];
+ base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(&seed_),
+ sizeof(seed_), hash_bytes);
+ memcpy(&seed_, hash_bytes, sizeof(seed_));
+ }
+ DCHECK_LE(min, max);
+ DCHECK_GT(min, 0);
+ int range = max - min + 1;
+ // Ports (and hence the extent of the |range|) are generally under 2^16, so
+ // the tiny non-uniformity in the pseudo-random distribution is not
+ // significant.
+ previous_suggestion_ = static_cast<int>(seed_ % range) + min;
+ return previous_suggestion_;
+}
+
+int PortSuggester::previous_suggestion() const {
+ DCHECK_LT(0u, call_count_);
+ return previous_suggestion_;
+}
+
+} // namespace net
diff --git a/chromium/net/quic/port_suggester.h b/chromium/net/quic/port_suggester.h
new file mode 100644
index 00000000000..0074f7c7459
--- /dev/null
+++ b/chromium/net/quic/port_suggester.h
@@ -0,0 +1,50 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_PORT_SUGGESTER_H_
+#define NET_QUIC_PORT_SUGGESTER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/sha1.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+class HostPortPair;
+
+// We provide a pseudo-random number generator that is always seeded the same
+// way for a given destination host-port pair. The generator is used to
+// consistently suggest (for that host-port pair) an ephemeral source port,
+// and hence increase the likelihood that a server's load balancer will direct
+// a repeated connection to the same server (with QUIC, further increasing the
+// chance of connection establishment with 0-RTT).
+class NET_EXPORT_PRIVATE PortSuggester
+ : public base::RefCounted<PortSuggester> {
+ public:
+ PortSuggester(const HostPortPair& server, uint64 seed);
+
+ // Generate a pseudo-random int in the inclusive range from |min| to |max|.
+ // Will (probably) return different numbers when called repeatedly.
+ int SuggestPort(int min, int max);
+
+ uint32 call_count() const { return call_count_; }
+ int previous_suggestion() const;
+
+ private:
+ friend class base::RefCounted<PortSuggester>;
+
+ virtual ~PortSuggester() {}
+
+ // We maintain the first 8 bytes of a hash as our seed_ state.
+ uint64 seed_;
+ uint32 call_count_; // Number of suggestions made.
+ int previous_suggestion_;
+
+ DISALLOW_COPY_AND_ASSIGN(PortSuggester);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_PORT_SUGGESTER_H_
diff --git a/chromium/net/quic/port_suggester_unittest.cc b/chromium/net/quic/port_suggester_unittest.cc
new file mode 100644
index 00000000000..add52584509
--- /dev/null
+++ b/chromium/net/quic/port_suggester_unittest.cc
@@ -0,0 +1,112 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/port_suggester.h"
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "net/base/host_port_pair.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace test {
+
+class PortSuggesterTest : public ::testing::Test {
+ protected:
+ PortSuggesterTest()
+ : entropy_(1345689),
+ min_ephemeral_port_(1025),
+ max_ephemeral_port_(65535) {
+ }
+
+ uint64 entropy_;
+ int min_ephemeral_port_;
+ int max_ephemeral_port_;
+};
+
+TEST_F(PortSuggesterTest, SmallRangeTest) {
+ // When the range is small (one wide), we always get that as our answer.
+ scoped_refptr<PortSuggester> port_suggester =
+ new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
+ // Test this for a few different (small) ranges.
+ for (int port = 2000; port < 2010; ++port) {
+ // Use |port| for both |min| and |max| delimiting the suggestion range.
+ EXPECT_EQ(port, port_suggester->SuggestPort(port, port));
+ EXPECT_EQ(port, port_suggester->previous_suggestion());
+ }
+}
+
+TEST_F(PortSuggesterTest, SuggestAllPorts) {
+ // We should eventually fill out any range, but we'll just ensure that we
+ // fill out a small range of ports.
+ scoped_refptr<PortSuggester> port_suggester =
+ new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
+ std::set<int> ports;
+ const uint32 port_range = 20;
+ const int insertion_limit = 200; // We should be done by then.
+ for (int i = 0; i < insertion_limit; ++i) {
+ ports.insert(port_suggester->SuggestPort(min_ephemeral_port_,
+ min_ephemeral_port_ + port_range - 1));
+ if (ports.size() == port_range) {
+ break;
+ }
+ }
+ EXPECT_EQ(port_range, ports.size());
+}
+
+TEST_F(PortSuggesterTest, AvoidDuplication) {
+ // When the range is large, duplicates are rare, but we'll ask for a few
+ // suggestions and make sure they are unique.
+ scoped_refptr<PortSuggester> port_suggester =
+ new PortSuggester(HostPortPair("www.example.com", 80), entropy_);
+ std::set<int> ports;
+ const size_t port_count = 200;
+ for (size_t i = 0; i < port_count; ++i) {
+ ports.insert(port_suggester->SuggestPort(min_ephemeral_port_,
+ max_ephemeral_port_));
+ }
+ EXPECT_EQ(port_suggester->call_count(), port_count);
+ EXPECT_EQ(port_count, ports.size());
+}
+
+TEST_F(PortSuggesterTest, ConsistentPorts) {
+ // For given hostname, port, and entropy, we should always get the same
+ // suggestions.
+ scoped_refptr<PortSuggester> port_suggester1 =
+ new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
+ scoped_refptr<PortSuggester> port_suggester2 =
+ new PortSuggester(HostPortPair("www.example.com", 443), entropy_);
+ for (int test_count = 20; test_count > 0; --test_count) {
+ EXPECT_EQ(port_suggester1->SuggestPort(min_ephemeral_port_,
+ min_ephemeral_port_),
+ port_suggester2->SuggestPort(min_ephemeral_port_,
+ min_ephemeral_port_));
+ }
+}
+
+TEST_F(PortSuggesterTest, DifferentHostPortEntropy) {
+ // When we have different hosts, port, or entropy, we probably won't collide.
+ scoped_refptr<PortSuggester> port_suggester[] = {
+ new PortSuggester(HostPortPair("www.example.com", 80), entropy_),
+ new PortSuggester(HostPortPair("www.example.ORG", 80), entropy_),
+ new PortSuggester(HostPortPair("www.example.com", 443), entropy_),
+ new PortSuggester(HostPortPair("www.example.com", 80), entropy_ + 123456),
+ };
+
+ std::set<int> ports;
+ const int port_count = 40;
+ size_t insertion_count = 0;
+ for (size_t j = 0; j < arraysize(port_suggester); ++j) {
+ for (int i = 0; i < port_count; ++i) {
+ ports.insert(port_suggester[j]->SuggestPort(min_ephemeral_port_,
+ max_ephemeral_port_));
+ ++insertion_count;
+ }
+ }
+ EXPECT_EQ(insertion_count, ports.size());
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/quic_ack_notifier.cc b/chromium/net/quic/quic_ack_notifier.cc
index 662b432d5c8..5eaf38581dc 100644
--- a/chromium/net/quic/quic_ack_notifier.cc
+++ b/chromium/net/quic/quic_ack_notifier.cc
@@ -4,6 +4,11 @@
#include "net/quic/quic_ack_notifier.h"
+#include <set>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+
namespace net {
QuicAckNotifier::DelegateInterface::DelegateInterface() {}
@@ -30,18 +35,14 @@ void QuicAckNotifier::AddSequenceNumbers(
}
}
-bool QuicAckNotifier::OnAck(SequenceNumberSet sequence_numbers) {
- // If the set of sequence numbers we are tracking is empty then this
- // QuicAckNotifier should have already been deleted.
- DCHECK(!sequence_numbers_.empty());
-
- for (SequenceNumberSet::iterator it = sequence_numbers.begin();
- it != sequence_numbers.end(); ++it) {
- sequence_numbers_.erase(*it);
- if (sequence_numbers_.empty()) {
- delegate_->OnAckNotification();
- return true;
- }
+bool QuicAckNotifier::OnAck(QuicPacketSequenceNumber sequence_number) {
+ DCHECK(ContainsKey(sequence_numbers_, sequence_number));
+ sequence_numbers_.erase(sequence_number);
+ if (IsEmpty()) {
+ // We have seen all the sequence numbers we were waiting for, trigger
+ // callback notification.
+ delegate_->OnAckNotification();
+ return true;
}
return false;
}
diff --git a/chromium/net/quic/quic_ack_notifier.h b/chromium/net/quic/quic_ack_notifier.h
index 8470681c650..5ec92134e78 100644
--- a/chromium/net/quic/quic_ack_notifier.h
+++ b/chromium/net/quic/quic_ack_notifier.h
@@ -5,7 +5,6 @@
#ifndef NET_QUIC_QUIC_ACK_NOTIFIER_H_
#define NET_QUIC_QUIC_ACK_NOTIFIER_H_
-#include "base/callback.h"
#include "net/quic/quic_protocol.h"
namespace net {
@@ -34,15 +33,17 @@ class NET_EXPORT_PRIVATE QuicAckNotifier {
// interested in.
void AddSequenceNumbers(const SequenceNumberSet& sequence_numbers);
- // Called by the QuicConnection on receipt of new ACK frames with a list of
- // ACKed sequence numbers.
- // Deletes any matching sequence numbers from the set of sequence numbers
- // being tracked. If this set is now empty, call the stored delegate's
+ // Called by the QuicConnection on receipt of new ACK frame, with the sequence
+ // number referenced by the ACK frame.
+ // Deletes the matching sequence number from the stored set of sequence
+ // numbers. If this set is now empty, call the stored delegate's
// OnAckNotification method.
//
- // Returns true if the provided sequence_numbers caused the delegate to be
+ // Returns true if the provided sequence_number caused the delegate to be
// called, false otherwise.
- bool OnAck(SequenceNumberSet sequence_numbers);
+ bool OnAck(QuicPacketSequenceNumber sequence_number);
+
+ bool IsEmpty() { return sequence_numbers_.empty(); }
// If a packet is retransmitted by the connection it will be sent with a
// different sequence number. Updates our internal set of sequence_numbers to
diff --git a/chromium/net/quic/quic_ack_notifier_manager.cc b/chromium/net/quic/quic_ack_notifier_manager.cc
new file mode 100644
index 00000000000..8676315d22f
--- /dev/null
+++ b/chromium/net/quic/quic_ack_notifier_manager.cc
@@ -0,0 +1,105 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_ack_notifier_manager.h"
+
+#include <stddef.h>
+#include <list>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include "base/stl_util.h"
+#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+AckNotifierManager::AckNotifierManager() {}
+
+AckNotifierManager::~AckNotifierManager() {
+ STLDeleteElements(&ack_notifiers_);
+}
+
+void AckNotifierManager::OnPacketAcked(
+ QuicPacketSequenceNumber sequence_number) {
+ // Inform all the registered AckNotifiers of the new ACK.
+ AckNotifierMap::iterator map_it = ack_notifier_map_.find(sequence_number);
+ if (map_it == ack_notifier_map_.end()) {
+ // No AckNotifier is interested in this sequence number.
+ return;
+ }
+
+ // One or more AckNotifiers are registered as interested in this sequence
+ // number. Iterate through them and call OnAck on each.
+ for (AckNotifierSet::iterator set_it = map_it->second.begin();
+ set_it != map_it->second.end(); ++set_it) {
+ QuicAckNotifier* ack_notifier = *set_it;
+ ack_notifier->OnAck(sequence_number);
+
+ // If this has resulted in an empty AckNotifer, erase it.
+ if (ack_notifier->IsEmpty()) {
+ delete ack_notifier;
+ ack_notifiers_.erase(ack_notifier);
+ }
+ }
+
+ // Remove the sequence number from the map as we have notified all the
+ // registered AckNotifiers, and we won't see it again.
+ ack_notifier_map_.erase(map_it);
+}
+
+void AckNotifierManager::UpdateSequenceNumber(
+ QuicPacketSequenceNumber old_sequence_number,
+ QuicPacketSequenceNumber new_sequence_number) {
+ AckNotifierMap::iterator map_it = ack_notifier_map_.find(old_sequence_number);
+ if (map_it != ack_notifier_map_.end()) {
+ // We will add an entry to the map for the new sequence number, and move
+ // the
+ // list of AckNotifiers over.
+ AckNotifierSet new_set;
+ for (AckNotifierSet::iterator notifier_it = map_it->second.begin();
+ notifier_it != map_it->second.end(); ++notifier_it) {
+ (*notifier_it)
+ ->UpdateSequenceNumber(old_sequence_number, new_sequence_number);
+ new_set.insert(*notifier_it);
+ }
+ ack_notifier_map_[new_sequence_number] = new_set;
+ ack_notifier_map_.erase(map_it);
+ }
+}
+
+void AckNotifierManager::OnSerializedPacket(
+ const SerializedPacket& serialized_packet) {
+ // Run through all the frames and if any of them are stream frames and have
+ // an AckNotifier registered, then inform the AckNotifier that it should be
+ // interested in this packet's sequence number.
+
+ RetransmittableFrames* frames = serialized_packet.retransmittable_frames;
+
+ // AckNotifiers can only be attached to retransmittable frames.
+ if (!frames) {
+ return;
+ }
+
+ for (QuicFrames::const_iterator it = frames->frames().begin();
+ it != frames->frames().end(); ++it) {
+ if (it->type == STREAM_FRAME && it->stream_frame->notifier != NULL) {
+ QuicAckNotifier* notifier = it->stream_frame->notifier;
+
+ // The AckNotifier needs to know it is tracking this packet's sequence
+ // number.
+ notifier->AddSequenceNumber(serialized_packet.sequence_number);
+
+ // Update the mapping in the other direction, from sequence
+ // number to AckNotifier.
+ ack_notifier_map_[serialized_packet.sequence_number].insert(notifier);
+
+ // Take ownership of the AckNotifier.
+ ack_notifiers_.insert(notifier);
+ }
+ }
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_ack_notifier_manager.h b/chromium/net/quic/quic_ack_notifier_manager.h
new file mode 100644
index 00000000000..5ddf794e7bb
--- /dev/null
+++ b/chromium/net/quic/quic_ack_notifier_manager.h
@@ -0,0 +1,78 @@
+// 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_NOTIFIER_MANAGER_H_
+#define NET_QUIC_QUIC_ACK_NOTIFIER_MANAGER_H_
+
+#include <map>
+
+#include "base/containers/hash_tables.h"
+#include "net/quic/quic_protocol.h"
+
+#if defined(COMPILER_GCC)
+namespace BASE_HASH_NAMESPACE {
+template<>
+struct hash<net::QuicAckNotifier*> {
+ std::size_t operator()(const net::QuicAckNotifier* ptr) const {
+ return hash<size_t>()(reinterpret_cast<size_t>(ptr));
+ }
+};
+}
+#endif
+
+namespace net {
+
+class QuicAckNotifier;
+
+// The AckNotifierManager is used by the QuicSentPacketManager to keep track of
+// all the AckNotifiers currently active. It owns the AckNotifiers which it gets
+// from the serialized packets passed into OnSerializedPacket. It maintains both
+// a set of AckNotifiers and a map from sequence number to AckNotifier the sake
+// of efficiency - we can quickly check the map to see if any AckNotifiers are
+// interested in a given sequence number.
+
+class NET_EXPORT_PRIVATE AckNotifierManager {
+ public:
+ AckNotifierManager();
+ virtual ~AckNotifierManager();
+
+ // Called when the connection receives a new AckFrame. If |sequence_number|
+ // exists in ack_notifier_map_ then the corresponding AckNotifiers will have
+ // their OnAck method called.
+ void OnPacketAcked(QuicPacketSequenceNumber sequence_number);
+
+ // If a packet has been retransmitted with a new sequence number, then this
+ // will be called. It updates the mapping in ack_notifier_map_, and also
+ // updates the internal set of sequence numbers in each matching AckNotifier.
+ void UpdateSequenceNumber(QuicPacketSequenceNumber old_sequence_number,
+ QuicPacketSequenceNumber new_sequence_number);
+
+ // This is called after a packet has been serialized, is ready to be sent, and
+ // contains retransmittable frames (which may have associated AckNotifiers).
+ // If any of the retransmittable frames included in |serialized_packet| have
+ // AckNotifiers registered, then add them to our internal map and additionally
+ // inform the AckNotifier of the sequence number which it should track.
+ void OnSerializedPacket(const SerializedPacket& serialized_packet);
+
+ private:
+ typedef base::hash_set<QuicAckNotifier*> AckNotifierSet;
+ typedef std::map<QuicPacketSequenceNumber, AckNotifierSet> AckNotifierMap;
+
+ // On every ACK frame received by the connection, all the ack_notifiers_ will
+ // be told which sequeunce numbers were ACKed.
+ // Once a given QuicAckNotifier has seen all the sequence numbers it is
+ // interested in, it will be deleted, and removed from this set.
+ // Owns the AckNotifiers in this set.
+ AckNotifierSet ack_notifiers_;
+
+ // Maps from sequence number to the AckNotifiers which are registered
+ // for that sequence number. On receipt of an ACK for a given sequence
+ // number, call OnAck for all mapped AckNotifiers.
+ // Does not own the AckNotifiers.
+ AckNotifierMap ack_notifier_map_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_ACK_NOTIFIER_MANAGER_H_
diff --git a/chromium/net/quic/quic_ack_notifier_test.cc b/chromium/net/quic/quic_ack_notifier_test.cc
index aa1ebfa955f..8facee340f0 100644
--- a/chromium/net/quic/quic_ack_notifier_test.cc
+++ b/chromium/net/quic/quic_ack_notifier_test.cc
@@ -31,74 +31,30 @@ class QuicAckNotifierTest : public ::testing::Test {
// Should trigger callback when we receive acks for all the registered seqnums.
TEST_F(QuicAckNotifierTest, TriggerCallback) {
EXPECT_CALL(delegate_, OnAckNotification()).Times(1);
- EXPECT_TRUE(notifier_->OnAck(sequence_numbers_));
-}
-
-// Should trigger callback when we receive acks for all the registered seqnums,
-// even though they are interspersed with other seqnums.
-TEST_F(QuicAckNotifierTest, TriggerCallbackInterspersed) {
- sequence_numbers_.insert(3);
- sequence_numbers_.insert(55);
- sequence_numbers_.insert(805);
-
- EXPECT_CALL(delegate_, OnAckNotification()).Times(1);
- EXPECT_TRUE(notifier_->OnAck(sequence_numbers_));
-}
-
-// Should trigger callback when we receive acks for all the registered seqnums,
-// even though they are split over multiple calls to OnAck.
-TEST_F(QuicAckNotifierTest, TriggerCallbackMultipleCalls) {
- SequenceNumberSet seqnums;
- seqnums.insert(26);
- EXPECT_CALL(delegate_, OnAckNotification()).Times(0);
- EXPECT_FALSE(notifier_->OnAck(seqnums));
-
- seqnums.clear();
- seqnums.insert(55);
- seqnums.insert(9001);
- seqnums.insert(99);
- EXPECT_CALL(delegate_, OnAckNotification()).Times(0);
- EXPECT_FALSE(notifier_->OnAck(seqnums));
-
- seqnums.clear();
- seqnums.insert(1234);
- EXPECT_CALL(delegate_, OnAckNotification()).Times(1);
- EXPECT_TRUE(notifier_->OnAck(seqnums));
+ EXPECT_FALSE(notifier_->OnAck(26));
+ EXPECT_FALSE(notifier_->OnAck(99));
+ EXPECT_TRUE(notifier_->OnAck(1234));
}
// Should not trigger callback if we never provide all the seqnums.
TEST_F(QuicAckNotifierTest, DoesNotTrigger) {
- SequenceNumberSet different_seqnums;
- different_seqnums.insert(14);
- different_seqnums.insert(15);
- different_seqnums.insert(16);
-
// Should not trigger callback as not all packets have been seen.
EXPECT_CALL(delegate_, OnAckNotification()).Times(0);
- EXPECT_FALSE(notifier_->OnAck(different_seqnums));
+ EXPECT_FALSE(notifier_->OnAck(26));
+ EXPECT_FALSE(notifier_->OnAck(99));
}
// Should trigger even after updating sequence numbers and receiving ACKs for
// new sequeunce numbers.
TEST_F(QuicAckNotifierTest, UpdateSeqNums) {
- // Uninteresting sequeunce numbers shouldn't trigger callback.
- SequenceNumberSet seqnums;
- seqnums.insert(6);
- seqnums.insert(7);
- seqnums.insert(2000);
- EXPECT_CALL(delegate_, OnAckNotification()).Times(0);
- EXPECT_FALSE(notifier_->OnAck(seqnums));
-
// Update a couple of the sequence numbers (i.e. retransmitted packets)
notifier_->UpdateSequenceNumber(99, 3000);
notifier_->UpdateSequenceNumber(1234, 3001);
- seqnums.clear();
- seqnums.insert(26); // original, unchanged
- seqnums.insert(3000); // updated
- seqnums.insert(3001); // updated
EXPECT_CALL(delegate_, OnAckNotification()).Times(1);
- EXPECT_TRUE(notifier_->OnAck(seqnums));
+ EXPECT_FALSE(notifier_->OnAck(26)); // original
+ EXPECT_FALSE(notifier_->OnAck(3000)); // updated
+ EXPECT_TRUE(notifier_->OnAck(3001)); // updated
}
} // namespace
diff --git a/chromium/net/quic/quic_alarm_test.cc b/chromium/net/quic/quic_alarm_test.cc
index cd7d8a559be..cc5028b8457 100644
--- a/chromium/net/quic/quic_alarm_test.cc
+++ b/chromium/net/quic/quic_alarm_test.cc
@@ -22,9 +22,7 @@ class MockDelegate : public QuicAlarm::Delegate {
class TestAlarm : public QuicAlarm {
public:
- TestAlarm(QuicAlarm::Delegate* delegate)
- : QuicAlarm(delegate) {
- }
+ explicit TestAlarm(QuicAlarm::Delegate* delegate) : QuicAlarm(delegate) {}
bool scheduled() const { return scheduled_; }
diff --git a/chromium/net/quic/quic_bandwidth.cc b/chromium/net/quic/quic_bandwidth.cc
index 37b3b3883f2..cdd2986b167 100644
--- a/chromium/net/quic/quic_bandwidth.cc
+++ b/chromium/net/quic/quic_bandwidth.cc
@@ -99,4 +99,9 @@ QuicBandwidth QuicBandwidth::Scale(float scale_factor) const {
return QuicBandwidth(bits_per_second_ * scale_factor);
}
+QuicTime::Delta QuicBandwidth::TransferTime(QuicByteCount bytes) const {
+ return QuicTime::Delta::FromMicroseconds(
+ bytes * 8 * base::Time::kMicrosecondsPerSecond / bits_per_second_);
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_bandwidth.h b/chromium/net/quic/quic_bandwidth.h
index 71c4b2d9268..6412aa5c68d 100644
--- a/chromium/net/quic/quic_bandwidth.h
+++ b/chromium/net/quic/quic_bandwidth.h
@@ -56,6 +56,8 @@ class NET_EXPORT_PRIVATE QuicBandwidth {
QuicBandwidth Scale(float scale_factor) const;
+ QuicTime::Delta TransferTime(QuicByteCount bytes) const;
+
private:
explicit QuicBandwidth(int64 bits_per_second);
int64 bits_per_second_;
diff --git a/chromium/net/quic/quic_bandwidth_test.cc b/chromium/net/quic/quic_bandwidth_test.cc
index 1090f0b4b27..e9913db76e0 100644
--- a/chromium/net/quic/quic_bandwidth_test.cc
+++ b/chromium/net/quic/quic_bandwidth_test.cc
@@ -78,5 +78,10 @@ TEST_F(QuicBandwidthTest, BytesPerPeriod) {
QuicTime::Delta::FromMilliseconds(100)));
}
+TEST_F(QuicBandwidthTest, TransferTime) {
+ EXPECT_EQ(QuicTime::Delta::FromSeconds(1),
+ QuicBandwidth::FromKBytesPerSecond(1).TransferTime(1000));
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_client_session.cc b/chromium/net/quic/quic_client_session.cc
index ca6941c7e1b..ab70e7f445c 100644
--- a/chromium/net/quic/quic_client_session.cc
+++ b/chromium/net/quic/quic_client_session.cc
@@ -15,6 +15,7 @@
#include "net/base/net_errors.h"
#include "net/quic/quic_connection_helper.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
+#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_stream_factory.h"
#include "net/ssl/ssl_info.h"
#include "net/udp/datagram_client_socket.h"
@@ -47,7 +48,7 @@ QuicClientSession::StreamRequest::~StreamRequest() {
}
int QuicClientSession::StreamRequest::StartRequest(
- const base::WeakPtr<QuicClientSession> session,
+ const base::WeakPtr<QuicClientSession>& session,
QuicReliableClientStream** stream,
const CompletionCallback& callback) {
session_ = session;
@@ -82,21 +83,24 @@ void QuicClientSession::StreamRequest::OnRequestCompleteFailure(int rv) {
QuicClientSession::QuicClientSession(
QuicConnection* connection,
scoped_ptr<DatagramClientSocket> socket,
+ scoped_ptr<QuicDefaultPacketWriter> writer,
QuicStreamFactory* stream_factory,
QuicCryptoClientStreamFactory* crypto_client_stream_factory,
const string& server_hostname,
const QuicConfig& config,
QuicCryptoClientConfig* crypto_config,
NetLog* net_log)
- : QuicSession(connection, config, false),
+ : QuicSession(connection, config),
require_confirmation_(false),
stream_factory_(stream_factory),
socket_(socket.Pass()),
+ writer_(writer.Pass()),
read_buffer_(new IOBufferWithSize(kMaxPacketSize)),
read_pending_(false),
num_total_streams_(0),
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)),
logger_(net_log_),
+ num_packets_read_(0),
weak_factory_(this) {
crypto_stream_.reset(
crypto_client_stream_factory ?
@@ -112,6 +116,12 @@ QuicClientSession::QuicClientSession(
}
QuicClientSession::~QuicClientSession() {
+ // The session must be closed before it is destroyed.
+ DCHECK(streams()->empty());
+ CloseAllStreams(ERR_UNEXPECTED);
+ DCHECK(observers_.empty());
+ CloseAllObservers(ERR_UNEXPECTED);
+
connection()->set_debug_visitor(NULL);
net_log_.EndEvent(NetLog::TYPE_QUIC_SESSION);
@@ -134,6 +144,38 @@ QuicClientSession::~QuicClientSession() {
UMA_HISTOGRAM_COUNTS("Net.QuicNumSentClientHellosCryptoHandshakeConfirmed",
crypto_stream_->num_sent_client_hellos());
}
+
+ UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumTotalStreams", num_total_streams_);
+}
+
+bool QuicClientSession::OnStreamFrames(
+ const std::vector<QuicStreamFrame>& frames) {
+ // Record total number of stream frames.
+ UMA_HISTOGRAM_COUNTS("Net.QuicNumStreamFramesInPacket", frames.size());
+
+ // Record number of frames per stream in packet.
+ typedef std::map<QuicStreamId, size_t> FrameCounter;
+ FrameCounter frames_per_stream;
+ for (size_t i = 0; i < frames.size(); ++i) {
+ frames_per_stream[frames[i].stream_id]++;
+ }
+ for (FrameCounter::const_iterator it = frames_per_stream.begin();
+ it != frames_per_stream.end(); ++it) {
+ UMA_HISTOGRAM_COUNTS("Net.QuicNumStreamFramesPerStreamInPacket",
+ it->second);
+ }
+
+ return QuicSession::OnStreamFrames(frames);
+}
+
+void QuicClientSession::AddObserver(Observer* observer) {
+ DCHECK(!ContainsKey(observers_, observer));
+ observers_.insert(observer);
+}
+
+void QuicClientSession::RemoveObserver(Observer* observer) {
+ DCHECK(ContainsKey(observers_, observer));
+ observers_.erase(observer);
}
int QuicClientSession::TryCreateStream(StreamRequest* request,
@@ -144,12 +186,12 @@ int QuicClientSession::TryCreateStream(StreamRequest* request,
}
if (goaway_received()) {
- DLOG(INFO) << "Going away.";
+ DVLOG(1) << "Going away.";
return ERR_CONNECTION_CLOSED;
}
if (!connection()->connected()) {
- DLOG(INFO) << "Already closed.";
+ DVLOG(1) << "Already closed.";
return ERR_CONNECTION_CLOSED;
}
@@ -172,18 +214,18 @@ void QuicClientSession::CancelRequest(StreamRequest* request) {
}
}
-QuicReliableClientStream* QuicClientSession::CreateOutgoingReliableStream() {
+QuicReliableClientStream* QuicClientSession::CreateOutgoingDataStream() {
if (!crypto_stream_->encryption_established()) {
- DLOG(INFO) << "Encryption not active so no outgoing stream created.";
+ DVLOG(1) << "Encryption not active so no outgoing stream created.";
return NULL;
}
if (GetNumOpenStreams() >= get_max_open_streams()) {
- DLOG(INFO) << "Failed to create a new outgoing stream. "
+ DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already " << GetNumOpenStreams() << " open.";
return NULL;
}
if (goaway_received()) {
- DLOG(INFO) << "Failed to create a new outgoing stream. "
+ DVLOG(1) << "Failed to create a new outgoing stream. "
<< "Already received goaway.";
return NULL;
}
@@ -198,6 +240,7 @@ QuicClientSession::CreateOutgoingReliableStreamImpl() {
new QuicReliableClientStream(GetNextStreamId(), this, net_log_);
ActivateStream(stream);
++num_total_streams_;
+ UMA_HISTOGRAM_COUNTS("Net.QuicSession.NumOpenStreams", GetNumOpenStreams());
return stream;
}
@@ -234,7 +277,7 @@ int QuicClientSession::GetNumSentClientHellos() const {
return crypto_stream_->num_sent_client_hellos();
}
-ReliableQuicStream* QuicClientSession::CreateIncomingReliableStream(
+QuicDataStream* QuicClientSession::CreateIncomingDataStream(
QuicStreamId id) {
DLOG(ERROR) << "Server push not supported";
return NULL;
@@ -276,6 +319,14 @@ void QuicClientSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
// following code needs to changed.
base::ResetAndReturn(&callback_).Run(OK);
}
+ if (event == HANDSHAKE_CONFIRMED) {
+ ObserverSet::iterator it = observers_.begin();
+ while (it != observers_.end()) {
+ Observer* observer = *it;
+ ++it;
+ observer->OnCryptoHandshakeConfirmed();
+ }
+ }
QuicSession::OnCryptoHandshakeEvent(event);
}
@@ -289,8 +340,10 @@ void QuicClientSession::OnCryptoHandshakeMessageReceived(
logger_.OnCryptoHandshakeMessageReceived(message);
}
-void QuicClientSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
- logger_.OnConnectionClose(error, from_peer);
+void QuicClientSession::OnConnectionClosed(QuicErrorCode error,
+ bool from_peer) {
+ DCHECK(!connection()->connected());
+ logger_.OnConnectionClosed(error, from_peer);
if (from_peer) {
UMA_HISTOGRAM_SPARSE_SLOWLY(
"Net.QuicSession.ConnectionCloseErrorCodeServer", error);
@@ -300,18 +353,30 @@ void QuicClientSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
}
if (error == QUIC_CONNECTION_TIMED_OUT) {
- UMA_HISTOGRAM_SPARSE_SLOWLY(
+ UMA_HISTOGRAM_COUNTS(
"Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut",
GetNumOpenStreams());
+ if (!IsCryptoHandshakeConfirmed()) {
+ // If there have been any streams created, they were 0-RTT speculative
+ // requests that have not be serviced.
+ UMA_HISTOGRAM_COUNTS(
+ "Net.QuicSession.ConnectionClose.NumTotalStreams.HandshakeTimedOut",
+ num_total_streams_);
+ }
}
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.QuicVersion",
connection()->version());
+ NotifyFactoryOfSessionGoingAway();
if (!callback_.is_null()) {
base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR);
}
- QuicSession::ConnectionClose(error, from_peer);
- NotifyFactoryOfSessionCloseLater();
+ socket_->Close();
+ QuicSession::OnConnectionClosed(error, from_peer);
+ DCHECK(streams()->empty());
+ CloseAllStreams(ERR_UNEXPECTED);
+ CloseAllObservers(ERR_UNEXPECTED);
+ NotifyFactoryOfSessionClosedLater();
}
void QuicClientSession::OnSuccessfulVersionNegotiation(
@@ -330,22 +395,28 @@ void QuicClientSession::StartReading() {
base::Bind(&QuicClientSession::OnReadComplete,
weak_factory_.GetWeakPtr()));
if (rv == ERR_IO_PENDING) {
+ num_packets_read_ = 0;
return;
}
- // Data was read, process it.
- // Schedule the work through the message loop to avoid recursive
- // callbacks.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&QuicClientSession::OnReadComplete,
- weak_factory_.GetWeakPtr(), rv));
+ if (++num_packets_read_ > 32) {
+ num_packets_read_ = 0;
+ // Data was read, process it.
+ // Schedule the work through the message loop to avoid recursive
+ // callbacks.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&QuicClientSession::OnReadComplete,
+ weak_factory_.GetWeakPtr(), rv));
+ } else {
+ OnReadComplete(rv);
+ }
}
void QuicClientSession::CloseSessionOnError(int error) {
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.CloseSessionOnError", -error);
CloseSessionOnErrorInner(error, QUIC_INTERNAL_ERROR);
- NotifyFactoryOfSessionClose();
+ NotifyFactoryOfSessionClosed();
}
void QuicClientSession::CloseSessionOnErrorInner(int net_error,
@@ -353,18 +424,31 @@ void QuicClientSession::CloseSessionOnErrorInner(int net_error,
if (!callback_.is_null()) {
base::ResetAndReturn(&callback_).Run(net_error);
}
+ CloseAllStreams(net_error);
+ CloseAllObservers(net_error);
+ net_log_.AddEvent(
+ NetLog::TYPE_QUIC_SESSION_CLOSE_ON_ERROR,
+ NetLog::IntegerCallback("net_error", net_error));
+
+ connection()->CloseConnection(quic_error, false);
+ DCHECK(!connection()->connected());
+}
+
+void QuicClientSession::CloseAllStreams(int net_error) {
while (!streams()->empty()) {
ReliableQuicStream* stream = streams()->begin()->second;
QuicStreamId id = stream->id();
static_cast<QuicReliableClientStream*>(stream)->OnError(net_error);
CloseStream(id);
}
- net_log_.AddEvent(
- NetLog::TYPE_QUIC_SESSION_CLOSE_ON_ERROR,
- NetLog::IntegerCallback("net_error", net_error));
+}
- connection()->CloseConnection(quic_error, false);
- DCHECK(!connection()->connected());
+void QuicClientSession::CloseAllObservers(int net_error) {
+ while (!observers_.empty()) {
+ Observer* observer = *observers_.begin();
+ observers_.erase(observer);
+ observer->OnSessionClosed(net_error);
+ }
}
base::Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
@@ -375,6 +459,7 @@ base::Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
dict->SetInteger("total_streams", num_total_streams_);
dict->SetString("peer_address", peer_address().ToString());
dict->SetString("guid", base::Uint64ToString(guid()));
+ dict->SetBoolean("connected", connection()->connected());
return dict;
}
@@ -388,10 +473,11 @@ void QuicClientSession::OnReadComplete(int result) {
result = ERR_CONNECTION_CLOSED;
if (result < 0) {
- DLOG(INFO) << "Closing session on read error: " << result;
+ DVLOG(1) << "Closing session on read error: " << result;
UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.ReadError", -result);
+ NotifyFactoryOfSessionGoingAway();
CloseSessionOnErrorInner(result, QUIC_PACKET_READ_ERROR);
- NotifyFactoryOfSessionCloseLater();
+ NotifyFactoryOfSessionClosedLater();
return;
}
@@ -406,26 +492,31 @@ void QuicClientSession::OnReadComplete(int result) {
// use a weak pointer to be safe.
connection()->ProcessUdpPacket(local_address, peer_address, packet);
if (!connection()->connected()) {
- stream_factory_->OnSessionClose(this);
+ stream_factory_->OnSessionClosed(this);
return;
}
StartReading();
}
-void QuicClientSession::NotifyFactoryOfSessionCloseLater() {
+void QuicClientSession::NotifyFactoryOfSessionGoingAway() {
+ if (stream_factory_)
+ stream_factory_->OnSessionGoingAway(this);
+}
+
+void QuicClientSession::NotifyFactoryOfSessionClosedLater() {
DCHECK_EQ(0u, GetNumOpenStreams());
DCHECK(!connection()->connected());
base::MessageLoop::current()->PostTask(
FROM_HERE,
- base::Bind(&QuicClientSession::NotifyFactoryOfSessionClose,
+ base::Bind(&QuicClientSession::NotifyFactoryOfSessionClosed,
weak_factory_.GetWeakPtr()));
}
-void QuicClientSession::NotifyFactoryOfSessionClose() {
+void QuicClientSession::NotifyFactoryOfSessionClosed() {
DCHECK_EQ(0u, GetNumOpenStreams());
- DCHECK(stream_factory_);
// Will delete |this|.
- stream_factory_->OnSessionClose(this);
+ if (stream_factory_)
+ stream_factory_->OnSessionClosed(this);
}
} // namespace net
diff --git a/chromium/net/quic/quic_client_session.h b/chromium/net/quic/quic_client_session.h
index d167237d809..07da96aa96f 100644
--- a/chromium/net/quic/quic_client_session.h
+++ b/chromium/net/quic/quic_client_session.h
@@ -25,6 +25,7 @@ namespace net {
class DatagramClientSocket;
class QuicConnectionHelper;
class QuicCryptoClientStreamFactory;
+class QuicDefaultPacketWriter;
class QuicStreamFactory;
class SSLInfo;
@@ -34,6 +35,14 @@ class QuicClientSessionPeer;
class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
public:
+ // An interface for observing events on a session.
+ class NET_EXPORT_PRIVATE Observer {
+ public:
+ virtual ~Observer() {}
+ virtual void OnCryptoHandshakeConfirmed() = 0;
+ virtual void OnSessionClosed(int error) = 0;
+ };
+
// A helper class used to manage a request to create a stream.
class NET_EXPORT_PRIVATE StreamRequest {
public:
@@ -44,7 +53,7 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
// |stream| will be updated with the newly created stream. If
// ERR_IO_PENDING is returned, then when the request is eventuallly
// complete |callback| will be called.
- int StartRequest(const base::WeakPtr<QuicClientSession> session,
+ int StartRequest(const base::WeakPtr<QuicClientSession>& session,
QuicReliableClientStream** stream,
const CompletionCallback& callback);
@@ -76,6 +85,7 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
// TODO(rch): decouple the factory from the session via a Delegate interface.
QuicClientSession(QuicConnection* connection,
scoped_ptr<DatagramClientSocket> socket,
+ scoped_ptr<QuicDefaultPacketWriter> writer,
QuicStreamFactory* stream_factory,
QuicCryptoClientStreamFactory* crypto_client_stream_factory,
const std::string& server_hostname,
@@ -85,6 +95,9 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
virtual ~QuicClientSession();
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
// Attempts to create a new stream. If the stream can be
// created immediately, returns OK. If the open stream limit
// has been reached, returns ERR_IO_PENDING, and |request|
@@ -99,7 +112,9 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
void CancelRequest(StreamRequest* request);
// QuicSession methods:
- virtual QuicReliableClientStream* CreateOutgoingReliableStream() OVERRIDE;
+ virtual bool OnStreamFrames(
+ const std::vector<QuicStreamFrame>& frames) OVERRIDE;
+ virtual QuicReliableClientStream* CreateOutgoingDataStream() OVERRIDE;
virtual QuicCryptoClientStream* GetCryptoStream() OVERRIDE;
virtual void CloseStream(QuicStreamId stream_id) OVERRIDE;
virtual void SendRstStream(QuicStreamId id,
@@ -112,7 +127,7 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
// QuicConnectionVisitorInterface methods:
- virtual void ConnectionClose(QuicErrorCode error, bool from_peer) OVERRIDE;
+ virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE;
virtual void OnSuccessfulVersionNegotiation(
const QuicVersion& version) OVERRIDE;
@@ -141,12 +156,12 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
protected:
// QuicSession methods:
- virtual ReliableQuicStream* CreateIncomingReliableStream(
- QuicStreamId id) OVERRIDE;
+ virtual QuicDataStream* CreateIncomingDataStream(QuicStreamId id) OVERRIDE;
private:
friend class test::QuicClientSessionPeer;
+ typedef std::set<Observer*> ObserverSet;
typedef std::list<StreamRequest*> StreamRequestQueue;
QuicReliableClientStream* CreateOutgoingReliableStreamImpl();
@@ -155,26 +170,45 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
void OnClosedStream();
+ // A Session may be closed via any of three methods:
+ // OnConnectionClosed - called by the connection when the connection has been
+ // closed, perhaps due to a timeout or a protocol error.
+ // CloseSessionOnError - called from the owner of the session,
+ // the QuicStreamFactory, when there is an error.
+ // OnReadComplete - when there is a read error.
+ // This method closes all stream and performs any necessary cleanup.
void CloseSessionOnErrorInner(int net_error, QuicErrorCode quic_error);
+ void CloseAllStreams(int net_error);
+ void CloseAllObservers(int net_error);
+
+ // Notifies the factory that this session is going away and no more streams
+ // should be created from it. This needs to be called before closing any
+ // streams, because closing a stream may cause a new stream to be created.
+ void NotifyFactoryOfSessionGoingAway();
+
// Posts a task to notify the factory that this session has been closed.
- void NotifyFactoryOfSessionCloseLater();
+ void NotifyFactoryOfSessionClosedLater();
// Notifies the factory that this session has been closed which will
// delete |this|.
- void NotifyFactoryOfSessionClose();
+ void NotifyFactoryOfSessionClosed();
bool require_confirmation_;
scoped_ptr<QuicCryptoClientStream> crypto_stream_;
QuicStreamFactory* stream_factory_;
scoped_ptr<DatagramClientSocket> socket_;
+ scoped_ptr<QuicDefaultPacketWriter> writer_;
scoped_refptr<IOBufferWithSize> read_buffer_;
+ ObserverSet observers_;
StreamRequestQueue stream_requests_;
bool read_pending_;
CompletionCallback callback_;
size_t num_total_streams_;
BoundNetLog net_log_;
QuicConnectionLogger logger_;
+ // Number of packets read in the current read loop.
+ size_t num_packets_read_;
base::WeakPtrFactory<QuicClientSession> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(QuicClientSession);
diff --git a/chromium/net/quic/quic_client_session_test.cc b/chromium/net/quic/quic_client_session_test.cc
index 385be52a5b9..f0b4dd4ecab 100644
--- a/chromium/net/quic/quic_client_session_test.cc
+++ b/chromium/net/quic/quic_client_session_test.cc
@@ -6,15 +6,18 @@
#include <vector>
+#include "base/rand_util.h"
#include "net/base/capturing_net_log.h"
#include "net/base/test_completion_callback.h"
#include "net/quic/crypto/aes_128_gcm_12_encrypter.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/quic_default_packet_writer.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_client_session_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/socket/socket_test_util.h"
#include "net/udp/datagram_client_socket.h"
using testing::_;
@@ -25,18 +28,62 @@ namespace {
const char kServerHostname[] = "www.example.com";
+class TestPacketWriter : public QuicDefaultPacketWriter {
+ public:
+ TestPacketWriter() {
+ }
+
+ // QuicPacketWriter
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), true);
+ FramerVisitorCapturingFrames visitor;
+ framer.set_visitor(&visitor);
+ QuicEncryptedPacket packet(buffer, buf_len);
+ EXPECT_TRUE(framer.ProcessPacket(packet));
+ header_ = *visitor.header();
+ return WriteResult(WRITE_STATUS_OK, packet.length());
+ }
+
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE {
+ // Chrome sockets' Write() methods buffer the data until the Write is
+ // permitted.
+ return true;
+ }
+
+ // Returns the header from the last packet written.
+ const QuicPacketHeader& header() { return header_; }
+
+ private:
+ QuicPacketHeader header_;
+};
+
class QuicClientSessionTest : public ::testing::Test {
protected:
QuicClientSessionTest()
- : guid_(1),
- connection_(new PacketSavingConnection(guid_, IPEndPoint(), false)),
- session_(connection_, scoped_ptr<DatagramClientSocket>(), NULL,
- NULL, kServerHostname, DefaultQuicConfig(), &crypto_config_,
+ : writer_(new TestPacketWriter()),
+ connection_(new PacketSavingConnection(false)),
+ session_(connection_, GetSocket().Pass(), writer_.Pass(), NULL, NULL,
+ kServerHostname, DefaultQuicConfig(), &crypto_config_,
&net_log_) {
session_.config()->SetDefaults();
crypto_config_.SetDefaults();
}
+ virtual void TearDown() OVERRIDE {
+ session_.CloseSessionOnError(ERR_ABORTED);
+ }
+
+ scoped_ptr<DatagramClientSocket> GetSocket() {
+ socket_factory_.AddSocketDataProvider(&socket_data_);
+ return socket_factory_.CreateDatagramClientSocket(
+ DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt),
+ &net_log_, NetLog::Source());
+ }
+
void CompleteCryptoHandshake() {
ASSERT_EQ(ERR_IO_PENDING,
session_.CryptoConnect(false, callback_.callback()));
@@ -45,9 +92,11 @@ class QuicClientSessionTest : public ::testing::Test {
ASSERT_EQ(OK, callback_.WaitForResult());
}
- QuicGuid guid_;
+ scoped_ptr<QuicDefaultPacketWriter> writer_;
PacketSavingConnection* connection_;
CapturingNetLog net_log_;
+ MockClientSocketFactory socket_factory_;
+ StaticSocketDataProvider socket_data_;
QuicClientSession session_;
MockClock clock_;
MockRandom random_;
@@ -57,46 +106,31 @@ class QuicClientSessionTest : public ::testing::Test {
};
TEST_F(QuicClientSessionTest, CryptoConnect) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
}
TEST_F(QuicClientSessionTest, MaxNumStreams) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
std::vector<QuicReliableClientStream*> streams;
for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
- QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream();
+ QuicReliableClientStream* stream = session_.CreateOutgoingDataStream();
EXPECT_TRUE(stream);
streams.push_back(stream);
}
- EXPECT_FALSE(session_.CreateOutgoingReliableStream());
+ EXPECT_FALSE(session_.CreateOutgoingDataStream());
// Close a stream and ensure I can now open a new one.
session_.CloseStream(streams[0]->id());
- EXPECT_TRUE(session_.CreateOutgoingReliableStream());
+ EXPECT_TRUE(session_.CreateOutgoingDataStream());
}
TEST_F(QuicClientSessionTest, MaxNumStreamsViaRequest) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
std::vector<QuicReliableClientStream*> streams;
for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
- QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream();
+ QuicReliableClientStream* stream = session_.CreateOutgoingDataStream();
EXPECT_TRUE(stream);
streams.push_back(stream);
}
@@ -116,17 +150,12 @@ TEST_F(QuicClientSessionTest, MaxNumStreamsViaRequest) {
}
TEST_F(QuicClientSessionTest, GoAwayReceived) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
// After receiving a GoAway, I should no longer be able to create outgoing
// streams.
session_.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away."));
- EXPECT_EQ(NULL, session_.CreateOutgoingReliableStream());
+ EXPECT_EQ(NULL, session_.CreateOutgoingDataStream());
}
} // namespace
diff --git a/chromium/net/quic/quic_config.cc b/chromium/net/quic/quic_config.cc
index 545d4c165e4..152da46a80f 100644
--- a/chromium/net/quic/quic_config.cc
+++ b/chromium/net/quic/quic_config.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/logging.h"
+#include "net/quic/quic_sent_packet_manager.h"
using std::string;
@@ -19,7 +20,9 @@ QuicNegotiableValue::QuicNegotiableValue(QuicTag tag, Presence presence)
}
QuicNegotiableUint32::QuicNegotiableUint32(QuicTag tag, Presence presence)
- : QuicNegotiableValue(tag, presence) {
+ : QuicNegotiableValue(tag, presence),
+ max_value_(0),
+ default_value_(0) {
}
void QuicNegotiableUint32::set(uint32 max, uint32 default_value) {
@@ -108,7 +111,9 @@ QuicErrorCode QuicNegotiableUint32::ProcessServerHello(
}
QuicNegotiableTag::QuicNegotiableTag(QuicTag tag, Presence presence)
- : QuicNegotiableValue(tag, presence) {
+ : QuicNegotiableValue(tag, presence),
+ negotiated_tag_(0),
+ default_value_(0) {
}
QuicNegotiableTag::~QuicNegotiableTag() {}
@@ -224,9 +229,13 @@ QuicConfig::QuicConfig() :
kICSL, QuicNegotiableValue::PRESENCE_REQUIRED),
keepalive_timeout_seconds_(kKATO, QuicNegotiableValue::PRESENCE_OPTIONAL),
max_streams_per_connection_(kMSPC, QuicNegotiableValue::PRESENCE_REQUIRED),
- max_time_before_crypto_handshake_(QuicTime::Delta::Zero()) {
- idle_connection_state_lifetime_seconds_.set(0, 0);
- keepalive_timeout_seconds_.set(0, 0);
+ max_time_before_crypto_handshake_(QuicTime::Delta::Zero()),
+ server_initial_congestion_window_(
+ kSWND, QuicNegotiableValue::PRESENCE_OPTIONAL),
+ initial_round_trip_time_us_(kIRTT, QuicNegotiableValue::PRESENCE_OPTIONAL) {
+ // All optional non-zero parameters should be initialized here.
+ server_initial_congestion_window_.set(kMaxInitialWindow,
+ kDefaultInitialWindow);
}
QuicConfig::~QuicConfig() {}
@@ -277,15 +286,44 @@ QuicTime::Delta QuicConfig::max_time_before_crypto_handshake() const {
return max_time_before_crypto_handshake_;
}
+void QuicConfig::set_server_initial_congestion_window(size_t max_initial_window,
+ size_t default_initial_window) {
+ server_initial_congestion_window_.set(max_initial_window,
+ default_initial_window);
+}
+
+uint32 QuicConfig::server_initial_congestion_window() const {
+ return server_initial_congestion_window_.GetUint32();
+}
+
+void QuicConfig::set_initial_round_trip_time_us(size_t max_rtt,
+ size_t default_rtt) {
+ initial_round_trip_time_us_.set(max_rtt, default_rtt);
+}
+
+uint32 QuicConfig::initial_round_trip_time_us() const {
+ return initial_round_trip_time_us_.GetUint32();
+}
+
bool QuicConfig::negotiated() {
+ // TODO(ianswett): Add the negotiated parameters once and iterate over all
+ // of them in negotiated, ToHandshakeMessage, ProcessClientHello, and
+ // ProcessServerHello.
return congestion_control_.negotiated() &&
idle_connection_state_lifetime_seconds_.negotiated() &&
keepalive_timeout_seconds_.negotiated() &&
- max_streams_per_connection_.negotiated();
+ max_streams_per_connection_.negotiated() &&
+ server_initial_congestion_window_.negotiated() &&
+ initial_round_trip_time_us_.negotiated();
}
void QuicConfig::SetDefaults() {
- congestion_control_.set(QuicTagVector(1, kQBIC), kQBIC);
+ QuicTagVector congestion_control;
+ if (FLAGS_enable_quic_pacing) {
+ congestion_control.push_back(kPACE);
+ }
+ congestion_control.push_back(kQBIC);
+ congestion_control_.set(congestion_control, kQBIC);
idle_connection_state_lifetime_seconds_.set(kDefaultTimeoutSecs,
kDefaultInitialTimeoutSecs);
// kKATO is optional. Return 0 if not negotiated.
@@ -294,6 +332,8 @@ void QuicConfig::SetDefaults() {
kDefaultMaxStreamsPerConnection);
max_time_before_crypto_handshake_ = QuicTime::Delta::FromSeconds(
kDefaultMaxTimeForCryptoHandshakeSecs);
+ server_initial_congestion_window_.set(kDefaultInitialWindow,
+ kDefaultInitialWindow);
}
void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
@@ -301,6 +341,9 @@ void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
idle_connection_state_lifetime_seconds_.ToHandshakeMessage(out);
keepalive_timeout_seconds_.ToHandshakeMessage(out);
max_streams_per_connection_.ToHandshakeMessage(out);
+ server_initial_congestion_window_.ToHandshakeMessage(out);
+ // TODO(ianswett): Don't transmit parameters which are optional and not set.
+ initial_round_trip_time_us_.ToHandshakeMessage(out);
}
QuicErrorCode QuicConfig::ProcessClientHello(
@@ -324,6 +367,14 @@ QuicErrorCode QuicConfig::ProcessClientHello(
error = max_streams_per_connection_.ProcessClientHello(
client_hello, error_details);
}
+ if (error == QUIC_NO_ERROR) {
+ error = server_initial_congestion_window_.ProcessClientHello(
+ client_hello, error_details);
+ }
+ if (error == QUIC_NO_ERROR) {
+ error = initial_round_trip_time_us_.ProcessClientHello(
+ client_hello, error_details);
+ }
return error;
}
@@ -348,8 +399,15 @@ QuicErrorCode QuicConfig::ProcessServerHello(
error = max_streams_per_connection_.ProcessServerHello(
server_hello, error_details);
}
+ if (error == QUIC_NO_ERROR) {
+ error = server_initial_congestion_window_.ProcessServerHello(
+ server_hello, error_details);
+ }
+ if (error == QUIC_NO_ERROR) {
+ error = initial_round_trip_time_us_.ProcessServerHello(
+ server_hello, error_details);
+ }
return error;
}
} // namespace net
-
diff --git a/chromium/net/quic/quic_config.h b/chromium/net/quic/quic_config.h
index c07f332ac6f..6c0561b1ca4 100644
--- a/chromium/net/quic/quic_config.h
+++ b/chromium/net/quic/quic_config.h
@@ -9,7 +9,6 @@
#include "base/basictypes.h"
#include "net/quic/crypto/crypto_handshake.h"
-#include "net/quic/crypto/crypto_utils.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
#include "net/quic/quic_utils.h"
@@ -41,6 +40,7 @@ class NET_EXPORT_PRIVATE QuicNegotiableValue {
class NET_EXPORT_PRIVATE QuicNegotiableUint32 : public QuicNegotiableValue {
public:
+ // Default and max values default to 0.
QuicNegotiableUint32(QuicTag name, Presence presence);
// Sets the maximum possible value that can be achieved after negotiation and
@@ -159,6 +159,18 @@ class NET_EXPORT_PRIVATE QuicConfig {
QuicTime::Delta max_time_before_crypto_handshake() const;
+ // Sets the server's TCP sender's max and default initial congestion window
+ // in packets.
+ void set_server_initial_congestion_window(size_t max_initial_window,
+ size_t default_initial_window);
+
+ uint32 server_initial_congestion_window() const;
+
+ // Sets an estimated initial round trip time in us.
+ void set_initial_round_trip_time_us(size_t max_rtt, size_t default_rtt);
+
+ uint32 initial_round_trip_time_us() const;
+
bool negotiated();
// SetDefaults sets the members to sensible, default values.
@@ -190,6 +202,10 @@ class NET_EXPORT_PRIVATE QuicConfig {
// Maximum time till the session can be alive before crypto handshake is
// finished. (Not negotiated).
QuicTime::Delta max_time_before_crypto_handshake_;
+ // Initial congestion window in packets.
+ QuicNegotiableUint32 server_initial_congestion_window_;
+ // Initial round trip time estimate in microseconds.
+ QuicNegotiableUint32 initial_round_trip_time_us_;
};
} // namespace net
diff --git a/chromium/net/quic/quic_config_test.cc b/chromium/net/quic/quic_config_test.cc
index eeaa97deaab..2434cd772fd 100644
--- a/chromium/net/quic/quic_config_test.cc
+++ b/chromium/net/quic/quic_config_test.cc
@@ -7,7 +7,9 @@
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_sent_packet_manager.h"
#include "net/quic/quic_time.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
using std::string;
@@ -20,12 +22,15 @@ class QuicConfigTest : public ::testing::Test {
protected:
QuicConfigTest() {
config_.SetDefaults();
+ config_.set_initial_round_trip_time_us(kMaxInitialRoundTripTimeUs, 0);
}
QuicConfig config_;
};
TEST_F(QuicConfigTest, ToHandshakeMessage) {
+ FLAGS_enable_quic_pacing = false;
+ config_.SetDefaults();
config_.set_idle_connection_state_lifetime(QuicTime::Delta::FromSeconds(5),
QuicTime::Delta::FromSeconds(2));
config_.set_max_streams_per_connection(4, 2);
@@ -48,6 +53,21 @@ TEST_F(QuicConfigTest, ToHandshakeMessage) {
EXPECT_EQ(kQBIC, *out);
}
+TEST_F(QuicConfigTest, ToHandshakeMessageWithPacing) {
+ ValueRestore<bool> old_flag(&FLAGS_enable_quic_pacing, true);
+
+ config_.SetDefaults();
+ CryptoHandshakeMessage msg;
+ config_.ToHandshakeMessage(&msg);
+
+ const QuicTag* out;
+ size_t out_len;
+ EXPECT_EQ(QUIC_NO_ERROR, msg.GetTaglist(kCGST, &out, &out_len));
+ EXPECT_EQ(2u, out_len);
+ EXPECT_EQ(kPACE, out[0]);
+ EXPECT_EQ(kQBIC, out[1]);
+}
+
TEST_F(QuicConfigTest, ProcessClientHello) {
QuicConfig client_config;
QuicTagVector cgst;
@@ -59,6 +79,9 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
QuicTime::Delta::FromSeconds(kDefaultTimeoutSecs));
client_config.set_max_streams_per_connection(
2 * kDefaultMaxStreamsPerConnection, kDefaultMaxStreamsPerConnection);
+ client_config.set_initial_round_trip_time_us(
+ 10 * base::Time::kMicrosecondsPerMillisecond,
+ 10 * base::Time::kMicrosecondsPerMillisecond);
CryptoHandshakeMessage msg;
client_config.ToHandshakeMessage(&msg);
@@ -72,6 +95,8 @@ TEST_F(QuicConfigTest, ProcessClientHello) {
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
config_.max_streams_per_connection());
EXPECT_EQ(QuicTime::Delta::FromSeconds(0), config_.keepalive_timeout());
+ EXPECT_EQ(10 * base::Time::kMicrosecondsPerMillisecond,
+ config_.initial_round_trip_time_us());
}
TEST_F(QuicConfigTest, ProcessServerHello) {
@@ -85,6 +110,11 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
server_config.set_max_streams_per_connection(
kDefaultMaxStreamsPerConnection / 2,
kDefaultMaxStreamsPerConnection / 2);
+ server_config.set_server_initial_congestion_window(kDefaultInitialWindow / 2,
+ kDefaultInitialWindow / 2);
+ server_config.set_initial_round_trip_time_us(
+ 10 * base::Time::kMicrosecondsPerMillisecond,
+ 10 * base::Time::kMicrosecondsPerMillisecond);
CryptoHandshakeMessage msg;
server_config.ToHandshakeMessage(&msg);
@@ -97,7 +127,11 @@ TEST_F(QuicConfigTest, ProcessServerHello) {
config_.idle_connection_state_lifetime());
EXPECT_EQ(kDefaultMaxStreamsPerConnection / 2,
config_.max_streams_per_connection());
+ EXPECT_EQ(kDefaultInitialWindow / 2,
+ config_.server_initial_congestion_window());
EXPECT_EQ(QuicTime::Delta::FromSeconds(0), config_.keepalive_timeout());
+ EXPECT_EQ(10 * base::Time::kMicrosecondsPerMillisecond,
+ config_.initial_round_trip_time_us());
}
TEST_F(QuicConfigTest, MissingValueInCHLO) {
diff --git a/chromium/net/quic/quic_connection.cc b/chromium/net/quic/quic_connection.cc
index 7417bd435a1..51a83cc41a0 100644
--- a/chromium/net/quic/quic_connection.cc
+++ b/chromium/net/quic/quic_connection.cc
@@ -4,12 +4,23 @@
#include "net/quic/quic_connection.h"
+#include <string.h>
+#include <sys/types.h>
#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <set>
+#include <utility>
#include "base/logging.h"
#include "base/stl_util.h"
+#include "net/base/net_errors.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/iovector.h"
+#include "net/quic/quic_bandwidth.h"
+#include "net/quic/quic_config.h"
#include "net/quic/quic_utils.h"
using base::hash_map;
@@ -24,27 +35,24 @@ using std::vector;
using std::set;
using std::string;
+int FLAGS_fake_packet_loss_percentage = 0;
+
+// If true, then QUIC connections will bundle acks with any outgoing packet when
+// an ack is being delayed. This is an optimization to reduce ack latency and
+// packet count of pure ack packets.
+bool FLAGS_bundle_ack_with_outgoing_packet = false;
+
namespace net {
+
+class QuicDecrypter;
+class QuicEncrypter;
+
namespace {
// The largest gap in packets we'll accept without closing the connection.
// This will likely have to be tuned.
const QuicPacketSequenceNumber kMaxPacketGap = 5000;
-// We want to make sure if we get a large nack packet, we don't queue up too
-// many packets at once. 10 is arbitrary.
-const size_t kMaxRetransmissionsPerAck = 10;
-
-// TCP retransmits after 2 nacks. We allow for a third in case of out-of-order
-// delivery.
-// TODO(ianswett): Change to match TCP's rule of retransmitting once an ack
-// at least 3 sequence numbers larger arrives.
-const size_t kNumberOfNacksBeforeRetransmission = 3;
-
-// Limit the number of packets we send per retransmission-alarm so we
-// eventually cede. 10 is arbitrary.
-const size_t kMaxPacketsPerRetransmissionAlarm = 10;
-
// 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;
@@ -85,7 +93,8 @@ class RetransmissionAlarm : public QuicAlarm::Delegate {
}
virtual QuicTime OnAlarm() OVERRIDE {
- return connection_->OnRetransmissionTimeout();
+ connection_->OnRetransmissionTimeout();
+ return QuicTime::Zero();
}
private:
@@ -101,7 +110,7 @@ class SendAlarm : public QuicAlarm::Delegate {
}
virtual QuicTime OnAlarm() OVERRIDE {
- connection_->OnCanWrite();
+ connection_->WriteIfNotBlocked();
// Never reschedule the alarm, since OnCanWrite does that.
return QuicTime::Zero();
}
@@ -127,7 +136,7 @@ class TimeoutAlarm : public QuicAlarm::Delegate {
};
// Indicates if any of the frames are intended to be sent with FORCE.
-// Returns true when one of the frames is a CONNECTION_CLOSE_FRAME.
+// Returns FORCE when one of the frames is a CONNECTION_CLOSE_FRAME.
net::QuicConnection::Force HasForcedFrames(
const RetransmittableFrames* retransmittable_frames) {
if (!retransmittable_frames) {
@@ -141,38 +150,49 @@ net::QuicConnection::Force HasForcedFrames(
return net::QuicConnection::NO_FORCE;
}
-} // namespace
+net::IsHandshake HasCryptoHandshake(
+ const RetransmittableFrames* retransmittable_frames) {
+ if (!retransmittable_frames) {
+ return net::NOT_HANDSHAKE;
+ }
+ for (size_t i = 0; i < retransmittable_frames->frames().size(); ++i) {
+ if (retransmittable_frames->frames()[i].type == STREAM_FRAME &&
+ retransmittable_frames->frames()[i].stream_frame->stream_id ==
+ kCryptoStreamId) {
+ return net::IS_HANDSHAKE;
+ }
+ }
+ return net::NOT_HANDSHAKE;
+}
-// TODO(rch): Remove this.
-// Because of a bug in the interaction between the TcpCubicSender and
-// QuicConnection, acks currently count against the congestion window.
-// This means that if acks are not acked, and data is only flowing in
-// one direction, then the connection will deadlock.
-// static
-bool QuicConnection::g_acks_do_not_instigate_acks = false;
+} // namespace
#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
QuicConnection::QuicConnection(QuicGuid guid,
IPEndPoint address,
QuicConnectionHelperInterface* helper,
+ QuicPacketWriter* writer,
bool is_server,
- QuicVersion version)
- : framer_(version,
+ const QuicVersionVector& supported_versions)
+ : framer_(supported_versions,
helper->GetClock()->ApproximateNow(),
is_server),
helper_(helper),
+ writer_(writer),
encryption_level_(ENCRYPTION_NONE),
clock_(helper->GetClock()),
random_generator_(helper->GetRandomGenerator()),
guid_(guid),
peer_address_(address),
largest_seen_packet_with_ack_(0),
- handling_retransmission_timeout_(false),
+ pending_version_negotiation_packet_(false),
write_blocked_(false),
+ received_packet_manager_(kTCP),
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))),
debug_visitor_(NULL),
packet_creator_(guid_, &framer_, random_generator_, is_server),
@@ -183,31 +203,23 @@ QuicConnection::QuicConnection(QuicGuid guid,
creation_time_(clock_->ApproximateNow()),
time_of_last_received_packet_(clock_->ApproximateNow()),
time_of_last_sent_packet_(clock_->ApproximateNow()),
- congestion_manager_(clock_, kTCP),
- sent_packet_manager_(is_server, this),
+ sequence_number_of_last_inorder_packet_(0),
+ sent_packet_manager_(is_server, this, clock_, kTCP),
version_negotiation_state_(START_NEGOTIATION),
- max_packets_per_retransmission_alarm_(kMaxPacketsPerRetransmissionAlarm),
is_server_(is_server),
connected_(true),
- received_truncated_ack_(false),
- send_ack_in_response_to_packet_(false),
address_migrating_(false) {
- helper_->SetConnection(this);
+ if (!is_server_) {
+ // Pacing will be enabled if the client negotiates it.
+ sent_packet_manager_.MaybeEnablePacing();
+ }
+ DVLOG(1) << ENDPOINT << "Created connection with guid: " << guid;
timeout_alarm_->Set(clock_->ApproximateNow().Add(idle_network_timeout_));
framer_.set_visitor(this);
framer_.set_received_entropy_calculator(&received_packet_manager_);
-
- /*
- if (FLAGS_fake_packet_loss_percentage > 0) {
- int32 seed = RandomBase::WeakSeed32();
- LOG(INFO) << ENDPOINT << "Seeding packet loss with " << seed;
- random_.reset(new MTRandom(seed));
- }
- */
}
QuicConnection::~QuicConnection() {
- STLDeleteElements(&ack_notifiers_);
STLDeleteElements(&undecryptable_packets_);
STLDeleteValues(&group_map_);
for (QueuedPacketList::iterator it = queued_packets_.begin();
@@ -216,13 +228,21 @@ QuicConnection::~QuicConnection() {
}
}
+void QuicConnection::SetFromConfig(const QuicConfig& config) {
+ DCHECK_LT(0u, config.server_initial_congestion_window());
+ SetIdleNetworkTimeout(config.idle_connection_state_lifetime());
+ sent_packet_manager_.SetFromConfig(config);
+ // TODO(satyamshekhar): Set congestion control and ICSL also.
+}
+
bool QuicConnection::SelectMutualVersion(
const QuicVersionVector& available_versions) {
// Try to find the highest mutual version by iterating over supported
// versions, starting with the highest, and breaking out of the loop once we
// find a matching version in the provided available_versions vector.
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- const QuicVersion& version = kSupportedQuicVersions[i];
+ const QuicVersionVector& supported_versions = framer_.supported_versions();
+ for (size_t i = 0; i < supported_versions.size(); ++i) {
+ const QuicVersion& version = supported_versions[i];
if (std::find(available_versions.begin(), available_versions.end(),
version) != available_versions.end()) {
framer_.set_version(version);
@@ -239,7 +259,7 @@ void QuicConnection::OnError(QuicFramer* framer) {
if (!connected_ || framer->error() == QUIC_DECRYPTION_FAILURE) {
return;
}
- SendConnectionClose(framer->error());
+ SendConnectionCloseWithDetails(framer->error(), framer->detailed_error());
}
void QuicConnection::OnPacket() {
@@ -259,6 +279,8 @@ void QuicConnection::OnPublicResetPacket(
}
bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
+ DVLOG(1) << ENDPOINT << "Received packet with mismatched version "
+ << received_version;
// TODO(satyamshekhar): Implement no server state in this mode.
if (!is_server_) {
LOG(DFATAL) << ENDPOINT << "Framer called OnProtocolVersionMismatch. "
@@ -283,7 +305,7 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
case NEGOTIATION_IN_PROGRESS:
if (!framer_.IsSupportedVersion(received_version)) {
- // Drop packets which can't be parsed due to version mismatch.
+ SendVersionNegotiationPacket();
return false;
}
break;
@@ -299,6 +321,7 @@ bool QuicConnection::OnProtocolVersionMismatch(QuicVersion received_version) {
version_negotiation_state_ = NEGOTIATED_VERSION;
visitor_->OnSuccessfulVersionNegotiation(received_version);
+ DVLOG(1) << ENDPOINT << "version negotiated " << received_version;
// Store the new version.
framer_.set_version(received_version);
@@ -343,6 +366,8 @@ void QuicConnection::OnVersionNegotiationPacket(
return;
}
+ DVLOG(1) << ENDPOINT << "negotiating version " << version();
+ server_supported_versions_ = packet.versions;
version_negotiation_state_ = NEGOTIATION_IN_PROGRESS;
RetransmitUnackedPackets(ALL_PACKETS);
}
@@ -350,6 +375,10 @@ void QuicConnection::OnVersionNegotiationPacket(
void QuicConnection::OnRevivedPacket() {
}
+bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
+ return true;
+}
+
bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
if (debug_visitor_) {
debug_visitor_->OnPacketHeader(header);
@@ -363,14 +392,14 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
++stats_.packets_dropped;
if (header.public_header.guid != guid_) {
- DLOG(INFO) << ENDPOINT << "Ignoring packet from unexpected GUID: "
+ DVLOG(1) << ENDPOINT << "Ignoring packet from unexpected GUID: "
<< header.public_header.guid << " instead of " << guid_;
return false;
}
if (!Near(header.packet_sequence_number,
last_header_.packet_sequence_number)) {
- DLOG(INFO) << ENDPOINT << "Packet " << header.packet_sequence_number
+ DVLOG(1) << ENDPOINT << "Packet " << header.packet_sequence_number
<< " out of bounds. Discarding";
SendConnectionCloseWithDetails(QUIC_INVALID_PACKET_HEADER,
"Packet sequence number out of bounds");
@@ -444,7 +473,7 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
DVLOG(1) << ENDPOINT << "OnAckFrame: " << incoming_ack;
if (last_header_.packet_sequence_number <= largest_seen_packet_with_ack_) {
- DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
+ DVLOG(1) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
@@ -453,16 +482,6 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
return false;
}
- // Reset the RTO timeout for each packet when an ack is received.
- if (retransmission_alarm_->IsSet()) {
- retransmission_alarm_->Cancel();
- QuicTime::Delta retransmission_delay =
- congestion_manager_.GetRetransmissionDelay(
- sent_packet_manager_.GetNumUnackedPackets(), 0);
- retransmission_alarm_->Set(clock_->ApproximateNow().Add(
- retransmission_delay));
- }
-
last_ack_frames_.push_back(incoming_ack);
return connected_;
}
@@ -470,10 +489,6 @@ bool QuicConnection::OnAckFrame(const QuicAckFrame& incoming_ack) {
void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
largest_seen_packet_with_ack_ = last_header_.packet_sequence_number;
- received_truncated_ack_ =
- incoming_ack.received_info.missing_packets.size() >=
- QuicFramer::GetMaxUnackedPackets(last_header_);
-
received_packet_manager_.UpdatePacketInformationReceivedByPeer(incoming_ack);
received_packet_manager_.UpdatePacketInformationSentByPeer(incoming_ack);
// Possibly close any FecGroups which are now irrelevant.
@@ -482,37 +497,23 @@ void QuicConnection::ProcessAckFrame(const QuicAckFrame& incoming_ack) {
sent_entropy_manager_.ClearEntropyBefore(
received_packet_manager_.least_packet_awaited_by_peer() - 1);
- retransmitted_nacked_packet_count_ = 0;
- SequenceNumberSet acked_packets;
- sent_packet_manager_.HandleAckForSentPackets(incoming_ack, &acked_packets);
- sent_packet_manager_.HandleAckForSentFecPackets(incoming_ack, &acked_packets);
- if (acked_packets.size() > 0) {
- // Inform all the registered AckNotifiers of the new ACKs.
- // TODO(rjshade): Make this more efficient by maintaining a mapping of
- // <sequence number, set<AckNotifierList>> so that OnAck
- // is only called on AckNotifiers that care about the
- // packets being ACKed.
- AckNotifierList::iterator it = ack_notifiers_.begin();
- while (it != ack_notifiers_.end()) {
- if ((*it)->OnAck(acked_packets)) {
- // The QuicAckNotifier has seen all the ACKs it was interested in, and
- // has triggered its callback. No more use for it.
- delete *it;
- it = ack_notifiers_.erase(it);
- } else {
- ++it;
- }
- }
+ bool reset_retransmission_alarm =
+ sent_packet_manager_.OnIncomingAck(incoming_ack.received_info,
+ time_of_last_received_packet_);
+ if (sent_packet_manager_.HasPendingRetransmissions()) {
+ WriteIfNotBlocked();
}
- // Clear the earliest retransmission timeouts that are no longer unacked to
- // ensure the priority queue doesn't become too large.
- while (!retransmission_timeouts_.empty() &&
- !sent_packet_manager_.IsUnacked(
- retransmission_timeouts_.top().sequence_number)) {
- retransmission_timeouts_.pop();
+
+ if (reset_retransmission_alarm) {
+ retransmission_alarm_->Cancel();
+ // Reset the RTO and FEC alarms if the are unacked packets.
+ if (sent_packet_manager_.HasUnackedPackets()) {
+ QuicTime::Delta retransmission_delay =
+ sent_packet_manager_.GetRetransmissionDelay();
+ retransmission_alarm_->Set(
+ clock_->ApproximateNow().Add(retransmission_delay));
+ }
}
- congestion_manager_.OnIncomingAckFrame(incoming_ack,
- time_of_last_received_packet_);
}
bool QuicConnection::OnCongestionFeedbackFrame(
@@ -545,11 +546,6 @@ bool QuicConnection::ValidateAckFrame(const QuicAckFrame& incoming_ack) {
return false;
}
- // We can't have too many unacked packets, or our ack frames go over
- // kMaxPacketSize.
- DCHECK_LE(incoming_ack.received_info.missing_packets.size(),
- QuicFramer::GetMaxUnackedPackets(last_header_));
-
if (incoming_ack.sent_info.least_unacked <
received_packet_manager_.peer_least_packet_awaiting_ack()) {
DLOG(ERROR) << ENDPOINT << "Peer's sent low least_unacked: "
@@ -614,7 +610,7 @@ bool QuicConnection::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
if (debug_visitor_) {
debug_visitor_->OnRstStreamFrame(frame);
}
- DLOG(INFO) << ENDPOINT << "Stream reset with error "
+ DVLOG(1) << ENDPOINT << "Stream reset with error "
<< QuicUtils::StreamErrorToString(frame.error_code);
last_rst_frames_.push_back(frame);
return connected_;
@@ -626,17 +622,16 @@ bool QuicConnection::OnConnectionCloseFrame(
if (debug_visitor_) {
debug_visitor_->OnConnectionCloseFrame(frame);
}
- DLOG(INFO) << ENDPOINT << "Connection closed with error "
+ DVLOG(1) << ENDPOINT << "Connection " << guid() << " closed with error "
<< QuicUtils::ErrorToString(frame.error_code)
<< " " << frame.error_details;
- CloseConnection(frame.error_code, true);
- DCHECK(!connected_);
- return false;
+ last_close_frames_.push_back(frame);
+ return connected_;
}
bool QuicConnection::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
DCHECK(connected_);
- DLOG(INFO) << ENDPOINT << "Go away received with error "
+ DVLOG(1) << ENDPOINT << "Go away received with error "
<< QuicUtils::ErrorToString(frame.error_code)
<< " and reason:" << frame.reason_phrase;
last_goaway_frames_.push_back(frame);
@@ -650,28 +645,36 @@ void QuicConnection::OnPacketComplete() {
return;
}
- DLOG(INFO) << ENDPOINT << (last_packet_revived_ ? "Revived" : "Got")
+ DVLOG(1) << ENDPOINT << (last_packet_revived_ ? "Revived" : "Got")
<< " packet " << last_header_.packet_sequence_number
<< " with " << last_ack_frames_.size() << " acks, "
<< last_congestion_frames_.size() << " congestions, "
<< last_goaway_frames_.size() << " goaways, "
<< last_rst_frames_.size() << " rsts, "
+ << last_close_frames_.size() << " closes, "
<< last_stream_frames_.size()
<< " stream frames for " << last_header_.public_header.guid;
- if (!last_packet_revived_) {
- congestion_manager_.RecordIncomingPacket(
- last_size_, last_header_.packet_sequence_number,
- time_of_last_received_packet_, last_packet_revived_);
- }
// Must called before ack processing, because processing acks removes entries
// from unacket_packets_, increasing the least_unacked.
const bool last_packet_should_instigate_ack = ShouldLastPacketInstigateAck();
+ // If the incoming packet was missing, send an ack immediately.
+ bool send_ack_immediately = received_packet_manager_.IsMissing(
+ last_header_.packet_sequence_number);
+
+ // Ensure the visitor can process the stream frames before recording and
+ // processing the rest of the packet.
if (last_stream_frames_.empty() ||
visitor_->OnStreamFrames(last_stream_frames_)) {
- received_packet_manager_.RecordPacketReceived(
- last_header_, time_of_last_received_packet_);
+ received_packet_manager_.RecordPacketReceived(last_size_,
+ last_header_,
+ time_of_last_received_packet_,
+ last_packet_revived_);
+ for (size_t i = 0; i < last_stream_frames_.size(); ++i) {
+ stats_.stream_bytes_received +=
+ last_stream_frames_[i].data.TotalBufferSize();
+ }
}
// Process stream resets, then acks, then congestion feedback.
@@ -685,11 +688,21 @@ void QuicConnection::OnPacketComplete() {
ProcessAckFrame(last_ack_frames_[i]);
}
for (size_t i = 0; i < last_congestion_frames_.size(); ++i) {
- congestion_manager_.OnIncomingQuicCongestionFeedbackFrame(
+ sent_packet_manager_.OnIncomingQuicCongestionFeedbackFrame(
last_congestion_frames_[i], time_of_last_received_packet_);
}
+ if (!last_close_frames_.empty()) {
+ CloseConnection(last_close_frames_[0].error_code, true);
+ DCHECK(!connected_);
+ }
- MaybeSendInResponseToPacket(last_packet_should_instigate_ack);
+ // If there are new missing packets to report, send an ack immediately.
+ if (received_packet_manager_.HasNewMissingPackets()) {
+ send_ack_immediately = true;
+ }
+
+ MaybeSendInResponseToPacket(send_ack_immediately,
+ last_packet_should_instigate_ack);
ClearLastFrames();
}
@@ -726,8 +739,7 @@ bool QuicConnection::ShouldLastPacketInstigateAck() {
// longer planning to send, we should send an ack to raise
// the high water mark.
if (!last_ack_frames_.empty() &&
- !last_ack_frames_.back().received_info.missing_packets.empty() &&
- sent_packet_manager_.HasUnackedPackets()) {
+ !last_ack_frames_.back().received_info.missing_packets.empty()) {
return sent_packet_manager_.GetLeastUnackedSentPacket() >
*last_ack_frames_.back().received_info.missing_packets.begin();
}
@@ -735,27 +747,29 @@ bool QuicConnection::ShouldLastPacketInstigateAck() {
}
void QuicConnection::MaybeSendInResponseToPacket(
+ bool send_ack_immediately,
bool last_packet_should_instigate_ack) {
- packet_generator_.StartBatchOperations();
-
- if (last_packet_should_instigate_ack ||
- !g_acks_do_not_instigate_acks) {
- if (send_ack_in_response_to_packet_) {
+ // |include_ack| is false since we decide about ack bundling below.
+ ScopedPacketBundler bundler(this, false);
+
+ if (last_packet_should_instigate_ack) {
+ // In general, we ack every second packet. When we don't ack the first
+ // packet, we set the delayed ack alarm. Thus, if the ack alarm is set
+ // then we know this is the second packet, and we should send an ack.
+ if (send_ack_immediately || ack_alarm_->IsSet()) {
SendAck();
- } else if (last_packet_should_instigate_ack) {
- // Set the ack alarm for when any retransmittable frame is received.
- if (!ack_alarm_->IsSet()) {
- ack_alarm_->Set(clock_->ApproximateNow().Add(
- congestion_manager_.DelayedAckTime()));
- }
+ DCHECK(!ack_alarm_->IsSet());
+ } else {
+ ack_alarm_->Set(clock_->ApproximateNow().Add(
+ sent_packet_manager_.DelayedAckTime()));
+ DVLOG(1) << "Ack timer set; next packet or timer will trigger ACK.";
}
- send_ack_in_response_to_packet_ = !send_ack_in_response_to_packet_;
}
if (!last_ack_frames_.empty()) {
// Now the we have received an ack, we might be able to send packets which
// are queued locally, or drain streams which are blocked.
- QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
+ QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(
time_of_last_received_packet_, NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA, NOT_HANDSHAKE);
if (delay.IsZero()) {
@@ -766,108 +780,58 @@ void QuicConnection::MaybeSendInResponseToPacket(
send_alarm_->Set(time_of_last_received_packet_.Add(delay));
}
}
- packet_generator_.FinishBatchOperations();
}
void QuicConnection::SendVersionNegotiationPacket() {
- QuicVersionVector supported_versions;
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- supported_versions.push_back(kSupportedQuicVersions[i]);
- }
- QuicEncryptedPacket* encrypted =
- packet_creator_.SerializeVersionNegotiationPacket(supported_versions);
+ scoped_ptr<QuicEncryptedPacket> version_packet(
+ packet_creator_.SerializeVersionNegotiationPacket(
+ framer_.supported_versions()));
// TODO(satyamshekhar): implement zero server state negotiation.
- int error;
- helper_->WritePacketToWire(*encrypted, &error);
- delete encrypted;
-}
-
-QuicConsumedData QuicConnection::SendvStreamDataInner(
- QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin,
- QuicAckNotifier* notifier) {
- // TODO(ianswett): Further improve sending by passing the iovec down
- // instead of batching into multiple stream frames in a single packet.
- const bool already_in_batch_mode = packet_generator_.InBatchMode();
- packet_generator_.StartBatchOperations();
-
- size_t bytes_written = 0;
- bool fin_consumed = false;
-
- for (int i = 0; i < iov_count; ++i) {
- bool send_fin = fin && (i == iov_count - 1);
- if (!send_fin && iov[i].iov_len == 0) {
- LOG(DFATAL) << "Attempt to send empty stream frame";
- }
-
- StringPiece data(static_cast<char*>(iov[i].iov_base), iov[i].iov_len);
- int currentOffset = offset + bytes_written;
- QuicConsumedData consumed_data =
- packet_generator_.ConsumeData(id,
- data,
- currentOffset,
- send_fin,
- notifier);
-
- DCHECK_LE(consumed_data.bytes_consumed, numeric_limits<uint32>::max());
- bytes_written += consumed_data.bytes_consumed;
- fin_consumed = consumed_data.fin_consumed;
- // If no bytes were consumed, bail now, because the stream can not write
- // more data.
- if (consumed_data.bytes_consumed < iov[i].iov_len) {
- break;
- }
- }
- // Handle the 0 byte write properly.
- if (iov_count == 0) {
- DCHECK(fin);
- QuicConsumedData consumed_data = packet_generator_.ConsumeData(
- id, StringPiece(), offset, fin, NULL);
- fin_consumed = consumed_data.fin_consumed;
+ WriteResult result =
+ writer_->WritePacket(version_packet->data(), version_packet->length(),
+ self_address().address(), peer_address(), this);
+ if (result.status == WRITE_STATUS_BLOCKED) {
+ write_blocked_ = true;
+ }
+ if (result.status == WRITE_STATUS_OK ||
+ (result.status == WRITE_STATUS_BLOCKED &&
+ writer_->IsWriteBlockedDataBuffered())) {
+ pending_version_negotiation_packet_ = false;
+ return;
}
-
- // Leave the generator in the original batch state.
- if (!already_in_batch_mode) {
- packet_generator_.FinishBatchOperations();
+ if (result.status == WRITE_STATUS_ERROR) {
+ // We can't send an error as the socket is presumably borked.
+ CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
}
- DCHECK_EQ(already_in_batch_mode, packet_generator_.InBatchMode());
-
- return QuicConsumedData(bytes_written, fin_consumed);
-}
-
-QuicConsumedData QuicConnection::SendvStreamData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin) {
- return SendvStreamDataInner(id, iov, iov_count, offset, fin, NULL);
+ pending_version_negotiation_packet_ = true;
}
-QuicConsumedData QuicConnection::SendvStreamDataAndNotifyWhenAcked(
+QuicConsumedData QuicConnection::SendStreamData(
QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
+ const IOVector& data,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier::DelegateInterface* delegate) {
- if (!fin && iov_count == 0) {
+ if (!fin && data.Empty()) {
LOG(DFATAL) << "Attempt to send empty stream frame";
}
- // This notifier will be deleted in ProcessAckFrame once it has seen ACKs for
- // all the consumed data (or below if no data was consumed).
- QuicAckNotifier* notifier = new QuicAckNotifier(delegate);
+
+ // This notifier will be owned by the AckNotifierManager (or deleted below if
+ // no data or FIN was consumed).
+ QuicAckNotifier* notifier = NULL;
+ if (delegate) {
+ notifier = new QuicAckNotifier(delegate);
+ }
+
+ // Opportunistically bundle an ack with this outgoing packet, unless it's the
+ // crypto stream.
+ ScopedPacketBundler ack_bundler(this, id != kCryptoStreamId);
QuicConsumedData consumed_data =
- SendvStreamDataInner(id, iov, iov_count, offset, fin, notifier);
+ packet_generator_.ConsumeData(id, data, offset, fin, notifier);
- if (consumed_data.bytes_consumed > 0) {
- // If some data was consumed, then the delegate should be registered for
- // notification when the data is ACKed.
- ack_notifiers_.push_back(notifier);
- } else {
- // No data was consumed, delete the notifier.
+ if (notifier &&
+ (consumed_data.bytes_consumed == 0 && !consumed_data.fin_consumed)) {
+ // No data was consumed, nor was a fin consumed, so delete the notifier.
delete notifier;
}
@@ -876,16 +840,18 @@ QuicConsumedData QuicConnection::SendvStreamDataAndNotifyWhenAcked(
void QuicConnection::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error) {
- LOG(INFO) << "Sending RST_STREAM: " << id << " code: " << error;
+ DVLOG(1) << "Sending RST_STREAM: " << id << " code: " << error;
+ // Opportunistically bundle an ack with this outgoing packet.
+ ScopedPacketBundler ack_bundler(this, true);
packet_generator_.AddControlFrame(
QuicFrame(new QuicRstStreamFrame(id, error)));
}
const QuicConnectionStats& QuicConnection::GetStats() {
// Update rtt and estimated bandwidth.
- stats_.rtt = congestion_manager_.SmoothedRtt().ToMicroseconds();
+ stats_.rtt = sent_packet_manager_.SmoothedRtt().ToMicroseconds();
stats_.estimated_bandwidth =
- congestion_manager_.BandwidthEstimate().ToBytesPerSecond();
+ sent_packet_manager_.BandwidthEstimate().ToBytesPerSecond();
return stats_;
}
@@ -949,6 +915,8 @@ bool QuicConnection::DoWrite() {
DCHECK(!write_blocked_);
WriteQueuedPackets();
+ WritePendingRetransmissions();
+
IsHandshake pending_handshake = visitor_->HasPendingHandshake() ?
IS_HANDSHAKE : NOT_HANDSHAKE;
// Sending queued packets may have caused the socket to become write blocked,
@@ -957,27 +925,22 @@ bool QuicConnection::DoWrite() {
// write more.
if (CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
pending_handshake)) {
- const bool already_in_batch_mode = packet_generator_.InBatchMode();
- if (!already_in_batch_mode) {
- packet_generator_.StartBatchOperations();
- }
+ // Set |include_ack| to false in bundler; ack inclusion happens elsewhere.
+ scoped_ptr<ScopedPacketBundler> bundler(
+ new ScopedPacketBundler(this, false));
bool all_bytes_written = visitor_->OnCanWrite();
- if (!already_in_batch_mode) {
- packet_generator_.FinishBatchOperations();
- }
-
+ bundler.reset();
// After the visitor writes, it may have caused the socket to become write
// blocked or the congestion manager to prohibit sending, so check again.
pending_handshake = visitor_->HasPendingHandshake() ? IS_HANDSHAKE
: NOT_HANDSHAKE;
- if (!write_blocked_ && !all_bytes_written &&
+ if (!all_bytes_written && !resume_writes_alarm_->IsSet() &&
CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
pending_handshake)) {
// We're not write blocked, but some stream didn't write out all of its
// bytes. Register for 'immediate' resumption so we'll keep writing after
// other quic connections have had a chance to use the socket.
- send_alarm_->Cancel();
- send_alarm_->Set(clock_->ApproximateNow());
+ resume_writes_alarm_->Set(clock_->ApproximateNow());
}
}
@@ -994,18 +957,29 @@ bool QuicConnection::ProcessValidatedPacket() {
time_of_last_received_packet_ = clock_->Now();
DVLOG(1) << ENDPOINT << "time of last received packet: "
<< time_of_last_received_packet_.ToDebuggingValue();
+
+ if (is_server_ && encryption_level_ == ENCRYPTION_NONE &&
+ last_size_ > options()->max_packet_length) {
+ options()->max_packet_length = last_size_;
+ }
return true;
}
bool QuicConnection::WriteQueuedPackets() {
DCHECK(!write_blocked_);
+ if (pending_version_negotiation_packet_) {
+ SendVersionNegotiationPacket();
+ }
+
QueuedPacketList::iterator packet_iterator = queued_packets_.begin();
while (!write_blocked_ && packet_iterator != queued_packets_.end()) {
if (WritePacket(packet_iterator->encryption_level,
packet_iterator->sequence_number,
packet_iterator->packet,
+ packet_iterator->transmission_type,
packet_iterator->retransmittable,
+ packet_iterator->handshake,
packet_iterator->forced)) {
packet_iterator = queued_packets_.erase(packet_iterator);
} else {
@@ -1018,112 +992,84 @@ bool QuicConnection::WriteQueuedPackets() {
return !write_blocked_;
}
-bool QuicConnection::MaybeRetransmitPacketForRTO(
- QuicPacketSequenceNumber sequence_number) {
- if (!sent_packet_manager_.IsUnacked(sequence_number)) {
- DVLOG(2) << ENDPOINT << "alarm fired for " << sequence_number
- << " but it has been acked or already retransmitted with"
- << " a different sequence number.";
- // So no extra delay is added for this packet.
- return true;
- }
+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 =
+ sent_packet_manager_.NextPendingRetransmission();
+ if (HasForcedFrames(&pending.retransmittable_frames) == NO_FORCE &&
+ !CanWrite(pending.transmission_type, HAS_RETRANSMITTABLE_DATA,
+ HasCryptoHandshake(&pending.retransmittable_frames))) {
+ break;
+ }
- // If the packet hasn't been acked and we're getting truncated acks, ignore
- // any RTO for packets larger than the peer's largest observed packet; it may
- // have been received by the peer and just wasn't acked due to the ack frame
- // running out of space.
- if (received_truncated_ack_ &&
- sequence_number > GetPeerLargestObservedPacket() &&
- // We allow retransmission of already retransmitted packets so that we
- // retransmit packets that were retransmissions of the packet with
- // sequence number < the largest observed field of the truncated ack.
- !sent_packet_manager_.IsRetransmission(sequence_number)) {
- return false;
- }
+ // Re-packetize the frames with a new sequence number for retransmission.
+ // Retransmitted data packets do not use FEC, even when it's enabled.
+ // Retransmitted packets use the same sequence number length as the
+ // original.
+ // Flush the packet creator before making a new packet.
+ // TODO(ianswett): Implement ReserializeAllFrames as a separate path that
+ // does not require the creator to be flushed.
+ Flush();
+ SerializedPacket serialized_packet = packet_creator_.ReserializeAllFrames(
+ pending.retransmittable_frames.frames(),
+ pending.sequence_number_length);
+
+ DVLOG(1) << ENDPOINT << "Retransmitting " << pending.sequence_number
+ << " as " << serialized_packet.sequence_number;
+ if (debug_visitor_) {
+ debug_visitor_->OnPacketRetransmitted(
+ pending.sequence_number, serialized_packet.sequence_number);
+ }
+ sent_packet_manager_.OnRetransmittedPacket(
+ pending.sequence_number, serialized_packet.sequence_number);
- ++stats_.rto_count;
- RetransmitPacket(sequence_number);
- return true;
+ SendOrQueuePacket(pending.retransmittable_frames.encryption_level(),
+ serialized_packet,
+ pending.transmission_type);
+ }
}
void QuicConnection::RetransmitUnackedPackets(
RetransmissionType retransmission_type) {
- SequenceNumberSet unacked_packets = sent_packet_manager_.GetUnackedPackets();
- if (unacked_packets.empty()) {
- return;
- }
+ sent_packet_manager_.RetransmitUnackedPackets(retransmission_type);
- for (SequenceNumberSet::const_iterator unacked_it = unacked_packets.begin();
- unacked_it != unacked_packets.end(); ++unacked_it) {
- const RetransmittableFrames& frames =
- sent_packet_manager_.GetRetransmittableFrames(*unacked_it);
- if (retransmission_type == ALL_PACKETS ||
- frames.encryption_level() == ENCRYPTION_INITIAL) {
- // TODO(satyamshekhar): Think about congestion control here.
- // Specifically, about the retransmission count of packets being sent
- // proactively to achieve 0 (minimal) RTT.
- RetransmitPacket(*unacked_it);
- }
- }
+ WriteIfNotBlocked();
}
-void QuicConnection::RetransmitPacket(
- QuicPacketSequenceNumber sequence_number) {
- DCHECK(sent_packet_manager_.IsUnacked(sequence_number));
-
- // TODO(pwestin): Need to fix potential issue with FEC and a 1 packet
- // congestion window see b/8331807 for details.
- congestion_manager_.AbandoningPacket(sequence_number);
-
- const RetransmittableFrames& retransmittable_frames =
- sent_packet_manager_.GetRetransmittableFrames(sequence_number);
-
- // Re-packetize the frames with a new sequence number for retransmission.
- // Retransmitted data packets do not use FEC, even when it's enabled.
- // Retransmitted packets use the same sequence number length as the original.
- QuicSequenceNumberLength original_sequence_number_length =
- sent_packet_manager_.GetSequenceNumberLength(sequence_number);
- SerializedPacket serialized_packet =
- packet_creator_.ReserializeAllFrames(retransmittable_frames.frames(),
- original_sequence_number_length);
-
- // A notifier may be waiting to hear about ACKs for the original sequence
- // number. Inform them that the sequence number has changed.
- for (AckNotifierList::iterator notifier_it = ack_notifiers_.begin();
- notifier_it != ack_notifiers_.end(); ++notifier_it) {
- (*notifier_it)->UpdateSequenceNumber(sequence_number,
- serialized_packet.sequence_number);
- }
-
- DLOG(INFO) << ENDPOINT << "Retransmitting " << sequence_number << " as "
- << serialized_packet.sequence_number;
- if (debug_visitor_) {
- debug_visitor_->OnPacketRetransmitted(sequence_number,
- serialized_packet.sequence_number);
+bool QuicConnection::ShouldGeneratePacket(
+ TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake) {
+ // We should serialize handshake packets immediately to ensure that they
+ // end up sent at the right encryption level.
+ if (handshake == IS_HANDSHAKE) {
+ return true;
}
- sent_packet_manager_.OnRetransmittedPacket(sequence_number,
- serialized_packet.sequence_number);
- SendOrQueuePacket(retransmittable_frames.encryption_level(),
- serialized_packet.sequence_number,
- serialized_packet.packet,
- serialized_packet.entropy_hash,
- HAS_RETRANSMITTABLE_DATA,
- HasForcedFrames(serialized_packet.retransmittable_frames));
+ return CanWrite(transmission_type, retransmittable, handshake);
}
-bool QuicConnection::CanWrite(Retransmission retransmission,
+bool QuicConnection::CanWrite(TransmissionType transmission_type,
HasRetransmittableData retransmittable,
IsHandshake handshake) {
- // TODO(ianswett): If the packet is a retransmit, the current send alarm may
- // be too long.
- if (write_blocked_ || send_alarm_->IsSet()) {
+ if (write_blocked_) {
+ return false;
+ }
+
+ // TODO(rch): consider removing this check so that if an ACK comes in
+ // before the alarm goes it, we might be able send out a packet.
+ // This check assumes that if the send alarm is set, it applies equally to all
+ // types of transmissions.
+ if (send_alarm_->IsSet()) {
+ DVLOG(1) << "Send alarm set. Not sending.";
return false;
}
QuicTime now = clock_->Now();
- QuicTime::Delta delay = congestion_manager_.TimeUntilSend(
- now, retransmission, retransmittable, handshake);
+ QuicTime::Delta delay = sent_packet_manager_.TimeUntilSend(
+ now, transmission_type, retransmittable, handshake);
if (delay.IsInfinite()) {
return false;
}
@@ -1132,97 +1078,64 @@ bool QuicConnection::CanWrite(Retransmission retransmission,
if (!delay.IsZero()) {
send_alarm_->Cancel();
send_alarm_->Set(now.Add(delay));
+ DVLOG(1) << "Delaying sending.";
return false;
}
return true;
}
-void QuicConnection::SetupRetransmission(
- QuicPacketSequenceNumber sequence_number,
- EncryptionLevel level) {
- if (!sent_packet_manager_.IsUnacked(sequence_number)) {
+void QuicConnection::SetupRetransmissionAlarm(
+ QuicPacketSequenceNumber sequence_number) {
+ if (!sent_packet_manager_.HasRetransmittableFrames(sequence_number)) {
DVLOG(1) << ENDPOINT << "Will not retransmit packet " << sequence_number;
return;
}
- size_t retransmission_count =
- sent_packet_manager_.GetRetransmissionCount(sequence_number);
- // TODO(rch): consider using a much smaller retransmisison_delay
- // for the ENCRYPTION_NONE packets.
- size_t effective_retransmission_count =
- level == ENCRYPTION_NONE ? 0 : retransmission_count;
- QuicTime::Delta retransmission_delay =
- congestion_manager_.GetRetransmissionDelay(
- sent_packet_manager_.GetNumUnackedPackets(),
- effective_retransmission_count);
-
- retransmission_timeouts_.push(RetransmissionTime(
- sequence_number,
- clock_->ApproximateNow().Add(retransmission_delay),
- false));
- // Do not set the retransmisson alarm if we're already handling the
- // retransmission alarm because the retransmission alarm will be reset when
- // OnRetransmissionTimeout completes.
- if (!handling_retransmission_timeout_ && !retransmission_alarm_->IsSet()) {
- retransmission_alarm_->Set(
- clock_->ApproximateNow().Add(retransmission_delay));
+ // Do not set the retransmission alarm if we're already handling one, since
+ // it will be reset when OnRetransmissionTimeout completes.
+ if (retransmission_alarm_->IsSet()) {
+ return;
}
- // TODO(satyamshekhar): restore packet reordering with Ian's TODO in
- // SendStreamData().
-}
-void QuicConnection::SetupAbandonFecTimer(
- QuicPacketSequenceNumber sequence_number) {
QuicTime::Delta retransmission_delay =
- QuicTime::Delta::FromMilliseconds(
- congestion_manager_.DefaultRetransmissionTime().ToMilliseconds() * 3);
- retransmission_timeouts_.push(RetransmissionTime(
- sequence_number,
- clock_->ApproximateNow().Add(retransmission_delay),
- true));
+ sent_packet_manager_.GetRetransmissionDelay();
+ retransmission_alarm_->Set(
+ clock_->ApproximateNow().Add(retransmission_delay));
}
bool QuicConnection::WritePacket(EncryptionLevel level,
QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
+ TransmissionType transmission_type,
HasRetransmittableData retransmittable,
+ IsHandshake handshake,
Force forced) {
- if (!connected_) {
- DLOG(INFO) << ENDPOINT
- << "Not sending packet as connection is disconnected.";
+ if (ShouldDiscardPacket(level, sequence_number, retransmittable)) {
delete packet;
- // Returning true because we deleted the packet and the caller shouldn't
- // delete it again.
return true;
}
- if (encryption_level_ == ENCRYPTION_FORWARD_SECURE &&
- level == ENCRYPTION_NONE) {
- // Drop packets that are NULL encrypted since the peer won't accept them
- // anymore.
- DLOG(INFO) << ENDPOINT << "Dropping packet: " << sequence_number
- << " since the packet is NULL encrypted.";
- sent_packet_manager_.DiscardPacket(sequence_number);
- delete packet;
- return true;
+ // If we're write blocked, we know we can't write.
+ if (write_blocked_) {
+ return false;
}
- Retransmission retransmission =
- sent_packet_manager_.IsRetransmission(sequence_number) ?
- IS_RETRANSMISSION : NOT_RETRANSMISSION;
- // TODO(wtc): use the same logic that is used in the packet generator.
- // Namely, a packet is a handshake if it contains a stream frame for the
- // crypto stream. It should be possible to look at the RetransmittableFrames
- // in the SerializedPacket to determine this for a packet.
- IsHandshake handshake = level == ENCRYPTION_NONE ? IS_HANDSHAKE
- : NOT_HANDSHAKE;
-
// If we are not forced and we can't write, then simply return false;
if (forced == NO_FORCE &&
- !CanWrite(retransmission, retransmittable, handshake)) {
+ !CanWrite(transmission_type, retransmittable, handshake)) {
return false;
}
+ // Some encryption algorithms require the packet sequence numbers not be
+ // repeated.
+ DCHECK_LE(sequence_number_of_last_inorder_packet_, sequence_number);
+ // Only increase this when packets have not been queued. Once they're queued
+ // due to a write block, there is the chance of sending forced and other
+ // higher priority packets out of order.
+ if (queued_packets_.empty()) {
+ sequence_number_of_last_inorder_packet_ = sequence_number;
+ }
+
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.EncryptPacket(level, sequence_number, *packet));
if (encrypted.get() == NULL) {
@@ -1231,13 +1144,27 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
CloseConnection(QUIC_ENCRYPTION_FAILURE, false);
return false;
}
- DLOG(INFO) << ENDPOINT << "Sending packet number " << sequence_number
+
+ // If it's the ConnectionClose packet, the only FORCED frame type,
+ // clone a copy for resending later by the TimeWaitListManager.
+ if (forced == FORCE) {
+ DCHECK(connection_close_packet_.get() == NULL);
+ connection_close_packet_.reset(encrypted->Clone());
+ }
+
+ if (encrypted->length() > options()->max_packet_length) {
+ LOG(DFATAL) << "Writing an encrypted packet larger than max_packet_length:"
+ << options()->max_packet_length << " encrypted length: "
+ << encrypted->length();
+ }
+ DVLOG(1) << ENDPOINT << "Sending packet number " << sequence_number
<< " : " << (packet->is_fec_packet() ? "FEC " :
(retransmittable == HAS_RETRANSMITTABLE_DATA
? "data bearing " : " ack only "))
<< ", encryption level: "
<< QuicUtils::EncryptionLevelToString(level)
- << ", length:" << packet->length();
+ << ", length:" << packet->length() << ", encrypted length:"
+ << encrypted->length();
DVLOG(2) << ENDPOINT << "packet(" << sequence_number << "): " << std::endl
<< QuicUtils::StringToHexASCIIDump(packet->AsStringPiece());
@@ -1246,135 +1173,196 @@ bool QuicConnection::WritePacket(EncryptionLevel level,
<< packet->length() << " " << encrypted->length() << " "
<< " forced: " << (forced == FORCE ? "yes" : "no");
- int error;
- QuicTime now = clock_->Now();
- if (!retransmission) {
- time_of_last_sent_packet_ = now;
+ DCHECK(pending_write_.get() == NULL);
+ pending_write_.reset(new PendingWrite(sequence_number, transmission_type,
+ retransmittable, level,
+ packet->is_fec_packet(),
+ packet->length()));
+
+ WriteResult result =
+ writer_->WritePacket(encrypted->data(), encrypted->length(),
+ self_address().address(), peer_address(), this);
+ if (result.error_code == ERR_IO_PENDING) {
+ DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status);
}
- DVLOG(1) << ENDPOINT << "time of last sent packet: "
- << now.ToDebuggingValue();
- if (WritePacketToWire(sequence_number, level, *encrypted, &error) == -1) {
- if (helper_->IsWriteBlocked(error)) {
- // TODO(satyashekhar): It might be more efficient (fewer system calls), if
- // all connections share this variable i.e this becomes a part of
- // PacketWriterInterface.
- write_blocked_ = true;
- // If the socket buffers the the data, then the packet should not
- // be queued and sent again, which would result in an unnecessary
- // duplicate packet being sent.
- if (helper_->IsWriteBlockedDataBuffered()) {
- delete packet;
- return true;
- }
- return false;
+ if (debug_visitor_) {
+ // Pass the write result to the visitor.
+ debug_visitor_->OnPacketSent(sequence_number, level, *encrypted, result);
+ }
+ if (result.status == WRITE_STATUS_BLOCKED) {
+ // TODO(satyashekhar): It might be more efficient (fewer system calls), if
+ // all connections share this variable i.e this becomes a part of
+ // PacketWriterInterface.
+ write_blocked_ = true;
+ // If the socket buffers the the data, then the packet should not
+ // be queued and sent again, which would result in an unnecessary
+ // duplicate packet being sent. The helper must call OnPacketSent
+ // when the packet is actually sent.
+ if (writer_->IsWriteBlockedDataBuffered()) {
+ delete packet;
+ return true;
+ }
+ pending_write_.reset();
+ return false;
+ }
+
+ if (OnPacketSent(result)) {
+ delete packet;
+ return true;
+ }
+ return false;
+}
+
+bool QuicConnection::ShouldDiscardPacket(
+ EncryptionLevel level,
+ QuicPacketSequenceNumber sequence_number,
+ HasRetransmittableData retransmittable) {
+ if (!connected_) {
+ DVLOG(1) << ENDPOINT
+ << "Not sending packet as connection is disconnected.";
+ return true;
+ }
+
+ if (encryption_level_ == ENCRYPTION_FORWARD_SECURE &&
+ level == ENCRYPTION_NONE) {
+ // Drop packets that are NULL encrypted since the peer won't accept them
+ // anymore.
+ DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
+ << " since the packet is NULL encrypted.";
+ sent_packet_manager_.DiscardUnackedPacket(sequence_number);
+ return true;
+ }
+
+ if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
+ if (!sent_packet_manager_.IsUnacked(sequence_number)) {
+ // This is a crazy edge case, but if we retransmit a packet,
+ // (but have to queue it for some reason) then receive an ack
+ // for the previous transmission (but not the retransmission)
+ // then receive a truncated ACK which causes us to raise the
+ // high water mark, all before we're able to send the packet
+ // then we can simply drop it.
+ DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
+ << " since it has already been acked.";
+ return true;
+ }
+
+ if (sent_packet_manager_.IsPreviousTransmission(sequence_number)) {
+ // If somehow we have already retransmitted this packet *before*
+ // we actually send it for the first time (I think this is probably
+ // impossible in the real world), then don't bother sending it.
+ // We don't want to call DiscardUnackedPacket because in this case
+ // the peer has not yet ACK'd the data. We need the subsequent
+ // retransmission to be sent.
+ DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
+ << " since it has already been retransmitted.";
+ return true;
+ }
+
+ if (!sent_packet_manager_.HasRetransmittableFrames(sequence_number)) {
+ DVLOG(1) << ENDPOINT << "Dropping packet: " << sequence_number
+ << " since a previous transmission has been acked.";
+ sent_packet_manager_.DiscardUnackedPacket(sequence_number);
+ return true;
}
+ }
+
+ return false;
+}
+
+bool QuicConnection::OnPacketSent(WriteResult result) {
+ DCHECK_NE(WRITE_STATUS_BLOCKED, result.status);
+ if (pending_write_.get() == NULL) {
+ LOG(DFATAL) << "OnPacketSent called without a pending write.";
+ return false;
+ }
+
+ QuicPacketSequenceNumber sequence_number = pending_write_->sequence_number;
+ TransmissionType transmission_type = pending_write_->transmission_type;
+ HasRetransmittableData retransmittable = pending_write_->retransmittable;
+ bool is_fec_packet = pending_write_->is_fec_packet;
+ size_t length = pending_write_->length;
+ pending_write_.reset();
+
+ if (result.status == WRITE_STATUS_ERROR) {
+ DVLOG(1) << "Write failed with error code: " << result.error_code;
// We can't send an error as the socket is presumably borked.
CloseConnection(QUIC_PACKET_WRITE_ERROR, false);
return false;
}
+ QuicTime now = clock_->Now();
+ if (transmission_type == NOT_RETRANSMISSION) {
+ time_of_last_sent_packet_ = now;
+ }
+ DVLOG(1) << ENDPOINT << "time of last sent packet: "
+ << now.ToDebuggingValue();
+
// Set the retransmit alarm only when we have sent the packet to the client
// and not when it goes to the pending queue, otherwise we will end up adding
// an entry to retransmission_timeout_ every time we attempt a write.
- if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
- SetupRetransmission(sequence_number, level);
- } else if (packet->is_fec_packet()) {
- SetupAbandonFecTimer(sequence_number);
+ if (retransmittable == HAS_RETRANSMITTABLE_DATA || is_fec_packet) {
+ SetupRetransmissionAlarm(sequence_number);
}
// TODO(ianswett): Change the sequence number length and other packet creator
// options by a more explicit API than setting a struct value directly.
packet_creator_.UpdateSequenceNumberLength(
received_packet_manager_.least_packet_awaited_by_peer(),
- congestion_manager_.BandwidthEstimate().ToBytesPerPeriod(
- congestion_manager_.SmoothedRtt()));
+ sent_packet_manager_.BandwidthEstimate().ToBytesPerPeriod(
+ sent_packet_manager_.SmoothedRtt()));
- congestion_manager_.SentPacket(sequence_number, now, packet->length(),
- retransmission, retransmittable);
+ sent_packet_manager_.OnPacketSent(sequence_number, now, length,
+ transmission_type, retransmittable);
- stats_.bytes_sent += encrypted->length();
+ stats_.bytes_sent += result.bytes_written;
++stats_.packets_sent;
- if (retransmission == IS_RETRANSMISSION) {
- stats_.bytes_retransmitted += encrypted->length();
+ if (transmission_type == NACK_RETRANSMISSION ||
+ transmission_type == RTO_RETRANSMISSION) {
+ stats_.bytes_retransmitted += result.bytes_written;
++stats_.packets_retransmitted;
}
- delete packet;
return true;
}
-int QuicConnection::WritePacketToWire(QuicPacketSequenceNumber sequence_number,
- EncryptionLevel level,
- const QuicEncryptedPacket& packet,
- int* error) {
- int bytes_written = helper_->WritePacketToWire(packet, error);
- if (debug_visitor_) {
- // WritePacketToWire returned -1, then |error| will be populated with
- // an error code, which we want to pass along to the visitor.
- debug_visitor_->OnPacketSent(sequence_number, level, packet,
- bytes_written == -1 ? *error : bytes_written);
- }
- return bytes_written;
-}
-
bool QuicConnection::OnSerializedPacket(
const SerializedPacket& serialized_packet) {
if (serialized_packet.retransmittable_frames) {
- serialized_packet.retransmittable_frames->set_encryption_level(
- encryption_level_);
+ serialized_packet.retransmittable_frames->
+ set_encryption_level(encryption_level_);
}
sent_packet_manager_.OnSerializedPacket(serialized_packet);
+ // The TransmissionType is NOT_RETRANSMISSION because all retransmissions
+ // serialize packets and invoke SendOrQueuePacket directly.
return SendOrQueuePacket(encryption_level_,
- serialized_packet.sequence_number,
- serialized_packet.packet,
- serialized_packet.entropy_hash,
- serialized_packet.retransmittable_frames != NULL ?
- HAS_RETRANSMITTABLE_DATA :
- NO_RETRANSMITTABLE_DATA,
- HasForcedFrames(
- serialized_packet.retransmittable_frames));
-}
-
-QuicPacketSequenceNumber QuicConnection::GetPeerLargestObservedPacket() {
- return received_packet_manager_.peer_largest_observed_packet();
+ serialized_packet,
+ NOT_RETRANSMISSION);
}
QuicPacketSequenceNumber QuicConnection::GetNextPacketSequenceNumber() {
return packet_creator_.sequence_number() + 1;
}
-void QuicConnection::OnPacketNacked(QuicPacketSequenceNumber sequence_number,
- size_t nack_count) {
- if (nack_count >= kNumberOfNacksBeforeRetransmission &&
- retransmitted_nacked_packet_count_ < kMaxRetransmissionsPerAck) {
- ++retransmitted_nacked_packet_count_;
- RetransmitPacket(sequence_number);
- }
-}
-
bool QuicConnection::SendOrQueuePacket(EncryptionLevel level,
- QuicPacketSequenceNumber sequence_number,
- QuicPacket* packet,
- QuicPacketEntropyHash entropy_hash,
- HasRetransmittableData retransmittable,
- Force forced) {
- sent_entropy_manager_.RecordPacketEntropyHash(sequence_number, entropy_hash);
- if (!WritePacket(level, sequence_number, packet, retransmittable, forced)) {
- queued_packets_.push_back(QueuedPacket(sequence_number, packet, level,
- retransmittable, forced));
- return false;
+ const SerializedPacket& packet,
+ TransmissionType transmission_type) {
+ IsHandshake handshake = HasCryptoHandshake(packet.retransmittable_frames);
+ Force forced = HasForcedFrames(packet.retransmittable_frames);
+ HasRetransmittableData retransmittable =
+ (transmission_type != NOT_RETRANSMISSION ||
+ packet.retransmittable_frames != NULL) ?
+ HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA;
+ sent_entropy_manager_.RecordPacketEntropyHash(packet.sequence_number,
+ packet.entropy_hash);
+ if (WritePacket(level, packet.sequence_number, packet.packet,
+ transmission_type, retransmittable, handshake, forced)) {
+ return true;
}
- return true;
-}
-
-bool QuicConnection::ShouldSimulateLostPacket() {
- // TODO(rch): enable this
+ queued_packets_.push_back(QueuedPacket(packet.sequence_number, packet.packet,
+ level, transmission_type,
+ retransmittable, handshake, forced));
return false;
- /*
- return FLAGS_fake_packet_loss_percentage > 0 &&
- random_->Rand32() % 100 < FLAGS_fake_packet_loss_percentage;
- */
}
void QuicConnection::UpdateSentPacketInfo(SentPacketInfo* sent_info) {
@@ -1385,14 +1373,13 @@ void QuicConnection::UpdateSentPacketInfo(SentPacketInfo* sent_info) {
void QuicConnection::SendAck() {
ack_alarm_->Cancel();
-
// TODO(rch): delay this until the CreateFeedbackFrame
// method is invoked. This requires changes SetShouldSendAck
// to be a no-arg method, and re-jiggering its implementation.
bool send_feedback = false;
- if (congestion_manager_.GenerateCongestionFeedback(
+ if (received_packet_manager_.GenerateCongestionFeedback(
&outgoing_congestion_feedback_)) {
- DVLOG(1) << ENDPOINT << "Sending feedback "
+ DVLOG(1) << ENDPOINT << "Sending feedback: "
<< outgoing_congestion_feedback_;
send_feedback = true;
}
@@ -1400,58 +1387,24 @@ void QuicConnection::SendAck() {
packet_generator_.SetShouldSendAck(send_feedback);
}
-void QuicConnection::MaybeAbandonFecPacket(
- QuicPacketSequenceNumber sequence_number) {
- if (!sent_packet_manager_.IsFecUnacked(sequence_number)) {
- DVLOG(2) << ENDPOINT << "no need to abandon fec packet: "
- << sequence_number << "; it's already acked'";
+void QuicConnection::OnRetransmissionTimeout() {
+ if (!sent_packet_manager_.HasUnackedPackets()) {
return;
}
- congestion_manager_.AbandoningPacket(sequence_number);
-}
-QuicTime QuicConnection::OnRetransmissionTimeout() {
- // This guards against registering the alarm later than we should.
- //
- // If we have packet A and B in the list and we call
- // MaybeRetransmitPacketForRTO on A, that may trigger a call to
- // SetRetransmissionAlarm if A is retransmitted as C. In that case we
- // don't want to register the alarm under SetRetransmissionAlarm; we
- // want to set it to the RTO of B when we return from this function.
- handling_retransmission_timeout_ = true;
-
- for (size_t i = 0; i < max_packets_per_retransmission_alarm_ &&
- !retransmission_timeouts_.empty(); ++i) {
- RetransmissionTime retransmission_time = retransmission_timeouts_.top();
- DCHECK(retransmission_time.scheduled_time.IsInitialized());
- if (retransmission_time.scheduled_time > clock_->ApproximateNow()) {
- break;
- }
- retransmission_timeouts_.pop();
+ ++stats_.rto_count;
- if (retransmission_time.for_fec) {
- MaybeAbandonFecPacket(retransmission_time.sequence_number);
- continue;
- } else if (
- !MaybeRetransmitPacketForRTO(retransmission_time.sequence_number)) {
- DLOG(INFO) << ENDPOINT << "MaybeRetransmitPacketForRTO failed: "
- << "adding an extra delay for "
- << retransmission_time.sequence_number;
- retransmission_time.scheduled_time = clock_->ApproximateNow().Add(
- congestion_manager_.DefaultRetransmissionTime());
- retransmission_timeouts_.push(retransmission_time);
- }
- }
+ sent_packet_manager_.OnRetransmissionTimeout();
- handling_retransmission_timeout_ = false;
+ WriteIfNotBlocked();
- if (retransmission_timeouts_.empty()) {
- return QuicTime::Zero();
+ // Ensure the retransmission alarm is always set if there are unacked packets.
+ if (sent_packet_manager_.HasUnackedPackets() && !HasQueuedData() &&
+ !retransmission_alarm_->IsSet()) {
+ QuicTime rto_timeout = clock_->ApproximateNow().Add(
+ sent_packet_manager_.GetRetransmissionDelay());
+ retransmission_alarm_->Set(rto_timeout);
}
-
- // We have packets remaining. Return the absolute RTO of the oldest packet
- // on the list.
- return retransmission_timeouts_.top().scheduled_time;
}
void QuicConnection::SetEncrypter(EncryptionLevel level,
@@ -1488,10 +1441,7 @@ const QuicDecrypter* QuicConnection::alternative_decrypter() const {
void QuicConnection::QueueUndecryptablePacket(
const QuicEncryptedPacket& packet) {
DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
- char* data = new char[packet.length()];
- memcpy(data, packet.data(), packet.length());
- undecryptable_packets_.push_back(
- new QuicEncryptedPacket(data, packet.length(), true));
+ undecryptable_packets_.push_back(packet.Clone());
}
void QuicConnection::MaybeProcessUndecryptablePackets() {
@@ -1584,15 +1534,13 @@ void QuicConnection::SendConnectionCloseWithDetails(QuicErrorCode error,
void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
const string& details) {
- DLOG(INFO) << ENDPOINT << "Force closing with error "
+ DVLOG(1) << ENDPOINT << "Force closing " << guid() << " with error "
<< QuicUtils::ErrorToString(error) << " (" << error << ") "
<< details;
+ ScopedPacketBundler ack_bundler(this, true);
QuicConnectionCloseFrame* frame = new QuicConnectionCloseFrame();
frame->error_code = error;
frame->error_details = details;
- UpdateSentPacketInfo(&frame->ack_frame.sent_info);
- received_packet_manager_.UpdateReceivedPacketInfo(
- &frame->ack_frame.received_info, clock_->ApproximateNow());
packet_generator_.AddControlFrame(QuicFrame(frame));
Flush();
}
@@ -1600,15 +1548,25 @@ void QuicConnection::SendConnectionClosePacket(QuicErrorCode error,
void QuicConnection::CloseConnection(QuicErrorCode error, bool from_peer) {
DCHECK(connected_);
connected_ = false;
- visitor_->ConnectionClose(error, from_peer);
+ visitor_->OnConnectionClosed(error, from_peer);
+ // Cancel the alarms so they don't trigger any action now that the
+ // connection is closed.
+ ack_alarm_->Cancel();
+ resume_writes_alarm_->Cancel();
+ retransmission_alarm_->Cancel();
+ send_alarm_->Cancel();
+ timeout_alarm_->Cancel();
}
void QuicConnection::SendGoAway(QuicErrorCode error,
QuicStreamId last_good_stream_id,
const string& reason) {
- DLOG(INFO) << ENDPOINT << "Going away with error "
+ DVLOG(1) << ENDPOINT << "Going away with error "
<< QuicUtils::ErrorToString(error)
<< " (" << error << ")";
+
+ // Opportunistically bundle an ack with this outgoing packet.
+ ScopedPacketBundler ack_bundler(this, true);
packet_generator_.AddControlFrame(
QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason)));
}
@@ -1635,15 +1593,12 @@ void QuicConnection::CloseFecGroupsBefore(
}
void QuicConnection::Flush() {
- if (!packet_generator_.InBatchMode()) {
- return;
- }
- packet_generator_.FinishBatchOperations();
- packet_generator_.StartBatchOperations();
+ packet_generator_.FlushAllQueuedFrames();
}
bool QuicConnection::HasQueuedData() const {
- return !queued_packets_.empty() || packet_generator_.HasQueuedFrames();
+ return pending_version_negotiation_packet_ ||
+ !queued_packets_.empty() || packet_generator_.HasQueuedFrames();
}
void QuicConnection::SetIdleNetworkTimeout(QuicTime::Delta timeout) {
@@ -1651,7 +1606,7 @@ void QuicConnection::SetIdleNetworkTimeout(QuicTime::Delta timeout) {
idle_network_timeout_ = timeout;
CheckForTimeout();
} else {
- idle_network_timeout_ = timeout;
+ idle_network_timeout_ = timeout;
}
}
@@ -1712,4 +1667,31 @@ bool QuicConnection::CheckForTimeout() {
return false;
}
+QuicConnection::ScopedPacketBundler::ScopedPacketBundler(
+ QuicConnection* connection,
+ bool include_ack)
+ : connection_(connection),
+ already_in_batch_mode_(connection->packet_generator_.InBatchMode()) {
+ // Move generator into batch mode. If caller wants us to include an ack,
+ // check the delayed-ack timer to see if there's ack info to be sent.
+ if (!already_in_batch_mode_) {
+ DVLOG(1) << "Entering Batch Mode.";
+ connection_->packet_generator_.StartBatchOperations();
+ }
+ if (include_ack && connection_->ack_alarm_->IsSet()) {
+ DVLOG(1) << "Bundling ack with outgoing packet.";
+ connection_->SendAck();
+ }
+}
+
+QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() {
+ // If we changed the generator's batch state, restore original batch state.
+ if (!already_in_batch_mode_) {
+ DVLOG(1) << "Leaving Batch Mode.";
+ connection_->packet_generator_.FinishBatchOperations();
+ }
+ DCHECK_EQ(already_in_batch_mode_,
+ connection_->packet_generator_.InBatchMode());
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_connection.h b/chromium/net/quic/quic_connection.h
index 15249097727..beb8985d4d1 100644
--- a/chromium/net/quic/quic_connection.h
+++ b/chromium/net/quic/quic_connection.h
@@ -16,34 +16,41 @@
#ifndef NET_QUIC_QUIC_CONNECTION_H_
#define NET_QUIC_QUIC_CONNECTION_H_
+#include <stddef.h>
#include <deque>
#include <list>
#include <map>
#include <queue>
-#include <set>
+#include <string>
#include <vector>
-#include "base/containers/hash_tables.h"
+#include "base/logging.h"
#include "net/base/iovec.h"
#include "net/base/ip_endpoint.h"
-#include "net/base/linked_hash_map.h"
-#include "net/quic/congestion_control/quic_congestion_manager.h"
+#include "net/quic/iovector.h"
#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_ack_notifier_manager.h"
#include "net/quic/quic_alarm.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_connection_stats.h"
-#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_packet_generator.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_received_packet_manager.h"
#include "net/quic/quic_sent_entropy_manager.h"
#include "net/quic/quic_sent_packet_manager.h"
+NET_EXPORT_PRIVATE extern int FLAGS_fake_packet_loss_percentage;
+NET_EXPORT_PRIVATE extern bool FLAGS_bundle_ack_with_outgoing_packet;
+
namespace net {
class QuicClock;
+class QuicConfig;
class QuicConnection;
+class QuicDecrypter;
+class QuicEncrypter;
class QuicFecGroup;
class QuicRandom;
@@ -71,12 +78,15 @@ class NET_EXPORT_PRIVATE QuicConnectionVisitorInterface {
// Called when the connection is closed either locally by the framer, or
// remotely by the peer.
- virtual void ConnectionClose(QuicErrorCode error,
- bool from_peer) = 0;
+ virtual void OnConnectionClosed(QuicErrorCode error,
+ bool from_peer) = 0;
// Called once a specific QUIC version is agreed by both endpoints.
virtual void OnSuccessfulVersionNegotiation(const QuicVersion& version) = 0;
+ // Indicates a new QuicConfig has been negotiated.
+ virtual void OnConfigNegotiated() = 0;
+
// Called when a blocked socket becomes writable. If all pending bytes for
// this visitor are consumed by the connection successfully this should
// return true, otherwise it should return false.
@@ -98,7 +108,7 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitorInterface
virtual void OnPacketSent(QuicPacketSequenceNumber sequence_number,
EncryptionLevel level,
const QuicEncryptedPacket& packet,
- int rv) = 0;
+ WriteResult result) = 0;
// Called when the contents of a packet have been retransmitted as
// a new packet.
@@ -153,32 +163,12 @@ class NET_EXPORT_PRIVATE QuicConnectionHelperInterface {
public:
virtual ~QuicConnectionHelperInterface() {}
- // Sets the QuicConnection to be used by this helper. This method
- // must only be called once.
- virtual void SetConnection(QuicConnection* connection) = 0;
-
// Returns a QuicClock to be used for all time related functions.
virtual const QuicClock* GetClock() const = 0;
// Returns a QuicRandom to be used for all random number related functions.
virtual QuicRandom* GetRandomGenerator() = 0;
- // Sends the packet out to the peer, possibly simulating packet
- // loss if FLAGS_fake_packet_loss_percentage is set. If the write
- // succeeded, returns the number of bytes written. If the write
- // failed, returns -1 and the error code will be copied to |*error|.
- virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
- int* error) = 0;
-
- // Returns true if the helper buffers and subsequently rewrites data
- // when an attempt to write results in the underlying socket becoming
- // write blocked.
- virtual bool IsWriteBlockedDataBuffered() = 0;
-
- // Returns true if |error| represents a write-block error code such
- // as EAGAIN or ERR_IO_PENDING.
- virtual bool IsWriteBlocked(int error) = 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.
@@ -196,41 +186,32 @@ class NET_EXPORT_PRIVATE QuicConnection
FORCE
};
- enum RetransmissionType {
- INITIAL_ENCRYPTION_ONLY,
- ALL_PACKETS
- };
-
// Constructs a new QuicConnection for the specified |guid| and |address|.
- // |helper| will be owned by this connection.
+ // |helper| and |writer| must outlive this connection.
QuicConnection(QuicGuid guid,
IPEndPoint address,
QuicConnectionHelperInterface* helper,
+ QuicPacketWriter* writer,
bool is_server,
- QuicVersion version);
+ const QuicVersionVector& supported_versions);
virtual ~QuicConnection();
- // Send the data in |iov| to the peer in as few packets as possible.
+ // Sets connection parameters from the supplied |config|.
+ void SetFromConfig(const QuicConfig& config);
+
+ // Send the data in |data| to the peer in as few packets as possible.
// 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.
- QuicConsumedData SendvStreamData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin);
-
- // Same as SendvStreamData, except the provided delegate will be informed
- // once ACKs have been received for all the packets written.
+ // If |delegate| is provided, then it will be informed once ACKs have been
+ // received for all the packets written in this call.
// The |delegate| is not owned by the QuicConnection and must outlive it.
- QuicConsumedData SendvStreamDataAndNotifyWhenAcked(
- QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin,
- QuicAckNotifier::DelegateInterface* delegate);
+ QuicConsumedData SendStreamData(QuicStreamId id,
+ const IOVector& data,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckNotifier::DelegateInterface* delegate);
// Send a stream reset frame to the peer.
virtual void SendRstStream(QuicStreamId id,
@@ -268,6 +249,9 @@ class NET_EXPORT_PRIVATE QuicConnection
// writes to happen. Returns false if the socket has become blocked.
virtual bool OnCanWrite() OVERRIDE;
+ // Called when a packet has been finally sent to the network.
+ bool OnPacketSent(WriteResult result);
+
// If the socket is not blocked, this allows queued writes to happen. Returns
// false if the socket has become blocked.
bool WriteIfNotBlocked();
@@ -280,6 +264,11 @@ class NET_EXPORT_PRIVATE QuicConnection
// The version of the protocol this connection is using.
QuicVersion version() const { return framer_.version(); }
+ // The versions of the protocol that this connection supports.
+ const QuicVersionVector& supported_versions() const {
+ return framer_.supported_versions();
+ }
+
// From QuicFramerVisitorInterface
virtual void OnError(QuicFramer* framer) OVERRIDE;
virtual bool OnProtocolVersionMismatch(QuicVersion received_version) OVERRIDE;
@@ -289,6 +278,7 @@ class NET_EXPORT_PRIVATE QuicConnection
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) OVERRIDE;
virtual void OnRevivedPacket() OVERRIDE;
+ virtual bool OnUnauthenticatedHeader(const QuicPacketHeader& header) OVERRIDE;
virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
virtual void OnFecProtectedPayload(base::StringPiece payload) OVERRIDE;
virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
@@ -303,19 +293,15 @@ class NET_EXPORT_PRIVATE QuicConnection
virtual void OnPacketComplete() OVERRIDE;
// QuicPacketGenerator::DelegateInterface
- virtual bool CanWrite(
- Retransmission is_retransmission,
- HasRetransmittableData has_retransmittable_data,
- IsHandshake handshake) OVERRIDE;
+ virtual bool ShouldGeneratePacket(TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake) OVERRIDE;
virtual QuicAckFrame* CreateAckFrame() OVERRIDE;
virtual QuicCongestionFeedbackFrame* CreateFeedbackFrame() OVERRIDE;
virtual bool OnSerializedPacket(const SerializedPacket& packet) OVERRIDE;
// QuicSentPacketManager::HelperInterface
- virtual QuicPacketSequenceNumber GetPeerLargestObservedPacket() OVERRIDE;
virtual QuicPacketSequenceNumber GetNextPacketSequenceNumber() OVERRIDE;
- virtual void OnPacketNacked(QuicPacketSequenceNumber sequence_number,
- size_t nack_count) OVERRIDE;
// Accessors
void set_visitor(QuicConnectionVisitorInterface* visitor) {
@@ -331,24 +317,25 @@ class NET_EXPORT_PRIVATE QuicConnection
const QuicClock* clock() const { return clock_; }
QuicRandom* random_generator() const { return random_generator_; }
- // Called by a RetransmissionAlarm when the timer goes off. If the peer
- // appears to be sending truncated acks, this returns false to indicate
- // failure, otherwise it calls MaybeRetransmitPacket and returns true.
- bool MaybeRetransmitPacketForRTO(QuicPacketSequenceNumber sequence_number);
-
- // Called to retransmit a packet, in the case a packet was sufficiently
- // nacked by the peer, or not acked within the time out window.
- void RetransmitPacket(QuicPacketSequenceNumber sequence_number);
-
QuicPacketCreator::Options* options() { return packet_creator_.options(); }
- bool connected() { return connected_; }
+ bool connected() const { return connected_; }
+
+ // Must only be called on client connections.
+ const QuicVersionVector& server_supported_versions() const {
+ DCHECK(!is_server_);
+ return server_supported_versions_;
+ }
size_t NumFecGroups() const { return group_map_.size(); }
// Testing only.
size_t NumQueuedPackets() const { return queued_packets_.size(); }
+ QuicEncryptedPacket* ReleaseConnectionClosePacket() {
+ return connection_close_packet_.release();
+ }
+
// Flush any queued frames immediately. Preserves the batch write mode and
// does nothing if there are no pending frames.
void Flush();
@@ -369,22 +356,18 @@ class NET_EXPORT_PRIVATE QuicConnection
// true. Otherwise, it will return false and will reset the timeout alarm.
bool CheckForTimeout();
- // Returns true of the next packet to be sent should be "lost" by
- // not actually writing it to the wire.
- bool ShouldSimulateLostPacket();
-
// Sets up a packet with an QuicAckFrame and sends it out.
void SendAck();
- // Called when an RTO fires. Returns the time when this alarm
- // should next fire, or 0 if no retransmission alarm should be set.
- QuicTime OnRetransmissionTimeout();
+ // Called when an RTO fires. Resets the retransmission alarm if there are
+ // remaining unacked packets.
+ void OnRetransmissionTimeout();
- // Retransmits unacked packets which were sent with initial encryption, if
- // |initial_encryption_only| is true, otherwise retransmits all unacked
- // packets. Used when the negotiated protocol version is different than what
- // was initially assumed and when the visitor wants to re-transmit packets
- // with initial encryption when the initial encrypter changes.
+ // Retransmits all unacked packets with retransmittable frames if
+ // |retransmission_type| is ALL_PACKETS, otherwise retransmits only initially
+ // encrypted packets. Used when the negotiated protocol version is different
+ // from what was initially assumed and when the visitor wants to re-transmit
+ // initially encrypted packets when the initial encrypter changes.
void RetransmitUnackedPackets(RetransmissionType retransmission_type);
// Changes the encrypter used for level |level| to |encrypter|. The function
@@ -416,7 +399,14 @@ class NET_EXPORT_PRIVATE QuicConnection
bool is_server() const { return is_server_; }
- static bool g_acks_do_not_instigate_acks;
+ // Returns the underlying sent packet manager.
+ const QuicSentPacketManager& sent_packet_manager() const {
+ return sent_packet_manager_;
+ }
+
+ bool CanWrite(TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake);
protected:
// Send a packet to the peer using encryption |level|. If |sequence_number|
@@ -425,15 +415,12 @@ class NET_EXPORT_PRIVATE QuicConnection
// Deletes |packet| via WritePacket call or transfers ownership to
// QueuedPacket, ultimately deleted via WritePacket. Updates the
// entropy map corresponding to |sequence_number| using |entropy_hash|.
- // |retransmittable| is supplied to the congestion manager, and when |forced|
- // is true, it bypasses the congestion manager.
+ // |transmission_type| and |retransmittable| are supplied to the congestion
+ // manager, and when |forced| is true, it bypasses the congestion manager.
// TODO(wtc): none of the callers check the return value.
virtual bool SendOrQueuePacket(EncryptionLevel level,
- QuicPacketSequenceNumber sequence_number,
- QuicPacket* packet,
- QuicPacketEntropyHash entropy_hash,
- HasRetransmittableData retransmittable,
- Force forced);
+ const SerializedPacket& packet,
+ TransmissionType transmission_type);
// Writes the given packet to socket, encrypted with |level|, with the help
// of helper. Returns true on successful write, false otherwise. However,
@@ -446,18 +433,15 @@ class NET_EXPORT_PRIVATE QuicConnection
bool WritePacket(EncryptionLevel level,
QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
+ TransmissionType transmission_type,
HasRetransmittableData retransmittable,
+ IsHandshake handshake,
Force force);
- int WritePacketToWire(QuicPacketSequenceNumber sequence_number,
- EncryptionLevel level,
- const QuicEncryptedPacket& packet,
- int* error);
-
// Make sure an ack we got from our peer is sane.
bool ValidateAckFrame(const QuicAckFrame& incoming_ack);
- QuicConnectionHelperInterface* helper() { return helper_.get(); }
+ QuicConnectionHelperInterface* helper() { return helper_; }
// Selects and updates the version of the protocol being used by selecting a
// version from |available_versions| which is also supported. Returns true if
@@ -467,16 +451,28 @@ class NET_EXPORT_PRIVATE QuicConnection
QuicFramer framer_;
private:
- friend class test::QuicConnectionPeer;
+ // Stores current batch state for connection, puts the connection
+ // into batch mode, and destruction restores the stored batch state.
+ // While the bundler is in scope, any generated frames are bundled
+ // as densely as possible into packets. In addition, this bundler
+ // can be configured to ensure that an ACK frame is included in the
+ // first packet created, if there's new ack information to be sent.
+ class ScopedPacketBundler {
+ public:
+ // In addition to all outgoing frames being bundled when the
+ // bundler is in scope, setting |include_ack| to true ensures that
+ // an ACK frame is opportunistically bundled with the first
+ // outgoing packet.
+ ScopedPacketBundler(QuicConnection* connection, bool include_ack);
+ ~ScopedPacketBundler();
+
+ private:
+ QuicConnection* connection_;
+ bool already_in_batch_mode_;
+ };
- // Inner helper function to SendvStreamData and
- // SendvStreamDataAndNotifyWhenAcked.
- QuicConsumedData SendvStreamDataInner(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin,
- QuicAckNotifier *notifier);
+ friend class ScopedPacketBundler;
+ friend class test::QuicConnectionPeer;
// Packets which have not been written to the wire.
// Owns the QuicPacket* packet.
@@ -484,33 +480,42 @@ class NET_EXPORT_PRIVATE QuicConnection
QueuedPacket(QuicPacketSequenceNumber sequence_number,
QuicPacket* packet,
EncryptionLevel level,
+ TransmissionType transmission_type,
HasRetransmittableData retransmittable,
+ IsHandshake handshake,
Force forced)
: sequence_number(sequence_number),
packet(packet),
encryption_level(level),
+ transmission_type(transmission_type),
retransmittable(retransmittable),
+ handshake(handshake),
forced(forced) {
}
QuicPacketSequenceNumber sequence_number;
QuicPacket* packet;
const EncryptionLevel encryption_level;
+ TransmissionType transmission_type;
HasRetransmittableData retransmittable;
+ IsHandshake handshake;
Force forced;
};
struct RetransmissionInfo {
RetransmissionInfo(QuicPacketSequenceNumber sequence_number,
- QuicSequenceNumberLength sequence_number_length)
+ QuicSequenceNumberLength sequence_number_length,
+ QuicTime sent_time)
: sequence_number(sequence_number),
sequence_number_length(sequence_number_length),
+ sent_time(sent_time),
number_nacks(0),
number_retransmissions(0) {
}
QuicPacketSequenceNumber sequence_number;
QuicSequenceNumberLength sequence_number_length;
+ QuicTime sent_time;
size_t number_nacks;
size_t number_retransmissions;
};
@@ -528,6 +533,28 @@ class NET_EXPORT_PRIVATE QuicConnection
bool for_fec;
};
+ struct PendingWrite {
+ PendingWrite(QuicPacketSequenceNumber sequence_number,
+ TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ EncryptionLevel level,
+ bool is_fec_packet,
+ size_t length)
+ : sequence_number(sequence_number),
+ transmission_type(transmission_type),
+ retransmittable(retransmittable),
+ level(level),
+ is_fec_packet(is_fec_packet),
+ length(length) { }
+
+ QuicPacketSequenceNumber sequence_number;
+ TransmissionType transmission_type;
+ HasRetransmittableData retransmittable;
+ EncryptionLevel level;
+ bool is_fec_packet;
+ size_t length;
+ };
+
class RetransmissionTimeComparator {
public:
bool operator()(const RetransmissionTime& lhs,
@@ -544,13 +571,11 @@ class NET_EXPORT_PRIVATE QuicConnection
std::vector<RetransmissionTime>,
RetransmissionTimeComparator>
RetransmissionTimeouts;
- typedef std::list<QuicAckNotifier*> AckNotifierList;
// Sends a version negotiation packet to the peer.
void SendVersionNegotiationPacket();
- void SetupRetransmission(QuicPacketSequenceNumber sequence_number,
- EncryptionLevel level);
+ void SetupRetransmissionAlarm(QuicPacketSequenceNumber sequence_number);
bool IsRetransmission(QuicPacketSequenceNumber sequence_number);
void SetupAbandonFecTimer(QuicPacketSequenceNumber sequence_number);
@@ -578,6 +603,14 @@ class NET_EXPORT_PRIVATE QuicConnection
// blocked when this is called.
bool WriteQueuedPackets();
+ // Writes as many pending retransmissions as possible.
+ void WritePendingRetransmissions();
+
+ // Returns true if the packet should be discarded and not sent.
+ bool ShouldDiscardPacket(EncryptionLevel level,
+ QuicPacketSequenceNumber sequence_number,
+ HasRetransmittableData retransmittable);
+
// Queues |packet| in the hopes that it can be decrypted in the
// future, when a new key is installed.
void QueueUndecryptablePacket(const QuicEncryptedPacket& packet);
@@ -599,9 +632,8 @@ class NET_EXPORT_PRIVATE QuicConnection
// Sends any packets which are a response to the last packet, including both
// acks and pending writes if an ack opened the congestion window.
- void MaybeSendInResponseToPacket(bool last_packet_should_instigate_ack);
-
- void MaybeAbandonFecPacket(QuicPacketSequenceNumber sequence_number);
+ void MaybeSendInResponseToPacket(bool send_ack_immediately,
+ bool last_packet_should_instigate_ack);
// Get the FEC group associate with the last processed packet or NULL, if the
// group has already been deleted.
@@ -610,7 +642,8 @@ class NET_EXPORT_PRIVATE QuicConnection
// Closes any FEC groups protecting packets before |sequence_number|.
void CloseFecGroupsBefore(QuicPacketSequenceNumber sequence_number);
- scoped_ptr<QuicConnectionHelperInterface> helper_;
+ QuicConnectionHelperInterface* helper_; // Not owned.
+ QuicPacketWriter* writer_; // Not owned.
EncryptionLevel encryption_level_;
const QuicClock* clock_;
QuicRandom* random_generator_;
@@ -629,9 +662,7 @@ class NET_EXPORT_PRIVATE QuicConnection
std::vector<QuicCongestionFeedbackFrame> last_congestion_frames_;
std::vector<QuicRstStreamFrame> last_rst_frames_;
std::vector<QuicGoAwayFrame> last_goaway_frames_;
- // Then number of packets retransmitted because of nacks
- // while processed the current ack frame.
- size_t retransmitted_nacked_packet_count_;
+ std::vector<QuicConnectionCloseFrame> last_close_frames_;
QuicCongestionFeedbackFrame outgoing_congestion_feedback_;
@@ -645,23 +676,21 @@ class NET_EXPORT_PRIVATE QuicConnection
// sent with the INITIAL encryption and the CHLO message was lost.
std::deque<QuicEncryptedPacket*> undecryptable_packets_;
- // Heap of packets that we might need to retransmit, and the time at
- // which we should retransmit them. Every time a packet is sent it is added
- // to this heap which is O(log(number of pending packets to be retransmitted))
- // which might be costly. This should be optimized to O(1) by maintaining a
- // priority queue of lists of packets to be retransmitted, where list x
- // contains all packets that have been retransmitted x times.
- RetransmissionTimeouts retransmission_timeouts_;
-
- // True while OnRetransmissionTimeout is running to prevent
- // SetRetransmissionAlarm from being called erroneously.
- bool handling_retransmission_timeout_;
+ // When the version negotiation packet could not be sent because the socket
+ // was not writable, this is set to true.
+ 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.
QueuedPacketList queued_packets_;
+ // Contains information about the current write in progress, if any.
+ scoped_ptr<PendingWrite> pending_write_;
+
+ // Contains the connection close packet if the connection has been closed.
+ scoped_ptr<QuicEncryptedPacket> connection_close_packet_;
+
// True when the socket becomes unwritable.
bool write_blocked_;
@@ -677,6 +706,9 @@ class NET_EXPORT_PRIVATE QuicConnection
// An alarm that is scheduled when the sent scheduler requires a
// a delay before sending packets and fires when the packet may be sent.
scoped_ptr<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_;
// An alarm that fires when the connection may have timed out.
scoped_ptr<QuicAlarm> timeout_alarm_;
@@ -702,19 +734,19 @@ class NET_EXPORT_PRIVATE QuicConnection
// The time that we last sent a packet for this connection.
QuicTime time_of_last_sent_packet_;
- // Congestion manager which controls the rate the connection sends packets
- // as well as collecting and generating congestion feedback.
- QuicCongestionManager congestion_manager_;
+ // Sequence number of the last packet guaranteed to be sent in packet sequence
+ // number order. Not set when packets are queued, since that may cause
+ // re-ordering.
+ QuicPacketSequenceNumber sequence_number_of_last_inorder_packet_;
// Sent packet manager which tracks the status of packets sent by this
- // connection.
+ // connection and contains the send and receive algorithms to determine when
+ // to send packets.
QuicSentPacketManager sent_packet_manager_;
// The state of connection in version negotiation finite state machine.
QuicVersionNegotiationState version_negotiation_state_;
- size_t max_packets_per_retransmission_alarm_;
-
// Tracks if the connection was created by the server.
bool is_server_;
@@ -722,20 +754,18 @@ class NET_EXPORT_PRIVATE QuicConnection
// close.
bool connected_;
- // True if the last ack received from the peer may have been truncated. False
- // otherwise.
- bool received_truncated_ack_;
- bool send_ack_in_response_to_packet_;
-
// Set to true if the udp packet headers have a new self or peer address.
// This is checked later on validating a data or version negotiation packet.
bool address_migrating_;
- // On every ACK frame received by this connection, all the ack_notifiers_ will
- // be told which sequeunce numbers were ACKed.
- // Once a given QuicAckNotifier has seen all the sequence numbers it is
- // interested in, it will be deleted, and removed from this list.
- AckNotifierList ack_notifiers_;
+ // An AckNotifier can register to be informed when ACKs have been received for
+ // all packets that a given block of data was sent in. The AckNotifierManager
+ // maintains the currently active notifiers.
+ AckNotifierManager ack_notifier_manager_;
+
+ // If non-empty this contains the set of versions received in a
+ // version negotiation packet.
+ QuicVersionVector server_supported_versions_;
DISALLOW_COPY_AND_ASSIGN(QuicConnection);
};
diff --git a/chromium/net/quic/quic_connection_helper.cc b/chromium/net/quic/quic_connection_helper.cc
index 703151b704f..543bf09f801 100644
--- a/chromium/net/quic/quic_connection_helper.cc
+++ b/chromium/net/quic/quic_connection_helper.cc
@@ -25,17 +25,22 @@ class QuicChromeAlarm : public QuicAlarm {
: QuicAlarm(delegate),
clock_(clock),
task_runner_(task_runner),
- task_posted_(false),
+ task_deadline_(QuicTime::Zero()),
weak_factory_(this) {}
protected:
virtual void SetImpl() OVERRIDE {
DCHECK(deadline().IsInitialized());
- if (task_posted_) {
- // Since tasks can not be un-posted, OnAlarm will be invoked which
- // will notice that deadline has not yet been reached, and will set
- // the alarm for the new deadline.
- return;
+ if (task_deadline_.IsInitialized()) {
+ if (task_deadline_ <= deadline()) {
+ // Since tasks can not be un-posted, OnAlarm will be invoked which
+ // will notice that deadline has not yet been reached, and will set
+ // the alarm for the new deadline.
+ return;
+ }
+ // The scheduled task is after new deadline. Invalidate the weak ptrs
+ // so that task does not execute when we're not expecting it.
+ weak_factory_.InvalidateWeakPtrs();
}
int64 delay_us = deadline().Subtract(clock_->Now()).ToMicroseconds();
@@ -46,7 +51,7 @@ class QuicChromeAlarm : public QuicAlarm {
FROM_HERE,
base::Bind(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMicroseconds(delay_us));
- task_posted_ = true;
+ task_deadline_ = deadline();
}
virtual void CancelImpl() OVERRIDE {
@@ -57,8 +62,8 @@ class QuicChromeAlarm : public QuicAlarm {
private:
void OnAlarm() {
- DCHECK(task_posted_);
- task_posted_ = false;
+ DCHECK(task_deadline_.IsInitialized());
+ task_deadline_ = QuicTime::Zero();
// The alarm may have been cancelled.
if (!deadline().IsInitialized()) {
return;
@@ -75,7 +80,12 @@ class QuicChromeAlarm : public QuicAlarm {
const QuicClock* clock_;
base::TaskRunner* task_runner_;
- bool task_posted_;
+ // If a task has been posted to the message loop, this is the time it
+ // was scheduled to fire. Tracking this allows us to avoid posting a
+ // new tast if the new deadline is in the future, but permits us to
+ // post a new task when the new deadline now earlier than when
+ // previously posted.
+ QuicTime task_deadline_;
base::WeakPtrFactory<QuicChromeAlarm> weak_factory_;
};
@@ -83,11 +93,9 @@ class QuicChromeAlarm : public QuicAlarm {
QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
const QuicClock* clock,
- QuicRandom* random_generator,
- DatagramClientSocket* socket)
+ QuicRandom* random_generator)
: weak_factory_(this),
task_runner_(task_runner),
- socket_(socket),
clock_(clock),
random_generator_(random_generator) {
}
@@ -95,10 +103,6 @@ QuicConnectionHelper::QuicConnectionHelper(base::TaskRunner* task_runner,
QuicConnectionHelper::~QuicConnectionHelper() {
}
-void QuicConnectionHelper::SetConnection(QuicConnection* connection) {
- connection_ = connection;
-}
-
const QuicClock* QuicConnectionHelper::GetClock() const {
return clock_;
}
@@ -107,51 +111,8 @@ QuicRandom* QuicConnectionHelper::GetRandomGenerator() {
return random_generator_;
}
-int QuicConnectionHelper::WritePacketToWire(
- const QuicEncryptedPacket& packet,
- int* error) {
- if (connection_->ShouldSimulateLostPacket()) {
- DLOG(INFO) << "Dropping packet due to fake packet loss.";
- *error = 0;
- return packet.length();
- }
-
- scoped_refptr<StringIOBuffer> buf(
- new StringIOBuffer(std::string(packet.data(),
- packet.length())));
- int rv = socket_->Write(buf.get(),
- packet.length(),
- base::Bind(&QuicConnectionHelper::OnWriteComplete,
- weak_factory_.GetWeakPtr()));
- if (rv >= 0) {
- *error = 0;
- } else {
- if (rv != ERR_IO_PENDING) {
- UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
- }
- *error = rv;
- rv = -1;
- }
- return rv;
-}
-
-bool QuicConnectionHelper::IsWriteBlockedDataBuffered() {
- // Chrome sockets' Write() methods buffer the data until the Write is
- // permitted.
- return true;
-}
-
-bool QuicConnectionHelper::IsWriteBlocked(int error) {
- return error == ERR_IO_PENDING;
-}
-
QuicAlarm* QuicConnectionHelper::CreateAlarm(QuicAlarm::Delegate* delegate) {
return new QuicChromeAlarm(clock_, task_runner_, delegate);
}
-void QuicConnectionHelper::OnWriteComplete(int result) {
- // TODO(rch): Inform the connection about the result.
- connection_->OnCanWrite();
-}
-
} // namespace net
diff --git a/chromium/net/quic/quic_connection_helper.h b/chromium/net/quic/quic_connection_helper.h
index 6667b958ab8..7098039c9eb 100644
--- a/chromium/net/quic/quic_connection_helper.h
+++ b/chromium/net/quic/quic_connection_helper.h
@@ -27,40 +27,23 @@ namespace net {
class QuicClock;
class QuicRandom;
-namespace test {
-class QuicConnectionHelperPeer;
-} // namespace test
-
class NET_EXPORT_PRIVATE QuicConnectionHelper
: public QuicConnectionHelperInterface {
public:
QuicConnectionHelper(base::TaskRunner* task_runner,
const QuicClock* clock,
- QuicRandom* random_generator,
- DatagramClientSocket* socket);
+ QuicRandom* random_generator);
virtual ~QuicConnectionHelper();
// QuicConnectionHelperInterface
- virtual void SetConnection(QuicConnection* connection) OVERRIDE;
virtual const QuicClock* GetClock() const OVERRIDE;
virtual QuicRandom* GetRandomGenerator() OVERRIDE;
- virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
- int* error) OVERRIDE;
- virtual bool IsWriteBlockedDataBuffered() OVERRIDE;
- virtual bool IsWriteBlocked(int error) OVERRIDE;
virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE;
private:
- friend class test::QuicConnectionHelperPeer;
-
- // A completion callback invoked when a write completes.
- void OnWriteComplete(int result);
-
base::WeakPtrFactory<QuicConnectionHelper> weak_factory_;
base::TaskRunner* task_runner_;
- DatagramClientSocket* socket_;
- QuicConnection* connection_;
const QuicClock* clock_;
QuicRandom* random_generator_;
diff --git a/chromium/net/quic/quic_connection_helper_test.cc b/chromium/net/quic/quic_connection_helper_test.cc
index aaa692b548c..2e677221a84 100644
--- a/chromium/net/quic/quic_connection_helper_test.cc
+++ b/chromium/net/quic/quic_connection_helper_test.cc
@@ -4,29 +4,14 @@
#include "net/quic/quic_connection_helper.h"
-#include <vector>
-
-#include "net/base/net_errors.h"
-#include "net/quic/crypto/quic_decrypter.h"
-#include "net/quic/crypto/quic_encrypter.h"
-#include "net/quic/quic_connection.h"
#include "net/quic/test_tools/mock_clock.h"
-#include "net/quic/test_tools/quic_connection_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/quic/test_tools/mock_random.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"
-using testing::_;
-using testing::AnyNumber;
-using testing::Return;
-
namespace net {
namespace test {
-
-const char kData[] = "foo";
-const bool kFromPeer = true;
+namespace {
class TestDelegate : public QuicAlarm::Delegate {
public:
@@ -38,226 +23,44 @@ class TestDelegate : public QuicAlarm::Delegate {
}
bool fired() const { return fired_; }
+ void Clear() { fired_= false; }
private:
bool fired_;
};
-class TestConnection : public QuicConnection {
- public:
- TestConnection(QuicGuid guid,
- IPEndPoint address,
- QuicConnectionHelper* helper)
- : QuicConnection(guid, address, helper, false, QuicVersionMax()) {
- }
-
- void SendAck() {
- QuicConnectionPeer::SendAck(this);
- }
-
- void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
- QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
- }
-
- using QuicConnection::SendOrQueuePacket;
-};
-
class QuicConnectionHelperTest : public ::testing::Test {
protected:
- // 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)
- : mode(mode),
- packet(packet) {
- }
- IoMode mode;
- QuicEncryptedPacket* packet;
- };
-
QuicConnectionHelperTest()
- : guid_(2),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
- net_log_(BoundNetLog()),
- frame_(1, false, 0, kData) {
- Initialize();
- }
-
- ~QuicConnectionHelperTest() {
- for (size_t i = 0; i < writes_.size(); i++) {
- delete writes_[i].packet;
- }
- }
-
- // Adds a packet to the list of expected writes.
- void AddWrite(IoMode mode, QuicEncryptedPacket* packet) {
- writes_.push_back(PacketToWrite(mode, packet));
- }
-
- // Returns the packet to be written at position |pos|.
- QuicEncryptedPacket* GetWrite(size_t pos) {
- return writes_[pos].packet;
- }
-
- bool AtEof() {
- return socket_data_->at_read_eof() && socket_data_->at_write_eof();
- }
-
- // 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++) {
- mock_writes_[i] = MockWrite(writes_[i].mode,
- writes_[i].packet->data(),
- writes_[i].packet->length());
- };
-
- socket_data_.reset(new StaticSocketDataProvider(NULL, 0, mock_writes_.get(),
- writes_.size()));
-
- socket_.reset(new MockUDPClientSocket(socket_data_.get(),
- net_log_.net_log()));
- socket_->Connect(IPEndPoint());
- runner_ = new TestTaskRunner(&clock_);
- helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
- &random_generator_, socket_.get());
- send_algorithm_ = new testing::StrictMock<MockSendAlgorithm>();
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
- WillRepeatedly(Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
- Return(QuicBandwidth::FromKBitsPerSecond(100)));
- EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(
- Return(QuicTime::Delta::FromMilliseconds(100)));
- ON_CALL(*send_algorithm_, SentPacket(_, _, _, _, _))
- .WillByDefault(Return(true));
- EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber());
- connection_.reset(new TestConnection(guid_, IPEndPoint(), helper_));
- connection_->set_visitor(&visitor_);
- connection_->SetSendAlgorithm(send_algorithm_);
+ : runner_(new TestTaskRunner(&clock_)),
+ helper_(runner_.get(), &clock_, &random_generator_) {
}
- // Returns a newly created packet to send kData on stream 1.
- QuicEncryptedPacket* ConstructDataPacket(
- QuicPacketSequenceNumber sequence_number) {
- InitializeHeader(sequence_number);
-
- return ConstructPacket(header_, QuicFrame(&frame_));
- }
-
- // Returns a newly created packet to send kData on stream 1.
- QuicPacket* ConstructRawDataPacket(
- QuicPacketSequenceNumber sequence_number) {
- InitializeHeader(sequence_number);
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&frame_));
- return framer_.BuildUnsizedDataPacket(header_, frames).packet;
- }
-
- // Returns a newly created packet to send ack data.
- QuicEncryptedPacket* ConstructAckPacket(
- QuicPacketSequenceNumber sequence_number) {
- InitializeHeader(sequence_number);
-
- QuicAckFrame ack(0, QuicTime::Zero(), sequence_number);
- ack.sent_info.entropy_hash = 0;
- ack.received_info.entropy_hash = 0;
-
- QuicCongestionFeedbackFrame feedback;
- feedback.type = kTCP;
- feedback.tcp.accumulated_number_of_lost_packets = 0;
- feedback.tcp.receive_window = 16000 << 4;
-
- QuicFrames frames;
- frames.push_back(QuicFrame(&ack));
- frames.push_back(QuicFrame(&feedback));
- scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header_, frames).packet);
- return framer_.EncryptPacket(
- ENCRYPTION_NONE, header_.packet_sequence_number, *packet);
- }
-
- // Returns a newly created packet to send a connection close frame.
- QuicEncryptedPacket* ConstructClosePacket(
- QuicPacketSequenceNumber sequence_number,
- QuicPacketSequenceNumber least_waiting) {
- InitializeHeader(sequence_number);
-
- QuicFrames frames;
- QuicAckFrame ack(0, QuicTime::Zero(), least_waiting + 1);
- ack.sent_info.entropy_hash = 0;
- ack.received_info.entropy_hash = 0;
- QuicConnectionCloseFrame close;
- close.error_code = QUIC_CONNECTION_TIMED_OUT;
- close.ack_frame = ack;
-
- return ConstructPacket(header_, QuicFrame(&close));
- }
-
- testing::StrictMock<MockSendAlgorithm>* send_algorithm_;
scoped_refptr<TestTaskRunner> runner_;
- QuicConnectionHelper* helper_;
- scoped_ptr<MockUDPClientSocket> socket_;
- scoped_ptr<MockWrite[]> mock_writes_;
+ QuicConnectionHelper helper_;
MockClock clock_;
MockRandom random_generator_;
- scoped_ptr<TestConnection> connection_;
- testing::StrictMock<MockConnectionVisitor> visitor_;
-
- private:
- void InitializeHeader(QuicPacketSequenceNumber sequence_number) {
- header_.public_header.guid = guid_;
- header_.public_header.reset_flag = false;
- header_.public_header.version_flag = true;
- header_.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
- header_.packet_sequence_number = sequence_number;
- header_.entropy_flag = false;
- header_.fec_flag = false;
- header_.is_in_fec_group = NOT_IN_FEC_GROUP;
- header_.fec_group = 0;
- }
-
- QuicEncryptedPacket* ConstructPacket(const QuicPacketHeader& header,
- const QuicFrame& frame) {
- QuicFrames frames;
- frames.push_back(frame);
- scoped_ptr<QuicPacket> packet(
- framer_.BuildUnsizedDataPacket(header_, frames).packet);
- return framer_.EncryptPacket(
- ENCRYPTION_NONE, header_.packet_sequence_number, *packet);
- }
-
- QuicGuid guid_;
- QuicFramer framer_;
- QuicPacketHeader header_;
- BoundNetLog net_log_;
- QuicStreamFrame frame_;
- scoped_ptr<StaticSocketDataProvider> socket_data_;
- std::vector<PacketToWrite> writes_;
};
TEST_F(QuicConnectionHelperTest, GetClock) {
- EXPECT_EQ(&clock_, helper_->GetClock());
+ EXPECT_EQ(&clock_, helper_.GetClock());
}
TEST_F(QuicConnectionHelperTest, GetRandomGenerator) {
- EXPECT_EQ(&random_generator_, helper_->GetRandomGenerator());
+ EXPECT_EQ(&random_generator_, helper_.GetRandomGenerator());
}
TEST_F(QuicConnectionHelperTest, CreateAlarm) {
TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
-
- // The timeout alarm task is always posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
alarm->Set(clock_.Now().Add(delta));
// Verify that the alarm task has been posted.
- ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ ASSERT_EQ(1u, runner_->GetPostedTasks().size());
EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[1].delay);
+ runner_->GetPostedTasks()[0].delay);
runner_->RunNextTask();
EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
@@ -266,16 +69,16 @@ TEST_F(QuicConnectionHelperTest, CreateAlarm) {
TEST_F(QuicConnectionHelperTest, CreateAlarmAndCancel) {
TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
alarm->Set(clock_.Now().Add(delta));
alarm->Cancel();
// The alarm task should still be posted.
- ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ ASSERT_EQ(1u, runner_->GetPostedTasks().size());
EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[1].delay);
+ runner_->GetPostedTasks()[0].delay);
runner_->RunNextTask();
EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
@@ -284,7 +87,7 @@ TEST_F(QuicConnectionHelperTest, CreateAlarmAndCancel) {
TEST_F(QuicConnectionHelperTest, CreateAlarmAndReset) {
TestDelegate* delegate = new TestDelegate();
- scoped_ptr<QuicAlarm> alarm(helper_->CreateAlarm(delegate));
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
alarm->Set(clock_.Now().Add(delta));
@@ -293,209 +96,51 @@ TEST_F(QuicConnectionHelperTest, CreateAlarmAndReset) {
alarm->Set(clock_.Now().Add(new_delta));
// The alarm task should still be posted.
- ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ ASSERT_EQ(1u, runner_->GetPostedTasks().size());
EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[1].delay);
+ runner_->GetPostedTasks()[0].delay);
runner_->RunNextTask();
EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
EXPECT_FALSE(delegate->fired());
// The alarm task should be posted again.
- ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ ASSERT_EQ(1u, runner_->GetPostedTasks().size());
runner_->RunNextTask();
EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
EXPECT_TRUE(delegate->fired());
}
-TEST_F(QuicConnectionHelperTest, TestRetransmission) {
- AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
- AddWrite(SYNCHRONOUS, ConstructDataPacket(2));
- Initialize();
-
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
-
- QuicTime::Delta kDefaultRetransmissionTime =
- QuicTime::Delta::FromMilliseconds(500);
- QuicTime start = clock_.ApproximateNow();
-
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION, _));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _));
-
- // Send a packet.
- struct iovec iov = {const_cast<char*>(kData),
- static_cast<size_t>(strlen(kData))};
- connection_->SendvStreamData(1, &iov, 1, 0, false);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, IS_RETRANSMISSION, _));
- // Since no ack was received, the retransmission alarm will fire and
- // retransmit it.
- runner_->RunNextTask();
-
- EXPECT_EQ(kDefaultRetransmissionTime,
- clock_.ApproximateNow().Subtract(start));
- EXPECT_TRUE(AtEof());
-}
+TEST_F(QuicConnectionHelperTest, CreateAlarmAndResetEarlier) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
-TEST_F(QuicConnectionHelperTest, TestMultipleRetransmission) {
- AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
- AddWrite(SYNCHRONOUS, ConstructDataPacket(2));
- AddWrite(SYNCHRONOUS, ConstructDataPacket(3));
- Initialize();
-
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
-
- QuicTime::Delta kDefaultRetransmissionTime =
- QuicTime::Delta::FromMilliseconds(500);
- QuicTime start = clock_.ApproximateNow();
-
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION, _));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _));
-
- // Send a packet.
- struct iovec iov = {const_cast<char*>(kData),
- static_cast<size_t>(strlen(kData))};
- connection_->SendvStreamData(1, &iov, 1, 0, false);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, IS_RETRANSMISSION, _));
- // Since no ack was received, the retransmission alarm will fire and
- // retransmit it.
- runner_->RunNextTask();
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(3);
+ alarm->Set(clock_.Now().Add(delta));
+ alarm->Cancel();
+ QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(clock_.Now().Add(new_delta));
- EXPECT_EQ(kDefaultRetransmissionTime,
- clock_.ApproximateNow().Subtract(start));
+ // Both alarm tasks will be posted.
+ ASSERT_EQ(2u, runner_->GetPostedTasks().size());
- // Since no ack was received, the retransmission alarm will fire and
- // retransmit it.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 3, _, IS_RETRANSMISSION, _));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(2, _));
+ // The earlier task will execute and will fire the alarm->
runner_->RunNextTask();
+ EXPECT_EQ(QuicTime::Zero().Add(new_delta), clock_.Now());
+ EXPECT_TRUE(delegate->fired());
+ delegate->Clear();
- EXPECT_EQ(kDefaultRetransmissionTime.Add(kDefaultRetransmissionTime),
- clock_.ApproximateNow().Subtract(start));
-
- EXPECT_TRUE(AtEof());
-}
-
-TEST_F(QuicConnectionHelperTest, InitialTimeout) {
- AddWrite(SYNCHRONOUS, ConstructClosePacket(1, 0));
- Initialize();
-
- // Verify that a single task was posted.
+ // The latter task is still posted.
ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- EXPECT_EQ(base::TimeDelta::FromSeconds(kDefaultInitialTimeoutSecs),
- runner_->GetPostedTasks().front().delay);
-
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA));
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillOnce(
- Return(QuicTime::Delta::FromMicroseconds(1)));
- // After we run the next task, we should close the connection.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
-
- runner_->RunNextTask();
- EXPECT_EQ(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(
- kDefaultInitialTimeoutSecs)),
- clock_.ApproximateNow());
- EXPECT_FALSE(connection_->connected());
- EXPECT_TRUE(AtEof());
-}
-
-TEST_F(QuicConnectionHelperTest, WritePacketToWire) {
- AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
- Initialize();
-
- int len = GetWrite(0)->length();
- int error = 0;
- EXPECT_EQ(len, helper_->WritePacketToWire(*GetWrite(0), &error));
- EXPECT_EQ(0, error);
- EXPECT_TRUE(AtEof());
-}
-
-TEST_F(QuicConnectionHelperTest, WritePacketToWireAsync) {
- AddWrite(ASYNC, ConstructClosePacket(1, 0));
- Initialize();
-
- EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(Return(true));
- int error = 0;
- EXPECT_EQ(-1, helper_->WritePacketToWire(*GetWrite(0), &error));
- EXPECT_EQ(ERR_IO_PENDING, error);
- base::MessageLoop::current()->RunUntilIdle();
- EXPECT_TRUE(AtEof());
-}
-TEST_F(QuicConnectionHelperTest, TimeoutAfterSend) {
- AddWrite(SYNCHRONOUS, ConstructAckPacket(1));
- AddWrite(SYNCHRONOUS, ConstructClosePacket(2, 1));
- Initialize();
-
- EXPECT_TRUE(connection_->connected());
- QuicTime start = clock_.ApproximateNow();
-
- // When we send a packet, the timeout will change to 5000 +
- // kDefaultInitialTimeoutSecs.
- clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(5000));
- EXPECT_EQ(5000u, clock_.ApproximateNow().Subtract(start).ToMicroseconds());
- EXPECT_CALL(*send_algorithm_,
- SentPacket(_, 1, _, NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA));
-
- // Send an ack so we don't set the retransmission alarm.
- connection_->SendAck();
-
- // The original alarm will fire. We should not time out because we had a
- // network event at t=5000. The alarm will reregister.
- runner_->RunNextTask();
-
- EXPECT_EQ(QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(
- kDefaultInitialTimeoutSecs)),
- clock_.ApproximateNow());
- EXPECT_TRUE(connection_->connected());
-
- // This time, we should time out.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, !kFromPeer));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA));
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillOnce(
- Return(QuicTime::Delta::FromMicroseconds(1)));
+ // When the latter task is executed, the weak ptr will be invalid and
+ // the alarm will not fire.
runner_->RunNextTask();
- EXPECT_EQ(kDefaultInitialTimeoutSecs * 1000000 + 5000,
- clock_.ApproximateNow().Subtract(
- QuicTime::Zero()).ToMicroseconds());
- EXPECT_FALSE(connection_->connected());
- EXPECT_TRUE(AtEof());
-}
-
-TEST_F(QuicConnectionHelperTest, SendSchedulerDelayThenSend) {
- AddWrite(SYNCHRONOUS, ConstructDataPacket(1));
- Initialize();
-
- // Test that if we send a packet with a delay, it ends up queued.
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(
- *send_algorithm_, TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
- Return(QuicTime::Delta::FromMicroseconds(1)));
-
- QuicPacket* packet = ConstructRawDataPacket(1);
- connection_->SendOrQueuePacket(ENCRYPTION_NONE, 1, packet, 0,
- HAS_RETRANSMITTABLE_DATA,
- QuicConnection::NO_FORCE);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION,
- _));
- EXPECT_EQ(1u, connection_->NumQueuedPackets());
-
- // Advance the clock to fire the alarm, and configure the scheduler
- // to permit the packet to be sent.
- EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(Return(true));
- EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber());
- runner_->RunNextTask();
- EXPECT_EQ(0u, connection_->NumQueuedPackets());
- EXPECT_TRUE(AtEof());
+ EXPECT_EQ(QuicTime::Zero().Add(delta), clock_.Now());
+ EXPECT_FALSE(delegate->fired());
}
+} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_connection_logger.cc b/chromium/net/quic/quic_connection_logger.cc
index 5195f4391a3..174d99a58c6 100644
--- a/chromium/net/quic/quic_connection_logger.cc
+++ b/chromium/net/quic/quic_connection_logger.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "net/base/net_log.h"
@@ -33,15 +34,15 @@ base::Value* NetLogQuicPacketSentCallback(
QuicPacketSequenceNumber sequence_number,
EncryptionLevel level,
size_t packet_size,
- int rv,
+ WriteResult result,
NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->SetInteger("encryption_level", level);
dict->SetString("packet_sequence_number",
base::Uint64ToString(sequence_number));
dict->SetInteger("size", packet_size);
- if (rv < 0) {
- dict->SetInteger("net_error", rv);
+ if (result.status != WRITE_STATUS_OK) {
+ dict->SetInteger("net_error", result.error_code);
}
return dict;
}
@@ -79,7 +80,7 @@ base::Value* NetLogQuicStreamFrameCallback(const QuicStreamFrame* frame,
dict->SetInteger("stream_id", frame->stream_id);
dict->SetBoolean("fin", frame->fin);
dict->SetString("offset", base::Uint64ToString(frame->offset));
- dict->SetInteger("length", frame->data.length());
+ dict->SetInteger("length", frame->data.TotalBufferSize());
return dict;
}
@@ -182,7 +183,7 @@ base::Value* NetLogQuicCryptoHandshakeMessageCallback(
return dict;
}
-base::Value* NetLogQuicConnectionClosedCallback(
+base::Value* NetLogQuicOnConnectionClosedCallback(
QuicErrorCode error,
bool from_peer,
NetLog::LogLevel /* log_level */) {
@@ -233,6 +234,8 @@ void QuicConnectionLogger::OnFrameAddedToPacket(const QuicFrame& frame) {
frame.congestion_feedback_frame));
break;
case RST_STREAM_FRAME:
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.RstStreamErrorCodeClient",
+ frame.rst_stream_frame->error_code);
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_SENT,
base::Bind(&NetLogQuicRstStreamFrameCallback,
@@ -255,11 +258,11 @@ void QuicConnectionLogger::OnPacketSent(
QuicPacketSequenceNumber sequence_number,
EncryptionLevel level,
const QuicEncryptedPacket& packet,
- int rv) {
+ WriteResult result) {
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_PACKET_SENT,
base::Bind(&NetLogQuicPacketSentCallback, sequence_number, level,
- packet.length(), rv));
+ packet.length(), result));
}
void QuicConnectionLogger:: OnPacketRetransmitted(
@@ -365,6 +368,8 @@ void QuicConnectionLogger::OnCongestionFeedbackFrame(
}
void QuicConnectionLogger::OnRstStreamFrame(const QuicRstStreamFrame& frame) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.RstStreamErrorCodeServer",
+ frame.error_code);
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_RST_STREAM_FRAME_RECEIVED,
base::Bind(&NetLogQuicRstStreamFrameCallback, &frame));
@@ -411,11 +416,11 @@ void QuicConnectionLogger::OnCryptoHandshakeMessageSent(
base::Bind(&NetLogQuicCryptoHandshakeMessageCallback, &message));
}
-void QuicConnectionLogger::OnConnectionClose(QuicErrorCode error,
- bool from_peer) {
+void QuicConnectionLogger::OnConnectionClosed(QuicErrorCode error,
+ bool from_peer) {
net_log_.AddEvent(
NetLog::TYPE_QUIC_SESSION_CLOSED,
- base::Bind(&NetLogQuicConnectionClosedCallback, error, from_peer));
+ base::Bind(&NetLogQuicOnConnectionClosedCallback, error, from_peer));
}
void QuicConnectionLogger::OnSuccessfulVersionNegotiation(
diff --git a/chromium/net/quic/quic_connection_logger.h b/chromium/net/quic/quic_connection_logger.h
index d498b128bd5..d162282204a 100644
--- a/chromium/net/quic/quic_connection_logger.h
+++ b/chromium/net/quic/quic_connection_logger.h
@@ -6,6 +6,7 @@
#define NET_QUIC_QUIC_CONNECTION_LOGGER_H_
#include "net/quic/quic_connection.h"
+#include "net/quic/quic_protocol.h"
namespace net {
@@ -28,7 +29,7 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
virtual void OnPacketSent(QuicPacketSequenceNumber sequence_number,
EncryptionLevel level,
const QuicEncryptedPacket& packet,
- int rv) OVERRIDE;
+ WriteResult result) OVERRIDE;
virtual void OnPacketRetransmitted(
QuicPacketSequenceNumber old_sequence_number,
QuicPacketSequenceNumber new_sequence_number) OVERRIDE;
@@ -55,7 +56,7 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger
const CryptoHandshakeMessage& message);
void OnCryptoHandshakeMessageSent(
const CryptoHandshakeMessage& message);
- void OnConnectionClose(QuicErrorCode error, bool from_peer);
+ void OnConnectionClosed(QuicErrorCode error, bool from_peer);
void OnSuccessfulVersionNegotiation(const QuicVersion& version);
private:
diff --git a/chromium/net/quic/quic_connection_stats.cc b/chromium/net/quic/quic_connection_stats.cc
index f66a5cba799..500b5f39166 100644
--- a/chromium/net/quic/quic_connection_stats.cc
+++ b/chromium/net/quic/quic_connection_stats.cc
@@ -4,13 +4,17 @@
#include "net/quic/quic_connection_stats.h"
+using std::ostream;
+
namespace net {
QuicConnectionStats::QuicConnectionStats()
: bytes_sent(0),
packets_sent(0),
+ stream_bytes_sent(0),
bytes_received(0),
packets_received(0),
+ stream_bytes_received(0),
bytes_retransmitted(0),
packets_retransmitted(0),
packets_revived(0),
@@ -22,4 +26,22 @@ QuicConnectionStats::QuicConnectionStats()
QuicConnectionStats::~QuicConnectionStats() {}
+ostream& operator<<(ostream& os, const QuicConnectionStats& s) {
+ os << "{ bytes sent: " << s.bytes_sent
+ << ", packets sent:" << s.packets_sent
+ << ", stream bytes sent: " << s.stream_bytes_sent
+ << ", bytes received: " << s.bytes_received
+ << ", packets received: " << s.packets_received
+ << ", stream bytes received: " << s.stream_bytes_received
+ << ", bytes retransmitted: " << s.bytes_retransmitted
+ << ", packets retransmitted: " << s.packets_retransmitted
+ << ", packets revived: " << s.packets_revived
+ << ", packets dropped:" << s.packets_dropped
+ << ", rto count: " << s.rto_count
+ << ", rtt(us): " << s.rtt
+ << ", estimated_bandwidth: " << s.estimated_bandwidth
+ << "}\n";
+ return os;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_connection_stats.h b/chromium/net/quic/quic_connection_stats.h
index f9336621f99..b0761d9ba8f 100644
--- a/chromium/net/quic/quic_connection_stats.h
+++ b/chromium/net/quic/quic_connection_stats.h
@@ -5,6 +5,8 @@
#ifndef NET_QUIC_QUIC_CONNECTION_STATS_H_
#define NET_QUIC_QUIC_CONNECTION_STATS_H_
+#include <ostream>
+
#include "base/basictypes.h"
#include "net/base/net_export.h"
@@ -15,23 +17,26 @@ namespace net {
// 3. CHLO sent to SHLO received time.
// 4. Number of migrations.
// 5. Number of out of order packets.
-// 6. Avg packet size.
-// 7. Number of connections that require more that 1-RTT.
-// 8. Avg number of streams / session.
-// 9. Number of duplicates received.
-// 10. Fraction of traffic sent/received that was not data (protocol overhead).
-// 11. Fraction of data transferred that was padding.
+// 6. Number of connections that require more that 1-RTT.
+// 7. Avg number of streams / session.
+// 8. Number of duplicates received.
+// 9. Fraction of data transferred that was padding.
// Structure to hold stats for a QuicConnection.
struct NET_EXPORT_PRIVATE QuicConnectionStats {
QuicConnectionStats();
~QuicConnectionStats();
+ NET_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os, const QuicConnectionStats& s);
+
uint64 bytes_sent; // includes retransmissions, fec.
uint32 packets_sent;
+ uint64 stream_bytes_sent; // non-retransmitted bytes sent in a stream frame.
uint64 bytes_received; // includes duplicate data for a stream, fec.
uint32 packets_received; // includes dropped packets
+ uint64 stream_bytes_received; // bytes received in a stream frame.
uint64 bytes_retransmitted;
uint32 packets_retransmitted;
@@ -40,7 +45,7 @@ struct NET_EXPORT_PRIVATE QuicConnectionStats {
uint32 packets_dropped; // duplicate or less than least unacked.
uint32 rto_count;
- uint32 rtt;
+ uint32 rtt; // In microseconds
uint64 estimated_bandwidth;
// TODO(satyamshekhar): Add window_size, mss and mtu.
};
diff --git a/chromium/net/quic/quic_connection_test.cc b/chromium/net/quic/quic_connection_test.cc
index afe8a7663b8..39655d0fe2a 100644
--- a/chromium/net/quic/quic_connection_test.cc
+++ b/chromium/net/quic/quic_connection_test.cc
@@ -6,14 +6,15 @@
#include "base/basictypes.h"
#include "base/bind.h"
+#include "base/stl_util.h"
#include "net/base/net_errors.h"
#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
#include "net/quic/crypto/null_encrypter.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
-#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_sent_packet_manager.h"
#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/mock_clock.h"
#include "net/quic/test_tools/mock_random.h"
@@ -51,6 +52,7 @@ const bool kEntropyFlag = true;
const QuicPacketEntropyHash kTestEntropyHash = 76;
const int kDefaultRetransmissionTimeMs = 500;
+const int kMinRetransmissionTimeMs = 200;
// Used by TestConnection::SendStreamData3.
const QuicStreamId kStreamId3 = 3;
@@ -236,21 +238,16 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
virtual void SetImpl() OVERRIDE {}
virtual void CancelImpl() OVERRIDE {}
+ using QuicAlarm::Fire;
};
TestConnectionHelper(MockClock* clock, MockRandom* random_generator)
: clock_(clock),
- random_generator_(random_generator),
- blocked_(false),
- is_server_(true),
- use_tagging_decrypter_(false),
- packets_write_attempts_(0) {
+ random_generator_(random_generator) {
clock_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
}
// QuicConnectionHelperInterface
- virtual void SetConnection(QuicConnection* connection) OVERRIDE {}
-
virtual const QuicClock* GetClock() const OVERRIDE {
return clock_;
}
@@ -259,68 +256,80 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
return random_generator_;
}
- virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
- int* error) OVERRIDE {
+ virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE {
+ return new TestAlarm(delegate);
+ }
+
+ private:
+ MockClock* clock_;
+ MockRandom* random_generator_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestConnectionHelper);
+};
+
+class TestPacketWriter : public QuicPacketWriter {
+ public:
+ TestPacketWriter()
+ : last_packet_size_(0),
+ blocked_(false),
+ is_write_blocked_data_buffered_(false),
+ is_server_(true),
+ final_bytes_of_last_packet_(0),
+ final_bytes_of_previous_packet_(0),
+ use_tagging_decrypter_(false),
+ packets_write_attempts_(0) {
+ }
+
+ // QuicPacketWriter
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
+ QuicEncryptedPacket packet(buffer, buf_len);
++packets_write_attempts_;
if (packet.length() >= sizeof(final_bytes_of_last_packet_)) {
+ final_bytes_of_previous_packet_ = final_bytes_of_last_packet_;
memcpy(&final_bytes_of_last_packet_, packet.data() + packet.length() - 4,
sizeof(final_bytes_of_last_packet_));
}
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), is_server_);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), !is_server_);
if (use_tagging_decrypter_) {
framer.SetDecrypter(new TaggingDecrypter);
}
- FramerVisitorCapturingFrames visitor;
- framer.set_visitor(&visitor);
+ visitor_.Reset();
+ framer.set_visitor(&visitor_);
EXPECT_TRUE(framer.ProcessPacket(packet));
- header_ = *visitor.header();
- frame_count_ = visitor.frame_count();
- if (visitor.ack()) {
- ack_.reset(new QuicAckFrame(*visitor.ack()));
- }
- if (visitor.feedback()) {
- feedback_.reset(new QuicCongestionFeedbackFrame(*visitor.feedback()));
- }
- if (visitor.stream_frames() != NULL && !visitor.stream_frames()->empty()) {
- stream_frames_ = *visitor.stream_frames();
- }
- if (visitor.version_negotiation_packet() != NULL) {
- version_negotiation_packet_.reset(new QuicVersionNegotiationPacket(
- *visitor.version_negotiation_packet()));
- }
if (blocked_) {
- *error = ERR_IO_PENDING;
- return -1;
+ return WriteResult(WRITE_STATUS_BLOCKED, -1);
}
- *error = 0;
last_packet_size_ = packet.length();
- return last_packet_size_;
+ return WriteResult(WRITE_STATUS_OK, last_packet_size_);
}
- virtual bool IsWriteBlockedDataBuffered() OVERRIDE {
- return false;
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE {
+ return is_write_blocked_data_buffered_;
}
- virtual bool IsWriteBlocked(int error) OVERRIDE {
- return error == ERR_IO_PENDING;
+ // Resets the visitor's state by clearing out the headers and frames.
+ void Reset() {
+ visitor_.Reset();
}
- virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE {
- return new TestAlarm(delegate);
- }
+ QuicPacketHeader* header() { return visitor_.header(); }
- QuicPacketHeader* header() { return &header_; }
+ size_t frame_count() const { return visitor_.frame_count(); }
- size_t frame_count() const { return frame_count_; }
+ QuicAckFrame* ack() { return visitor_.ack(); }
- QuicAckFrame* ack() { return ack_.get(); }
+ QuicCongestionFeedbackFrame* feedback() { return visitor_.feedback(); }
- QuicCongestionFeedbackFrame* feedback() { return feedback_.get(); }
+ QuicConnectionCloseFrame* close() { return visitor_.close(); }
const vector<QuicStreamFrame>* stream_frames() const {
- return &stream_frames_;
+ return visitor_.stream_frames();
}
size_t last_packet_size() {
@@ -328,11 +337,15 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
}
QuicVersionNegotiationPacket* version_negotiation_packet() {
- return version_negotiation_packet_.get();
+ return visitor_.version_negotiation_packet();
}
void set_blocked(bool blocked) { blocked_ = blocked; }
+ void set_is_write_blocked_data_buffered(bool buffered) {
+ is_write_blocked_data_buffered_ = buffered;
+ }
+
void set_is_server(bool is_server) { is_server_ = is_server; }
// final_bytes_of_last_packet_ returns the last four bytes of the previous
@@ -341,6 +354,11 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
// a given packet.
uint32 final_bytes_of_last_packet() { return final_bytes_of_last_packet_; }
+ // Returns the final bytes of the second to last packet.
+ uint32 final_bytes_of_previous_packet() {
+ return final_bytes_of_previous_packet_;
+ }
+
void use_tagging_decrypter() {
use_tagging_decrypter_ = true;
}
@@ -348,22 +366,17 @@ class TestConnectionHelper : public QuicConnectionHelperInterface {
uint32 packets_write_attempts() { return packets_write_attempts_; }
private:
- MockClock* clock_;
- MockRandom* random_generator_;
- QuicPacketHeader header_;
- size_t frame_count_;
- scoped_ptr<QuicAckFrame> ack_;
- scoped_ptr<QuicCongestionFeedbackFrame> feedback_;
- vector<QuicStreamFrame> stream_frames_;
- scoped_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
+ FramerVisitorCapturingFrames visitor_;
size_t last_packet_size_;
bool blocked_;
+ bool is_write_blocked_data_buffered_;
bool is_server_;
uint32 final_bytes_of_last_packet_;
+ uint32 final_bytes_of_previous_packet_;
bool use_tagging_decrypter_;
uint32 packets_write_attempts_;
- DISALLOW_COPY_AND_ASSIGN(TestConnectionHelper);
+ DISALLOW_COPY_AND_ASSIGN(TestPacketWriter);
};
class TestConnection : public QuicConnection {
@@ -371,10 +384,13 @@ class TestConnection : public QuicConnection {
TestConnection(QuicGuid guid,
IPEndPoint address,
TestConnectionHelper* helper,
+ TestPacketWriter* writer,
bool is_server)
- : QuicConnection(guid, address, helper, is_server, QuicVersionMax()),
- helper_(helper) {
- helper_->set_is_server(!is_server);
+ : QuicConnection(guid, address, helper, writer, is_server,
+ QuicSupportedVersions()),
+ helper_(helper),
+ writer_(writer) {
+ writer_->set_is_server(is_server);
}
void SendAck() {
@@ -389,46 +405,38 @@ class TestConnection : public QuicConnection {
QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
}
- bool SendOrQueuePacket(EncryptionLevel level,
- QuicPacketSequenceNumber sequence_number,
- QuicPacket* packet,
- QuicPacketEntropyHash entropy_hash,
- HasRetransmittableData retransmittable) {
- return SendOrQueuePacket(level,
- sequence_number,
- packet,
- entropy_hash,
- retransmittable,
- NO_FORCE);
- }
-
- QuicConsumedData SendStreamData(QuicStreamId id,
- StringPiece data,
- QuicStreamOffset offset,
- bool fin) {
- struct iovec iov = {const_cast<char*>(data.data()),
- static_cast<size_t>(data.size())};
- return SendvStreamData(id, &iov, 1, offset, fin);
+ void SendPacket(EncryptionLevel level,
+ QuicPacketSequenceNumber sequence_number,
+ QuicPacket* packet,
+ QuicPacketEntropyHash entropy_hash,
+ HasRetransmittableData retransmittable) {
+ RetransmittableFrames* retransmittable_frames =
+ retransmittable == HAS_RETRANSMITTABLE_DATA ?
+ new RetransmittableFrames() : NULL;
+ OnSerializedPacket(
+ SerializedPacket(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
+ packet, entropy_hash, retransmittable_frames));
}
- QuicConsumedData SendStreamDataAndNotifyWhenAcked(
+ QuicConsumedData SendStreamDataWithString(
QuicStreamId id,
StringPiece data,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier::DelegateInterface* delegate) {
- struct iovec iov = {const_cast<char*>(data.data()),
- static_cast<size_t>(data.size())};
- return SendvStreamDataAndNotifyWhenAcked(id, &iov, 1, offset, fin,
- delegate);
+ IOVector data_iov;
+ if (!data.empty()) {
+ data_iov.Append(const_cast<char*>(data.data()), data.size());
+ }
+ return QuicConnection::SendStreamData(id, data_iov, offset, fin, delegate);
}
QuicConsumedData SendStreamData3() {
- return SendStreamData(kStreamId3, "food", 0, !kFin);
+ return SendStreamDataWithString(kStreamId3, "food", 0, !kFin, NULL);
}
QuicConsumedData SendStreamData5() {
- return SendStreamData(kStreamId5, "food2", 0, !kFin);
+ return SendStreamDataWithString(kStreamId5, "food2", 0, !kFin, NULL);
}
// The crypto stream has special semantics so that it is not blocked by a
@@ -439,7 +447,7 @@ class TestConnection : public QuicConnection {
QuicConsumedData SendCryptoStreamData() {
this->Flush();
QuicConsumedData consumed =
- SendStreamData(kCryptoStreamId, "chlo", 0, !kFin);
+ SendStreamDataWithString(kCryptoStreamId, "chlo", 0, !kFin, NULL);
this->Flush();
return consumed;
}
@@ -453,51 +461,62 @@ class TestConnection : public QuicConnection {
}
void set_is_server(bool is_server) {
- helper_->set_is_server(!is_server);
+ writer_->set_is_server(is_server);
QuicPacketCreatorPeer::SetIsServer(
QuicConnectionPeer::GetPacketCreator(this), is_server);
QuicConnectionPeer::SetIsServer(this, is_server);
}
- QuicAlarm* GetAckAlarm() {
- return QuicConnectionPeer::GetAckAlarm(this);
+ TestConnectionHelper::TestAlarm* GetAckAlarm() {
+ return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+ QuicConnectionPeer::GetAckAlarm(this));
+ }
+
+ TestConnectionHelper::TestAlarm* GetRetransmissionAlarm() {
+ return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+ QuicConnectionPeer::GetRetransmissionAlarm(this));
}
- QuicAlarm* GetRetransmissionAlarm() {
- return QuicConnectionPeer::GetRetransmissionAlarm(this);
+ TestConnectionHelper::TestAlarm* GetSendAlarm() {
+ return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+ QuicConnectionPeer::GetSendAlarm(this));
}
- QuicAlarm* GetSendAlarm() {
- return QuicConnectionPeer::GetSendAlarm(this);
+ TestConnectionHelper::TestAlarm* GetResumeWritesAlarm() {
+ return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+ QuicConnectionPeer::GetResumeWritesAlarm(this));
}
- QuicAlarm* GetTimeoutAlarm() {
- return QuicConnectionPeer::GetTimeoutAlarm(this);
+ TestConnectionHelper::TestAlarm* GetTimeoutAlarm() {
+ return reinterpret_cast<TestConnectionHelper::TestAlarm*>(
+ QuicConnectionPeer::GetTimeoutAlarm(this));
}
- using QuicConnection::SendOrQueuePacket;
using QuicConnection::SelectMutualVersion;
private:
TestConnectionHelper* helper_;
+ TestPacketWriter* writer_;
DISALLOW_COPY_AND_ASSIGN(TestConnection);
};
-class QuicConnectionTest : public ::testing::Test {
+class QuicConnectionTest : public ::testing::TestWithParam<bool> {
protected:
QuicConnectionTest()
: guid_(42),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
- creator_(guid_, &framer_, QuicRandom::GetInstance(), false),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
+ creator_(guid_, &framer_, &random_generator_, false),
send_algorithm_(new StrictMock<MockSendAlgorithm>),
helper_(new TestConnectionHelper(&clock_, &random_generator_)),
- connection_(guid_, IPEndPoint(), helper_, false),
- frame1_(1, false, 0, data1),
- frame2_(1, false, 3, data2),
+ writer_(new TestPacketWriter()),
+ connection_(guid_, IPEndPoint(), helper_.get(), writer_.get(), false),
+ frame1_(1, false, 0, MakeIOVector(data1)),
+ frame2_(1, false, 3, MakeIOVector(data2)),
accept_packet_(true) {
connection_.set_visitor(&visitor_);
connection_.SetSendAlgorithm(send_algorithm_);
+ framer_.set_received_entropy_calculator(&entropy_calculator_);
// Simplify tests by not sending feedback unless specifically configured.
SetFeedback(NULL);
EXPECT_CALL(
@@ -505,23 +524,19 @@ class QuicConnectionTest : public ::testing::Test {
QuicTime::Delta::Zero()));
EXPECT_CALL(*receive_algorithm_,
RecordIncomingPacket(_, _, _, _)).Times(AnyNumber());
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(Return(
QuicBandwidth::FromKBitsPerSecond(100)));
EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(Return(
QuicTime::Delta::FromMilliseconds(100)));
- ON_CALL(*send_algorithm_, SentPacket(_, _, _, _, _))
+ ON_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.WillByDefault(Return(true));
- // TODO(rch): remove this.
- QuicConnection::g_acks_do_not_instigate_acks = true;
EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber());
- }
-
- ~QuicConnectionTest() {
- // TODO(rch): remove this.
- QuicConnection::g_acks_do_not_instigate_acks = false;
+ EXPECT_CALL(visitor_, OnCanWrite()).Times(AnyNumber()).WillRepeatedly(
+ Return(true));
}
QuicAckFrame* outgoing_ack() {
@@ -530,27 +545,35 @@ class QuicConnectionTest : public ::testing::Test {
}
QuicAckFrame* last_ack() {
- return helper_->ack();
+ return writer_->ack();
}
QuicCongestionFeedbackFrame* last_feedback() {
- return helper_->feedback();
+ return writer_->feedback();
+ }
+
+ QuicConnectionCloseFrame* last_close() {
+ return writer_->close();
}
QuicPacketHeader* last_header() {
- return helper_->header();
+ return writer_->header();
}
size_t last_sent_packet_size() {
- return helper_->last_packet_size();
+ return writer_->last_packet_size();
}
uint32 final_bytes_of_last_packet() {
- return helper_->final_bytes_of_last_packet();
+ return writer_->final_bytes_of_last_packet();
+ }
+
+ uint32 final_bytes_of_previous_packet() {
+ return writer_->final_bytes_of_previous_packet();
}
void use_tagging_decrypter() {
- helper_->use_tagging_decrypter();
+ writer_->use_tagging_decrypter();
}
void ProcessPacket(QuicPacketSequenceNumber number) {
@@ -664,32 +687,32 @@ class QuicConnectionTest : public ::testing::Test {
return encrypted->length();
}
- QuicByteCount SendStreamDataToPeer(QuicStreamId id, StringPiece data,
- QuicStreamOffset offset, bool fin,
+ QuicByteCount SendStreamDataToPeer(QuicStreamId id,
+ StringPiece data,
+ QuicStreamOffset offset,
+ bool fin,
QuicPacketSequenceNumber* last_packet) {
QuicByteCount packet_size;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
.WillOnce(DoAll(SaveArg<2>(&packet_size), Return(true)));
- connection_.SendStreamData(id, data, offset, fin);
+ connection_.SendStreamDataWithString(id, data, offset, fin, NULL);
if (last_packet != NULL) {
*last_packet =
QuicConnectionPeer::GetPacketCreator(&connection_)->sequence_number();
}
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AnyNumber());
return packet_size;
}
void SendAckPacketToPeer() {
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendAck();
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AnyNumber());
}
- QuicPacketEntropyHash ProcessAckPacket(QuicAckFrame* frame,
- bool expect_writes) {
- if (expect_writes) {
- EXPECT_CALL(visitor_, OnCanWrite()).Times(1).WillOnce(Return(true));
- }
+ QuicPacketEntropyHash ProcessAckPacket(QuicAckFrame* frame) {
return ProcessFramePacket(QuicFrame(frame));
}
@@ -735,7 +758,6 @@ class QuicConnectionTest : public ::testing::Test {
QuicConnectionCloseFrame qccf;
qccf.error_code = QUIC_PEER_GOING_AWAY;
- qccf.ack_frame = QuicAckFrame(0, QuicTime::Zero(), 1);
QuicFrames frames;
QuicFrame frame(&qccf);
@@ -755,15 +777,21 @@ class QuicConnectionTest : public ::testing::Test {
return QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs);
}
+ QuicTime::Delta DefaultDelayedAckTime() {
+ return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
+ }
+
QuicGuid guid_;
QuicFramer framer_;
QuicPacketCreator creator_;
+ MockEntropyCalculator entropy_calculator_;
MockSendAlgorithm* send_algorithm_;
TestReceiveAlgorithm* receive_algorithm_;
MockClock clock_;
MockRandom random_generator_;
- TestConnectionHelper* helper_;
+ scoped_ptr<TestConnectionHelper> helper_;
+ scoped_ptr<TestPacketWriter> writer_;
TestConnection connection_;
StrictMock<MockConnectionVisitor> visitor_;
@@ -865,7 +893,7 @@ TEST_F(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
// retransmitted, and will remove it from the missing list.
creator_.set_sequence_number(5);
QuicAckFrame frame(0, QuicTime::Zero(), 4);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
// Force an ack to be sent.
SendAckPacketToPeer();
@@ -875,36 +903,46 @@ TEST_F(QuicConnectionTest, PacketsOutOfOrderWithAdditionsAndLeastAwaiting) {
TEST_F(QuicConnectionTest, RejectPacketTooFarOut) {
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_PACKET_HEADER, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
ProcessDataPacket(6000, 0, !kEntropyFlag);
}
TEST_F(QuicConnectionTest, TruncatedAck) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(2);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- for (int i = 0; i < 200; ++i) {
+ QuicPacketSequenceNumber num_packets = 256 * 2 + 1;
+ for (QuicPacketSequenceNumber i = 0; i < num_packets; ++i) {
SendStreamDataToPeer(1, "foo", i * 3, !kFin, NULL);
}
- QuicAckFrame frame(0, QuicTime::Zero(), 1);
- frame.received_info.largest_observed = 193;
- InsertMissingPacketsBetween(&frame.received_info, 1, 193);
- frame.received_info.entropy_hash =
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 193) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 192);
-
- ProcessAckPacket(&frame, true);
+ QuicAckFrame frame(num_packets, QuicTime::Zero(), 1);
+ // Create an ack with 256 nacks, none adjacent to one another.
+ for (QuicPacketSequenceNumber i = 1; i <= 256; ++i) {
+ frame.received_info.missing_packets.insert(i * 2);
+ }
+ frame.received_info.entropy_hash = 0;
+ EXPECT_CALL(entropy_calculator_,
+ EntropyHash(511)).WillOnce(testing::Return(0));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(256);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+ ProcessAckPacket(&frame);
- EXPECT_TRUE(QuicConnectionPeer::GetReceivedTruncatedAck(&connection_));
+ QuicReceivedPacketManager* received_packet_manager =
+ QuicConnectionPeer::GetReceivedPacketManager(&connection_);
+ // A truncated ack will not have the true largest observed.
+ EXPECT_GT(num_packets,
+ received_packet_manager->peer_largest_observed_packet());
frame.received_info.missing_packets.erase(192);
- frame.received_info.entropy_hash =
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 193) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 191);
+ frame.received_info.entropy_hash = 2;
- ProcessAckPacket(&frame, true);
- EXPECT_FALSE(QuicConnectionPeer::GetReceivedTruncatedAck(&connection_));
+ // Removing one missing packet allows us to ack 192 and one more range.
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+ ProcessAckPacket(&frame);
+ EXPECT_EQ(num_packets,
+ received_packet_manager->peer_largest_observed_packet());
}
TEST_F(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
@@ -925,40 +963,72 @@ TEST_F(QuicConnectionTest, AckReceiptCausesAckSendBadEntropy) {
// Skip a packet and then record an ack.
creator_.set_sequence_number(2);
QuicAckFrame frame(0, QuicTime::Zero(), 3);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
+}
+
+TEST_F(QuicConnectionTest, OutOfOrderReceiptCausesAckSend) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ ProcessPacket(3);
+ // Should ack immediately since we have missing packets.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+
+ ProcessPacket(2);
+ // Should ack immediately since we have missing packets.
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
+
+ ProcessPacket(1);
+ // Should ack immediately, since this fills the last hole.
+ EXPECT_EQ(3u, writer_->packets_write_attempts());
+
+ ProcessPacket(4);
+ // Should not cause an ack.
+ EXPECT_EQ(3u, writer_->packets_write_attempts());
}
TEST_F(QuicConnectionTest, AckReceiptCausesAckSend) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- QuicPacketSequenceNumber largest_observed;
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
+ QuicPacketSequenceNumber original;
QuicByteCount packet_size;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _))
- .WillOnce(DoAll(SaveArg<1>(&largest_observed), SaveArg<2>(&packet_size),
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
+ .WillOnce(DoAll(SaveArg<1>(&original), SaveArg<2>(&packet_size),
Return(true)));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _)).Times(1);
- connection_.SendStreamData(1, "foo", 0, !kFin);
- QuicAckFrame frame(1, QuicTime::Zero(), largest_observed);
- frame.received_info.missing_packets.insert(largest_observed);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
+ QuicAckFrame frame(original, QuicTime::Zero(), 1);
+ frame.received_info.missing_packets.insert(original);
frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
- &connection_, largest_observed - 1);
- ProcessAckPacket(&frame, true);
- ProcessAckPacket(&frame, true);
- // Third nack should retransmit the largest observed packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, packet_size - kQuicVersionSize,
- IS_RETRANSMISSION, _));
- ProcessAckPacket(&frame, true);
+ &connection_, original - 1);
+ // First nack triggers early retransmit.
+ QuicPacketSequenceNumber retransmission;
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, packet_size - kQuicVersionSize,
+ NACK_RETRANSMISSION, _))
+ .WillOnce(DoAll(SaveArg<1>(&retransmission), Return(true)));
+ ProcessAckPacket(&frame);
+
+ QuicAckFrame frame2(retransmission, QuicTime::Zero(), 1);
+ frame2.received_info.missing_packets.insert(original);
+ frame2.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, retransmission) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, original);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _));
+
+ ProcessAckPacket(&frame2);
// Now if the peer sends an ack which still reports the retransmitted packet
// as missing, then that will count as a packet which instigates an ack.
- ProcessAckPacket(&frame, true);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _));
- ProcessAckPacket(&frame, true);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
+ ProcessAckPacket(&frame2);
+ ProcessAckPacket(&frame2);
- // But an ack with no new missing packest will not send an ack.
- frame.received_info.missing_packets.clear();
- ProcessAckPacket(&frame, true);
- ProcessAckPacket(&frame, true);
+ // But an ack with no missing packets will not send an ack.
+ frame2.received_info.missing_packets.clear();
+ frame2.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, retransmission);
+ ProcessAckPacket(&frame2);
+ ProcessAckPacket(&frame2);
}
TEST_F(QuicConnectionTest, LeastUnackedLower) {
@@ -968,24 +1038,25 @@ TEST_F(QuicConnectionTest, LeastUnackedLower) {
SendStreamDataToPeer(1, "bar", 3, !kFin, NULL);
SendStreamDataToPeer(1, "eep", 6, !kFin, NULL);
- // Start out saying the least unacked is 2
+ // Start out saying the least unacked is 2.
creator_.set_sequence_number(5);
QuicAckFrame frame(0, QuicTime::Zero(), 2);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
// Change it to 1, but lower the sequence number to fake out-of-order packets.
// This should be fine.
creator_.set_sequence_number(1);
QuicAckFrame frame2(0, QuicTime::Zero(), 1);
// The scheduler will not process out of order acks.
- ProcessAckPacket(&frame2, false);
+ EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
+ ProcessAckPacket(&frame2);
// Now claim it's one, but set the ordering so it was sent "after" the first
// one. This should cause a connection error.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, false));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
creator_.set_sequence_number(7);
- ProcessAckPacket(&frame2, false);
+ ProcessAckPacket(&frame2);
}
TEST_F(QuicConnectionTest, LargestObservedLower) {
@@ -994,52 +1065,29 @@ TEST_F(QuicConnectionTest, LargestObservedLower) {
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
SendStreamDataToPeer(1, "bar", 3, !kFin, NULL);
SendStreamDataToPeer(1, "eep", 6, !kFin, NULL);
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
// Start out saying the largest observed is 2.
QuicAckFrame frame(2, QuicTime::Zero(), 0);
frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
&connection_, 2);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
// Now change it to 1, and it should cause a connection error.
QuicAckFrame frame2(1, QuicTime::Zero(), 0);
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false));
- ProcessAckPacket(&frame2, false);
-}
-
-TEST_F(QuicConnectionTest, LeastUnackedGreaterThanPacketSequenceNumber) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- // Create an ack with least_unacked is 2 in packet number 1.
- creator_.set_sequence_number(0);
- QuicAckFrame frame(0, QuicTime::Zero(), 2);
- ProcessAckPacket(&frame, false);
-}
-
-TEST_F(QuicConnectionTest,
- NackSequenceNumberGreaterThanLargestReceived) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
- SendStreamDataToPeer(1, "bar", 3, !kFin, NULL);
- SendStreamDataToPeer(1, "eep", 6, !kFin, NULL);
-
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- QuicAckFrame frame(0, QuicTime::Zero(), 1);
- frame.received_info.missing_packets.insert(3);
- ProcessAckPacket(&frame, false);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, false));
+ EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
+ ProcessAckPacket(&frame2);
}
TEST_F(QuicConnectionTest, AckUnsentData) {
// Ack a packet which has not been sent.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_ACK_DATA, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, false));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
QuicAckFrame frame(1, QuicTime::Zero(), 0);
- ProcessAckPacket(&frame, false);
+ EXPECT_CALL(visitor_, OnCanWrite()).Times(0);
+ ProcessAckPacket(&frame);
}
TEST_F(QuicConnectionTest, AckAll) {
@@ -1048,7 +1096,7 @@ TEST_F(QuicConnectionTest, AckAll) {
creator_.set_sequence_number(1);
QuicAckFrame frame1(0, QuicTime::Zero(), 1);
- ProcessAckPacket(&frame1, true);
+ ProcessAckPacket(&frame1);
}
TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
@@ -1066,7 +1114,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillOnce(Return(
QuicBandwidth::FromKBitsPerSecond(1000 * 256)));
- SendStreamDataToPeer(1u, "bar", 3, !kFin, &last_packet);
+ SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet);
EXPECT_EQ(2u, last_packet);
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
connection_.options()->send_sequence_number_length);
@@ -1088,7 +1136,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillOnce(Return(
QuicBandwidth::FromKBitsPerSecond(1000ll * 256 * 256 * 256)));
- SendStreamDataToPeer(1u, "bar", 9, !kFin, &last_packet);
+ SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet);
EXPECT_EQ(4u, last_packet);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
connection_.options()->send_sequence_number_length);
@@ -1098,7 +1146,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsBandwidth) {
EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillOnce(Return(
QuicBandwidth::FromKBitsPerSecond(1000ll * 256 * 256 * 256 * 256)));
- SendStreamDataToPeer(1u, "foo", 12, !kFin, &last_packet);
+ SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet);
EXPECT_EQ(5u, last_packet);
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
connection_.options()->send_sequence_number_length);
@@ -1117,7 +1165,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(100);
- SendStreamDataToPeer(1u, "bar", 3, !kFin, &last_packet);
+ SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet);
EXPECT_EQ(PACKET_2BYTE_SEQUENCE_NUMBER,
connection_.options()->send_sequence_number_length);
EXPECT_EQ(PACKET_1BYTE_SEQUENCE_NUMBER,
@@ -1135,7 +1183,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
100 * 256 * 256);
- SendStreamDataToPeer(1u, "bar", 9, !kFin, &last_packet);
+ SendStreamDataToPeer(1, "bar", 9, !kFin, &last_packet);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
connection_.options()->send_sequence_number_length);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
@@ -1144,7 +1192,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
QuicConnectionPeer::GetPacketCreator(&connection_)->set_sequence_number(
100 * 256 * 256 * 256);
- SendStreamDataToPeer(1u, "foo", 12, !kFin, &last_packet);
+ SendStreamDataToPeer(1, "foo", 12, !kFin, &last_packet);
EXPECT_EQ(PACKET_6BYTE_SEQUENCE_NUMBER,
connection_.options()->send_sequence_number_length);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
@@ -1153,7 +1201,7 @@ TEST_F(QuicConnectionTest, SendingDifferentSequenceNumberLengthsUnackedDelta) {
TEST_F(QuicConnectionTest, BasicSending) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(6);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(6);
QuicPacketSequenceNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
EXPECT_EQ(1u, last_packet);
@@ -1164,7 +1212,7 @@ TEST_F(QuicConnectionTest, BasicSending) {
SendAckPacketToPeer(); // Packet 3
EXPECT_EQ(1u, last_ack()->sent_info.least_unacked);
- SendStreamDataToPeer(1u, "bar", 3, !kFin, &last_packet); // Packet 4
+ SendStreamDataToPeer(1, "bar", 3, !kFin, &last_packet); // Packet 4
EXPECT_EQ(4u, last_packet);
SendAckPacketToPeer(); // Packet 5
EXPECT_EQ(1u, last_ack()->sent_info.least_unacked);
@@ -1173,7 +1221,7 @@ TEST_F(QuicConnectionTest, BasicSending) {
QuicAckFrame frame(3, QuicTime::Zero(), 0);
frame.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 3);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
SendAckPacketToPeer(); // Packet 6
// As soon as we've acked one, we skip ack packets 2 and 3 and note lack of
@@ -1184,7 +1232,7 @@ TEST_F(QuicConnectionTest, BasicSending) {
QuicAckFrame frame2(6, QuicTime::Zero(), 0);
frame2.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 6);
- ProcessAckPacket(&frame2, true); // Acks don't instigate acks.
+ ProcessAckPacket(&frame2); // Acks don't instigate acks.
// Verify that we did not send an ack.
EXPECT_EQ(6u, last_header()->packet_sequence_number);
@@ -1214,11 +1262,11 @@ TEST_F(QuicConnectionTest, FECSending) {
connection_.options()->max_packets_per_fec_group = 2;
// Send 4 data packets and 2 FEC packets.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(6);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
// The first stream frame will consume 2 fewer bytes than the other three.
const string payload(payload_length * 4 - 6, 'a');
- connection_.SendStreamData(1, payload, 0, !kFin);
- // Expect the FEC group to be closed after SendStreamData.
+ connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
+ // Expect the FEC group to be closed after SendStreamDataWithString.
EXPECT_FALSE(creator_.ShouldSendFec(true));
}
@@ -1233,9 +1281,9 @@ TEST_F(QuicConnectionTest, FECQueueing) {
connection_.options()->max_packets_per_fec_group = 2;
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- helper_->set_blocked(true);
+ writer_->set_blocked(true);
const string payload(payload_length, 'a');
- connection_.SendStreamData(1, payload, 0, !kFin);
+ connection_.SendStreamDataWithString(1, payload, 0, !kFin, NULL);
EXPECT_FALSE(creator_.ShouldSendFec(true));
// Expect the first data packet and the fec packet to be queued.
EXPECT_EQ(2u, connection_.NumQueuedPackets());
@@ -1244,51 +1292,96 @@ TEST_F(QuicConnectionTest, FECQueueing) {
TEST_F(QuicConnectionTest, AbandonFECFromCongestionWindow) {
connection_.options()->max_packets_per_fec_group = 1;
// 1 Data and 1 FEC packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(2);
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
- // Larger timeout for FEC bytes to expire.
const QuicTime::Delta retransmission_time =
QuicTime::Delta::FromMilliseconds(5000);
clock_.AdvanceTime(retransmission_time);
- // Send only data packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
- // Abandon both FEC and data packet.
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(2);
-
+ // Abandon FEC packet and data packet.
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(visitor_, OnCanWrite());
connection_.OnRetransmissionTimeout();
}
TEST_F(QuicConnectionTest, DontAbandonAckedFEC) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.options()->max_packets_per_fec_group = 1;
- const QuicPacketSequenceNumber sequence_number =
- QuicConnectionPeer::GetPacketCreator(&connection_)->sequence_number() + 1;
// 1 Data and 1 FEC packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(2);
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ // Send some more data afterwards to ensure early retransmit doesn't trigger.
+ connection_.SendStreamDataWithString(1, "foo", 3, !kFin, NULL);
+ connection_.SendStreamDataWithString(1, "foo", 6, !kFin, NULL);
QuicAckFrame ack_fec(2, QuicTime::Zero(), 1);
// Data packet missing.
+ // TODO(ianswett): Note that this is not a sensible ack, since if the FEC was
+ // received, it would cause the covered packet to be acked as well.
ack_fec.received_info.missing_packets.insert(1);
ack_fec.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
- ProcessAckPacket(&ack_fec, true);
+ ProcessAckPacket(&ack_fec);
clock_.AdvanceTime(DefaultRetransmissionTime());
- // Abandon only data packet, FEC has been acked.
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(sequence_number, _)).Times(1);
- // Send only data packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
- connection_.OnRetransmissionTimeout();
+ // Don't abandon the acked FEC packet, but it will abandon 2 the subsequent
+ // FEC packets.
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(5);
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(3);
+ connection_.GetRetransmissionAlarm()->Fire();
+}
+
+TEST_F(QuicConnectionTest, DontAbandonAllFEC) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ connection_.options()->max_packets_per_fec_group = 1;
+
+ // 1 Data and 1 FEC packet.
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(6);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ // Send some more data afterwards to ensure early retransmit doesn't trigger.
+ connection_.SendStreamDataWithString(1, "foo", 3, !kFin, NULL);
+ // Advance the time so not all the FEC packets are abandoned.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
+ connection_.SendStreamDataWithString(1, "foo", 6, !kFin, NULL);
+
+ QuicAckFrame ack_fec(5, QuicTime::Zero(), 1);
+ // Ack all data packets, but no fec packets.
+ ack_fec.received_info.missing_packets.insert(2);
+ ack_fec.received_info.missing_packets.insert(4);
+ ack_fec.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 5) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 4) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+
+ // Lose the first FEC packet and ack the three data packets.
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(3);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _));
+ ProcessAckPacket(&ack_fec);
+
+ clock_.AdvanceTime(DefaultRetransmissionTime().Subtract(
+ QuicTime::Delta::FromMilliseconds(1)));
+
+ // Don't abandon the acked FEC packet, but it will abandon 1 of the subsequent
+ // FEC packets.
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(4, _));
+ connection_.GetRetransmissionAlarm()->Fire();
+
+ // Ensure the connection's alarm is still set, in order to abandon the third
+ // FEC packet.
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
TEST_F(QuicConnectionTest, FramePacking) {
@@ -1305,22 +1398,21 @@ TEST_F(QuicConnectionTest, FramePacking) {
&TestConnection::SendStreamData5)),
Return(true)));
- // Unblock the connection.
- connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.Times(1);
- connection_.OnCanWrite();
+ // Unblock the connection.
+ connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's an ack and two stream frames from
// two different streams.
- EXPECT_EQ(3u, helper_->frame_count());
- EXPECT_TRUE(helper_->ack());
- EXPECT_EQ(2u, helper_->stream_frames()->size());
- EXPECT_EQ(kStreamId3, (*helper_->stream_frames())[0].stream_id);
- EXPECT_EQ(kStreamId5, (*helper_->stream_frames())[1].stream_id);
+ EXPECT_EQ(3u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ EXPECT_EQ(2u, writer_->stream_frames()->size());
+ EXPECT_EQ(kStreamId3, (*writer_->stream_frames())[0].stream_id);
+ EXPECT_EQ(kStreamId5, (*writer_->stream_frames())[1].stream_id);
}
TEST_F(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
@@ -1338,20 +1430,18 @@ TEST_F(QuicConnectionTest, FramePackingNonCryptoThenCrypto) {
&TestConnection::SendCryptoStreamData)),
Return(true)));
- // Unblock the connection.
- connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.Times(2);
- connection_.OnCanWrite();
+ // Unblock the connection.
+ connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's the crypto stream frame.
- EXPECT_EQ(1u, helper_->frame_count());
- EXPECT_TRUE(helper_->ack());
- EXPECT_EQ(1u, helper_->stream_frames()->size());
- EXPECT_EQ(kCryptoStreamId, (*helper_->stream_frames())[0].stream_id);
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->stream_frames()->size());
+ EXPECT_EQ(kCryptoStreamId, (*writer_->stream_frames())[0].stream_id);
}
TEST_F(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
@@ -1369,20 +1459,18 @@ TEST_F(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
&TestConnection::SendStreamData3)),
Return(true)));
- // Unblock the connection.
- connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.Times(3);
- connection_.OnCanWrite();
+ // Unblock the connection.
+ connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's the stream frame from stream 3.
- EXPECT_EQ(1u, helper_->frame_count());
- EXPECT_TRUE(helper_->ack());
- EXPECT_EQ(1u, helper_->stream_frames()->size());
- EXPECT_EQ(kStreamId3, (*helper_->stream_frames())[0].stream_id);
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->stream_frames()->size());
+ EXPECT_EQ(kStreamId3, (*writer_->stream_frames())[0].stream_id);
}
TEST_F(QuicConnectionTest, FramePackingFEC) {
@@ -1401,48 +1489,87 @@ TEST_F(QuicConnectionTest, FramePackingFEC) {
&TestConnection::SendStreamData5)),
Return(true)));
- // Unblock the connection.
- connection_.GetSendAlarm()->Cancel();
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION, _)).Times(2);
- connection_.OnCanWrite();
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _)).Times(2);
+ // Unblock the connection.
+ connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
// Parse the last packet and ensure it's in an fec group.
- EXPECT_EQ(1u, helper_->header()->fec_group);
- EXPECT_EQ(0u, helper_->frame_count());
+ EXPECT_EQ(1u, writer_->header()->fec_group);
+ EXPECT_EQ(0u, writer_->frame_count());
+}
+
+TEST_F(QuicConnectionTest, FramePackingAckResponse) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ // Process a data packet to queue up a pending ack.
+ EXPECT_CALL(visitor_, OnStreamFrames(_)).WillOnce(Return(true));
+ ProcessDataPacket(1, 1, kEntropyFlag);
+
+ EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(DoAll(
+ IgnoreResult(InvokeWithoutArgs(&connection_,
+ &TestConnection::SendStreamData3)),
+ IgnoreResult(InvokeWithoutArgs(&connection_,
+ &TestConnection::SendStreamData5)),
+ Return(true)));
+
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
+ .Times(1);
+
+ // Process an ack to cause the visitor's OnCanWrite to be invoked.
+ creator_.set_sequence_number(2);
+ QuicAckFrame ack_one(0, QuicTime::Zero(), 0);
+ ProcessAckPacket(&ack_one);
+
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
+ EXPECT_FALSE(connection_.HasQueuedData());
+
+ // Parse the last packet and ensure it's an ack and two stream frames from
+ // two different streams.
+ EXPECT_EQ(3u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ ASSERT_EQ(2u, writer_->stream_frames()->size());
+ EXPECT_EQ(kStreamId3, (*writer_->stream_frames())[0].stream_id);
+ EXPECT_EQ(kStreamId5, (*writer_->stream_frames())[1].stream_id);
}
TEST_F(QuicConnectionTest, FramePackingSendv) {
- // Send two stream frames in 1 packet by using writev.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _));
+ // Send data in 1 packet by writing multiple blocks in a single iovector
+ // using writev.
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
char data[] = "ABCD";
- iovec iov[2] = { {static_cast<void*>(data), 2},
- {static_cast<void*>(data + 2), 2} };
- connection_.SendvStreamData(1, iov, 2, 0, !kFin);
+ IOVector data_iov;
+ data_iov.AppendNoCoalesce(data, 2);
+ data_iov.AppendNoCoalesce(data + 2, 2);
+ connection_.SendStreamData(1, data_iov, 0, !kFin, NULL);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
- // Parse the last packet and ensure it's two stream frames from one stream.
- // TODO(ianswett): Ideally this would arrive in one frame in the future.
- EXPECT_EQ(2u, helper_->frame_count());
- EXPECT_EQ(2u, helper_->stream_frames()->size());
- EXPECT_EQ(1u, (*helper_->stream_frames())[0].stream_id);
- EXPECT_EQ(1u, (*helper_->stream_frames())[1].stream_id);
+ // Parse the last packet and ensure multiple iovector blocks have
+ // been packed into a single stream frame from one stream.
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->stream_frames()->size());
+ QuicStreamFrame frame = (*writer_->stream_frames())[0];
+ EXPECT_EQ(1u, frame.stream_id);
+ EXPECT_EQ("ABCD", string(static_cast<char*>
+ (frame.data.iovec()[0].iov_base),
+ (frame.data.iovec()[0].iov_len)));
}
TEST_F(QuicConnectionTest, FramePackingSendvQueued) {
// Try to send two stream frames in 1 packet by using writev.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
- helper_->set_blocked(true);
+ writer_->set_blocked(true);
char data[] = "ABCD";
- iovec iov[2] = { {static_cast<void*>(data), 2},
- {static_cast<void*>(data + 2), 2} };
- connection_.SendvStreamData(1, iov, 2, 0, !kFin);
+ IOVector data_iov;
+ data_iov.AppendNoCoalesce(data, 2);
+ data_iov.AppendNoCoalesce(data + 2, 2);
+ connection_.SendStreamData(1, data_iov, 0, !kFin, NULL);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
EXPECT_TRUE(connection_.HasQueuedData());
@@ -1453,35 +1580,30 @@ TEST_F(QuicConnectionTest, FramePackingSendvQueued) {
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Unblock the writes and actually send.
- helper_->set_blocked(false);
- EXPECT_CALL(visitor_, OnCanWrite());
+ writer_->set_blocked(false);
EXPECT_TRUE(connection_.OnCanWrite());
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- // Parse the last packet and ensure it's two stream frames from one stream.
- // TODO(ianswett): Ideally this would arrive in one frame in the future.
- EXPECT_EQ(2u, helper_->frame_count());
- EXPECT_EQ(2u, helper_->stream_frames()->size());
- EXPECT_EQ(1u, (*helper_->stream_frames())[0].stream_id);
- EXPECT_EQ(1u, (*helper_->stream_frames())[1].stream_id);
+ // Parse the last packet and ensure it's one stream frame from one stream.
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->stream_frames()->size());
+ EXPECT_EQ(1u, (*writer_->stream_frames())[0].stream_id);
}
TEST_F(QuicConnectionTest, SendingZeroBytes) {
// Send a zero byte write with a fin using writev.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _));
-
- iovec iov[1];
- connection_.SendvStreamData(1, iov, 0, 0, kFin);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
+ IOVector empty_iov;
+ connection_.SendStreamData(1, empty_iov, 0, kFin, NULL);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
- // Parse the last packet and ensure it's two stream frames from one stream.
- // TODO(ianswett): Ideally this would arrive in one frame in the future.
- EXPECT_EQ(1u, helper_->frame_count());
- EXPECT_EQ(1u, helper_->stream_frames()->size());
- EXPECT_EQ(1u, (*helper_->stream_frames())[0].stream_id);
- EXPECT_TRUE((*helper_->stream_frames())[0].fin);
+ // Parse the last packet and ensure it's one stream frame from one stream.
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_EQ(1u, writer_->stream_frames()->size());
+ EXPECT_EQ(1u, (*writer_->stream_frames())[0].stream_id);
+ EXPECT_TRUE((*writer_->stream_frames())[0].fin);
}
TEST_F(QuicConnectionTest, OnCanWrite) {
@@ -1501,33 +1623,68 @@ TEST_F(QuicConnectionTest, OnCanWrite) {
connection_.OnCanWrite();
// Parse the last packet and ensure it's the two stream frames from
// two different streams.
- EXPECT_EQ(2u, helper_->frame_count());
- EXPECT_EQ(2u, helper_->stream_frames()->size());
- EXPECT_EQ(kStreamId3, (*helper_->stream_frames())[0].stream_id);
- EXPECT_EQ(kStreamId5, (*helper_->stream_frames())[1].stream_id);
+ EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_EQ(2u, writer_->stream_frames()->size());
+ EXPECT_EQ(kStreamId3, (*writer_->stream_frames())[0].stream_id);
+ EXPECT_EQ(kStreamId5, (*writer_->stream_frames())[1].stream_id);
}
TEST_F(QuicConnectionTest, RetransmitOnNack) {
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(2);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(2, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1);
QuicPacketSequenceNumber last_packet;
QuicByteCount second_packet_size;
- SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
+ SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 1
second_packet_size =
- SendStreamDataToPeer(1, "foos", 3, !kFin, &last_packet); // Packet 2
+ SendStreamDataToPeer(3, "foos", 3, !kFin, &last_packet); // Packet 2
+ SendStreamDataToPeer(3, "fooos", 7, !kFin, &last_packet); // Packet 3
+
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ // Peer acks one but not two or three. Right now we only retransmit on
+ // explicit nack, so it should not trigger a retransmission.
+ QuicAckFrame ack_one(1, QuicTime::Zero(), 0);
+ ack_one.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ ProcessAckPacket(&ack_one);
+ ProcessAckPacket(&ack_one);
+ ProcessAckPacket(&ack_one);
+
+ // Peer acks up to 3 with two explicitly missing.
+ // Early retransmit causes 2 to be retransmitted on the first ack.
+ QuicAckFrame nack_two(3, QuicTime::Zero(), 0);
+ nack_two.received_info.missing_packets.insert(2);
+ nack_two.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ // The third nack should trigger a retransmission.
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, second_packet_size - kQuicVersionSize,
+ NACK_RETRANSMISSION, _)).Times(1);
+ ProcessAckPacket(&nack_two);
+}
+
+TEST_F(QuicConnectionTest, DiscardRetransmit) {
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _)).Times(1);
+ QuicPacketSequenceNumber last_packet;
+ SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
+ SendStreamDataToPeer(1, "foos", 3, !kFin, &last_packet); // Packet 2
SendStreamDataToPeer(1, "fooos", 7, !kFin, &last_packet); // Packet 3
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Peer acks one but not two or three. Right now we only retransmit on
- // explicit nack, so it should not trigger a retransimission.
+ // explicit nack, so it should not trigger a retransmission.
QuicAckFrame ack_one(1, QuicTime::Zero(), 0);
ack_one.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
- ProcessAckPacket(&ack_one, true);
- ProcessAckPacket(&ack_one, true);
- ProcessAckPacket(&ack_one, true);
+ ProcessAckPacket(&ack_one);
+ ProcessAckPacket(&ack_one);
+ ProcessAckPacket(&ack_one);
// Peer acks up to 3 with two explicitly missing. Two nacks should cause no
// change.
@@ -1537,147 +1694,172 @@ TEST_F(QuicConnectionTest, RetransmitOnNack) {
QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
- ProcessAckPacket(&nack_two, true);
- ProcessAckPacket(&nack_two, true);
+ // The first nack should trigger a fast retransmission, but we'll be
+ // write blocked, so the packet will be queued.
+ writer_->set_blocked(true);
+
+ ProcessAckPacket(&nack_two);
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
+
+ // Now, ack the previous transmission.
+ QuicAckFrame ack_all(3, QuicTime::Zero(), 0);
+ ack_all.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 3);
+ ProcessAckPacket(&ack_all);
- // The third nack should trigger a retransimission.
+ // Unblock the socket and attempt to send the queued packets. However,
+ // since the previous transmission has been acked, we will not
+ // send the retransmission.
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, second_packet_size - kQuicVersionSize,
- IS_RETRANSMISSION, _)).Times(1);
- ProcessAckPacket(&nack_two, true);
+ OnPacketSent(_, _, _, _, _)).Times(0);
+
+ writer_->set_blocked(false);
+ connection_.OnCanWrite();
+
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
TEST_F(QuicConnectionTest, RetransmitNackedLargestObserved) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
QuicPacketSequenceNumber largest_observed;
QuicByteCount packet_size;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.WillOnce(DoAll(SaveArg<1>(&largest_observed), SaveArg<2>(&packet_size),
Return(true)));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _)).Times(1);
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ connection_.SendStreamDataWithString(3, "foo", 0, !kFin, NULL);
QuicAckFrame frame(1, QuicTime::Zero(), largest_observed);
frame.received_info.missing_packets.insert(largest_observed);
frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
&connection_, largest_observed - 1);
- ProcessAckPacket(&frame, true);
- ProcessAckPacket(&frame, true);
- // Third nack should retransmit the largest observed packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, packet_size - kQuicVersionSize,
- IS_RETRANSMISSION, _));
- ProcessAckPacket(&frame, true);
+ // The first nack should retransmit the largest observed packet.
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, packet_size - kQuicVersionSize,
+ NACK_RETRANSMISSION, _));
+ ProcessAckPacket(&frame);
}
-TEST_F(QuicConnectionTest, RetransmitNackedPacketsOnTruncatedAck) {
- for (int i = 0; i < 200; ++i) {
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
- connection_.SendStreamData(1, "foo", i * 3, !kFin);
+TEST_F(QuicConnectionTest, QueueAfterTwoRTOs) {
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ connection_.SendStreamDataWithString(1, "foo", i * 3, !kFin, NULL);
}
- // Make a truncated ack frame.
- QuicAckFrame frame(0, QuicTime::Zero(), 1);
- frame.received_info.largest_observed = 193;
- InsertMissingPacketsBetween(&frame.received_info, 1, 193);
- frame.received_info.entropy_hash =
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 193) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 192);
-
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessAckPacket(&frame, true);
- EXPECT_TRUE(QuicConnectionPeer::GetReceivedTruncatedAck(&connection_));
-
- QuicConnectionPeer::SetMaxPacketsPerRetransmissionAlarm(&connection_, 200);
+ // Block the congestion window and ensure they're queued.
+ writer_->set_blocked(true);
clock_.AdvanceTime(DefaultRetransmissionTime());
- // Only packets that are less than largest observed should be retransmitted.
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(192);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(192);
- connection_.OnRetransmissionTimeout();
+ // Only one packet should be retransmitted.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(10);
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_TRUE(connection_.HasQueuedData());
+ // Unblock the congestion window.
+ writer_->set_blocked(false);
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(
2 * DefaultRetransmissionTime().ToMicroseconds()));
// Retransmit already retransmitted packets event though the sequence number
// greater than the largest observed.
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(192);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(192);
- connection_.OnRetransmissionTimeout();
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(10);
+ connection_.GetRetransmissionAlarm()->Fire();
+ connection_.OnCanWrite();
+}
+
+TEST_F(QuicConnectionTest, WriteBlockedThenSent) {
+ writer_->set_blocked(true);
+
+ writer_->set_is_write_blocked_data_buffered(true);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ connection_.OnPacketSent(WriteResult(WRITE_STATUS_OK, 0));
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, ResumptionAlarmThenWriteBlocked) {
+ // Set the send and resumption alarm, then block the connection.
+ connection_.GetResumeWritesAlarm()->Set(clock_.ApproximateNow());
+ connection_.GetSendAlarm()->Set(clock_.ApproximateNow());
+ QuicConnectionPeer::SetIsWriteBlocked(&connection_, true);
+
+ // Fire the alarms and ensure the connection is still write blocked.
+ connection_.GetResumeWritesAlarm()->Fire();
+ connection_.GetSendAlarm()->Fire();
+ EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
}
TEST_F(QuicConnectionTest, LimitPacketsPerNack) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(12, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(11);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(15, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(4);
int offset = 0;
- // Send packets 1 to 12
- for (int i = 0; i < 12; ++i) {
+ // Send packets 1 to 15.
+ for (int i = 0; i < 15; ++i) {
SendStreamDataToPeer(1, "foo", offset, !kFin, NULL);
offset += 3;
}
- // Ack 12, nack 1-11
- QuicAckFrame nack(12, QuicTime::Zero(), 0);
- for (int i = 1; i < 12; ++i) {
+ // Ack 15, nack 1-14.
+ QuicAckFrame nack(15, QuicTime::Zero(), 0);
+ for (int i = 1; i < 15; ++i) {
nack.received_info.missing_packets.insert(i);
}
nack.received_info.entropy_hash =
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 12) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 11);
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 15) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 14);
- // Nack three times.
- ProcessAckPacket(&nack, true);
- ProcessAckPacket(&nack, true);
- // The third call should trigger retransmitting 10 packets.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(10);
- ProcessAckPacket(&nack, true);
+ // 13 packets have been NACK'd 3 times, but we limit retransmissions to 2.
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ ProcessAckPacket(&nack);
- // The fourth call should trigger retransmitting the 11th packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
- ProcessAckPacket(&nack, true);
+ // The next call should trigger retransmitting 2 more packets.
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ ProcessAckPacket(&nack);
}
// Test sending multiple acks from the connection to the session.
TEST_F(QuicConnectionTest, MultipleAcks) {
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(6);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(6);
QuicPacketSequenceNumber last_packet;
- SendStreamDataToPeer(1u, "foo", 0, !kFin, &last_packet); // Packet 1
+ SendStreamDataToPeer(1, "foo", 0, !kFin, &last_packet); // Packet 1
EXPECT_EQ(1u, last_packet);
- SendStreamDataToPeer(3u, "foo", 0, !kFin, &last_packet); // Packet 2
+ SendStreamDataToPeer(3, "foo", 0, !kFin, &last_packet); // Packet 2
EXPECT_EQ(2u, last_packet);
SendAckPacketToPeer(); // Packet 3
- SendStreamDataToPeer(5u, "foo", 0, !kFin, &last_packet); // Packet 4
+ SendStreamDataToPeer(5, "foo", 0, !kFin, &last_packet); // Packet 4
EXPECT_EQ(4u, last_packet);
- SendStreamDataToPeer(1u, "foo", 3, !kFin, &last_packet); // Packet 5
+ SendStreamDataToPeer(1, "foo", 3, !kFin, &last_packet); // Packet 5
EXPECT_EQ(5u, last_packet);
- SendStreamDataToPeer(3u, "foo", 3, !kFin, &last_packet); // Packet 6
+ SendStreamDataToPeer(3, "foo", 3, !kFin, &last_packet); // Packet 6
EXPECT_EQ(6u, last_packet);
- // Client will ack packets 1, [!2], 3, 4, 5
+ // Client will ack packets 1, 2, [!3], 4, 5.
QuicAckFrame frame1(5, QuicTime::Zero(), 0);
- frame1.received_info.missing_packets.insert(2);
+ frame1.received_info.missing_packets.insert(3);
frame1.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 5) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 2);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessAckPacket(&frame1, true);
+ ProcessAckPacket(&frame1);
- // Now the client implicitly acks 2, and explicitly acks 6
+ // Now the client implicitly acks 3, and explicitly acks 6.
QuicAckFrame frame2(6, QuicTime::Zero(), 0);
frame2.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 6);
- ProcessAckPacket(&frame2, true);
+ ProcessAckPacket(&frame2);
}
TEST_F(QuicConnectionTest, DontLatchUnackedPacket) {
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL); // Packet 1;
SendAckPacketToPeer(); // Packet 2
@@ -1685,7 +1867,7 @@ TEST_F(QuicConnectionTest, DontLatchUnackedPacket) {
QuicAckFrame frame(1, QuicTime::Zero(), 0);
frame.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
&connection_, 1);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
// Verify that our internal state has least-unacked as 3.
EXPECT_EQ(3u, outgoing_ack()->sent_info.least_unacked);
@@ -1740,7 +1922,7 @@ TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPacket) {
// Don't send missing packet 1.
ProcessFecPacket(3, 1, false, !kEntropyFlag, NULL);
- // out of order
+ // Out of order.
ProcessFecProtectedPacket(2, true, !kEntropyFlag);
// Entropy flag should be false, so entropy should be 0.
EXPECT_EQ(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
@@ -1759,7 +1941,7 @@ TEST_F(QuicConnectionTest, ReviveMissingPacketAfterDataPackets) {
EXPECT_NE(0u, QuicConnectionPeer::ReceivedEntropyHash(&connection_, 2));
}
-TEST_F(QuicConnectionTest, TestRetransmit) {
+TEST_F(QuicConnectionTest, RTO) {
QuicTime default_retransmission_time = clock_.ApproximateNow().Add(
DefaultRetransmissionTime());
SendStreamDataToPeer(1, "foo", 0, !kFin, NULL);
@@ -1768,16 +1950,18 @@ TEST_F(QuicConnectionTest, TestRetransmit) {
EXPECT_EQ(1u, last_header()->packet_sequence_number);
EXPECT_EQ(default_retransmission_time,
connection_.GetRetransmissionAlarm()->deadline());
- // Simulate the retransimission alarm firing
+ // Simulate the retransmission alarm firing.
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _)).Times(1);
- connection_.RetransmitPacket(1);
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1u, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 2u, _, _, _));
+ connection_.GetRetransmissionAlarm()->Fire();
EXPECT_EQ(2u, last_header()->packet_sequence_number);
- EXPECT_EQ(2u, outgoing_ack()->sent_info.least_unacked);
+ // We do not raise the high water mark yet.
+ EXPECT_EQ(1u, outgoing_ack()->sent_info.least_unacked);
}
-TEST_F(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
+TEST_F(QuicConnectionTest, RTOWithSameEncryptionLevel) {
QuicTime default_retransmission_time = clock_.ApproximateNow().Add(
DefaultRetransmissionTime());
use_tagging_decrypter();
@@ -1795,21 +1979,57 @@ TEST_F(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
EXPECT_EQ(default_retransmission_time,
connection_.GetRetransmissionAlarm()->deadline());
- // Simulate the retransimission alarm firing
+ {
+ InSequence s;
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 3, _, RTO_RETRANSMISSION, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 4, _, RTO_RETRANSMISSION, _));
+ }
+
+ // Simulate the retransmission alarm firing.
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(2);
+ connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- connection_.RetransmitPacket(1);
// Packet should have been sent with ENCRYPTION_NONE.
- EXPECT_EQ(0x01010101u, final_bytes_of_last_packet());
+ EXPECT_EQ(0x01010101u, final_bytes_of_previous_packet());
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- connection_.RetransmitPacket(2);
// Packet should have been sent with ENCRYPTION_INITIAL.
EXPECT_EQ(0x02020202u, final_bytes_of_last_packet());
}
+TEST_F(QuicConnectionTest, SendHandshakeMessages) {
+ use_tagging_decrypter();
+ // A TaggingEncrypter puts kTagSize copies of the given byte (0x01 here) at
+ // the end of the packet. We can test this to check which encrypter was used.
+ connection_.SetEncrypter(ENCRYPTION_NONE, new TaggingEncrypter(0x01));
+
+ // Attempt to send a handshake message while the congestion manager
+ // does not permit sending.
+ EXPECT_CALL(*send_algorithm_,
+ TimeUntilSend(_, _, _, IS_HANDSHAKE)).WillRepeatedly(
+ testing::Return(QuicTime::Delta::Infinite()));
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ // The packet should be serialized, but not queued.
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
+
+ // Switch to the new encrypter.
+ connection_.SetEncrypter(ENCRYPTION_INITIAL, new TaggingEncrypter(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+
+ // Now become writeable and flush the packets.
+ EXPECT_CALL(*send_algorithm_,
+ TimeUntilSend(_, _, _, IS_HANDSHAKE)).WillRepeatedly(
+ testing::Return(QuicTime::Delta::Zero()));
+ EXPECT_CALL(visitor_, OnCanWrite());
+ connection_.OnCanWrite();
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
+
+ // Verify that the handshake packet went out at the null encryption.
+ EXPECT_EQ(0x01010101u, final_bytes_of_last_packet());
+}
+
TEST_F(QuicConnectionTest,
DropRetransmitsForNullEncryptedPacketAfterForwardSecure) {
use_tagging_decrypter();
@@ -1821,17 +2041,18 @@ TEST_F(QuicConnectionTest,
new TaggingEncrypter(0x02));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(0);
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(sequence_number, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(sequence_number, _)).Times(1);
QuicTime default_retransmission_time = clock_.ApproximateNow().Add(
DefaultRetransmissionTime());
EXPECT_EQ(default_retransmission_time,
connection_.GetRetransmissionAlarm()->deadline());
- // Simulate the retransimission alarm firing
+ // Simulate the retransmission alarm firing.
clock_.AdvanceTime(DefaultRetransmissionTime());
- connection_.OnRetransmissionTimeout();
+ connection_.GetRetransmissionAlarm()->Fire();
}
TEST_F(QuicConnectionTest, RetransmitPacketsWithInitialEncryption) {
@@ -1846,10 +2067,10 @@ TEST_F(QuicConnectionTest, RetransmitPacketsWithInitialEncryption) {
SendStreamDataToPeer(2, "bar", 0, !kFin, NULL);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(1);
- connection_.RetransmitUnackedPackets(QuicConnection::INITIAL_ENCRYPTION_ONLY);
+ connection_.RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY);
}
TEST_F(QuicConnectionTest, BufferNonDecryptablePackets) {
@@ -1881,132 +2102,158 @@ TEST_F(QuicConnectionTest, BufferNonDecryptablePackets) {
TEST_F(QuicConnectionTest, TestRetransmitOrder) {
QuicByteCount first_packet_size;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).WillOnce(
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).WillOnce(
DoAll(SaveArg<2>(&first_packet_size), Return(true)));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(2);
- connection_.SendStreamData(1, "first_packet", 0, !kFin);
+ connection_.SendStreamDataWithString(3, "first_packet", 0, !kFin, NULL);
QuicByteCount second_packet_size;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).WillOnce(
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).WillOnce(
DoAll(SaveArg<2>(&second_packet_size), Return(true)));
- connection_.SendStreamData(1, "second_packet", 12, !kFin);
+ connection_.SendStreamDataWithString(3, "second_packet", 12, !kFin, NULL);
EXPECT_NE(first_packet_size, second_packet_size);
// Advance the clock by huge time to make sure packets will be retransmitted.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
{
InSequence s;
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, first_packet_size, _, _));
+ OnPacketSent(_, _, first_packet_size, _, _));
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, second_packet_size, _, _));
+ OnPacketSent(_, _, second_packet_size, _, _));
}
- connection_.OnRetransmissionTimeout();
+ connection_.GetRetransmissionAlarm()->Fire();
+
+ // Advance again and expect the packets to be sent again in the same order.
+ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(20));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+ {
+ InSequence s;
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, first_packet_size, _, _));
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, second_packet_size, _, _));
+ }
+ connection_.GetRetransmissionAlarm()->Fire();
}
-TEST_F(QuicConnectionTest, TestRetransmissionCountCalculation) {
+TEST_F(QuicConnectionTest, RetransmissionCountCalculation) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(2);
QuicPacketSequenceNumber original_sequence_number;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.WillOnce(DoAll(SaveArg<1>(&original_sequence_number), Return(true)));
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+
EXPECT_TRUE(QuicConnectionPeer::IsSavedForRetransmission(
&connection_, original_sequence_number));
- EXPECT_EQ(0u, QuicConnectionPeer::GetRetransmissionCount(
+ EXPECT_FALSE(QuicConnectionPeer::IsRetransmission(
&connection_, original_sequence_number));
// Force retransmission due to RTO.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAbandoned(original_sequence_number, _)).Times(1);
QuicPacketSequenceNumber rto_sequence_number;
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, IS_RETRANSMISSION, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, RTO_RETRANSMISSION, _))
.WillOnce(DoAll(SaveArg<1>(&rto_sequence_number), Return(true)));
- connection_.OnRetransmissionTimeout();
+ connection_.GetRetransmissionAlarm()->Fire();
EXPECT_FALSE(QuicConnectionPeer::IsSavedForRetransmission(
&connection_, original_sequence_number));
ASSERT_TRUE(QuicConnectionPeer::IsSavedForRetransmission(
&connection_, rto_sequence_number));
- EXPECT_EQ(1u, QuicConnectionPeer::GetRetransmissionCount(
+ EXPECT_TRUE(QuicConnectionPeer::IsRetransmission(
&connection_, rto_sequence_number));
// Once by explicit nack.
- QuicPacketSequenceNumber nack_sequence_number;
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAbandoned(rto_sequence_number, _)).Times(1);
+ QuicPacketSequenceNumber nack_sequence_number = 0;
// Ack packets might generate some other packets, which are not
// retransmissions. (More ack packets).
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.Times(AnyNumber());
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, IS_RETRANSMISSION, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NACK_RETRANSMISSION, _))
.WillOnce(DoAll(SaveArg<1>(&nack_sequence_number), Return(true)));
QuicAckFrame ack(rto_sequence_number, QuicTime::Zero(), 0);
// Ack the retransmitted packet.
+ ack.received_info.missing_packets.insert(original_sequence_number);
ack.received_info.missing_packets.insert(rto_sequence_number);
- ack.received_info.entropy_hash = QuicConnectionPeer::GetSentEntropyHash(
- &connection_, rto_sequence_number - 1);
+ ack.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_,
+ rto_sequence_number - 1) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_,
+ original_sequence_number);
for (int i = 0; i < 3; i++) {
- ProcessAckPacket(&ack, true);
+ ProcessAckPacket(&ack);
}
+ ASSERT_NE(0u, nack_sequence_number);
EXPECT_FALSE(QuicConnectionPeer::IsSavedForRetransmission(
&connection_, rto_sequence_number));
- EXPECT_TRUE(QuicConnectionPeer::IsSavedForRetransmission(
+ ASSERT_TRUE(QuicConnectionPeer::IsSavedForRetransmission(
&connection_, nack_sequence_number));
- EXPECT_EQ(2u, QuicConnectionPeer::GetRetransmissionCount(
+ EXPECT_TRUE(QuicConnectionPeer::IsRetransmission(
&connection_, nack_sequence_number));
}
TEST_F(QuicConnectionTest, SetRTOAfterWritingToSocket) {
- helper_->set_blocked(true);
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ writer_->set_blocked(true);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
// Make sure that RTO is not started when the packet is queued.
- EXPECT_EQ(0u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
// Test that RTO is started once we write to the socket.
- helper_->set_blocked(false);
- EXPECT_CALL(visitor_, OnCanWrite());
+ writer_->set_blocked(false);
connection_.OnCanWrite();
- EXPECT_EQ(1u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
+ EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
}
TEST_F(QuicConnectionTest, DelayRTOWithAckReceipt) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, NOT_RETRANSMISSION, _))
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, NOT_RETRANSMISSION, _))
.Times(2);
- connection_.SendStreamData(1, "foo", 0, !kFin);
- connection_.SendStreamData(2, "bar", 0, !kFin);
- EXPECT_EQ(2u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ connection_.SendStreamDataWithString(2, "bar", 0, !kFin, NULL);
+ QuicAlarm* retransmission_alarm = connection_.GetRetransmissionAlarm();
+ EXPECT_TRUE(retransmission_alarm->IsSet());
// Advance the time right before the RTO, then receive an ack for the first
// packet to delay the RTO.
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_EQ(2u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
QuicAckFrame ack(1, QuicTime::Zero(), 0);
- ProcessAckPacket(&ack, true);
- EXPECT_EQ(1u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
+ ack.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ ProcessAckPacket(&ack);
+ EXPECT_TRUE(retransmission_alarm->IsSet());
// Move forward past the original RTO and ensure the RTO is still pending.
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_EQ(1u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
// Ensure the second packet gets retransmitted when it finally fires.
- EXPECT_TRUE(
- QuicConnectionPeer::GetRetransmissionAlarm(&connection_)->IsSet());
- EXPECT_GE(
- QuicConnectionPeer::GetRetransmissionAlarm(&connection_)->deadline(),
- clock_.ApproximateNow());
+ EXPECT_TRUE(retransmission_alarm->IsSet());
+ EXPECT_GE(retransmission_alarm->deadline(), clock_.ApproximateNow());
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_LT(
- QuicConnectionPeer::GetRetransmissionAlarm(&connection_)->deadline(),
- clock_.ApproximateNow());
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, IS_RETRANSMISSION, _));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _));
- connection_.OnRetransmissionTimeout();
-
- // The new retransmitted sequence number should now be in the timeout queue.
- EXPECT_EQ(1u, QuicConnectionPeer::GetNumRetransmissionTimeouts(&connection_));
+ EXPECT_LT(retransmission_alarm->deadline(), clock_.ApproximateNow());
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, RTO_RETRANSMISSION, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _));
+ // Manually cancel the alarm to simulate a real test.
+ connection_.GetRetransmissionAlarm()->Fire();
+
+ // The new retransmitted sequence number should set the RTO to a larger value
+ // than previously.
+ EXPECT_TRUE(retransmission_alarm->IsSet());
+ QuicTime next_rto_time = retransmission_alarm->deadline();
+ QuicTime::Delta expected_rto =
+ connection_.sent_packet_manager().GetRetransmissionDelay();
+ EXPECT_EQ(next_rto_time, clock_.ApproximateNow().Add(expected_rto));
}
TEST_F(QuicConnectionTest, TestQueued) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- helper_->set_blocked(true);
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ writer_->set_blocked(true);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Attempt to send all packets, but since we're actually still
@@ -2015,24 +2262,23 @@ TEST_F(QuicConnectionTest, TestQueued) {
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Unblock the writes and actually send.
- helper_->set_blocked(false);
- EXPECT_CALL(visitor_, OnCanWrite());
+ writer_->set_blocked(false);
EXPECT_TRUE(connection_.OnCanWrite());
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
TEST_F(QuicConnectionTest, CloseFecGroup) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- // Don't send missing packet 1
- // Don't send missing packet 2
+ // Don't send missing packet 1.
+ // Don't send missing packet 2.
ProcessFecProtectedPacket(3, false, !kEntropyFlag);
- // Don't send missing FEC packet 3
+ // Don't send missing FEC packet 3.
ASSERT_EQ(1u, connection_.NumFecGroups());
- // Now send non-fec protected ack packet and close the group
+ // Now send non-fec protected ack packet and close the group.
QuicAckFrame frame(0, QuicTime::Zero(), 5);
creator_.set_sequence_number(4);
- ProcessAckPacket(&frame, true);
+ ProcessAckPacket(&frame);
ASSERT_EQ(0u, connection_.NumFecGroups());
}
@@ -2070,18 +2316,25 @@ TEST_F(QuicConnectionTest, DontUpdateQuicCongestionFeedbackFrameForRevived) {
TEST_F(QuicConnectionTest, InitialTimeout) {
EXPECT_TRUE(connection_.connected());
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
QuicTime default_timeout = clock_.ApproximateNow().Add(
QuicTime::Delta::FromSeconds(kDefaultInitialTimeoutSecs));
EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
- // Simulate the timeout alarm firing
+ // Simulate the timeout alarm firing.
clock_.AdvanceTime(
QuicTime::Delta::FromSeconds(kDefaultInitialTimeoutSecs));
- EXPECT_TRUE(connection_.CheckForTimeout());
+ connection_.GetTimeoutAlarm()->Fire();
+ EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
+
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetResumeWritesAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetRetransmissionAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
+ EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
}
TEST_F(QuicConnectionTest, TimeoutAfterSend) {
@@ -2094,7 +2347,7 @@ TEST_F(QuicConnectionTest, TimeoutAfterSend) {
// kDefaultInitialTimeoutSecs.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- // Send an ack so we don't set the retransimission alarm.
+ // Send an ack so we don't set the retransmission alarm.
SendAckPacketToPeer();
EXPECT_EQ(default_timeout, connection_.GetTimeoutAlarm()->deadline());
@@ -2103,18 +2356,20 @@ TEST_F(QuicConnectionTest, TimeoutAfterSend) {
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(
kDefaultInitialTimeoutSecs * 1000000 - 5000));
EXPECT_EQ(default_timeout, clock_.ApproximateNow());
- EXPECT_FALSE(connection_.CheckForTimeout());
+ connection_.GetTimeoutAlarm()->Fire();
+ EXPECT_TRUE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_TRUE(connection_.connected());
EXPECT_EQ(default_timeout.Add(QuicTime::Delta::FromMilliseconds(5)),
connection_.GetTimeoutAlarm()->deadline());
// This time, we should time out.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, false));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_CONNECTION_TIMED_OUT, false));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_EQ(default_timeout.Add(QuicTime::Delta::FromMilliseconds(5)),
clock_.ApproximateNow());
- EXPECT_TRUE(connection_.CheckForTimeout());
+ connection_.GetTimeoutAlarm()->Fire();
+ EXPECT_FALSE(connection_.GetTimeoutAlarm()->IsSet());
EXPECT_FALSE(connection_.connected());
}
@@ -2125,8 +2380,8 @@ TEST_F(QuicConnectionTest, SendScheduler) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- connection_.SendOrQueuePacket(
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
@@ -2137,8 +2392,8 @@ TEST_F(QuicConnectionTest, SendSchedulerDelay) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(1)));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, _, _)).Times(0);
- connection_.SendOrQueuePacket(
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 1, _, _, _)).Times(0);
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
}
@@ -2147,22 +2402,22 @@ TEST_F(QuicConnectionTest, SendSchedulerForce) {
// Test that if we force send a packet, it is not queued.
QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, IS_RETRANSMISSION, _, _)).Times(0);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- connection_.SendOrQueuePacket(
+ TimeUntilSend(_, NACK_RETRANSMISSION, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
- // XXX: fixme. was: connection_.SendOrQueuePacket(1, packet, kForce);
+ // XXX: fixme. was: connection_.SendPacket(1, packet, kForce);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
TEST_F(QuicConnectionTest, SendSchedulerEAGAIN) {
QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
- helper_->set_blocked(true);
+ writer_->set_blocked(true);
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, _, _)).Times(0);
- connection_.SendOrQueuePacket(
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 1, _, _, _)).Times(0);
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
}
@@ -2173,7 +2428,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenSend) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(1)));
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -2183,43 +2438,41 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenSend) {
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
testing::Return(QuicTime::Delta::Zero()));
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
- connection_.GetSendAlarm()->Cancel();
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _));
- EXPECT_CALL(visitor_, OnCanWrite());
- connection_.OnCanWrite();
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
TEST_F(QuicConnectionTest, SendSchedulerDelayThenRetransmit) {
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, NOT_RETRANSMISSION, _, _))
.WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, 1, _, NOT_RETRANSMISSION, _));
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ OnPacketSent(_, 1, _, NOT_RETRANSMISSION, _));
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
// Advance the time for retransmission of lost packet.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(501));
- // Test that if we send a retransmit with a delay, it ends up queued.
+ // Test that if we send a retransmit with a delay, it ends up queued in the
+ // sent packet manager, but not yet serialized.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, IS_RETRANSMISSION, _, _)).WillOnce(
+ TimeUntilSend(_, RTO_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(1)));
- connection_.OnRetransmissionTimeout();
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
+ connection_.GetRetransmissionAlarm()->Fire();
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
// Advance the clock to fire the alarm, and configure the scheduler
// to permit the packet to be sent.
EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, IS_RETRANSMISSION, _, _)).WillOnce(
- testing::Return(QuicTime::Delta::Zero()));
+ TimeUntilSend(_, RTO_RETRANSMISSION, _, _)).Times(2).
+ WillRepeatedly(testing::Return(QuicTime::Delta::Zero()));
// Ensure the scheduler is notified this is a retransmit.
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, IS_RETRANSMISSION, _));
+ OnPacketSent(_, _, _, RTO_RETRANSMISSION, _));
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(1));
- connection_.GetSendAlarm()->Cancel();
- EXPECT_CALL(visitor_, OnCanWrite());
- connection_.OnCanWrite();
+ connection_.GetSendAlarm()->Fire();
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
@@ -2228,13 +2481,13 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayAndQueue) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(1)));
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Attempt to send another packet and make sure that it gets queued.
packet = ConstructDataPacket(2, 0, !kEntropyFlag);
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, 2, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(2u, connection_.NumQueuedPackets());
}
@@ -2245,7 +2498,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndSend) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(10)));
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -2256,8 +2509,8 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndSend) {
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
testing::Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, _, _));
- ProcessAckPacket(&frame, true);
+ OnPacketSent(_, _, _, _, _));
+ ProcessAckPacket(&frame);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
// Ensure alarm is not set
@@ -2270,7 +2523,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndHold) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(10)));
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -2280,7 +2533,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenAckAndHold) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(1)));
- ProcessAckPacket(&frame, false);
+ ProcessAckPacket(&frame);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
}
@@ -2290,7 +2543,7 @@ TEST_F(QuicConnectionTest, SendSchedulerDelayThenOnCanWrite) {
EXPECT_CALL(*send_algorithm_,
TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
testing::Return(QuicTime::Delta::FromMicroseconds(10)));
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -2314,7 +2567,8 @@ TEST_F(QuicConnectionTest, TestQueueLimitsOnSendStreamData) {
testing::Return(QuicTime::Delta::FromMicroseconds(10)));
const string payload(payload_length, 'a');
EXPECT_EQ(0u,
- connection_.SendStreamData(1, payload, 0, !kFin).bytes_consumed);
+ connection_.SendStreamDataWithString(3, payload, 0,
+ !kFin, NULL).bytes_consumed);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
}
@@ -2327,30 +2581,103 @@ TEST_F(QuicConnectionTest, LoopThroughSendingPackets) {
NOT_IN_FEC_GROUP, &payload_length);
// Queue the first packet.
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(7);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(7);
// The first stream frame will consume 2 fewer bytes than the other six.
const string payload(payload_length * 7 - 12, 'a');
EXPECT_EQ(payload.size(),
- connection_.SendStreamData(1, payload, 0, !kFin).bytes_consumed);
+ connection_.SendStreamDataWithString(1, payload, 0,
+ !kFin, NULL).bytes_consumed);
+}
+
+TEST_F(QuicConnectionTest, SendDelayedAckOnTimer) {
+ QuicTime ack_time = clock_.ApproximateNow().Add(DefaultDelayedAckTime());
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+ ProcessPacket(1);
+ // Check if delayed ack timer is running for the expected interval.
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+ EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
+ // Simulate delayed ack alarm firing.
+ connection_.GetAckAlarm()->Fire();
+ // Check that ack is sent and that delayed ack alarm is reset.
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ ProcessPacket(1);
+ ProcessPacket(2);
+ // Check that ack is sent and that delayed ack alarm is reset.
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, NoAckOnOldNacks) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ // Drop one packet, triggering a sequence of acks.
+ ProcessPacket(2);
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ writer_->Reset();
+ ProcessPacket(3);
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ writer_->Reset();
+ ProcessPacket(4);
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ writer_->Reset();
+ ProcessPacket(5);
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ // Now only set the timer on the 6th packet, instead of sending another ack.
+ writer_->Reset();
+ ProcessPacket(6);
+ EXPECT_EQ(0u, writer_->frame_count());
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, SendDelayedAckOnOutgoingPacket) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ ProcessPacket(1);
+ connection_.SendStreamDataWithString(kStreamId3, "foo", 0, !kFin, NULL);
+ // Check that ack is bundled with outgoing data and that delayed ack
+ // alarm is reset.
+ EXPECT_EQ(2u, writer_->frame_count());
+ EXPECT_TRUE(writer_->ack());
+ EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
+}
+
+TEST_F(QuicConnectionTest, DontSendDelayedAckOnOutgoingCryptoPacket) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ ProcessPacket(1);
+ connection_.SendStreamDataWithString(kCryptoStreamId, "foo", 0, !kFin, NULL);
+ // Check that ack is not bundled with outgoing data.
+ EXPECT_EQ(1u, writer_->frame_count());
+ EXPECT_FALSE(writer_->ack());
+ EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
}
TEST_F(QuicConnectionTest, NoAckForClose) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(0);
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_PEER_GOING_AWAY, true));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(0);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, true));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
ProcessClosePacket(2, 0);
}
TEST_F(QuicConnectionTest, SendWhenDisconnected) {
EXPECT_TRUE(connection_.connected());
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_PEER_GOING_AWAY, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, false));
connection_.CloseConnection(QUIC_PEER_GOING_AWAY, false);
EXPECT_FALSE(connection_.connected());
QuicPacket* packet = ConstructDataPacket(1, 0, !kEntropyFlag);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, _, _)).Times(0);
- connection_.SendOrQueuePacket(
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 1, _, _, _)).Times(0);
+ connection_.SendPacket(
ENCRYPTION_NONE, 1, packet, kTestEntropyHash, HAS_RETRANSMITTABLE_DATA);
}
@@ -2362,7 +2689,7 @@ TEST_F(QuicConnectionTest, PublicReset) {
header.rejected_sequence_number = 10101;
scoped_ptr<QuicEncryptedPacket> packet(
framer_.BuildPublicResetPacket(header));
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_PUBLIC_RESET, true));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PUBLIC_RESET, true));
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *packet);
}
@@ -2377,12 +2704,22 @@ TEST_F(QuicConnectionTest, GoAway) {
ProcessGoAwayPacket(&goaway);
}
+TEST_F(QuicConnectionTest, InvalidPacket) {
+ EXPECT_CALL(visitor_,
+ OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
+ QuicEncryptedPacket encrypted(NULL, 0);
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), encrypted);
+ // The connection close packet should have error details.
+ ASSERT_TRUE(last_close() != NULL);
+ EXPECT_EQ("Unable to read public flags.", last_close()->error_details);
+}
+
TEST_F(QuicConnectionTest, MissingPacketsBeforeLeastUnacked) {
QuicAckFrame ack(0, QuicTime::Zero(), 4);
- // Set the sequence number of the ack packet to be least unacked (4)
+ // Set the sequence number of the ack packet to be least unacked (4).
creator_.set_sequence_number(3);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessAckPacket(&ack, true);
+ ProcessAckPacket(&ack);
EXPECT_TRUE(outgoing_ack()->received_info.missing_packets.empty());
}
@@ -2409,7 +2746,7 @@ TEST_F(QuicConnectionTest, UpdateEntropyForReceivedPackets) {
ack.sent_info.entropy_hash = kRandomEntropyHash;
creator_.set_sequence_number(5);
QuicPacketEntropyHash six_packet_entropy_hash = 0;
- if (ProcessAckPacket(&ack, true)) {
+ if (ProcessAckPacket(&ack)) {
six_packet_entropy_hash = 1 << 6;
}
@@ -2429,7 +2766,7 @@ TEST_F(QuicConnectionTest, UpdateEntropyHashUptoCurrentPacket) {
// Current packet is the least unacked packet.
QuicAckFrame ack(0, QuicTime::Zero(), 23);
ack.sent_info.entropy_hash = kRandomEntropyHash;
- QuicPacketEntropyHash ack_entropy_hash = ProcessAckPacket(&ack, true);
+ QuicPacketEntropyHash ack_entropy_hash = ProcessAckPacket(&ack);
EXPECT_EQ((kRandomEntropyHash + ack_entropy_hash),
outgoing_ack()->received_info.entropy_hash);
ProcessDataPacket(25, 1, kEntropyFlag);
@@ -2476,7 +2813,7 @@ TEST_F(QuicConnectionTest, CheckSentEntropyHash) {
packet_entropy_hash = 1 << (i % 8);
}
QuicPacket* packet = ConstructDataPacket(i, 0, entropy_flag);
- connection_.SendOrQueuePacket(
+ connection_.SendPacket(
ENCRYPTION_NONE, i, packet, packet_entropy_hash,
HAS_RETRANSMITTABLE_DATA);
@@ -2515,20 +2852,95 @@ TEST_F(QuicConnectionTest, ServerSendsVersionNegotiationPacket) {
framer_.set_version(QuicVersionMax());
connection_.set_is_server(true);
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
- EXPECT_TRUE(helper_->version_negotiation_packet() != NULL);
+ EXPECT_TRUE(writer_->version_negotiation_packet() != NULL);
+
+ size_t num_versions = arraysize(kSupportedQuicVersions);
+ EXPECT_EQ(num_versions,
+ writer_->version_negotiation_packet()->versions.size());
+
+ // We expect all versions in kSupportedQuicVersions to be
+ // included in the packet.
+ for (size_t i = 0; i < num_versions; ++i) {
+ EXPECT_EQ(kSupportedQuicVersions[i],
+ writer_->version_negotiation_packet()->versions[i]);
+ }
+}
+
+TEST_F(QuicConnectionTest, ServerSendsVersionNegotiationPacketSocketBlocked) {
+ framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
+
+ QuicPacketHeader header;
+ header.public_header.guid = guid_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = true;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.packet_sequence_number = 12;
+ header.fec_group = 0;
+
+ QuicFrames frames;
+ QuicFrame frame(&frame1_);
+ frames.push_back(frame);
+ scoped_ptr<QuicPacket> packet(
+ framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicEncryptedPacket> encrypted(
+ framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
+
+ framer_.set_version(QuicVersionMax());
+ connection_.set_is_server(true);
+ writer_->set_blocked(true);
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+ EXPECT_EQ(0u, writer_->last_packet_size());
+ EXPECT_TRUE(connection_.HasQueuedData());
+ EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
+
+ writer_->set_blocked(false);
+ connection_.OnCanWrite();
+ EXPECT_TRUE(writer_->version_negotiation_packet() != NULL);
size_t num_versions = arraysize(kSupportedQuicVersions);
EXPECT_EQ(num_versions,
- helper_->version_negotiation_packet()->versions.size());
+ writer_->version_negotiation_packet()->versions.size());
// We expect all versions in kSupportedQuicVersions to be
// included in the packet.
for (size_t i = 0; i < num_versions; ++i) {
EXPECT_EQ(kSupportedQuicVersions[i],
- helper_->version_negotiation_packet()->versions[i]);
+ writer_->version_negotiation_packet()->versions[i]);
}
}
+TEST_F(QuicConnectionTest,
+ ServerSendsVersionNegotiationPacketSocketBlockedDataBuffered) {
+ framer_.set_version_for_tests(QUIC_VERSION_UNSUPPORTED);
+
+ QuicPacketHeader header;
+ header.public_header.guid = guid_;
+ header.public_header.reset_flag = false;
+ header.public_header.version_flag = true;
+ header.entropy_flag = false;
+ header.fec_flag = false;
+ header.packet_sequence_number = 12;
+ header.fec_group = 0;
+
+ QuicFrames frames;
+ QuicFrame frame(&frame1_);
+ frames.push_back(frame);
+ scoped_ptr<QuicPacket> packet(
+ framer_.BuildUnsizedDataPacket(header, frames).packet);
+ scoped_ptr<QuicEncryptedPacket> encrypted(
+ framer_.EncryptPacket(ENCRYPTION_NONE, 12, *packet));
+
+ framer_.set_version(QuicVersionMax());
+ connection_.set_is_server(true);
+ writer_->set_blocked(true);
+ writer_->set_is_write_blocked_data_buffered(true);
+ connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
+ EXPECT_EQ(0u, writer_->last_packet_size());
+ EXPECT_FALSE(connection_.HasQueuedData());
+ EXPECT_TRUE(QuicConnectionPeer::IsWriteBlocked(&connection_));
+}
+
TEST_F(QuicConnectionTest, ClientHandlesVersionNegotiation) {
// Start out with some unsupported version.
QuicConnectionPeer::GetFramer(&connection_)->set_version_for_tests(
@@ -2588,8 +3000,9 @@ TEST_F(QuicConnectionTest, BadVersionNegotiation) {
// Send a version negotiation packet with the version the client started with.
// It should be rejected.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
- false));
+ EXPECT_CALL(visitor_,
+ OnConnectionClosed(QUIC_INVALID_VERSION_NEGOTIATION_PACKET,
+ false));
scoped_ptr<QuicEncryptedPacket> encrypted(
framer_.BuildVersionNegotiationPacket(
header.public_header, supported_versions));
@@ -2597,36 +3010,42 @@ TEST_F(QuicConnectionTest, BadVersionNegotiation) {
}
TEST_F(QuicConnectionTest, CheckSendStats) {
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(_, _)).Times(3);
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION, _));
- connection_.SendStreamData(1u, "first", 0, !kFin);
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
+ connection_.SendStreamDataWithString(3, "first", 0, !kFin, NULL);
size_t first_packet_size = last_sent_packet_size();
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, NOT_RETRANSMISSION, _));
- connection_.SendStreamData(1u, "second", 0, !kFin);
+ OnPacketSent(_, _, _, NOT_RETRANSMISSION, _));
+ connection_.SendStreamDataWithString(5, "second", 0, !kFin, NULL);
size_t second_packet_size = last_sent_packet_size();
// 2 retransmissions due to rto, 1 due to explicit nack.
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
EXPECT_CALL(*send_algorithm_,
- SentPacket(_, _, _, IS_RETRANSMISSION, _)).Times(3);
+ OnPacketSent(_, _, _, RTO_RETRANSMISSION, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, NACK_RETRANSMISSION, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(3);
+ EXPECT_CALL(visitor_, OnCanWrite()).WillRepeatedly(Return(true));
// Retransmit due to RTO.
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(10));
- connection_.OnRetransmissionTimeout();
+ connection_.GetRetransmissionAlarm()->Fire();
- // Retransmit due to explicit nacks
+ // Retransmit due to explicit nacks.
QuicAckFrame nack_three(4, QuicTime::Zero(), 0);
nack_three.received_info.missing_packets.insert(3);
+ nack_three.received_info.missing_packets.insert(1);
nack_three.received_info.entropy_hash =
QuicConnectionPeer::GetSentEntropyHash(&connection_, 4) ^
QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
- QuicConnectionPeer::GetSentEntropyHash(&connection_, 2);
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
QuicFrame frame(&nack_three);
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
- EXPECT_CALL(visitor_, OnCanWrite()).Times(3).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(1);
+ EXPECT_CALL(visitor_, OnCanWrite()).Times(4).WillRepeatedly(Return(true));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessFramePacket(frame);
@@ -2645,7 +3064,7 @@ TEST_F(QuicConnectionTest, CheckSendStats) {
EXPECT_EQ(2 * first_packet_size + second_packet_size - kQuicVersionSize,
stats.bytes_retransmitted);
EXPECT_EQ(3u, stats.packets_retransmitted);
- EXPECT_EQ(2u, stats.rto_count);
+ EXPECT_EQ(1u, stats.rto_count);
}
TEST_F(QuicConnectionTest, CheckReceiveStats) {
@@ -2672,10 +3091,10 @@ TEST_F(QuicConnectionTest, CheckReceiveStats) {
}
TEST_F(QuicConnectionTest, TestFecGroupLimits) {
- // Create and return a group for 1
+ // Create and return a group for 1.
ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 1) != NULL);
- // Create and return a group for 2
+ // Create and return a group for 2.
ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 2) != NULL);
// Create and return a group for 4. This should remove 1 but not 2.
@@ -2693,7 +3112,7 @@ TEST_F(QuicConnectionTest, TestFecGroupLimits) {
ASSERT_TRUE(QuicConnectionPeer::GetFecGroup(&connection_, 3) == NULL);
}
-TEST_F(QuicConnectionTest, DontProcessFramesIfPacketClosedConnection) {
+TEST_F(QuicConnectionTest, ProcessFramesIfPacketClosedConnection) {
// Construct a packet with stream frame and connection close frame.
header_.public_header.guid = guid_;
header_.packet_sequence_number = 1;
@@ -2705,7 +3124,6 @@ TEST_F(QuicConnectionTest, DontProcessFramesIfPacketClosedConnection) {
QuicConnectionCloseFrame qccf;
qccf.error_code = QUIC_PEER_GOING_AWAY;
- qccf.ack_frame = QuicAckFrame(0, QuicTime::Zero(), 1);
QuicFrame close_frame(&qccf);
QuicFrame stream_frame(&frame1_);
@@ -2718,8 +3136,8 @@ TEST_F(QuicConnectionTest, DontProcessFramesIfPacketClosedConnection) {
scoped_ptr<QuicEncryptedPacket> encrypted(framer_.EncryptPacket(
ENCRYPTION_NONE, 1, *packet));
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_PEER_GOING_AWAY, true));
- EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(0);
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, true));
+ EXPECT_CALL(visitor_, OnStreamFrames(_)).Times(1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
connection_.ProcessUdpPacket(IPEndPoint(), IPEndPoint(), *encrypted);
@@ -2755,41 +3173,41 @@ TEST_F(QuicConnectionTest, SelectMutualVersion) {
}
TEST_F(QuicConnectionTest, ConnectionCloseWhenNotWriteBlocked) {
- helper_->set_blocked(false); // Already default.
+ writer_->set_blocked(false); // Already default.
// Send a packet (but write will not block).
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- EXPECT_EQ(1u, helper_->packets_write_attempts());
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
// Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_PACKET_HEADER, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
ProcessDataPacket(6000, 0, !kEntropyFlag);
- EXPECT_EQ(2u, helper_->packets_write_attempts());
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
}
TEST_F(QuicConnectionTest, ConnectionCloseWhenWriteBlocked) {
EXPECT_EQ(0u, connection_.NumQueuedPackets());
- helper_->set_blocked(true);
+ writer_->set_blocked(true);
// Send a packet to so that write will really block.
- connection_.SendStreamData(1, "foo", 0, !kFin);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
- EXPECT_EQ(1u, helper_->packets_write_attempts());
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
// Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_PACKET_HEADER, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
ProcessDataPacket(6000, 0, !kEntropyFlag);
- EXPECT_EQ(1u, helper_->packets_write_attempts());
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
}
TEST_F(QuicConnectionTest, ConnectionCloseWhenNothingPending) {
- helper_->set_blocked(true);
+ writer_->set_blocked(true);
// Send an erroneous packet to close the connection.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_INVALID_PACKET_HEADER, false));
+ EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_PACKET_HEADER, false));
ProcessDataPacket(6000, 0, !kEntropyFlag);
- EXPECT_EQ(1u, helper_->packets_write_attempts());
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
}
TEST_F(QuicConnectionTest, AckNotifierTriggerCallback) {
@@ -2800,12 +3218,14 @@ TEST_F(QuicConnectionTest, AckNotifierTriggerCallback) {
EXPECT_CALL(delegate, OnAckNotification()).Times(1);;
// Send some data, which will register the delegate to be notified.
- connection_.SendStreamDataAndNotifyWhenAcked(1, "foo", 0, !kFin, &delegate);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, &delegate);
// Process an ACK from the server which should trigger the callback.
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
QuicAckFrame frame(1, QuicTime::Zero(), 0);
- ProcessAckPacket(&frame, true);
+ frame.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ ProcessAckPacket(&frame);
}
TEST_F(QuicConnectionTest, AckNotifierFailToTriggerCallback) {
@@ -2815,22 +3235,26 @@ TEST_F(QuicConnectionTest, AckNotifierFailToTriggerCallback) {
MockAckNotifierDelegate delegate;
EXPECT_CALL(delegate, OnAckNotification()).Times(0);;
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(2);
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(2);
// Send some data, which will register the delegate to be notified. This will
// not be ACKed and so the delegate should never be called.
- connection_.SendStreamDataAndNotifyWhenAcked(1, "foo", 0, !kFin, &delegate);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, &delegate);
// Send some other data which we will ACK.
- connection_.SendStreamData(1, "foo", 0, !kFin);
- connection_.SendStreamData(1, "bar", 0, !kFin);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ connection_.SendStreamDataWithString(1, "bar", 0, !kFin, NULL);
// Now we receive ACK for packets 2 and 3, but importantly missing packet 1
// which we registered to be notified about.
QuicAckFrame frame(3, QuicTime::Zero(), 0);
frame.received_info.missing_packets.insert(1);
- ProcessAckPacket(&frame, true);
+ frame.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 3) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _));
+ ProcessAckPacket(&frame);
}
TEST_F(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
@@ -2841,34 +3265,32 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterRetransmission) {
EXPECT_CALL(delegate, OnAckNotification()).Times(1);;
// In total expect ACKs for all 4 packets.
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(4);
-
- // We will lose the second packet.
- EXPECT_CALL(*send_algorithm_, OnIncomingLoss(_)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(4);
// Send four packets, and register to be notified on ACK of packet 2.
- connection_.SendStreamData(1, "foo", 0, !kFin);
- connection_.SendStreamDataAndNotifyWhenAcked(1, "bar", 0, !kFin, &delegate);
- connection_.SendStreamData(1, "baz", 0, !kFin);
- connection_.SendStreamData(1, "qux", 0, !kFin);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, NULL);
+ connection_.SendStreamDataWithString(1, "bar", 0, !kFin, &delegate);
+ connection_.SendStreamDataWithString(1, "baz", 0, !kFin, NULL);
+ connection_.SendStreamDataWithString(1, "qux", 0, !kFin, NULL);
- // Now we receive ACK for packets 1, 3, and 4.
+ // Now we receive ACK for packets 1, 3, and 4, which invokes fast retransmit.
QuicAckFrame frame(4, QuicTime::Zero(), 0);
frame.received_info.missing_packets.insert(2);
- ProcessAckPacket(&frame, true);
-
- // Advance time to trigger RTO, for packet 2 (which should be retransmitted as
- // packet 5).
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(2, _)).Times(1);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(1);
-
- clock_.AdvanceTime(DefaultRetransmissionTime());
- connection_.OnRetransmissionTimeout();
+ frame.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 4) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 2) ^
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(2, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(2, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
+ ProcessAckPacket(&frame);
// Now we get an ACK for packet 5 (retransmitted packet 2), which should
// trigger the callback.
QuicAckFrame second_ack_frame(5, QuicTime::Zero(), 0);
- ProcessAckPacket(&second_ack_frame, true);
+ second_ack_frame.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 5);
+ ProcessAckPacket(&second_ack_frame);
}
// TODO(rjshade): Add a similar test that FEC recovery on peer (and resulting
@@ -2882,16 +3304,18 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) {
EXPECT_CALL(delegate, OnAckNotification()).Times(1);;
// Expect ACKs for 1 packet.
- EXPECT_CALL(*send_algorithm_, OnIncomingAck(_, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(1);
// Send one packet, and register to be notified on ACK.
- connection_.SendStreamDataAndNotifyWhenAcked(1, "foo", 0, !kFin, &delegate);
+ connection_.SendStreamDataWithString(1, "foo", 0, !kFin, &delegate);
// 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(1, QuicTime::Zero(), 0);
+ ack_frame.received_info.entropy_hash =
+ QuicConnectionPeer::GetSentEntropyHash(&connection_, 1);
frames.push_back(QuicFrame(&ack_frame));
// Dummy stream frame to satisfy expectations set elsewhere.
@@ -2903,7 +3327,7 @@ TEST_F(QuicConnectionTest, AckNotifierCallbackAfterFECRecovery) {
ack_header.public_header.version_flag = false;
ack_header.entropy_flag = !kEntropyFlag;
ack_header.fec_flag = true;
- ack_header.packet_sequence_number = 42;
+ ack_header.packet_sequence_number = 1;
ack_header.is_in_fec_group = IN_FEC_GROUP;
ack_header.fec_group = 1;
@@ -2925,7 +3349,7 @@ class MockQuicConnectionDebugVisitor
void(QuicPacketSequenceNumber,
EncryptionLevel,
const QuicEncryptedPacket&,
- int));
+ WriteResult));
MOCK_METHOD2(OnPacketRetransmitted,
void(QuicPacketSequenceNumber,
@@ -2977,6 +3401,17 @@ TEST_F(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
connection_.OnPacketHeader(header);
}
+TEST_F(QuicConnectionTest, Pacing) {
+ ValueRestore<bool> old_flag(&FLAGS_enable_quic_pacing, true);
+
+ TestConnection server(guid_, IPEndPoint(), helper_.get(), writer_.get(),
+ true);
+ TestConnection client(guid_, IPEndPoint(), helper_.get(), writer_.get(),
+ false);
+ EXPECT_TRUE(client.sent_packet_manager().using_pacing());
+ EXPECT_FALSE(server.sent_packet_manager().using_pacing());
+}
+
} // 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 b0f81174b71..3e5f84059fc 100644
--- a/chromium/net/quic/quic_crypto_client_stream.cc
+++ b/chromium/net/quic/quic_crypto_client_stream.cc
@@ -170,7 +170,25 @@ void QuicCryptoClientStream::DoHandshakeLoop(
if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
crypto_config_->FillInchoateClientHello(
- server_hostname_, cached, &crypto_negotiated_params_, &out);
+ server_hostname_,
+ session()->connection()->supported_versions().front(),
+ cached, &crypto_negotiated_params_, &out);
+ // Pad the inchoate client hello to fill up a packet.
+ const size_t kFramingOverhead = 50; // A rough estimate.
+ const size_t max_packet_size =
+ session()->connection()->options()->max_packet_length;
+ if (max_packet_size <= kFramingOverhead) {
+ DLOG(DFATAL) << "max_packet_length (" << max_packet_size
+ << ") has no room for framing overhead.";
+ CloseConnection(QUIC_INTERNAL_ERROR);
+ return;
+ }
+ if (kClientHelloMinimumSize > max_packet_size - kFramingOverhead) {
+ DLOG(DFATAL) << "Client hello won't fit in a single packet.";
+ CloseConnection(QUIC_INTERNAL_ERROR);
+ return;
+ }
+ out.set_minimum_size(max_packet_size - kFramingOverhead);
next_state_ = STATE_RECV_REJ;
DVLOG(1) << "Client: Sending " << out.DebugString();
SendHandshakeMessage(out);
@@ -180,6 +198,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(
error = crypto_config_->FillClientHello(
server_hostname_,
session()->connection()->guid(),
+ session()->connection()->supported_versions().front(),
cached,
session()->connection()->clock()->WallNow(),
session()->connection()->random_generator(),
@@ -333,8 +352,10 @@ void QuicCryptoClientStream::DoHandshakeLoop(
return;
}
error = crypto_config_->ProcessServerHello(
- *in, session()->connection()->guid(), cached,
- &crypto_negotiated_params_, &error_details);
+ *in, session()->connection()->guid(),
+ session()->connection()->server_supported_versions(),
+ cached, &crypto_negotiated_params_, &error_details);
+
if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(
error, "Server hello invalid: " + error_details);
@@ -346,6 +367,8 @@ void QuicCryptoClientStream::DoHandshakeLoop(
error, "Server hello invalid: " + error_details);
return;
}
+ session()->OnConfigNegotiated();
+
CrypterPair* crypters =
&crypto_negotiated_params_.forward_secure_crypters;
// TODO(agl): we don't currently latch this decrypter because the idea
diff --git a/chromium/net/quic/quic_crypto_client_stream.h b/chromium/net/quic/quic_crypto_client_stream.h
index 5a9042b925c..ca2fea74d75 100644
--- a/chromium/net/quic/quic_crypto_client_stream.h
+++ b/chromium/net/quic/quic_crypto_client_stream.h
@@ -9,8 +9,8 @@
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
-#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/proof_verifier.h"
+#include "net/quic/crypto/quic_crypto_client_config.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_crypto_stream.h"
diff --git a/chromium/net/quic/quic_crypto_client_stream_test.cc b/chromium/net/quic/quic_crypto_client_stream_test.cc
index 2ad9a3a21c1..8154d177988 100644
--- a/chromium/net/quic/quic_crypto_client_stream_test.cc
+++ b/chromium/net/quic/quic_crypto_client_stream_test.cc
@@ -24,9 +24,8 @@ const char kServerHostname[] = "example.com";
class QuicCryptoClientStreamTest : public ::testing::Test {
public:
QuicCryptoClientStreamTest()
- : addr_(),
- connection_(new PacketSavingConnection(1, addr_, true)),
- session_(new TestSession(connection_, DefaultQuicConfig(), true)),
+ : connection_(new PacketSavingConnection(false)),
+ session_(new TestSession(connection_, DefaultQuicConfig())),
stream_(new QuicCryptoClientStream(kServerHostname, session_.get(),
&crypto_config_)) {
session_->SetCryptoStream(stream_.get());
@@ -43,7 +42,6 @@ class QuicCryptoClientStreamTest : public ::testing::Test {
message_data_.reset(framer.ConstructHandshakeMessage(message_));
}
- IPEndPoint addr_;
PacketSavingConnection* connection_;
scoped_ptr<TestSession> session_;
scoped_ptr<QuicCryptoClientStream> stream_;
@@ -53,47 +51,27 @@ class QuicCryptoClientStreamTest : public ::testing::Test {
};
TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
EXPECT_FALSE(stream_->encryption_established());
EXPECT_FALSE(stream_->handshake_confirmed());
}
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
EXPECT_TRUE(stream_->encryption_established());
EXPECT_TRUE(stream_->handshake_confirmed());
}
TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
EXPECT_CALL(*connection_, SendConnectionClose(
QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
- stream_->ProcessData(message_data_->data(), message_data_->length());
+ stream_->ProcessRawData(message_data_->data(), message_data_->length());
}
TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
EXPECT_TRUE(stream_->CryptoConnect());
message_.set_tag(kCHLO);
@@ -101,19 +79,15 @@ TEST_F(QuicCryptoClientStreamTest, BadMessageType) {
EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
QUIC_INVALID_CRYPTO_MESSAGE_TYPE, "Expected REJ"));
- stream_->ProcessData(message_data_->data(), message_data_->length());
+ stream_->ProcessRawData(message_data_->data(), message_data_->length());
}
TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
const QuicConfig* config = session_->config();
- EXPECT_EQ(kQBIC, config->congestion_control());
+ EXPECT_EQ(FLAGS_enable_quic_pacing ? kPACE : kQBIC,
+ config->congestion_control());
EXPECT_EQ(kDefaultTimeoutSecs,
config->idle_connection_state_lifetime().ToSeconds());
EXPECT_EQ(kDefaultMaxStreamsPerConnection,
@@ -127,11 +101,6 @@ TEST_F(QuicCryptoClientStreamTest, NegotiatedParameters) {
}
TEST_F(QuicCryptoClientStreamTest, InvalidHostname) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
stream_.reset(new QuicCryptoClientStream("invalid", session_.get(),
&crypto_config_));
session_->SetCryptoStream(stream_.get());
@@ -145,8 +114,8 @@ TEST_F(QuicCryptoClientStreamTest, ExpiredServerConfig) {
// Seed the config with a cached server config.
CompleteCryptoHandshake();
- connection_ = new PacketSavingConnection(1, addr_, true);
- session_.reset(new TestSession(connection_, QuicConfig(), true));
+ connection_ = new PacketSavingConnection(true);
+ session_.reset(new TestSession(connection_, DefaultQuicConfig()));
stream_.reset(new QuicCryptoClientStream(kServerHostname, session_.get(),
&crypto_config_));
diff --git a/chromium/net/quic/quic_crypto_server_stream.cc b/chromium/net/quic/quic_crypto_server_stream.cc
index 63637f54294..c0ae1f19b92 100644
--- a/chromium/net/quic/quic_crypto_server_stream.cc
+++ b/chromium/net/quic/quic_crypto_server_stream.cc
@@ -7,8 +7,8 @@
#include "base/base64.h"
#include "crypto/secure_hash.h"
#include "net/quic/crypto/crypto_protocol.h"
-#include "net/quic/crypto/crypto_server_config.h"
#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
@@ -19,10 +19,15 @@ QuicCryptoServerStream::QuicCryptoServerStream(
const QuicCryptoServerConfig& crypto_config,
QuicSession* session)
: QuicCryptoStream(session),
- crypto_config_(crypto_config) {
+ crypto_config_(crypto_config),
+ validate_client_hello_cb_(NULL) {
}
QuicCryptoServerStream::~QuicCryptoServerStream() {
+ // Detach from the validation callback.
+ if (validate_client_hello_cb_ != NULL) {
+ validate_client_hello_cb_->Cancel();
+ }
}
void QuicCryptoServerStream::OnHandshakeMessage(
@@ -40,10 +45,33 @@ void QuicCryptoServerStream::OnHandshakeMessage(
return;
}
+ if (validate_client_hello_cb_ != NULL) {
+ // Already processing some other handshake message. The protocol
+ // does not allow for clients to send multiple handshake messages
+ // before the server has a chance to respond.
+ CloseConnection(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
+ return;
+ }
+
+ validate_client_hello_cb_ = new ValidateCallback(this);
+ return crypto_config_.ValidateClientHello(
+ message,
+ session()->connection()->peer_address(),
+ session()->connection()->clock(),
+ validate_client_hello_cb_);
+}
+
+void QuicCryptoServerStream::FinishProcessingHandshakeMessage(
+ const CryptoHandshakeMessage& message,
+ const ValidateClientHelloResultCallback::Result& result) {
+ // Clear the callback that got us here.
+ DCHECK(validate_client_hello_cb_ != NULL);
+ validate_client_hello_cb_ = NULL;
+
string error_details;
CryptoHandshakeMessage reply;
-
- QuicErrorCode error = ProcessClientHello(message, &reply, &error_details);
+ QuicErrorCode error = ProcessClientHello(
+ message, result, &reply, &error_details);
if (error != QUIC_NO_ERROR) {
CloseConnectionWithDetails(error, error_details);
@@ -62,6 +90,7 @@ void QuicCryptoServerStream::OnHandshakeMessage(
CloseConnectionWithDetails(error, error_details);
return;
}
+ session()->OnConfigNegotiated();
config->ToHandshakeMessage(&reply);
@@ -127,15 +156,34 @@ bool QuicCryptoServerStream::GetBase64SHA256ClientChannelID(
QuicErrorCode QuicCryptoServerStream::ProcessClientHello(
const CryptoHandshakeMessage& message,
+ const ValidateClientHelloResultCallback::Result& result,
CryptoHandshakeMessage* reply,
string* error_details) {
return crypto_config_.ProcessClientHello(
- message,
+ result,
session()->connection()->guid(),
session()->connection()->peer_address(),
+ session()->connection()->version(),
+ session()->connection()->supported_versions(),
session()->connection()->clock(),
session()->connection()->random_generator(),
&crypto_negotiated_params_, reply, error_details);
}
+QuicCryptoServerStream::ValidateCallback::ValidateCallback(
+ QuicCryptoServerStream* parent) : parent_(parent) {
+}
+
+void QuicCryptoServerStream::ValidateCallback::Cancel() {
+ parent_ = NULL;
+}
+
+void QuicCryptoServerStream::ValidateCallback::RunImpl(
+ const CryptoHandshakeMessage& client_hello,
+ const Result& result) {
+ if (parent_ != NULL) {
+ parent_->FinishProcessingHandshakeMessage(client_hello, result);
+ }
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_crypto_server_stream.h b/chromium/net/quic/quic_crypto_server_stream.h
index b4967d866ce..43924d54d93 100644
--- a/chromium/net/quic/quic_crypto_server_stream.h
+++ b/chromium/net/quic/quic_crypto_server_stream.h
@@ -8,6 +8,7 @@
#include <string>
#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_crypto_stream.h"
@@ -40,14 +41,44 @@ class NET_EXPORT_PRIVATE QuicCryptoServerStream : public QuicCryptoStream {
protected:
virtual QuicErrorCode ProcessClientHello(
const CryptoHandshakeMessage& message,
+ const ValidateClientHelloResultCallback::Result& result,
CryptoHandshakeMessage* reply,
std::string* error_details);
private:
friend class test::CryptoTestUtils;
+ class ValidateCallback : public ValidateClientHelloResultCallback {
+ public:
+ explicit ValidateCallback(QuicCryptoServerStream* parent);
+ // To allow the parent to detach itself from the callback before deletion.
+ void Cancel();
+
+ // From ValidateClientHelloResultCallback
+ virtual void RunImpl(const CryptoHandshakeMessage& client_hello,
+ const Result& result) OVERRIDE;
+
+ private:
+ QuicCryptoServerStream* parent_;
+
+ DISALLOW_COPY_AND_ASSIGN(ValidateCallback);
+ };
+
+ // Invoked by ValidateCallback::RunImpl once initial validation of
+ // the client hello is complete. Finishes processing of the client
+ // hello message and handles handshake success/failure.
+ void FinishProcessingHandshakeMessage(
+ const CryptoHandshakeMessage& message,
+ const ValidateClientHelloResultCallback::Result& result);
+
// crypto_config_ contains crypto parameters for the handshake.
const QuicCryptoServerConfig& crypto_config_;
+
+ // Pointer to the active callback that will receive the result of
+ // the client hello validation request and forward it to
+ // FinishProcessingHandshakeMessage for processing. NULL if no
+ // handshake message is being validated.
+ ValidateCallback* validate_client_hello_cb_;
};
} // namespace net
diff --git a/chromium/net/quic/quic_crypto_server_stream_test.cc b/chromium/net/quic/quic_crypto_server_stream_test.cc
index 9e92b2b0854..9897e22f738 100644
--- a/chromium/net/quic/quic_crypto_server_stream_test.cc
+++ b/chromium/net/quic/quic_crypto_server_stream_test.cc
@@ -12,8 +12,8 @@
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_protocol.h"
-#include "net/quic/crypto/crypto_server_config.h"
#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_random.h"
@@ -21,6 +21,7 @@
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/delayed_verify_strike_register_client.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -30,23 +31,33 @@ class QuicConnection;
class ReliableQuicStream;
} // namespace net
+using std::pair;
using testing::_;
namespace net {
namespace test {
+
+class QuicCryptoServerConfigPeer {
+ public:
+ static string GetPrimaryOrbit(const QuicCryptoServerConfig& config) {
+ base::AutoLock lock(config.configs_lock_);
+ CHECK(config.primary_config_ != NULL);
+ return string(reinterpret_cast<const char*>(config.primary_config_->orbit),
+ kOrbitSize);
+ }
+};
+
namespace {
-class QuicCryptoServerStreamTest : public ::testing::Test {
+class QuicCryptoServerStreamTest : public testing::TestWithParam<bool> {
public:
QuicCryptoServerStreamTest()
- : guid_(1),
- addr_(ParseIPLiteralToNumber("192.0.2.33", &ip_) ?
- ip_ : IPAddressNumber(), 1),
- connection_(new PacketSavingConnection(guid_, addr_, true)),
- session_(connection_, QuicConfig(), true),
+ : connection_(new PacketSavingConnection(true)),
+ session_(connection_, DefaultQuicConfig()),
crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance()),
- stream_(crypto_config_, &session_) {
+ stream_(crypto_config_, &session_),
+ strike_register_client_(NULL) {
config_.SetDefaults();
session_.config()->SetDefaults();
session_.SetCryptoStream(&stream_);
@@ -55,10 +66,28 @@ class QuicCryptoServerStreamTest : public ::testing::Test {
connection_->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
// TODO(rtenneti): Enable testing of ProofSource.
// crypto_config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
+ crypto_config_.set_strike_register_no_startup_period();
CryptoTestUtils::SetupCryptoServerConfigForTest(
connection_->clock(), connection_->random_generator(),
session_.config(), &crypto_config_);
+
+ if (AsyncStrikeRegisterVerification()) {
+ string orbit =
+ QuicCryptoServerConfigPeer::GetPrimaryOrbit(crypto_config_);
+ strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
+ 10000, // strike_register_max_entries
+ static_cast<uint32>(connection_->clock()->WallNow().ToUNIXSeconds()),
+ 60, // strike_register_window_secs
+ reinterpret_cast<const uint8 *>(orbit.data()),
+ StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
+ strike_register_client_->StartDelayingVerification();
+ crypto_config_.SetStrikeRegisterClient(strike_register_client_);
+ }
+ }
+
+ bool AsyncStrikeRegisterVerification() {
+ return GetParam();
}
void ConstructHandshakeMessage() {
@@ -72,9 +101,6 @@ class QuicCryptoServerStreamTest : public ::testing::Test {
}
protected:
- IPAddressNumber ip_;
- QuicGuid guid_;
- IPEndPoint addr_;
PacketSavingConnection* connection_;
TestSession session_;
QuicConfig config_;
@@ -83,24 +109,17 @@ class QuicCryptoServerStreamTest : public ::testing::Test {
CryptoHandshakeMessage message_;
scoped_ptr<QuicData> message_data_;
CryptoTestUtils::FakeClientOptions client_options_;
+ DelayedVerifyStrikeRegisterClient* strike_register_client_;
};
-TEST_F(QuicCryptoServerStreamTest, NotInitiallyConected) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
+INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
+TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
EXPECT_FALSE(stream_.encryption_established());
EXPECT_FALSE(stream_.handshake_confirmed());
}
-TEST_F(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
+TEST_P(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
// CompleteCryptoHandshake returns the number of client hellos sent. This
// test should send:
// * One to get a source-address token and certificates.
@@ -110,27 +129,16 @@ TEST_F(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
EXPECT_TRUE(stream_.handshake_confirmed());
}
-TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
- QuicGuid guid(1);
- IPAddressNumber ip;
- ParseIPLiteralToNumber("127.0.0.1", &ip);
- IPEndPoint addr(ip, 0);
- PacketSavingConnection* client_conn =
- new PacketSavingConnection(guid, addr, false);
- PacketSavingConnection* server_conn =
- new PacketSavingConnection(guid, addr, false);
+TEST_P(QuicCryptoServerStreamTest, ZeroRTT) {
+ PacketSavingConnection* client_conn = new PacketSavingConnection(false);
+ PacketSavingConnection* server_conn = new PacketSavingConnection(false);
client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
server_conn->AdvanceTime(QuicTime::Delta::FromSeconds(100000));
QuicConfig client_config;
client_config.SetDefaults();
scoped_ptr<TestSession> client_session(
- new TestSession(client_conn, client_config, false));
+ new TestSession(client_conn, client_config));
QuicCryptoClientConfig client_crypto_config;
client_crypto_config.SetDefaults();
@@ -143,8 +151,7 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
CHECK(client->CryptoConnect());
CHECK_EQ(1u, client_conn->packets_.size());
- scoped_ptr<TestSession> server_session(
- new TestSession(server_conn, config_, true));
+ scoped_ptr<TestSession> server_session(new TestSession(server_conn, config_));
scoped_ptr<QuicCryptoServerStream> server(
new QuicCryptoServerStream(crypto_config_, server_session.get()));
server_session->SetCryptoStream(server.get());
@@ -156,8 +163,8 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
// Now do another handshake, hopefully in 0-RTT.
LOG(INFO) << "Resetting for 0-RTT handshake attempt";
- client_conn = new PacketSavingConnection(guid, addr, false);
- server_conn = new PacketSavingConnection(guid, addr, false);
+ client_conn = new PacketSavingConnection(false);
+ server_conn = new PacketSavingConnection(false);
// We need to advance time past the strike-server window so that it's
// authoritative in this time span.
client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(102000));
@@ -166,8 +173,8 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
// This causes the client's nonce to be different and thus stops the
// strike-register from rejecting the repeated nonce.
reinterpret_cast<MockRandom*>(client_conn->random_generator())->ChangeValue();
- client_session.reset(new TestSession(client_conn, client_config, false));
- server_session.reset(new TestSession(server_conn, config_, true));
+ client_session.reset(new TestSession(client_conn, client_config));
+ server_session.reset(new TestSession(server_conn, config_));
client.reset(new QuicCryptoClientStream(
"test.example.com", client_session.get(), &client_crypto_config));
client_session->SetCryptoStream(client.get());
@@ -178,44 +185,58 @@ TEST_F(QuicCryptoServerStreamTest, ZeroRTT) {
CHECK(client->CryptoConnect());
- CryptoTestUtils::CommunicateHandshakeMessages(
- client_conn, client.get(), server_conn, server.get());
+ if (AsyncStrikeRegisterVerification()) {
+ EXPECT_FALSE(client->handshake_confirmed());
+ EXPECT_FALSE(server->handshake_confirmed());
+
+ // Advance the handshake. Expect that the server will be stuck
+ // waiting for client nonce verification to complete.
+ pair<size_t, size_t> messages_moved = CryptoTestUtils::AdvanceHandshake(
+ client_conn, client.get(), 0, server_conn, server.get(), 0);
+ EXPECT_EQ(1u, messages_moved.first);
+ EXPECT_EQ(0u, messages_moved.second);
+ EXPECT_EQ(1, strike_register_client_->PendingVerifications());
+ EXPECT_FALSE(client->handshake_confirmed());
+ EXPECT_FALSE(server->handshake_confirmed());
+
+ // The server handshake completes once the nonce verification completes.
+ strike_register_client_->RunPendingVerifications();
+ EXPECT_FALSE(client->handshake_confirmed());
+ EXPECT_TRUE(server->handshake_confirmed());
+
+ messages_moved = CryptoTestUtils::AdvanceHandshake(
+ client_conn, client.get(), messages_moved.first,
+ server_conn, server.get(), messages_moved.second);
+ EXPECT_EQ(1u, messages_moved.first);
+ EXPECT_EQ(1u, messages_moved.second);
+ EXPECT_TRUE(client->handshake_confirmed());
+ EXPECT_TRUE(server->handshake_confirmed());
+ } else {
+ CryptoTestUtils::CommunicateHandshakeMessages(
+ client_conn, client.get(), server_conn, server.get());
+ }
+
EXPECT_EQ(1, client->num_sent_client_hellos());
}
-TEST_F(QuicCryptoServerStreamTest, MessageAfterHandshake) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
+TEST_P(QuicCryptoServerStreamTest, MessageAfterHandshake) {
CompleteCryptoHandshake();
EXPECT_CALL(*connection_, SendConnectionClose(
QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
message_.set_tag(kCHLO);
ConstructHandshakeMessage();
- stream_.ProcessData(message_data_->data(), message_data_->length());
+ stream_.ProcessRawData(message_data_->data(), message_data_->length());
}
-TEST_F(QuicCryptoServerStreamTest, BadMessageType) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
+TEST_P(QuicCryptoServerStreamTest, BadMessageType) {
message_.set_tag(kSHLO);
ConstructHandshakeMessage();
EXPECT_CALL(*connection_, SendConnectionClose(
QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
- stream_.ProcessData(message_data_->data(), message_data_->length());
+ stream_.ProcessRawData(message_data_->data(), message_data_->length());
}
-TEST_F(QuicCryptoServerStreamTest, WithoutCertificates) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
+TEST_P(QuicCryptoServerStreamTest, WithoutCertificates) {
crypto_config_.SetProofSource(NULL);
client_options_.dont_verify_certs = true;
@@ -226,12 +247,7 @@ TEST_F(QuicCryptoServerStreamTest, WithoutCertificates) {
EXPECT_TRUE(stream_.handshake_confirmed());
}
-TEST_F(QuicCryptoServerStreamTest, ChannelID) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
+TEST_P(QuicCryptoServerStreamTest, ChannelID) {
client_options_.channel_id_enabled = true;
// TODO(rtenneti): Enable testing of ProofVerifier.
// CompleteCryptoHandshake verifies
diff --git a/chromium/net/quic/quic_crypto_stream.cc b/chromium/net/quic/quic_crypto_stream.cc
index 3c10c5bfbf9..d79fa735786 100644
--- a/chromium/net/quic/quic_crypto_stream.cc
+++ b/chromium/net/quic/quic_crypto_stream.cc
@@ -24,7 +24,8 @@ QuicCryptoStream::QuicCryptoStream(QuicSession* session)
}
void QuicCryptoStream::OnError(CryptoFramer* framer) {
- session()->ConnectionClose(framer->error(), false);
+ DLOG(WARNING) << "Error processing crypto data: "
+ << QuicUtils::ErrorToString(framer->error());
}
void QuicCryptoStream::OnHandshakeMessage(
@@ -32,8 +33,8 @@ void QuicCryptoStream::OnHandshakeMessage(
session()->OnCryptoHandshakeMessageReceived(message);
}
-uint32 QuicCryptoStream::ProcessData(const char* data,
- uint32 data_len) {
+uint32 QuicCryptoStream::ProcessRawData(const char* data,
+ uint32 data_len) {
// Do not process handshake messages after the handshake is confirmed.
if (handshake_confirmed()) {
CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
@@ -46,13 +47,8 @@ uint32 QuicCryptoStream::ProcessData(const char* data,
return data_len;
}
-void QuicCryptoStream::CloseConnection(QuicErrorCode error) {
- session()->connection()->SendConnectionClose(error);
-}
-
-void QuicCryptoStream::CloseConnectionWithDetails(QuicErrorCode error,
- const string& details) {
- session()->connection()->SendConnectionCloseWithDetails(error, details);
+QuicPriority QuicCryptoStream::EffectivePriority() const {
+ return QuicUtils::HighestPriority();
}
void QuicCryptoStream::SendHandshakeMessage(
@@ -63,7 +59,7 @@ void QuicCryptoStream::SendHandshakeMessage(
// any other frames in a single packet.
session()->connection()->Flush();
// TODO(wtc): check the return value.
- WriteData(string(data.data(), data.length()), false);
+ WriteOrBufferData(string(data.data(), data.length()), false);
session()->connection()->Flush();
}
diff --git a/chromium/net/quic/quic_crypto_stream.h b/chromium/net/quic/quic_crypto_stream.h
index c402b0d9b44..a082d50dbf2 100644
--- a/chromium/net/quic/quic_crypto_stream.h
+++ b/chromium/net/quic/quic_crypto_stream.h
@@ -38,7 +38,8 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
const CryptoHandshakeMessage& message) OVERRIDE;
// ReliableQuicStream implementation
- virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE;
+ virtual uint32 ProcessRawData(const char* data, uint32 data_len) OVERRIDE;
+ virtual QuicPriority EffectivePriority() const OVERRIDE;
// Sends |message| to the peer.
// TODO(wtc): return a success/failure status.
@@ -50,10 +51,6 @@ class NET_EXPORT_PRIVATE QuicCryptoStream
const QuicCryptoNegotiatedParameters& crypto_negotiated_params() const;
protected:
- // Closes the connection
- void CloseConnection(QuicErrorCode error);
- void CloseConnectionWithDetails(QuicErrorCode error, const string& details);
-
bool encryption_established_;
bool handshake_confirmed_;
diff --git a/chromium/net/quic/quic_crypto_stream_test.cc b/chromium/net/quic/quic_crypto_stream_test.cc
index cc69304b749..c8dbab51453 100644
--- a/chromium/net/quic/quic_crypto_stream_test.cc
+++ b/chromium/net/quic/quic_crypto_stream_test.cc
@@ -46,9 +46,8 @@ class MockQuicCryptoStream : public QuicCryptoStream {
class QuicCryptoStreamTest : public ::testing::Test {
public:
QuicCryptoStreamTest()
- : addr_(IPAddressNumber(), 1),
- connection_(new MockConnection(1, addr_, false)),
- session_(connection_, true),
+ : connection_(new MockConnection(false)),
+ session_(connection_),
stream_(&session_) {
message_.set_tag(kSHLO);
message_.SetStringPiece(1, "abc");
@@ -62,7 +61,6 @@ class QuicCryptoStreamTest : public ::testing::Test {
}
protected:
- IPEndPoint addr_;
MockConnection* connection_;
MockSession session_;
MockQuicCryptoStream stream_;
@@ -78,16 +76,10 @@ TEST_F(QuicCryptoStreamTest, NotInitiallyConected) {
EXPECT_FALSE(stream_.handshake_confirmed());
}
-TEST_F(QuicCryptoStreamTest, OnErrorClosesConnection) {
- CryptoFramer framer;
- EXPECT_CALL(session_, ConnectionClose(QUIC_NO_ERROR, false));
- stream_.OnError(&framer);
-}
-
-TEST_F(QuicCryptoStreamTest, ProcessData) {
+TEST_F(QuicCryptoStreamTest, ProcessRawData) {
EXPECT_EQ(message_data_->length(),
- stream_.ProcessData(message_data_->data(),
- message_data_->length()));
+ stream_.ProcessRawData(message_data_->data(),
+ message_data_->length()));
ASSERT_EQ(1u, stream_.messages()->size());
const CryptoHandshakeMessage& message = (*stream_.messages())[0];
EXPECT_EQ(kSHLO, message.tag());
@@ -106,7 +98,7 @@ TEST_F(QuicCryptoStreamTest, ProcessBadData) {
EXPECT_CALL(*connection_,
SendConnectionClose(QUIC_CRYPTO_TAGS_OUT_OF_ORDER));
- EXPECT_EQ(0u, stream_.ProcessData(bad.data(), bad.length()));
+ EXPECT_EQ(0u, stream_.ProcessRawData(bad.data(), bad.length()));
}
} // namespace
diff --git a/chromium/net/quic/quic_data_reader.cc b/chromium/net/quic/quic_data_reader.cc
index 3bb7fc3f8ab..b9a6acf32f5 100644
--- a/chromium/net/quic/quic_data_reader.cc
+++ b/chromium/net/quic/quic_data_reader.cc
@@ -4,6 +4,9 @@
#include "net/quic/quic_data_reader.h"
+#include "net/base/int128.h"
+#include "net/quic/quic_protocol.h"
+
using base::StringPiece;
namespace net {
@@ -59,6 +62,37 @@ bool QuicDataReader::ReadUInt128(uint128* result) {
return true;
}
+bool QuicDataReader::ReadUFloat16(uint64* result) {
+ uint16 value;
+ if (!ReadUInt16(&value)) {
+ return false;
+ }
+
+ *result = value;
+ if (*result < (1 << kUFloat16MantissaEffectiveBits)) {
+ // Fast path: either the value is denormalized (no hidden bit), or
+ // normalized (hidden bit set, exponent offset by one) with exponent zero.
+ // Zero exponent offset by one sets the bit exactly where the hidden bit is.
+ // So in both cases the value encodes itself.
+ return true;
+ }
+
+ uint16 exponent = value >> kUFloat16MantissaBits; // No sign extend on uint!
+ // After the fast pass, the exponent is at least one (offset by one).
+ // Un-offset the exponent.
+ --exponent;
+ DCHECK_GE(exponent, 1);
+ DCHECK_LE(exponent, kUFloat16MaxExponent);
+ // Here we need to clear the exponent and set the hidden bit. We have already
+ // decremented the exponent, so when we subtract it, it leaves behind the
+ // hidden bit.
+ *result -= exponent << kUFloat16MantissaBits;
+ *result <<= exponent;
+ DCHECK_GE(value, 1 << kUFloat16MantissaEffectiveBits);
+ DCHECK_LE(value, kUFloat16MaxValue);
+ return true;
+}
+
bool QuicDataReader::ReadStringPiece16(StringPiece* result) {
// Read resultant length.
uint16 result_len;
diff --git a/chromium/net/quic/quic_data_reader.h b/chromium/net/quic/quic_data_reader.h
index fff07ddc703..9effa1cc896 100644
--- a/chromium/net/quic/quic_data_reader.h
+++ b/chromium/net/quic/quic_data_reader.h
@@ -59,6 +59,11 @@ class NET_EXPORT_PRIVATE QuicDataReader {
// Returns true on success, false otherwise.
bool ReadUInt128(uint128* result);
+ // Reads a 16-bit unsigned float into the given output parameter.
+ // Forwards the internal iterator on success.
+ // Returns true on success, false otherwise.
+ bool ReadUFloat16(uint64* result);
+
// Reads a string prefixed with 16-bit length into the given output parameter.
//
// NOTE: Does not copy but rather references strings in the underlying buffer.
diff --git a/chromium/net/quic/quic_data_stream.cc b/chromium/net/quic/quic_data_stream.cc
new file mode 100644
index 00000000000..3c992a777b0
--- /dev/null
+++ b/chromium/net/quic/quic_data_stream.cc
@@ -0,0 +1,333 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_data_stream.h"
+
+#include "base/logging.h"
+#include "net/quic/quic_session.h"
+#include "net/quic/quic_spdy_decompressor.h"
+#include "net/spdy/write_blocked_list.h"
+
+using base::StringPiece;
+using std::min;
+
+namespace net {
+
+#define ENDPOINT (session()->is_server() ? "Server: " : " Client: ")
+
+namespace {
+
+// This is somewhat arbitrary. It's possible, but unlikely, we will either fail
+// to set a priority client-side, or cancel a stream before stripping the
+// priority from the wire server-side. In either case, start out with a
+// priority in the middle.
+QuicPriority kDefaultPriority = 3;
+
+// Appends bytes from data into partial_data_buffer. Once partial_data_buffer
+// reaches 4 bytes, copies the data into 'result' and clears
+// partial_data_buffer.
+// Returns the number of bytes consumed.
+uint32 StripUint32(const char* data, uint32 data_len,
+ string* partial_data_buffer,
+ uint32* result) {
+ DCHECK_GT(4u, partial_data_buffer->length());
+ size_t missing_size = 4 - partial_data_buffer->length();
+ if (data_len < missing_size) {
+ StringPiece(data, data_len).AppendToString(partial_data_buffer);
+ return data_len;
+ }
+ StringPiece(data, missing_size).AppendToString(partial_data_buffer);
+ DCHECK_EQ(4u, partial_data_buffer->length());
+ memcpy(result, partial_data_buffer->data(), 4);
+ partial_data_buffer->clear();
+ return missing_size;
+}
+
+} // namespace
+
+QuicDataStream::QuicDataStream(QuicStreamId id,
+ QuicSession* session)
+ : ReliableQuicStream(id, session),
+ visitor_(NULL),
+ headers_decompressed_(false),
+ priority_(kDefaultPriority),
+ headers_id_(0),
+ decompression_failed_(false),
+ priority_parsed_(false) {
+ DCHECK_NE(kCryptoStreamId, id);
+}
+
+QuicDataStream::~QuicDataStream() {
+}
+
+size_t QuicDataStream::Readv(const struct iovec* iov, size_t iov_len) {
+ if (FinishedReadingHeaders()) {
+ // If the headers have been read, simply delegate to the sequencer's
+ // Readv method.
+ return sequencer()->Readv(iov, iov_len);
+ }
+ // Otherwise, copy decompressed header data into |iov|.
+ size_t bytes_consumed = 0;
+ size_t iov_index = 0;
+ while (iov_index < iov_len &&
+ decompressed_headers_.length() > bytes_consumed) {
+ size_t bytes_to_read = min(iov[iov_index].iov_len,
+ decompressed_headers_.length() - bytes_consumed);
+ char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
+ memcpy(iov_ptr,
+ decompressed_headers_.data() + bytes_consumed, bytes_to_read);
+ bytes_consumed += bytes_to_read;
+ ++iov_index;
+ }
+ decompressed_headers_.erase(0, bytes_consumed);
+ return bytes_consumed;
+}
+
+int QuicDataStream::GetReadableRegions(iovec* iov, size_t iov_len) {
+ if (FinishedReadingHeaders()) {
+ return sequencer()->GetReadableRegions(iov, iov_len);
+ }
+ if (iov_len == 0) {
+ return 0;
+ }
+ iov[0].iov_base = static_cast<void*>(
+ const_cast<char*>(decompressed_headers_.data()));
+ iov[0].iov_len = decompressed_headers_.length();
+ return 1;
+}
+
+bool QuicDataStream::IsDoneReading() const {
+ if (!headers_decompressed_ || !decompressed_headers_.empty()) {
+ return false;
+ }
+ return sequencer()->IsClosed();
+}
+
+bool QuicDataStream::HasBytesToRead() const {
+ return !decompressed_headers_.empty() || sequencer()->HasBytesToRead();
+}
+
+void QuicDataStream::set_priority(QuicPriority priority) {
+ DCHECK_EQ(0u, stream_bytes_written());
+ priority_ = priority;
+}
+
+QuicPriority QuicDataStream::EffectivePriority() const {
+ return priority();
+}
+
+uint32 QuicDataStream::ProcessRawData(const char* data, uint32 data_len) {
+ DCHECK_NE(0u, data_len);
+
+ uint32 total_bytes_consumed = 0;
+ if (headers_id_ == 0u) {
+ total_bytes_consumed += StripPriorityAndHeaderId(data, data_len);
+ data += total_bytes_consumed;
+ data_len -= total_bytes_consumed;
+ if (data_len == 0 || total_bytes_consumed == 0) {
+ return total_bytes_consumed;
+ }
+ }
+ DCHECK_NE(0u, headers_id_);
+
+ // Once the headers are finished, we simply pass the data through.
+ if (headers_decompressed_) {
+ // Some buffered header data remains.
+ if (!decompressed_headers_.empty()) {
+ ProcessHeaderData();
+ }
+ if (decompressed_headers_.empty()) {
+ DVLOG(1) << "Delegating procesing to ProcessData";
+ total_bytes_consumed += ProcessData(data, data_len);
+ }
+ return total_bytes_consumed;
+ }
+
+ QuicHeaderId current_header_id =
+ session()->decompressor()->current_header_id();
+ // Ensure that this header id looks sane.
+ if (headers_id_ < current_header_id ||
+ headers_id_ > kMaxHeaderIdDelta + current_header_id) {
+ DVLOG(1) << ENDPOINT
+ << "Invalid headers for stream: " << id()
+ << " header_id: " << headers_id_
+ << " current_header_id: " << current_header_id;
+ session()->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
+ return total_bytes_consumed;
+ }
+
+ // If we are head-of-line blocked on decompression, then back up.
+ if (current_header_id != headers_id_) {
+ session()->MarkDecompressionBlocked(headers_id_, id());
+ DVLOG(1) << ENDPOINT
+ << "Unable to decompress header data for stream: " << id()
+ << " header_id: " << headers_id_;
+ return total_bytes_consumed;
+ }
+
+ // Decompressed data will be delivered to decompressed_headers_.
+ size_t bytes_consumed = session()->decompressor()->DecompressData(
+ StringPiece(data, data_len), this);
+ DCHECK_NE(0u, bytes_consumed);
+ if (bytes_consumed > data_len) {
+ DCHECK(false) << "DecompressData returned illegal value";
+ OnDecompressionError();
+ return total_bytes_consumed;
+ }
+ total_bytes_consumed += bytes_consumed;
+ data += bytes_consumed;
+ data_len -= bytes_consumed;
+
+ if (decompression_failed_) {
+ // The session will have been closed in OnDecompressionError.
+ return total_bytes_consumed;
+ }
+
+ // Headers are complete if the decompressor has moved on to the
+ // next stream.
+ headers_decompressed_ =
+ session()->decompressor()->current_header_id() != headers_id_;
+ if (!headers_decompressed_) {
+ DCHECK_EQ(0u, data_len);
+ }
+
+ ProcessHeaderData();
+
+ if (!headers_decompressed_ || !decompressed_headers_.empty()) {
+ return total_bytes_consumed;
+ }
+
+ // We have processed all of the decompressed data but we might
+ // have some more raw data to process.
+ if (data_len > 0) {
+ total_bytes_consumed += ProcessData(data, data_len);
+ }
+
+ // The sequencer will push any additional buffered frames if this data
+ // has been completely consumed.
+ return total_bytes_consumed;
+}
+
+const IPEndPoint& QuicDataStream::GetPeerAddress() {
+ return session()->peer_address();
+}
+
+QuicSpdyCompressor* QuicDataStream::compressor() {
+ return session()->compressor();
+}
+
+bool QuicDataStream::GetSSLInfo(SSLInfo* ssl_info) {
+ return session()->GetSSLInfo(ssl_info);
+}
+
+uint32 QuicDataStream::ProcessHeaderData() {
+ if (decompressed_headers_.empty()) {
+ return 0;
+ }
+
+ size_t bytes_processed = ProcessData(decompressed_headers_.data(),
+ decompressed_headers_.length());
+ if (bytes_processed == decompressed_headers_.length()) {
+ decompressed_headers_.clear();
+ } else {
+ decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
+ }
+ return bytes_processed;
+}
+
+void QuicDataStream::OnDecompressorAvailable() {
+ DCHECK_EQ(headers_id_,
+ session()->decompressor()->current_header_id());
+ DCHECK(!headers_decompressed_);
+ DCHECK(!decompression_failed_);
+ DCHECK_EQ(0u, decompressed_headers_.length());
+
+ while (!headers_decompressed_) {
+ struct iovec iovec;
+ if (sequencer()->GetReadableRegions(&iovec, 1) == 0) {
+ return;
+ }
+
+ size_t bytes_consumed = session()->decompressor()->DecompressData(
+ StringPiece(static_cast<char*>(iovec.iov_base),
+ iovec.iov_len),
+ this);
+ DCHECK_LE(bytes_consumed, iovec.iov_len);
+ if (decompression_failed_) {
+ return;
+ }
+ sequencer()->MarkConsumed(bytes_consumed);
+
+ headers_decompressed_ =
+ session()->decompressor()->current_header_id() != headers_id_;
+ }
+
+ // Either the headers are complete, or the all data as been consumed.
+ ProcessHeaderData(); // Unprocessed headers remain in decompressed_headers_.
+ if (IsDoneReading()) {
+ OnFinRead();
+ } else if (FinishedReadingHeaders()) {
+ sequencer()->FlushBufferedFrames();
+ }
+}
+
+bool QuicDataStream::OnDecompressedData(StringPiece data) {
+ data.AppendToString(&decompressed_headers_);
+ return true;
+}
+
+void QuicDataStream::OnDecompressionError() {
+ DCHECK(!decompression_failed_);
+ decompression_failed_ = true;
+ session()->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
+}
+
+void QuicDataStream::OnClose() {
+ ReliableQuicStream::OnClose();
+
+ if (visitor_) {
+ Visitor* visitor = visitor_;
+ // Calling Visitor::OnClose() may result the destruction of the visitor,
+ // so we need to ensure we don't call it again.
+ visitor_ = NULL;
+ visitor->OnClose(this);
+ }
+}
+
+uint32 QuicDataStream::StripPriorityAndHeaderId(
+ const char* data, uint32 data_len) {
+ uint32 total_bytes_parsed = 0;
+
+ if (!priority_parsed_ && session()->connection()->is_server()) {
+ QuicPriority temporary_priority = priority_;
+ total_bytes_parsed = StripUint32(
+ data, data_len, &headers_id_and_priority_buffer_, &temporary_priority);
+ if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.size() == 0) {
+ priority_parsed_ = true;
+
+ // Spdy priorities are inverted, so the highest numerical value is the
+ // lowest legal priority.
+ if (temporary_priority > QuicUtils::LowestPriority()) {
+ session()->connection()->SendConnectionClose(QUIC_INVALID_PRIORITY);
+ return 0;
+ }
+ priority_ = temporary_priority;
+ }
+ data += total_bytes_parsed;
+ data_len -= total_bytes_parsed;
+ }
+ if (data_len > 0 && headers_id_ == 0u) {
+ // The headers ID has not yet been read. Strip it from the beginning of
+ // the data stream.
+ total_bytes_parsed += StripUint32(
+ data, data_len, &headers_id_and_priority_buffer_, &headers_id_);
+ }
+ return total_bytes_parsed;
+}
+
+bool QuicDataStream::FinishedReadingHeaders() {
+ return headers_decompressed_ && decompressed_headers_.empty();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_data_stream.h b/chromium/net/quic/quic_data_stream.h
new file mode 100644
index 00000000000..84990439e55
--- /dev/null
+++ b/chromium/net/quic/quic_data_stream.h
@@ -0,0 +1,140 @@
+// 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.
+//
+// The base class for streams which deliver data to/from an application.
+// In each direction, the data on such a stream first contains compressed
+// headers then body data.
+
+#ifndef NET_QUIC_QUIC_DATA_STREAM_H_
+#define NET_QUIC_QUIC_DATA_STREAM_H_
+
+#include <sys/types.h>
+
+#include <list>
+
+#include "base/strings/string_piece.h"
+#include "net/base/iovec.h"
+#include "net/base/net_export.h"
+#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_spdy_compressor.h"
+#include "net/quic/quic_spdy_decompressor.h"
+#include "net/quic/quic_stream_sequencer.h"
+#include "net/quic/reliable_quic_stream.h"
+
+namespace net {
+
+namespace test {
+class QuicDataStreamPeer;
+class ReliableQuicStreamPeer;
+} // namespace test
+
+class IPEndPoint;
+class QuicSession;
+class SSLInfo;
+
+// All this does right now is send data to subclasses via the sequencer.
+class NET_EXPORT_PRIVATE QuicDataStream : public ReliableQuicStream,
+ public QuicSpdyDecompressor::Visitor {
+ public:
+ // Visitor receives callbacks from the stream.
+ class Visitor {
+ public:
+ Visitor() {}
+
+ // Called when the stream is closed.
+ virtual void OnClose(QuicDataStream* stream) = 0;
+
+ protected:
+ virtual ~Visitor() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Visitor);
+ };
+
+ QuicDataStream(QuicStreamId id, QuicSession* session);
+
+ virtual ~QuicDataStream();
+
+ // ReliableQuicStream implementation
+ virtual void OnClose() OVERRIDE;
+ // By default, this is the same as priority(), however it allows streams
+ // to temporarily alter effective priority. For example if a SPDY stream has
+ // compressed but not written headers it can write the headers with a higher
+ // priority.
+ virtual QuicPriority EffectivePriority() const OVERRIDE;
+ virtual uint32 ProcessRawData(const char* data, uint32 data_len) OVERRIDE;
+
+ // QuicSpdyDecompressor::Visitor implementation.
+ virtual bool OnDecompressedData(base::StringPiece data) OVERRIDE;
+ virtual void OnDecompressionError() OVERRIDE;
+
+ virtual uint32 ProcessData(const char* data, uint32 data_len) = 0;
+
+ // This block of functions wraps the sequencer's functions of the same
+ // name. These methods return uncompressed data until that has
+ // been fully processed. Then they simply delegate to the sequencer.
+ virtual size_t Readv(const struct iovec* iov, size_t iov_len);
+ virtual int GetReadableRegions(iovec* iov, size_t iov_len);
+ // Returns true when all data has been read from the peer, including the fin.
+ virtual bool IsDoneReading() const;
+ virtual bool HasBytesToRead() const;
+
+ // Called by the session when a decompression blocked stream
+ // becomes unblocked.
+ virtual void OnDecompressorAvailable();
+
+ void set_visitor(Visitor* visitor) { visitor_ = visitor; }
+
+ bool headers_decompressed() const { return headers_decompressed_; }
+
+ const IPEndPoint& GetPeerAddress();
+
+ QuicSpdyCompressor* compressor();
+
+ // Gets the SSL connection information.
+ bool GetSSLInfo(SSLInfo* ssl_info);
+
+ protected:
+ // Sets priority_ to priority. This should only be called before bytes are
+ // written to the server.
+ void set_priority(QuicPriority priority);
+ // This is protected because external classes should use EffectivePriority
+ // instead.
+ QuicPriority priority() const { return priority_; }
+
+ private:
+ friend class test::QuicDataStreamPeer;
+ friend class test::ReliableQuicStreamPeer;
+ friend class QuicStreamUtils;
+
+ uint32 ProcessHeaderData();
+
+ uint32 StripPriorityAndHeaderId(const char* data, uint32 data_len);
+
+ bool FinishedReadingHeaders();
+
+ Visitor* visitor_;
+ // True if the headers have been completely decompresssed.
+ bool headers_decompressed_;
+ // The priority of the stream, once parsed.
+ QuicPriority priority_;
+ // ID of the header block sent by the peer, once parsed.
+ QuicHeaderId headers_id_;
+ // Buffer into which we write bytes from priority_ and headers_id_
+ // until each is fully parsed.
+ string headers_id_and_priority_buffer_;
+ // Contains a copy of the decompressed headers until they are consumed
+ // via ProcessData or Readv.
+ string decompressed_headers_;
+ // True if an error was encountered during decompression.
+ bool decompression_failed_;
+ // True if the priority has been read, false otherwise.
+ bool priority_parsed_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicDataStream);
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_DATA_STREAM_H_
diff --git a/chromium/net/quic/quic_data_stream_test.cc b/chromium/net/quic/quic_data_stream_test.cc
new file mode 100644
index 00000000000..551ef445715
--- /dev/null
+++ b/chromium/net/quic/quic_data_stream_test.cc
@@ -0,0 +1,450 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_data_stream.h"
+
+#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_connection.h"
+#include "net/quic/quic_spdy_compressor.h"
+#include "net/quic/quic_spdy_decompressor.h"
+#include "net/quic/quic_utils.h"
+#include "net/quic/spdy_utils.h"
+#include "net/quic/test_tools/quic_session_peer.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using base::StringPiece;
+using std::min;
+using testing::_;
+using testing::InSequence;
+using testing::Return;
+using testing::SaveArg;
+using testing::StrEq;
+using testing::StrictMock;
+
+namespace net {
+namespace test {
+namespace {
+
+const QuicGuid kStreamId = 3;
+const bool kIsServer = true;
+const bool kShouldProcessData = true;
+
+class TestStream : public QuicDataStream {
+ public:
+ TestStream(QuicStreamId id,
+ QuicSession* session,
+ bool should_process_data)
+ : QuicDataStream(id, session),
+ should_process_data_(should_process_data) {}
+
+ virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE {
+ EXPECT_NE(0u, data_len);
+ DVLOG(1) << "ProcessData data_len: " << data_len;
+ data_ += string(data, data_len);
+ return should_process_data_ ? data_len : 0;
+ }
+
+ using ReliableQuicStream::WriteOrBufferData;
+ using ReliableQuicStream::CloseReadSide;
+ using ReliableQuicStream::CloseWriteSide;
+
+ const string& data() const { return data_; }
+
+ private:
+ bool should_process_data_;
+ string data_;
+};
+
+class QuicDataStreamTest : public ::testing::TestWithParam<bool> {
+ public:
+ QuicDataStreamTest() {
+ headers_[":host"] = "www.google.com";
+ headers_[":path"] = "/index.hml";
+ headers_[":scheme"] = "https";
+ headers_["cookie"] =
+ "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
+ "__utmc=160408618; "
+ "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
+ "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
+ "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
+ "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
+ "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
+ "1zFMi5vzcns38-8_Sns; "
+ "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
+ "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
+ "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
+ "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
+ "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
+ "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
+ "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
+ "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
+ "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
+ "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
+ "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
+ "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
+ "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
+ "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
+ "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
+ }
+
+ void Initialize(bool stream_should_process_data) {
+ connection_ = new StrictMock<MockConnection>(kIsServer);
+ session_.reset(new StrictMock<MockSession>(connection_));
+ stream_.reset(new TestStream(kStreamId, session_.get(),
+ stream_should_process_data));
+ stream2_.reset(new TestStream(kStreamId + 2, session_.get(),
+ stream_should_process_data));
+ compressor_.reset(new QuicSpdyCompressor());
+ decompressor_.reset(new QuicSpdyDecompressor);
+ write_blocked_list_ =
+ QuicSessionPeer::GetWriteblockedStreams(session_.get());
+ }
+
+ protected:
+ MockConnection* connection_;
+ scoped_ptr<MockSession> session_;
+ scoped_ptr<TestStream> stream_;
+ scoped_ptr<TestStream> stream2_;
+ scoped_ptr<QuicSpdyCompressor> compressor_;
+ scoped_ptr<QuicSpdyDecompressor> decompressor_;
+ SpdyHeaderBlock headers_;
+ WriteBlockedList<QuicStreamId>* write_blocked_list_;
+};
+
+TEST_F(QuicDataStreamTest, ProcessHeaders) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers));
+
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data());
+ EXPECT_EQ(QuicUtils::HighestPriority(), stream_->EffectivePriority());
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersWithInvalidHeaderId) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ compressed_headers[4] = '\xFF'; // Illegal header id.
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers));
+
+ EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID));
+ stream_->OnStreamFrame(frame);
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersWithInvalidPriority) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ compressed_headers[0] = '\xFF'; // Illegal priority.
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(compressed_headers));
+
+ EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_PRIORITY));
+ stream_->OnStreamFrame(frame);
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersAndBody) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ string body = "this is the body";
+ string data = compressed_headers + body;
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
+
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
+ stream_->data());
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersAndBodyFragments) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::LowestPriority(), headers_);
+ string body = "this is the body";
+ string data = compressed_headers + body;
+
+ for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
+ Initialize(kShouldProcessData);
+ for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
+ size_t remaining_data = data.length() - offset;
+ StringPiece fragment(data.data() + offset,
+ min(fragment_size, remaining_data));
+ QuicStreamFrame frame(kStreamId, false, offset, MakeIOVector(fragment));
+
+ stream_->OnStreamFrame(frame);
+ }
+ ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
+ stream_->data()) << "fragment_size: " << fragment_size;
+ }
+
+ for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
+ Initialize(kShouldProcessData);
+
+ StringPiece fragment1(data.data(), split_point);
+ QuicStreamFrame frame1(kStreamId, false, 0, MakeIOVector(fragment1));
+ stream_->OnStreamFrame(frame1);
+
+ StringPiece fragment2(data.data() + split_point, data.size() - split_point);
+ QuicStreamFrame frame2(
+ kStreamId, false, split_point, MakeIOVector(fragment2));
+ stream_->OnStreamFrame(frame2);
+
+ ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
+ stream_->data()) << "split_point: " << split_point;
+ }
+ EXPECT_EQ(QuicUtils::LowestPriority(), stream_->EffectivePriority());
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersAndBodyReadv) {
+ Initialize(!kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ string body = "this is the body";
+ string data = compressed_headers + body;
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
+ string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ string uncompressed_data = uncompressed_headers + body;
+
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(uncompressed_headers, stream_->data());
+
+ char buffer[2048];
+ ASSERT_LT(data.length(), arraysize(buffer));
+ struct iovec vec;
+ vec.iov_base = buffer;
+ vec.iov_len = arraysize(buffer);
+
+ size_t bytes_read = stream_->Readv(&vec, 1);
+ EXPECT_EQ(uncompressed_headers.length(), bytes_read);
+ EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read));
+
+ bytes_read = stream_->Readv(&vec, 1);
+ EXPECT_EQ(body.length(), bytes_read);
+ EXPECT_EQ(body, string(buffer, bytes_read));
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
+ Initialize(!kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ string body = "this is the body";
+ string data = compressed_headers + body;
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
+ string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ string uncompressed_data = uncompressed_headers + body;
+
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(uncompressed_headers, stream_->data());
+
+ char buffer[1];
+ struct iovec vec;
+ vec.iov_base = buffer;
+ vec.iov_len = arraysize(buffer);
+ for (size_t i = 0; i < uncompressed_data.length(); ++i) {
+ size_t bytes_read = stream_->Readv(&vec, 1);
+ ASSERT_EQ(1u, bytes_read);
+ EXPECT_EQ(uncompressed_data.data()[i], buffer[0]);
+ }
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
+ Initialize(!kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ string body = "this is the body";
+ string data = compressed_headers + body;
+ QuicStreamFrame frame(kStreamId, false, 0, MakeIOVector(data));
+ string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ string uncompressed_data = uncompressed_headers + body;
+
+ stream_->OnStreamFrame(frame);
+ EXPECT_EQ(uncompressed_headers, stream_->data());
+
+ char buffer1[1];
+ char buffer2[1];
+ struct iovec vec[2];
+ vec[0].iov_base = buffer1;
+ vec[0].iov_len = arraysize(buffer1);
+ vec[1].iov_base = buffer2;
+ vec[1].iov_len = arraysize(buffer2);
+ for (size_t i = 0; i < uncompressed_data.length(); i += 2) {
+ size_t bytes_read = stream_->Readv(vec, 2);
+ ASSERT_EQ(2u, bytes_read) << i;
+ ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i;
+ ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i;
+ }
+}
+
+TEST_F(QuicDataStreamTest, ProcessCorruptHeadersEarly) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers1 = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ QuicStreamFrame frame1(
+ stream_->id(), false, 0, MakeIOVector(compressed_headers1));
+ string decompressed_headers1 =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ headers_["content-type"] = "text/plain";
+ string compressed_headers2 = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ // Corrupt the compressed data.
+ compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1;
+ QuicStreamFrame frame2(
+ stream2_->id(), false, 0, MakeIOVector(compressed_headers2));
+ string decompressed_headers2 =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ // Deliver frame2 to stream2 out of order. The decompressor is not
+ // available yet, so no data will be processed. The compressed data
+ // will be buffered until OnDecompressorAvailable() is called
+ // to process it.
+ stream2_->OnStreamFrame(frame2);
+ EXPECT_EQ("", stream2_->data());
+
+ // Now deliver frame1 to stream1. The decompressor is available so
+ // the data will be processed, and the decompressor will become
+ // available for stream2.
+ stream_->OnStreamFrame(frame1);
+ EXPECT_EQ(decompressed_headers1, stream_->data());
+
+ // Verify that the decompressor is available, and inform stream2
+ // that it can now decompress the buffered compressed data. Since
+ // the compressed data is corrupt, the stream will shutdown the session.
+ EXPECT_EQ(2u, session_->decompressor()->current_header_id());
+ EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE));
+ stream2_->OnDecompressorAvailable();
+ EXPECT_EQ("", stream2_->data());
+}
+
+TEST_F(QuicDataStreamTest, ProcessPartialHeadersEarly) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers1 = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ QuicStreamFrame frame1(
+ stream_->id(), false, 0, MakeIOVector(compressed_headers1));
+ string decompressed_headers1 =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ headers_["content-type"] = "text/plain";
+ string compressed_headers2 = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ string partial_compressed_headers =
+ compressed_headers2.substr(0, compressed_headers2.length() / 2);
+ QuicStreamFrame frame2(
+ stream2_->id(), false, 0, MakeIOVector(partial_compressed_headers));
+ string decompressed_headers2 =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ // Deliver frame2 to stream2 out of order. The decompressor is not
+ // available yet, so no data will be processed. The compressed data
+ // will be buffered until OnDecompressorAvailable() is called
+ // to process it.
+ stream2_->OnStreamFrame(frame2);
+ EXPECT_EQ("", stream2_->data());
+
+ // Now deliver frame1 to stream1. The decompressor is available so
+ // the data will be processed, and the decompressor will become
+ // available for stream2.
+ stream_->OnStreamFrame(frame1);
+ EXPECT_EQ(decompressed_headers1, stream_->data());
+
+ // Verify that the decompressor is available, and inform stream2
+ // that it can now decompress the buffered compressed data. Since
+ // the compressed data is incomplete it will not be passed to
+ // the stream.
+ EXPECT_EQ(2u, session_->decompressor()->current_header_id());
+ stream2_->OnDecompressorAvailable();
+ EXPECT_EQ("", stream2_->data());
+
+ // Now send remaining data and verify that we have now received the
+ // compressed headers.
+ string remaining_compressed_headers =
+ compressed_headers2.substr(partial_compressed_headers.length());
+
+ QuicStreamFrame frame3(stream2_->id(), false,
+ partial_compressed_headers.length(),
+ MakeIOVector(remaining_compressed_headers));
+ stream2_->OnStreamFrame(frame3);
+ EXPECT_EQ(decompressed_headers2, stream2_->data());
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersEarly) {
+ Initialize(kShouldProcessData);
+
+ string compressed_headers1 = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ QuicStreamFrame frame1(
+ stream_->id(), false, 0, MakeIOVector(compressed_headers1));
+ string decompressed_headers1 =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ headers_["content-type"] = "text/plain";
+ string compressed_headers2 = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ QuicStreamFrame frame2(
+ stream2_->id(), false, 0, MakeIOVector(compressed_headers2));
+ string decompressed_headers2 =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ // Deliver frame2 to stream2 out of order. The decompressor is not
+ // available yet, so no data will be processed. The compressed data
+ // will be buffered until OnDecompressorAvailable() is called
+ // to process it.
+ stream2_->OnStreamFrame(frame2);
+ EXPECT_EQ("", stream2_->data());
+
+ // Now deliver frame1 to stream1. The decompressor is available so
+ // the data will be processed, and the decompressor will become
+ // available for stream2.
+ stream_->OnStreamFrame(frame1);
+ EXPECT_EQ(decompressed_headers1, stream_->data());
+
+ // Verify that the decompressor is available, and inform stream2
+ // that it can now decompress the buffered compressed data.
+ EXPECT_EQ(2u, session_->decompressor()->current_header_id());
+ stream2_->OnDecompressorAvailable();
+ EXPECT_EQ(decompressed_headers2, stream2_->data());
+}
+
+TEST_F(QuicDataStreamTest, ProcessHeadersDelay) {
+ Initialize(!kShouldProcessData);
+
+ string compressed_headers = compressor_->CompressHeadersWithPriority(
+ QuicUtils::HighestPriority(), headers_);
+ QuicStreamFrame frame1(
+ stream_->id(), false, 0, MakeIOVector(compressed_headers));
+ string decompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+
+ // Send the headers to the stream and verify they were decompressed.
+ stream_->OnStreamFrame(frame1);
+ EXPECT_EQ(2u, session_->decompressor()->current_header_id());
+
+ // Verify that we are now able to handle the body data,
+ // even though the stream has not processed the headers.
+ EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID))
+ .Times(0);
+ QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
+ MakeIOVector("body data"));
+ stream_->OnStreamFrame(frame2);
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/quic_data_writer.cc b/chromium/net/quic/quic_data_writer.cc
index 61e72922365..b7aff26fe01 100644
--- a/chromium/net/quic/quic_data_writer.cc
+++ b/chromium/net/quic/quic_data_writer.cc
@@ -56,6 +56,45 @@ bool QuicDataWriter::WriteUInt64(uint64 value) {
return WriteBytes(&value, sizeof(value));
}
+bool QuicDataWriter::WriteUFloat16(uint64 value) {
+ uint16 result;
+ if (value < (GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
+ // Fast path: either the value is denormalized, or has exponent zero.
+ // Both cases are represented by the value itself.
+ result = value;
+ } else if (value >= kUFloat16MaxValue) {
+ // Value is out of range; clamp it to the maximum representable.
+ result = numeric_limits<uint16>::max();
+ } else {
+ // The highest bit is between position 13 and 42 (zero-based), which
+ // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10,
+ // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11
+ // and count the shifts.
+ uint16 exponent = 0;
+ for (uint16 offset = 16; offset > 0; offset /= 2) {
+ // Right-shift the value until the highest bit is in position 11.
+ // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30),
+ // shift if the bit is at or above 11 + offset.
+ if (value >= (GG_UINT64_C(1) << (kUFloat16MantissaBits + offset))) {
+ exponent += offset;
+ value >>= offset;
+ }
+ }
+
+ DCHECK_GE(exponent, 1);
+ DCHECK_LE(exponent, kUFloat16MaxExponent);
+ DCHECK_GE(value, GG_UINT64_C(1) << kUFloat16MantissaBits);
+ DCHECK_LT(value, GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits);
+
+ // Hidden bit (position 11) is set. We should remove it and increment the
+ // exponent. Equivalently, we just add it to the exponent.
+ // This hides the bit.
+ result = value + (exponent << kUFloat16MantissaBits);
+ }
+
+ return WriteBytes(&result, sizeof(result));
+}
+
bool QuicDataWriter::WriteStringPiece16(StringPiece val) {
if (val.length() > numeric_limits<uint16>::max()) {
return false;
@@ -66,6 +105,18 @@ bool QuicDataWriter::WriteStringPiece16(StringPiece val) {
return WriteBytes(val.data(), val.size());
}
+bool QuicDataWriter::WriteIOVector(const IOVector& data) {
+ char *dest = BeginWrite(data.TotalBufferSize());
+ if (!dest) {
+ return false;
+ }
+ for (size_t i = 0; i < data.Size(); ++i) {
+ WriteBytes(data.iovec()[i].iov_base, data.iovec()[i].iov_len);
+ }
+
+ return true;
+}
+
char* QuicDataWriter::BeginWrite(size_t length) {
if (length_ > capacity_) {
return NULL;
diff --git a/chromium/net/quic/quic_data_writer.h b/chromium/net/quic/quic_data_writer.h
index b18121da459..f8a3751bf1b 100644
--- a/chromium/net/quic/quic_data_writer.h
+++ b/chromium/net/quic/quic_data_writer.h
@@ -43,7 +43,12 @@ class NET_EXPORT_PRIVATE QuicDataWriter {
bool WriteUInt32(uint32 value);
bool WriteUInt48(uint64 value);
bool WriteUInt64(uint64 value);
+ // Write unsigned floating point corresponding to the value. Large values are
+ // clamped to the maximum representable (kUFloat16MaxValue). Values that can
+ // not be represented directly are rounded down.
+ bool WriteUFloat16(uint64 value);
bool WriteStringPiece16(base::StringPiece val);
+ bool WriteIOVector(const IOVector& data);
bool WriteBytes(const void* data, size_t data_len);
bool WriteRepeatedByte(uint8 byte, size_t count);
// Fills the remaining buffer with null characters.
diff --git a/chromium/net/quic/quic_data_writer_test.cc b/chromium/net/quic/quic_data_writer_test.cc
index 4fbd7e4efdf..9106947b52e 100644
--- a/chromium/net/quic/quic_data_writer_test.cc
+++ b/chromium/net/quic/quic_data_writer_test.cc
@@ -4,13 +4,15 @@
#include "net/quic/quic_data_writer.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_data_reader.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
namespace {
-TEST(QuicDataWriterTest, WriteUint8ToOffset) {
+TEST(QuicDataWriterTest, WriteUInt8ToOffset) {
QuicDataWriter writer(4);
writer.WriteUInt32(0xfefdfcfb);
@@ -19,17 +21,15 @@ TEST(QuicDataWriterTest, WriteUint8ToOffset) {
EXPECT_TRUE(writer.WriteUInt8ToOffset(3, 2));
EXPECT_TRUE(writer.WriteUInt8ToOffset(4, 3));
- char* data = writer.take();
+ scoped_ptr<char[]> data(writer.take());
EXPECT_EQ(1, data[0]);
EXPECT_EQ(2, data[1]);
EXPECT_EQ(3, data[2]);
EXPECT_EQ(4, data[3]);
-
- delete[] data;
}
-TEST(QuicDataWriterDeathTest, WriteUint8ToOffset) {
+TEST(QuicDataWriterDeathTest, WriteUInt8ToOffset) {
QuicDataWriter writer(4);
#if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
@@ -41,6 +41,127 @@ TEST(QuicDataWriterDeathTest, WriteUint8ToOffset) {
#endif
}
+TEST(QuicDataWriterTest, SanityCheckUFloat16Consts) {
+ // Check the arithmetic on the constants - otherwise the values below make
+ // no sense.
+ EXPECT_EQ(30, kUFloat16MaxExponent);
+ EXPECT_EQ(11, kUFloat16MantissaBits);
+ EXPECT_EQ(12, kUFloat16MantissaEffectiveBits);
+ EXPECT_EQ(GG_UINT64_C(0x3FFC0000000), kUFloat16MaxValue);
+}
+
+TEST(QuicDataWriterTest, WriteUFloat16) {
+ struct TestCase {
+ uint64 decoded;
+ uint16 encoded;
+ };
+ TestCase test_cases[] = {
+ // Small numbers represent themselves.
+ { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 },
+ { 7, 7 }, { 15, 15 }, { 31, 31 }, { 42, 42 }, { 123, 123 }, { 1234, 1234 },
+ // Check transition through 2^11.
+ { 2046, 2046 }, { 2047, 2047 }, { 2048, 2048 }, { 2049, 2049 },
+ // Running out of mantissa at 2^12.
+ { 4094, 4094 }, { 4095, 4095 }, { 4096, 4096 }, { 4097, 4096 },
+ { 4098, 4097 }, { 4099, 4097 }, { 4100, 4098 }, { 4101, 4098 },
+ // Check transition through 2^13.
+ { 8190, 6143 }, { 8191, 6143 }, { 8192, 6144 }, { 8193, 6144 },
+ { 8194, 6144 }, { 8195, 6144 }, { 8196, 6145 }, { 8197, 6145 },
+ // Half-way through the exponents.
+ { 0x7FF8000, 0x87FF }, { 0x7FFFFFF, 0x87FF }, { 0x8000000, 0x8800 },
+ { 0xFFF0000, 0x8FFF }, { 0xFFFFFFF, 0x8FFF }, { 0x10000000, 0x9000 },
+ // Transition into the largest exponent.
+ { 0x1FFFFFFFFFE, 0xF7FF}, { 0x1FFFFFFFFFF, 0xF7FF},
+ { 0x20000000000, 0xF800}, { 0x20000000001, 0xF800},
+ { 0x2003FFFFFFE, 0xF800}, { 0x2003FFFFFFF, 0xF800},
+ { 0x20040000000, 0xF801}, { 0x20040000001, 0xF801},
+ // Transition into the max value and clamping.
+ { 0x3FF80000000, 0xFFFE}, { 0x3FFBFFFFFFF, 0xFFFE},
+ { 0x3FFC0000000, 0xFFFF}, { 0x3FFC0000001, 0xFFFF},
+ { 0x3FFFFFFFFFF, 0xFFFF}, { 0x40000000000, 0xFFFF},
+ { 0xFFFFFFFFFFFFFFFF, 0xFFFF},
+ };
+ int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+
+ for (int i = 0; i < num_test_cases; ++i) {
+ QuicDataWriter writer(2);
+ EXPECT_TRUE(writer.WriteUFloat16(test_cases[i].decoded));
+ scoped_ptr<char[]> data(writer.take());
+ EXPECT_EQ(test_cases[i].encoded, *reinterpret_cast<uint16*>(data.get()));
+ }
+}
+
+TEST(QuicDataWriterTest, ReadUFloat16) {
+ struct TestCase {
+ uint64 decoded;
+ uint16 encoded;
+ };
+ TestCase test_cases[] = {
+ // There are fewer decoding test cases because encoding truncates, and
+ // decoding returns the smallest expansion.
+ // Small numbers represent themselves.
+ { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 },
+ { 7, 7 }, { 15, 15 }, { 31, 31 }, { 42, 42 }, { 123, 123 }, { 1234, 1234 },
+ // Check transition through 2^11.
+ { 2046, 2046 }, { 2047, 2047 }, { 2048, 2048 }, { 2049, 2049 },
+ // Running out of mantissa at 2^12.
+ { 4094, 4094 }, { 4095, 4095 }, { 4096, 4096 },
+ { 4098, 4097 }, { 4100, 4098 },
+ // Check transition through 2^13.
+ { 8190, 6143 }, { 8192, 6144 }, { 8196, 6145 },
+ // Half-way through the exponents.
+ { 0x7FF8000, 0x87FF }, { 0x8000000, 0x8800 },
+ { 0xFFF0000, 0x8FFF }, { 0x10000000, 0x9000 },
+ // Transition into the largest exponent.
+ { 0x1FFE0000000, 0xF7FF}, { 0x20000000000, 0xF800},
+ { 0x20040000000, 0xF801},
+ // Transition into the max value.
+ { 0x3FF80000000, 0xFFFE}, { 0x3FFC0000000, 0xFFFF},
+ };
+ int num_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
+
+ for (int i = 0; i < num_test_cases; ++i) {
+ QuicDataReader reader(reinterpret_cast<char*>(&test_cases[i].encoded), 2);
+ uint64 value;
+ EXPECT_TRUE(reader.ReadUFloat16(&value));
+ EXPECT_EQ(test_cases[i].decoded, value);
+ }
+}
+
+TEST(QuicDataWriterTest, RoundTripUFloat16) {
+ // Just test all 16-bit encoded values. 0 and max already tested above.
+ uint64 previous_value = 0;
+ for (uint16 i = 1; i < 0xFFFF; ++i) {
+ // Read the two bytes.
+ QuicDataReader reader(reinterpret_cast<char*>(&i), 2);
+ uint64 value;
+ // All values must be decodable.
+ EXPECT_TRUE(reader.ReadUFloat16(&value));
+ // Check that small numbers represent themselves
+ if (i < 4097)
+ EXPECT_EQ(i, value);
+ // Check there's monotonic growth.
+ EXPECT_LT(previous_value, value);
+ // Check that precision is within 0.5% away from the denormals.
+ if (i > 2000)
+ EXPECT_GT(previous_value * 1005, value * 1000);
+ // Check we're always within the promised range.
+ EXPECT_LT(value, GG_UINT64_C(0x3FFC0000000));
+ previous_value = value;
+ QuicDataWriter writer(6);
+ EXPECT_TRUE(writer.WriteUFloat16(value - 1));
+ EXPECT_TRUE(writer.WriteUFloat16(value));
+ EXPECT_TRUE(writer.WriteUFloat16(value + 1));
+ scoped_ptr<char[]> data(writer.take());
+ // Check minimal decoding (previous decoding has previous encoding).
+ EXPECT_EQ(i-1, *reinterpret_cast<uint16*>(data.get()));
+ // Check roundtrip.
+ EXPECT_EQ(i, *reinterpret_cast<uint16*>(data.get() + 2));
+ // Check next decoding.
+ EXPECT_EQ(i < 4096? i+1 : i, *reinterpret_cast<uint16*>(data.get() + 4));
+ }
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_default_packet_writer.cc b/chromium/net/quic/quic_default_packet_writer.cc
new file mode 100644
index 00000000000..74b86af2a98
--- /dev/null
+++ b/chromium/net/quic/quic_default_packet_writer.cc
@@ -0,0 +1,62 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_default_packet_writer.h"
+
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/metrics/sparse_histogram.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+
+namespace net {
+
+QuicDefaultPacketWriter::QuicDefaultPacketWriter() : weak_factory_(this) {
+}
+
+QuicDefaultPacketWriter::QuicDefaultPacketWriter(DatagramClientSocket* socket)
+ : weak_factory_(this),
+ socket_(socket) {
+}
+
+QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
+
+WriteResult QuicDefaultPacketWriter::WritePacket(
+ const char* buffer, size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) {
+ scoped_refptr<StringIOBuffer> buf(
+ new StringIOBuffer(std::string(buffer, buf_len)));
+ int rv = socket_->Write(buf.get(),
+ buf_len,
+ base::Bind(&QuicDefaultPacketWriter::OnWriteComplete,
+ weak_factory_.GetWeakPtr()));
+ WriteStatus status = WRITE_STATUS_OK;
+ if (rv < 0) {
+ if (rv != ERR_IO_PENDING) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.QuicSession.WriteError", -rv);
+ status = WRITE_STATUS_ERROR;
+ } else {
+ status = WRITE_STATUS_BLOCKED;
+ }
+ }
+
+ return WriteResult(status, rv);
+}
+
+bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
+ // Chrome sockets' Write() methods buffer the data until the Write is
+ // permitted.
+ return true;
+}
+
+void QuicDefaultPacketWriter::OnWriteComplete(int rv) {
+ DCHECK_NE(rv, ERR_IO_PENDING);
+ WriteResult result(rv < 0 ? WRITE_STATUS_ERROR : WRITE_STATUS_OK, rv);
+ connection_->OnPacketSent(result);
+ connection_->OnCanWrite();
+}
+
+} // namespace net
diff --git a/chromium/net/quic/quic_default_packet_writer.h b/chromium/net/quic/quic_default_packet_writer.h
new file mode 100644
index 00000000000..f60c76ea9be
--- /dev/null
+++ b/chromium/net/quic/quic_default_packet_writer.h
@@ -0,0 +1,50 @@
+// 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_DEFAULT_PACKET_WRITER_H_
+#define NET_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_connection.h"
+#include "net/quic/quic_packet_writer.h"
+#include "net/quic/quic_protocol.h"
+#include "net/udp/datagram_client_socket.h"
+
+namespace net {
+
+class QuicBlockedWriterInterface;
+
+// Chrome specific packet writer which uses a DatagramClientSocket for writing
+// data.
+class NET_EXPORT_PRIVATE QuicDefaultPacketWriter : public QuicPacketWriter {
+ public:
+ QuicDefaultPacketWriter();
+ explicit QuicDefaultPacketWriter(DatagramClientSocket* socket);
+ virtual ~QuicDefaultPacketWriter();
+
+ // QuicPacketWriter
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE;
+
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE;
+
+ void OnWriteComplete(int rv);
+ void SetConnection(QuicConnection* connection) {
+ connection_ = connection;
+ }
+
+ private:
+ base::WeakPtrFactory<QuicDefaultPacketWriter> weak_factory_;
+ DatagramClientSocket* socket_;
+ QuicConnection* connection_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_
diff --git a/chromium/net/quic/quic_end_to_end_unittest.cc b/chromium/net/quic/quic_end_to_end_unittest.cc
new file mode 100644
index 00000000000..90c670bfbeb
--- /dev/null
+++ b/chromium/net/quic/quic_end_to_end_unittest.cc
@@ -0,0 +1,310 @@
+// 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 "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/base/test_completion_callback.h"
+#include "net/base/upload_bytes_element_reader.h"
+#include "net/base/upload_data_stream.h"
+#include "net/cert/mock_cert_verifier.h"
+#include "net/dns/mapped_host_resolver.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_network_session.h"
+#include "net/http/http_network_transaction.h"
+#include "net/http/http_server_properties_impl.h"
+#include "net/http/http_transaction_unittest.h"
+#include "net/http/transport_security_state.h"
+#include "net/proxy/proxy_service.h"
+#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
+#include "net/tools/quic/test_tools/server_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+extern int FLAGS_fake_packet_loss_percentage;
+
+using base::StringPiece;
+using net::tools::QuicInMemoryCache;
+using net::tools::test::QuicInMemoryCachePeer;
+using net::tools::test::ServerThread;
+
+namespace net {
+namespace test {
+
+namespace {
+
+const char kResponseBody[] = "some arbitrary response body";
+
+// Factory for creating HttpTransactions, used by TestTransactionConsumer.
+class TestTransactionFactory : public HttpTransactionFactory {
+ public:
+ TestTransactionFactory(const HttpNetworkSession::Params& params)
+ : session_(new HttpNetworkSession(params)) {}
+
+ virtual ~TestTransactionFactory() {
+ FLAGS_fake_packet_loss_percentage = 0;
+ }
+
+ // HttpTransactionFactory methods
+ virtual int CreateTransaction(RequestPriority priority,
+ scoped_ptr<HttpTransaction>* trans,
+ HttpTransactionDelegate* delegate) OVERRIDE {
+ EXPECT_TRUE(delegate == NULL);
+ trans->reset(new HttpNetworkTransaction(priority, session_));
+ return OK;
+ }
+
+ virtual HttpCache* GetCache() OVERRIDE {
+ return NULL;
+ }
+
+ virtual HttpNetworkSession* GetSession() OVERRIDE {
+ return session_;
+ };
+
+ private:
+ scoped_refptr<HttpNetworkSession> session_;
+};
+
+} // namespace
+
+class QuicEndToEndTest : public PlatformTest {
+ protected:
+ QuicEndToEndTest()
+ : host_resolver_impl_(CreateResolverImpl()),
+ host_resolver_(host_resolver_impl_.PassAs<HostResolver>()),
+ ssl_config_service_(new SSLConfigServiceDefaults),
+ proxy_service_(ProxyService::CreateDirect()),
+ auth_handler_factory_(
+ HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
+ strike_register_no_startup_period_(false) {
+ request_.method = "GET";
+ request_.url = GURL("http://www.google.com/");
+ request_.load_flags = 0;
+
+ params_.enable_quic = true;
+ params_.quic_clock = NULL;
+ params_.quic_random = NULL;
+ params_.host_resolver = &host_resolver_;
+ params_.cert_verifier = &cert_verifier_;
+ params_.transport_security_state = &transport_security_state_;
+ 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();
+ }
+
+ // Creates a mock host resolver in which www.google.com
+ // resolves to localhost.
+ static MockHostResolver* CreateResolverImpl() {
+ MockHostResolver* resolver = new MockHostResolver();
+ resolver->rules()->AddRule("www.google.com", "127.0.0.1");
+ return resolver;
+ }
+
+ virtual void SetUp() {
+ QuicInMemoryCachePeer::ResetForTests();
+ StartServer();
+
+ // Use a mapped host resolver so that request for www.google.com (port 80)
+ // reach the server running on localhost.
+ std::string map_rule = "MAP www.google.com www.google.com:" +
+ base::IntToString(server_thread_->GetPort());
+ EXPECT_TRUE(host_resolver_.AddRuleFromString(map_rule));
+
+ // 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("www.google.com:80");
+
+ transaction_factory_.reset(new TestTransactionFactory(params_));
+ }
+
+ virtual void TearDown() {
+ StopServer();
+ QuicInMemoryCachePeer::ResetForTests();
+ }
+
+ // Starts the QUIC server listening on a random port.
+ void StartServer() {
+ net::IPAddressNumber ip;
+ CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
+ server_address_ = IPEndPoint(ip, 0);
+ server_config_.SetDefaults();
+ server_thread_.reset(new ServerThread(server_address_, server_config_,
+ QuicSupportedVersions(),
+ strike_register_no_startup_period_));
+ server_thread_->Start();
+ server_thread_->WaitForServerStartup();
+ server_address_ = IPEndPoint(server_address_.address(),
+ server_thread_->GetPort());
+ server_started_ = true;
+ }
+
+ // Stops the QUIC server.
+ void StopServer() {
+ if (!server_started_) {
+ return;
+ }
+ if (server_thread_.get()) {
+ server_thread_->Quit();
+ server_thread_->Join();
+ }
+ }
+
+ // Adds an entry to the cache used by the QUIC server to serve
+ // responses.
+ void AddToCache(const StringPiece& method,
+ const StringPiece& path,
+ const StringPiece& version,
+ const StringPiece& response_code,
+ const StringPiece& response_detail,
+ const StringPiece& body) {
+ QuicInMemoryCache::GetInstance()->AddSimpleResponse(
+ method, path, version, response_code, response_detail, body);
+ }
+
+ // Populates |request_body_| with |length_| ASCII bytes.
+ void GenerateBody(size_t length) {
+ request_body_.clear();
+ request_body_.reserve(length);
+ for (size_t i = 0; i < length; ++i) {
+ request_body_.append(1, static_cast<char>(32 + i % (126 - 32)));
+ }
+ }
+
+ // Initializes |request_| for a post of |length| bytes.
+ void InitializePostRequest(size_t length) {
+ GenerateBody(length);
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(
+ new UploadBytesElementReader(request_body_.data(),
+ request_body_.length()));
+ upload_data_stream_.reset(new UploadDataStream(element_readers.Pass(), 0));
+ request_.method = "POST";
+ request_.url = GURL("http://www.google.com/");
+ request_.upload_data_stream = upload_data_stream_.get();
+ ASSERT_EQ(OK, request_.upload_data_stream->Init(CompletionCallback()));
+ }
+
+ // Checks that |consumer| completed and received |status_line| and |body|.
+ void CheckResponse(const TestTransactionConsumer& consumer,
+ const std::string& status_line,
+ const std::string& body) {
+ ASSERT_TRUE(consumer.is_done());
+ EXPECT_EQ(OK, consumer.error());
+ EXPECT_EQ(status_line,
+ consumer.response_info()->headers->GetStatusLine());
+ EXPECT_EQ(body, consumer.content());
+ }
+
+ scoped_ptr<MockHostResolver> host_resolver_impl_;
+ MappedHostResolver host_resolver_;
+ MockCertVerifier cert_verifier_;
+ TransportSecurityState transport_security_state_;
+ scoped_refptr<SSLConfigServiceDefaults> ssl_config_service_;
+ scoped_ptr<ProxyService> proxy_service_;
+ scoped_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
+ HttpServerPropertiesImpl http_server_properties;
+ HttpNetworkSession::Params params_;
+ scoped_ptr<TestTransactionFactory> transaction_factory_;
+ HttpRequestInfo request_;
+ std::string request_body_;
+ scoped_ptr<UploadDataStream> upload_data_stream_;
+ scoped_ptr<ServerThread> server_thread_;
+ IPEndPoint server_address_;
+ std::string server_hostname_;
+ QuicConfig server_config_;
+ bool server_started_;
+ bool strike_register_no_startup_period_;
+};
+
+TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
+ std::string response(10 * 1024, 'x');
+
+ AddToCache("GET", request_.url.spec(),
+ "HTTP/1.1", "200", "OK",
+ response);
+
+ 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 OK", response);
+}
+
+// http://crbug.com/307284
+TEST_F(QuicEndToEndTest, DISABLED_LargePostWithNoPacketLoss) {
+ InitializePostRequest(10 * 1024 * 1024);
+
+ AddToCache("POST", request_.url.spec(),
+ "HTTP/1.1", "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 OK", kResponseBody);
+}
+
+TEST_F(QuicEndToEndTest, LargePostWithPacketLoss) {
+ // FLAGS_fake_packet_loss_percentage = 30;
+ InitializePostRequest(1024 * 1024);
+
+ const char kResponseBody[] = "some really big response body";
+ AddToCache("POST", request_.url.spec(),
+ "HTTP/1.1", "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 OK", kResponseBody);
+}
+
+TEST_F(QuicEndToEndTest, UberTest) {
+ // FLAGS_fake_packet_loss_percentage = 30;
+
+ const char kResponseBody[] = "some really big response body";
+ AddToCache("GET", request_.url.spec(),
+ "HTTP/1.1", "200", "OK",
+ kResponseBody);
+
+ std::vector<TestTransactionConsumer*> consumers;
+ size_t num_requests = 100;
+ for (size_t i = 0; i < num_requests; ++i) {
+ TestTransactionConsumer* consumer =
+ new TestTransactionConsumer(DEFAULT_PRIORITY,
+ transaction_factory_.get());
+ consumers.push_back(consumer);
+ consumer->Start(&request_, BoundNetLog());
+ }
+
+ // Will terminate when the last consumer completes.
+ base::MessageLoop::current()->Run();
+
+ for (size_t i = 0; i < num_requests; ++i) {
+ CheckResponse(*consumers[i], "HTTP/1.1 200 OK", kResponseBody);
+ }
+ STLDeleteElements(&consumers);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/quic_fec_group.cc b/chromium/net/quic/quic_fec_group.cc
index f5f4a77b908..4be48100e76 100644
--- a/chromium/net/quic/quic_fec_group.cc
+++ b/chromium/net/quic/quic_fec_group.cc
@@ -134,7 +134,7 @@ bool QuicFecGroup::UpdateParity(StringPiece payload, bool entropy) {
payload_parity_len_ = payload.size();
}
DCHECK_LE(payload.size(), kMaxPacketSize);
- if (received_packets_.size() == 0 &&
+ if (received_packets_.empty() &&
min_protected_packet_ == kNoSequenceNumber) {
// Initialize the parity to the value of this payload
memcpy(payload_parity_, payload.data(), payload.size());
diff --git a/chromium/net/quic/quic_fec_group_test.cc b/chromium/net/quic/quic_fec_group_test.cc
index d9c303aee5b..3de40b1bc7c 100644
--- a/chromium/net/quic/quic_fec_group_test.cc
+++ b/chromium/net/quic/quic_fec_group_test.cc
@@ -43,7 +43,7 @@ class QuicFecGroupTest : public ::testing::Test {
protected:
void RunTest(size_t num_packets, size_t lost_packet, bool out_of_order) {
size_t max_len = strlen(kData[0]);
- scoped_ptr<char[]>redundancy(new char[max_len]);
+ scoped_ptr<char[]> redundancy(new char[max_len]);
bool entropy_redundancy = false;
for (size_t packet = 0; packet < num_packets; ++packet) {
for (size_t i = 0; i < max_len; i++) {
diff --git a/chromium/net/quic/quic_framer.cc b/chromium/net/quic/quic_framer.cc
index cfc8c95774b..cc02882ddc9 100644
--- a/chromium/net/quic/quic_framer.cc
+++ b/chromium/net/quic/quic_framer.cc
@@ -13,6 +13,8 @@
using base::StringPiece;
using std::make_pair;
using std::map;
+using std::max;
+using std::min;
using std::numeric_limits;
using std::string;
@@ -20,19 +22,6 @@ namespace net {
namespace {
-// TODO(jri): Remove uses of QuicFrameTypeOld when
-// QUIC versions < 10 are no longer supported.
-enum QuicFrameTypeOld {
- PADDING_FRAME_OLD = 0,
- STREAM_FRAME_OLD,
- ACK_FRAME_OLD,
- CONGESTION_FEEDBACK_FRAME_OLD,
- RST_STREAM_FRAME_OLD,
- CONNECTION_CLOSE_FRAME_OLD,
- GOAWAY_FRAME_OLD,
- NUM_FRAME_TYPES_OLD
-};
-
// Mask to select the lowest 48 bits of a sequence number.
const QuicPacketSequenceNumber k6ByteSequenceNumberMask =
GG_UINT64_C(0x0000FFFFFFFFFFFF);
@@ -46,6 +35,10 @@ const QuicPacketSequenceNumber k1ByteSequenceNumberMask =
const QuicGuid k1ByteGuidMask = GG_UINT64_C(0x00000000000000FF);
const QuicGuid k4ByteGuidMask = GG_UINT64_C(0x00000000FFFFFFFF);
+// Number of bits the sequence number length bits are shifted from the right
+// edge of the public header.
+const uint8 kPublicHeaderSequenceNumberShift = 4;
+
// New Frame Types, QUIC v. >= 10:
// There are two interpretations for the Frame Type byte in the QUIC protocol,
// resulting in two Frame Types: Special Frame Types and Regular Frame Types.
@@ -72,16 +65,6 @@ const uint8 kQuicFrameTypeStreamMask = 0x80;
const uint8 kQuicFrameTypeAckMask = 0x40;
const uint8 kQuicFrameTypeCongestionFeedbackMask = 0x20;
-// Mask to determine if it's a special frame type(Stream, Ack, or
-// Congestion Control) by checking if the first bit is 0, then shifting right.
-// TODO(jri): Remove kQuicFrameType0BitMask constant from v. 10 onwards.
-// Replaced by kQuicFrameTypeStream defined above.
-const uint8 kQuicFrameType0BitMask = 0x01;
-
-// Default frame type shift and mask.
-const uint8 kQuicDefaultFrameTypeShift = 3;
-const uint8 kQuicDefaultFrameTypeMask = 0x07;
-
// Stream frame relative shifts and masks for interpreting the stream flags.
// StreamID may be 1, 2, 3, or 4 bytes.
const uint8 kQuicStreamIdShift = 2;
@@ -99,8 +82,15 @@ const uint8 kQuicStreamDataLengthMask = 0x01;
const uint8 kQuicStreamFinShift = 1;
const uint8 kQuicStreamFinMask = 0x01;
+// Sequence number size shift used in AckFrames.
+const uint8 kQuicSequenceNumberLengthShift = 2;
+
+// Acks may be truncated.
+const uint8 kQuicAckTruncatedShift = 1;
+const uint8 kQuicAckTruncatedMask = 0x01;
-const uint32 kInvalidDeltaTime = 0xffffffff;
+// Acks may not have any nacks.
+const uint8 kQuicHasNacksMask = 0x01;
// Returns the absolute value of the difference between |a| and |b|.
QuicPacketSequenceNumber Delta(QuicPacketSequenceNumber a,
@@ -120,21 +110,24 @@ QuicPacketSequenceNumber ClosestTo(QuicPacketSequenceNumber target,
} // namespace
-QuicFramer::QuicFramer(QuicVersion version,
+QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
QuicTime creation_time,
bool is_server)
: visitor_(NULL),
fec_builder_(NULL),
+ entropy_calculator_(NULL),
error_(QUIC_NO_ERROR),
last_sequence_number_(0),
last_serialized_guid_(0),
- quic_version_(version),
- decrypter_(QuicDecrypter::Create(kNULL)),
+ supported_versions_(supported_versions),
alternative_decrypter_latch_(false),
is_server_(is_server),
creation_time_(creation_time) {
- DCHECK(IsSupportedVersion(version));
- encrypter_[ENCRYPTION_NONE].reset(QuicEncrypter::Create(kNULL));
+ DCHECK(!supported_versions.empty());
+ quic_version_ = supported_versions_[0];
+ decrypter_.reset(QuicDecrypter::Create(kNULL));
+ encrypter_[ENCRYPTION_NONE].reset(
+ QuicEncrypter::Create(kNULL));
}
QuicFramer::~QuicFramer() {}
@@ -150,11 +143,13 @@ size_t QuicFramer::GetMinStreamFrameSize(QuicVersion version,
}
// static
-size_t QuicFramer::GetMinAckFrameSize() {
+size_t QuicFramer::GetMinAckFrameSize(
+ QuicVersion version,
+ QuicSequenceNumberLength sequence_number_length,
+ QuicSequenceNumberLength largest_observed_length) {
return kQuicFrameTypeSize + kQuicEntropyHashSize +
- PACKET_6BYTE_SEQUENCE_NUMBER + kQuicEntropyHashSize +
- PACKET_6BYTE_SEQUENCE_NUMBER + kQuicDeltaTimeLargestObservedSize +
- kNumberOfMissingPacketsSize;
+ sequence_number_length + kQuicEntropyHashSize +
+ largest_observed_length + kQuicDeltaTimeLargestObservedSize;
}
// static
@@ -165,8 +160,7 @@ size_t QuicFramer::GetMinRstStreamFrameSize() {
// static
size_t QuicFramer::GetMinConnectionCloseFrameSize() {
- return kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize +
- GetMinAckFrameSize();
+ return kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize;
}
// static
@@ -176,16 +170,6 @@ size_t QuicFramer::GetMinGoAwayFrameSize() {
}
// static
-// TODO(satyamshekhar): 16 - Crypto hash for integrity. Not a static value. Use
-// QuicEncrypter::GetMaxPlaintextSize.
-// 16 is a conservative estimate in the case of AEAD_AES_128_GCM_12, which uses
-// 12-byte tags.
-size_t QuicFramer::GetMaxUnackedPackets(QuicPacketHeader header) {
- return (kMaxPacketSize - GetPacketHeaderSize(header) -
- GetMinAckFrameSize() - 16) / PACKET_6BYTE_SEQUENCE_NUMBER;
-}
-
-// static
size_t QuicFramer::GetStreamIdSize(QuicStreamId stream_id) {
// Sizes are 1 through 4 bytes.
for (int i = 1; i <= 4; ++i) {
@@ -223,20 +207,20 @@ size_t QuicFramer::GetVersionNegotiationPacketSize(size_t number_versions) {
}
// static
-bool QuicFramer::CanTruncate(const QuicFrame& frame, size_t free_bytes) {
- // TODO(ianswett): GetMinConnectionCloseFrameSize may be incorrect, because
- // checking for it here results in frames not being added, but the resulting
- // frames do actually fit.
+bool QuicFramer::CanTruncate(
+ QuicVersion version, const QuicFrame& frame, size_t free_bytes) {
if ((frame.type == ACK_FRAME || frame.type == CONNECTION_CLOSE_FRAME) &&
- free_bytes >= GetMinAckFrameSize()) {
+ free_bytes >= GetMinAckFrameSize(version,
+ PACKET_6BYTE_SEQUENCE_NUMBER,
+ PACKET_6BYTE_SEQUENCE_NUMBER)) {
return true;
}
return false;
}
bool QuicFramer::IsSupportedVersion(const QuicVersion version) const {
- for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- if (version == kSupportedQuicVersions[i]) {
+ for (size_t i = 0; i < supported_versions_.size(); ++i) {
+ if (version == supported_versions_[i]) {
return true;
}
}
@@ -244,43 +228,43 @@ bool QuicFramer::IsSupportedVersion(const QuicVersion version) const {
}
size_t QuicFramer::GetSerializedFrameLength(
- const QuicFrame& frame, size_t free_bytes, bool first_frame) {
+ const QuicFrame& frame,
+ size_t free_bytes,
+ bool first_frame,
+ bool last_frame,
+ QuicSequenceNumberLength sequence_number_length) {
if (frame.type == PADDING_FRAME) {
// PADDING implies end of packet.
return free_bytes;
}
- // See if it fits as the non-last frame.
- size_t frame_len = ComputeFrameLength(frame, false);
- // STREAM frames save two bytes when they're the last frame in the packet.
- if (frame_len > free_bytes && frame.type == STREAM_FRAME) {
- frame_len = ComputeFrameLength(frame, true);
- }
+ size_t frame_len =
+ ComputeFrameLength(frame, last_frame, sequence_number_length);
if (frame_len > free_bytes) {
// Only truncate the first frame in a packet, so if subsequent ones go
// over, stop including more frames.
if (!first_frame) {
return 0;
}
- if (CanTruncate(frame, free_bytes)) {
+ if (CanTruncate(quic_version_, frame, free_bytes)) {
// Truncate the frame so the packet will not exceed kMaxPacketSize.
// Note that we may not use every byte of the writer in this case.
- DLOG(INFO) << "Truncating large frame";
+ DVLOG(1) << "Truncating large frame";
return free_bytes;
}
}
return frame_len;
}
+QuicFramer::AckFrameInfo::AckFrameInfo() : max_delta(0) { }
+
+QuicFramer::AckFrameInfo::~AckFrameInfo() { }
+
QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash(
const QuicPacketHeader& header) const {
- if (!header.entropy_flag) {
- // TODO(satyamshekhar): Return some more better value here (something that
- // is not a constant).
- return 0;
- }
- return 1 << (header.packet_sequence_number % 8);
+ return header.entropy_flag << (header.packet_sequence_number % 8);
}
+// Test only.
SerializedPacket QuicFramer::BuildUnsizedDataPacket(
const QuicPacketHeader& header,
const QuicFrames& frames) {
@@ -288,8 +272,11 @@ SerializedPacket QuicFramer::BuildUnsizedDataPacket(
size_t packet_size = GetPacketHeaderSize(header);
for (size_t i = 0; i < frames.size(); ++i) {
DCHECK_LE(packet_size, max_plaintext_size);
+ bool first_frame = i == 0;
+ bool last_frame = i == frames.size() - 1;
const size_t frame_size = GetSerializedFrameLength(
- frames[i], max_plaintext_size - packet_size, i == 0);
+ frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
+ header.public_header.sequence_number_length);
DCHECK(frame_size);
packet_size += frame_size;
}
@@ -303,7 +290,7 @@ SerializedPacket QuicFramer::BuildDataPacket(
QuicDataWriter writer(packet_size);
const SerializedPacket kNoPacket(
0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL);
- if (!WritePacketHeader(header, &writer)) {
+ if (!AppendPacketHeader(header, &writer)) {
return kNoPacket;
}
@@ -326,7 +313,8 @@ SerializedPacket QuicFramer::BuildDataPacket(
}
break;
case ACK_FRAME:
- if (!AppendAckFramePayload(*frame.ack_frame, &writer)) {
+ if (!AppendAckFramePayloadAndTypeByte(
+ header, *frame.ack_frame, &writer)) {
return kNoPacket;
}
break;
@@ -388,7 +376,7 @@ SerializedPacket QuicFramer::BuildFecPacket(const QuicPacketHeader& header,
QuicDataWriter writer(len);
const SerializedPacket kNoPacket(
0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL);
- if (!WritePacketHeader(header, &writer)) {
+ if (!AppendPacketHeader(header, &writer)) {
return kNoPacket;
}
@@ -465,8 +453,6 @@ QuicEncryptedPacket* QuicFramer::BuildVersionNegotiationPacket(
}
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
- // TODO(satyamshekhar): Don't RaiseError (and close the connection) for
- // invalid (unauthenticated) packets.
DCHECK(!reader_.get());
reader_.reset(new QuicDataReader(packet.data(), packet.length()));
@@ -476,6 +462,7 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
QuicPacketPublicHeader public_header;
if (!ProcessPublicHeader(&public_header)) {
DLOG(WARNING) << "Unable to process public header.";
+ DCHECK_NE("", detailed_error_);
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
@@ -522,7 +509,6 @@ bool QuicFramer::ProcessDataPacket(
const QuicEncryptedPacket& packet) {
QuicPacketHeader header(public_header);
if (!ProcessPacketHeader(&header, packet)) {
- DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessPacketHeader sets the error.
DLOG(WARNING) << "Unable to process data packet header.";
return false;
}
@@ -543,7 +529,7 @@ bool QuicFramer::ProcessDataPacket(
StringPiece payload = reader_->PeekRemainingPayload();
visitor_->OnFecProtectedPayload(payload);
}
- if (!ProcessFrameData()) {
+ if (!ProcessFrameData(header)) {
DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
DLOG(WARNING) << "Unable to process frame data.";
return false;
@@ -594,7 +580,7 @@ bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header,
}
reader_.reset(new QuicDataReader(payload.data(), payload.length()));
- if (!ProcessFrameData()) {
+ if (!ProcessFrameData(*header)) {
DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error.
DLOG(WARNING) << "Unable to process frame data.";
return false;
@@ -605,8 +591,8 @@ bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header,
return true;
}
-bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* writer) {
+bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
+ QuicDataWriter* writer) {
DCHECK(header.fec_group > 0 || header.is_in_fec_group == NOT_IN_FEC_GROUP);
uint8 public_flags = 0;
if (header.public_header.reset_flag) {
@@ -615,20 +601,10 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
if (header.public_header.version_flag) {
public_flags |= PACKET_PUBLIC_FLAGS_VERSION;
}
- switch (header.public_header.sequence_number_length) {
- case PACKET_1BYTE_SEQUENCE_NUMBER:
- public_flags |= PACKET_PUBLIC_FLAGS_1BYTE_SEQUENCE;
- break;
- case PACKET_2BYTE_SEQUENCE_NUMBER:
- public_flags |= PACKET_PUBLIC_FLAGS_2BYTE_SEQUENCE;
- break;
- case PACKET_4BYTE_SEQUENCE_NUMBER:
- public_flags |= PACKET_PUBLIC_FLAGS_4BYTE_SEQUENCE;
- break;
- case PACKET_6BYTE_SEQUENCE_NUMBER:
- public_flags |= PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE;
- break;
- }
+
+ public_flags |=
+ GetSequenceNumberFlags(header.public_header.sequence_number_length)
+ << kPublicHeaderSequenceNumberShift;
switch (header.public_header.guid_length) {
case PACKET_0BYTE_GUID:
@@ -641,7 +617,7 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
return false;
}
if (!writer->WriteUInt8(header.public_header.guid & k1ByteGuidMask)) {
- return false;
+ return false;
}
break;
case PACKET_4BYTE_GUID:
@@ -794,20 +770,9 @@ bool QuicFramer::ProcessPublicHeader(
break;
}
- switch (public_flags & PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE) {
- case PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE:
- public_header->sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER;
- break;
- case PACKET_PUBLIC_FLAGS_4BYTE_SEQUENCE:
- public_header->sequence_number_length = PACKET_4BYTE_SEQUENCE_NUMBER;
- break;
- case PACKET_PUBLIC_FLAGS_2BYTE_SEQUENCE:
- public_header->sequence_number_length = PACKET_2BYTE_SEQUENCE_NUMBER;
- break;
- case PACKET_PUBLIC_FLAGS_1BYTE_SEQUENCE:
- public_header->sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
- break;
- }
+ public_header->sequence_number_length =
+ ReadSequenceNumberLength(
+ public_flags >> kPublicHeaderSequenceNumberShift);
// Read the version only if the packet is from the client.
// version flag from the server means version negotiation packet.
@@ -848,6 +813,91 @@ bool QuicFramer::ReadGuidFromPacket(const QuicEncryptedPacket& packet,
return reader.ReadUInt64(guid);
}
+// static
+QuicSequenceNumberLength QuicFramer::ReadSequenceNumberLength(uint8 flags) {
+ switch (flags & PACKET_FLAGS_6BYTE_SEQUENCE) {
+ case PACKET_FLAGS_6BYTE_SEQUENCE:
+ return PACKET_6BYTE_SEQUENCE_NUMBER;
+ case PACKET_FLAGS_4BYTE_SEQUENCE:
+ return PACKET_4BYTE_SEQUENCE_NUMBER;
+ case PACKET_FLAGS_2BYTE_SEQUENCE:
+ return PACKET_2BYTE_SEQUENCE_NUMBER;
+ case PACKET_FLAGS_1BYTE_SEQUENCE:
+ return PACKET_1BYTE_SEQUENCE_NUMBER;
+ default:
+ LOG(DFATAL) << "Unreachable case statement.";
+ return PACKET_6BYTE_SEQUENCE_NUMBER;
+ }
+}
+
+// static
+QuicSequenceNumberLength QuicFramer::GetMinSequenceNumberLength(
+ QuicPacketSequenceNumber sequence_number) {
+ if (sequence_number < 1 << (PACKET_1BYTE_SEQUENCE_NUMBER * 8)) {
+ return PACKET_1BYTE_SEQUENCE_NUMBER;
+ } else if (sequence_number < 1 << (PACKET_2BYTE_SEQUENCE_NUMBER * 8)) {
+ return PACKET_2BYTE_SEQUENCE_NUMBER;
+ } else if (sequence_number <
+ GG_UINT64_C(1) << (PACKET_4BYTE_SEQUENCE_NUMBER * 8)) {
+ return PACKET_4BYTE_SEQUENCE_NUMBER;
+ } else {
+ return PACKET_6BYTE_SEQUENCE_NUMBER;
+ }
+}
+
+// static
+uint8 QuicFramer::GetSequenceNumberFlags(
+ QuicSequenceNumberLength sequence_number_length) {
+ switch (sequence_number_length) {
+ case PACKET_1BYTE_SEQUENCE_NUMBER:
+ return PACKET_FLAGS_1BYTE_SEQUENCE;
+ case PACKET_2BYTE_SEQUENCE_NUMBER:
+ return PACKET_FLAGS_2BYTE_SEQUENCE;
+ case PACKET_4BYTE_SEQUENCE_NUMBER:
+ return PACKET_FLAGS_4BYTE_SEQUENCE;
+ case PACKET_6BYTE_SEQUENCE_NUMBER:
+ return PACKET_FLAGS_6BYTE_SEQUENCE;
+ default:
+ LOG(DFATAL) << "Unreachable case statement.";
+ return PACKET_FLAGS_6BYTE_SEQUENCE;
+ }
+}
+
+// static
+QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo(
+ const QuicAckFrame& frame) {
+ const ReceivedPacketInfo& received_info = frame.received_info;
+
+ AckFrameInfo ack_info;
+ if (!received_info.missing_packets.empty()) {
+ DCHECK_GE(received_info.largest_observed,
+ *received_info.missing_packets.rbegin());
+ size_t cur_range_length = 0;
+ SequenceNumberSet::const_iterator iter =
+ received_info.missing_packets.begin();
+ QuicPacketSequenceNumber last_missing = *iter;
+ ++iter;
+ for (; iter != received_info.missing_packets.end(); ++iter) {
+ if (cur_range_length != numeric_limits<uint8>::max() &&
+ *iter == (last_missing + 1)) {
+ ++cur_range_length;
+ } else {
+ ack_info.nack_ranges[last_missing - cur_range_length]
+ = cur_range_length;
+ cur_range_length = 0;
+ }
+ ack_info.max_delta = max(ack_info.max_delta, *iter - last_missing);
+ last_missing = *iter;
+ }
+ // Include the last nack range.
+ ack_info.nack_ranges[last_missing - cur_range_length] = cur_range_length;
+ // Include the range to the largest observed.
+ ack_info.max_delta = max(ack_info.max_delta,
+ received_info.largest_observed - last_missing);
+ }
+ return ack_info;
+}
+
bool QuicFramer::ProcessPacketHeader(
QuicPacketHeader* header,
const QuicEncryptedPacket& packet) {
@@ -862,6 +912,10 @@ bool QuicFramer::ProcessPacketHeader(
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
+ if (!visitor_->OnUnauthenticatedHeader(*header)) {
+ return false;
+ }
+
if (!DecryptPayload(*header, packet)) {
set_detailed_error("Unable to decrypt payload.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
@@ -920,7 +974,7 @@ bool QuicFramer::ProcessPacketSequenceNumber(
return true;
}
-bool QuicFramer::ProcessFrameData() {
+bool QuicFramer::ProcessFrameData(const QuicPacketHeader& header) {
if (reader_->IsDoneReading()) {
set_detailed_error("Packet has no frames.");
return RaiseError(QUIC_MISSING_PAYLOAD);
@@ -932,223 +986,107 @@ bool QuicFramer::ProcessFrameData() {
return RaiseError(QUIC_INVALID_FRAME_DATA);
}
- // TODO(jri): Remove this entire if block when support for
- // QUIC version < 10 removed.
- if (version() < QUIC_VERSION_10) {
- // Special frame type processing for QUIC version < 10.
- if ((frame_type & kQuicFrameType0BitMask) == 0) {
+ if (frame_type & kQuicFrameTypeSpecialMask) {
+ // Stream Frame
+ if (frame_type & kQuicFrameTypeStreamMask) {
QuicStreamFrame frame;
if (!ProcessStreamFrame(frame_type, &frame)) {
return RaiseError(QUIC_INVALID_STREAM_DATA);
}
if (!visitor_->OnStreamFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
+ DVLOG(1) << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
continue;
}
- frame_type >>= 1;
- if ((frame_type & kQuicFrameType0BitMask) == 0) {
+ // Ack Frame
+ if (frame_type & kQuicFrameTypeAckMask) {
QuicAckFrame frame;
- if (!ProcessAckFrame(&frame)) {
+ if (!ProcessAckFrame(header, frame_type, &frame)) {
return RaiseError(QUIC_INVALID_ACK_DATA);
}
if (!visitor_->OnAckFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
+ DVLOG(1) << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
continue;
}
- frame_type >>= 1;
- if ((frame_type & kQuicFrameType0BitMask) == 0) {
+ // Congestion Feedback Frame
+ if (frame_type & kQuicFrameTypeCongestionFeedbackMask) {
QuicCongestionFeedbackFrame frame;
if (!ProcessQuicCongestionFeedbackFrame(&frame)) {
return RaiseError(QUIC_INVALID_CONGESTION_FEEDBACK_DATA);
}
if (!visitor_->OnCongestionFeedbackFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
+ DVLOG(1) << "Visitor asked to stop further processing.";
// Returning true since there was no parsing error.
return true;
}
continue;
}
- frame_type >>= 1;
- switch (frame_type) {
- // STREAM_FRAME, ACK_FRAME, and CONGESTION_FEEDBACK_FRAME are handled
- // above.
- case PADDING_FRAME_OLD:
- // We're done with the packet.
- return true;
-
- case RST_STREAM_FRAME_OLD: {
- QuicRstStreamFrame frame;
- if (!ProcessRstStreamFrame(&frame)) {
- return RaiseError(QUIC_INVALID_RST_STREAM_DATA);
- }
- if (!visitor_->OnRstStreamFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
- }
-
- case CONNECTION_CLOSE_FRAME_OLD: {
- QuicConnectionCloseFrame frame;
- if (!ProcessConnectionCloseFrame(&frame)) {
- return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA);
- }
+ // This was a special frame type that did not match any
+ // of the known ones. Error.
+ set_detailed_error("Illegal frame type.");
+ DLOG(WARNING) << "Illegal frame type: "
+ << static_cast<int>(frame_type);
+ return RaiseError(QUIC_INVALID_FRAME_DATA);
+ }
- if (!visitor_->OnAckFrame(frame.ack_frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
+ switch (frame_type) {
+ case PADDING_FRAME:
+ // We're done with the packet.
+ return true;
- if (!visitor_->OnConnectionCloseFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
+ case RST_STREAM_FRAME: {
+ QuicRstStreamFrame frame;
+ if (!ProcessRstStreamFrame(&frame)) {
+ return RaiseError(QUIC_INVALID_RST_STREAM_DATA);
}
-
- case GOAWAY_FRAME_OLD: {
- QuicGoAwayFrame goaway_frame;
- if (!ProcessGoAwayFrame(&goaway_frame)) {
- return RaiseError(QUIC_INVALID_GOAWAY_DATA);
- }
- if (!visitor_->OnGoAwayFrame(goaway_frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
+ if (!visitor_->OnRstStreamFrame(frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
}
-
- set_detailed_error("Illegal frame type.");
- DLOG(WARNING) << "Illegal frame type: "
- << static_cast<int>(frame_type);
- return RaiseError(QUIC_INVALID_FRAME_DATA);
+ continue;
}
- } else {
- // TODO(jri): Retain this else block when support for
- // QUIC version < 10 removed. Remove above if block.
-
- // Special frame type processing for QUIC version >= 10.
- if (frame_type & kQuicFrameTypeSpecialMask) {
- // Stream Frame
- if (frame_type & kQuicFrameTypeStreamMask) {
- QuicStreamFrame frame;
- if (!ProcessStreamFrame(frame_type, &frame)) {
- return RaiseError(QUIC_INVALID_STREAM_DATA);
- }
- if (!visitor_->OnStreamFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
+
+ case CONNECTION_CLOSE_FRAME: {
+ QuicConnectionCloseFrame frame;
+ if (!ProcessConnectionCloseFrame(&frame)) {
+ return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA);
}
- // Ack Frame
- if (frame_type & kQuicFrameTypeAckMask) {
- QuicAckFrame frame;
- if (!ProcessAckFrame(&frame)) {
- return RaiseError(QUIC_INVALID_ACK_DATA);
- }
- if (!visitor_->OnAckFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
+ if (!visitor_->OnConnectionCloseFrame(frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
}
+ continue;
+ }
- // Congestion Feedback Frame
- if (frame_type & kQuicFrameTypeCongestionFeedbackMask) {
- QuicCongestionFeedbackFrame frame;
- if (!ProcessQuicCongestionFeedbackFrame(&frame)) {
- return RaiseError(QUIC_INVALID_CONGESTION_FEEDBACK_DATA);
- }
- if (!visitor_->OnCongestionFeedbackFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
+ case GOAWAY_FRAME: {
+ QuicGoAwayFrame goaway_frame;
+ if (!ProcessGoAwayFrame(&goaway_frame)) {
+ return RaiseError(QUIC_INVALID_GOAWAY_DATA);
+ }
+ if (!visitor_->OnGoAwayFrame(goaway_frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
}
+ continue;
+ }
- // This was a special frame type that did not match any
- // of the known ones. Error.
+ default:
set_detailed_error("Illegal frame type.");
DLOG(WARNING) << "Illegal frame type: "
<< static_cast<int>(frame_type);
return RaiseError(QUIC_INVALID_FRAME_DATA);
- }
-
- switch (frame_type) {
- case PADDING_FRAME:
- // We're done with the packet.
- return true;
-
- case RST_STREAM_FRAME: {
- QuicRstStreamFrame frame;
- if (!ProcessRstStreamFrame(&frame)) {
- return RaiseError(QUIC_INVALID_RST_STREAM_DATA);
- }
- if (!visitor_->OnRstStreamFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
- }
-
- case CONNECTION_CLOSE_FRAME: {
- QuicConnectionCloseFrame frame;
- if (!ProcessConnectionCloseFrame(&frame)) {
- return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA);
- }
-
- if (!visitor_->OnAckFrame(frame.ack_frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
-
- if (!visitor_->OnConnectionCloseFrame(frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
- }
-
- case GOAWAY_FRAME: {
- QuicGoAwayFrame goaway_frame;
- if (!ProcessGoAwayFrame(&goaway_frame)) {
- return RaiseError(QUIC_INVALID_GOAWAY_DATA);
- }
- if (!visitor_->OnGoAwayFrame(goaway_frame)) {
- DLOG(INFO) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- continue;
- }
-
- default:
- set_detailed_error("Illegal frame type.");
- DLOG(WARNING) << "Illegal frame type: "
- << static_cast<int>(frame_type);
- return RaiseError(QUIC_INVALID_FRAME_DATA);
- }
}
}
@@ -1159,12 +1097,7 @@ bool QuicFramer::ProcessStreamFrame(uint8 frame_type,
QuicStreamFrame* frame) {
uint8 stream_flags = frame_type;
- // TODO(jri): Remove if block after support for ver. < 10 removed.
- if (version() < QUIC_VERSION_10) {
- stream_flags >>= 1;
- } else {
- stream_flags &= ~kQuicFrameTypeStreamMask;
- }
+ stream_flags &= ~kQuicFrameTypeStreamMask;
// Read from right to left: StreamID, Offset, Data Length, Fin.
const uint8 stream_id_length = (stream_flags & kQuicStreamIDLengthMask) + 1;
@@ -1195,86 +1128,129 @@ bool QuicFramer::ProcessStreamFrame(uint8 frame_type,
return false;
}
+ StringPiece frame_data;
if (has_data_length) {
- if (!reader_->ReadStringPiece16(&frame->data)) {
+ if (!reader_->ReadStringPiece16(&frame_data)) {
set_detailed_error("Unable to read frame data.");
return false;
}
} else {
- if (!reader_->ReadStringPiece(&frame->data, reader_->BytesRemaining())) {
+ if (!reader_->ReadStringPiece(&frame_data, reader_->BytesRemaining())) {
set_detailed_error("Unable to read frame data.");
return false;
}
}
+ // Point frame to the right data.
+ frame->data.Clear();
+ if (!frame_data.empty()) {
+ frame->data.Append(const_cast<char*>(frame_data.data()), frame_data.size());
+ }
return true;
}
-bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) {
- if (!ProcessSentInfo(&frame->sent_info)) {
+bool QuicFramer::ProcessAckFrame(const QuicPacketHeader& header,
+ uint8 frame_type,
+ QuicAckFrame* frame) {
+ if (!ProcessSentInfo(header, &frame->sent_info)) {
return false;
}
- if (!ProcessReceivedInfo(&frame->received_info)) {
+ if (!ProcessReceivedInfo(frame_type, &frame->received_info)) {
return false;
}
return true;
}
-bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
+bool QuicFramer::ProcessReceivedInfo(uint8 frame_type,
+ ReceivedPacketInfo* received_info) {
+ // Determine the three lengths from the frame type: largest observed length,
+ // missing sequence number length, and missing range length.
+ const QuicSequenceNumberLength missing_sequence_number_length =
+ ReadSequenceNumberLength(frame_type);
+ frame_type >>= kQuicSequenceNumberLengthShift;
+ const QuicSequenceNumberLength largest_observed_sequence_number_length =
+ ReadSequenceNumberLength(frame_type);
+ frame_type >>= kQuicSequenceNumberLengthShift;
+ received_info->is_truncated = frame_type & kQuicAckTruncatedMask;
+ frame_type >>= kQuicAckTruncatedShift;
+ bool has_nacks = frame_type & kQuicHasNacksMask;
+
if (!reader_->ReadBytes(&received_info->entropy_hash, 1)) {
set_detailed_error("Unable to read entropy hash for received packets.");
return false;
}
- if (!ProcessPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER,
- &received_info->largest_observed)) {
- set_detailed_error("Unable to read largest observed.");
- return false;
+ if (!reader_->ReadBytes(&received_info->largest_observed,
+ largest_observed_sequence_number_length)) {
+ set_detailed_error("Unable to read largest observed.");
+ return false;
}
- uint32 delta_time_largest_observed_us;
- if (!reader_->ReadUInt32(&delta_time_largest_observed_us)) {
+ uint64 delta_time_largest_observed_us;
+ if (!reader_->ReadUFloat16(&delta_time_largest_observed_us)) {
set_detailed_error("Unable to read delta time largest observed.");
return false;
}
- if (delta_time_largest_observed_us == kInvalidDeltaTime) {
+ if (delta_time_largest_observed_us == kUFloat16MaxValue) {
received_info->delta_time_largest_observed = QuicTime::Delta::Infinite();
} else {
received_info->delta_time_largest_observed =
QuicTime::Delta::FromMicroseconds(delta_time_largest_observed_us);
}
- uint8 num_missing_packets;
- if (!reader_->ReadBytes(&num_missing_packets, 1)) {
- set_detailed_error("Unable to read num missing packets.");
+ if (!has_nacks) {
+ return true;
+ }
+
+ uint8 num_missing_ranges;
+ if (!reader_->ReadBytes(&num_missing_ranges, 1)) {
+ set_detailed_error("Unable to read num missing packet ranges.");
return false;
}
- for (int i = 0; i < num_missing_packets; ++i) {
- QuicPacketSequenceNumber sequence_number;
- if (!ProcessPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER,
- &sequence_number)) {
- set_detailed_error("Unable to read sequence number in missing packets.");
+ QuicPacketSequenceNumber last_sequence_number =
+ received_info->largest_observed;
+ for (size_t i = 0; i < num_missing_ranges; ++i) {
+ QuicPacketSequenceNumber missing_delta = 0;
+ if (!reader_->ReadBytes(&missing_delta, missing_sequence_number_length)) {
+ set_detailed_error("Unable to read missing sequence number delta.");
return false;
}
- received_info->missing_packets.insert(sequence_number);
+ last_sequence_number -= missing_delta;
+ QuicPacketSequenceNumber range_length = 0;
+ if (!reader_->ReadBytes(&range_length, PACKET_1BYTE_SEQUENCE_NUMBER)) {
+ set_detailed_error("Unable to read missing sequence number range.");
+ return false;
+ }
+ for (size_t i = 0; i <= range_length; ++i) {
+ received_info->missing_packets.insert(last_sequence_number - i);
+ }
+ // Subtract an extra 1 to ensure ranges are represented efficiently and
+ // can't overlap by 1 sequence number. This allows a missing_delta of 0
+ // to represent an adjacent nack range.
+ last_sequence_number -= (range_length + 1);
}
return true;
}
-bool QuicFramer::ProcessSentInfo(SentPacketInfo* sent_info) {
+bool QuicFramer::ProcessSentInfo(const QuicPacketHeader& header,
+ SentPacketInfo* sent_info) {
if (!reader_->ReadBytes(&sent_info->entropy_hash, 1)) {
set_detailed_error("Unable to read entropy hash for sent packets.");
return false;
}
- if (!ProcessPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER,
- &sent_info->least_unacked)) {
- set_detailed_error("Unable to read least unacked.");
+ QuicPacketSequenceNumber least_unacked_delta = 0;
+ if (!reader_->ReadBytes(&least_unacked_delta,
+ header.public_header.sequence_number_length)) {
+ set_detailed_error("Unable to read least unacked delta.");
return false;
}
+ DCHECK_GE(header.packet_sequence_number, least_unacked_delta);
+ sent_info->least_unacked =
+ header.packet_sequence_number - least_unacked_delta;
return true;
}
@@ -1324,7 +1300,7 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
inter_arrival->received_packet_times.insert(
make_pair(smallest_received, time_received));
- for (int i = 0; i < num_received_packets - 1; ++i) {
+ for (uint8 i = 0; i < num_received_packets - 1; ++i) {
uint16 sequence_delta;
if (!reader_->ReadUInt16(&sequence_delta)) {
set_detailed_error(
@@ -1362,6 +1338,7 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
"Unable to read accumulated number of lost packets.");
return false;
}
+ // TODO(ianswett): Remove receive window, since it's constant.
uint16 receive_window = 0;
if (!reader_->ReadUInt16(&receive_window)) {
set_detailed_error("Unable to read receive window.");
@@ -1433,11 +1410,6 @@ bool QuicFramer::ProcessConnectionCloseFrame(QuicConnectionCloseFrame* frame) {
}
frame->error_details = error_details.as_string();
- if (!ProcessAckFrame(&frame->ack_frame)) {
- DLOG(WARNING) << "Unable to process ack frame.";
- return false;
- }
-
return true;
}
@@ -1552,9 +1524,7 @@ QuicEncryptedPacket* QuicFramer::EncryptPacket(
size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
// In order to keep the code simple, we don't have the current encryption
- // level to hand. At the moment, the NullEncrypter has a tag length of 16
- // bytes and AES-GCM has a tag length of 12. We take the minimum plaintext
- // length just to be safe.
+ // level to hand. Both the NullEncrypter and AES-GCM have a tag length of 12.
size_t min_plaintext_size = ciphertext_size;
for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; i++) {
@@ -1613,19 +1583,36 @@ bool QuicFramer::DecryptPayload(const QuicPacketHeader& header,
return true;
}
-size_t QuicFramer::ComputeFrameLength(const QuicFrame& frame,
- bool last_frame_in_packet) {
+size_t QuicFramer::GetAckFrameSize(
+ const QuicAckFrame& ack,
+ QuicSequenceNumberLength sequence_number_length) {
+ AckFrameInfo ack_info = GetAckFrameInfo(ack);
+ QuicSequenceNumberLength largest_observed_length =
+ GetMinSequenceNumberLength(ack.received_info.largest_observed);
+ QuicSequenceNumberLength missing_sequence_number_length =
+ GetMinSequenceNumberLength(ack_info.max_delta);
+
+ return GetMinAckFrameSize(quic_version_,
+ sequence_number_length,
+ largest_observed_length) +
+ (ack_info.nack_ranges.empty() ? 0 : kNumberOfMissingPacketsSize) +
+ ack_info.nack_ranges.size() *
+ (missing_sequence_number_length + PACKET_1BYTE_SEQUENCE_NUMBER);
+}
+
+size_t QuicFramer::ComputeFrameLength(
+ const QuicFrame& frame,
+ bool last_frame_in_packet,
+ QuicSequenceNumberLength sequence_number_length) {
switch (frame.type) {
case STREAM_FRAME:
return GetMinStreamFrameSize(quic_version_,
frame.stream_frame->stream_id,
frame.stream_frame->offset,
last_frame_in_packet) +
- frame.stream_frame->data.size();
+ frame.stream_frame->data.TotalBufferSize();
case ACK_FRAME: {
- const QuicAckFrame& ack = *frame.ack_frame;
- return GetMinAckFrameSize() + PACKET_6BYTE_SEQUENCE_NUMBER *
- ack.received_info.missing_packets.size();
+ return GetAckFrameSize(*frame.ack_frame, sequence_number_length);
}
case CONGESTION_FEEDBACK_FRAME: {
size_t len = kQuicFrameTypeSize;
@@ -1656,7 +1643,7 @@ size_t QuicFramer::ComputeFrameLength(const QuicFrame& frame,
break;
default:
set_detailed_error("Illegal feedback type.");
- DLOG(INFO) << "Illegal feedback type: " << congestion_feedback.type;
+ DVLOG(1) << "Illegal feedback type: " << congestion_feedback.type;
break;
}
return len;
@@ -1664,13 +1651,9 @@ size_t QuicFramer::ComputeFrameLength(const QuicFrame& frame,
case RST_STREAM_FRAME:
return GetMinRstStreamFrameSize() +
frame.rst_stream_frame->error_details.size();
- case CONNECTION_CLOSE_FRAME: {
- const QuicAckFrame& ack = frame.connection_close_frame->ack_frame;
+ case CONNECTION_CLOSE_FRAME:
return GetMinConnectionCloseFrameSize() +
- frame.connection_close_frame->error_details.size() +
- PACKET_6BYTE_SEQUENCE_NUMBER *
- ack.received_info.missing_packets.size();
- }
+ frame.connection_close_frame->error_details.size();
case GOAWAY_FRAME:
return GetMinGoAwayFrameSize() + frame.goaway_frame->reason_phrase.size();
case PADDING_FRAME:
@@ -1712,45 +1695,18 @@ bool QuicFramer::AppendTypeByte(const QuicFrame& frame,
// stream id 2 bits.
type_byte <<= kQuicStreamIdShift;
type_byte |= GetStreamIdSize(frame.stream_frame->stream_id) - 1;
-
- // TODO(jri): Remove if block when support for QUIC ver. < 10 removed.
- if (version() < QUIC_VERSION_10) {
- type_byte <<= 1; // Leaves the last bit as a 0.
- } else {
- type_byte |= kQuicFrameTypeStreamMask; // Set Stream Frame Type to 1.
- }
- break;
- }
- case ACK_FRAME: {
- // TODO(ianswett): Use extra 5 bits in the ack framing.
- // TODO(jri): Remove if block when support for QUIC ver. < 10 removed.
- if (version() < QUIC_VERSION_10) {
- type_byte = 0x01;
- } else {
- type_byte = kQuicFrameTypeAckMask;
- }
+ type_byte |= kQuicFrameTypeStreamMask; // Set Stream Frame Type to 1.
break;
}
+ case ACK_FRAME:
+ return true;
case CONGESTION_FEEDBACK_FRAME: {
// TODO(ianswett): Use extra 5 bits in the congestion feedback framing.
- // TODO(jri): Remove if block when support for QUIC ver. < 10 removed.
- if (version() < QUIC_VERSION_10) {
- type_byte = 0x03;
- } else {
- type_byte = kQuicFrameTypeCongestionFeedbackMask;
- }
+ type_byte = kQuicFrameTypeCongestionFeedbackMask;
break;
}
default:
type_byte = frame.type;
- // TODO(jri): Remove if block when support for QUIC ver. < 10 removed.
- if (version() < QUIC_VERSION_10) {
- if (type_byte > 0) {
- type_byte += 3;
- }
- type_byte = (type_byte << kQuicDefaultFrameTypeShift) |
- kQuicDefaultFrameTypeMask;
- }
break;
}
@@ -1801,16 +1757,24 @@ bool QuicFramer::AppendStreamFramePayload(
return false;
}
if (!last_frame_in_packet) {
- if (!writer->WriteUInt16(frame.data.size())) {
+ if (!writer->WriteUInt16(frame.data.TotalBufferSize())) {
return false;
}
}
- if (!writer->WriteBytes(frame.data.data(), frame.data.size())) {
+
+ if (!writer->WriteIOVector(frame.data)) {
return false;
}
return true;
}
+// static
+bool QuicFramer::HasVersionFlag(const QuicEncryptedPacket& packet) {
+ return packet.length() > 0 &&
+ (packet.data()[0] & PACKET_PUBLIC_FLAGS_VERSION) != 0;
+}
+
+// static
QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved(
const SequenceNumberSet& missing_packets,
SequenceNumberSet::const_iterator largest_written) {
@@ -1828,77 +1792,143 @@ QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved(
return *largest_written;
}
-// TODO(ianswett): Use varints or another more compact approach for all deltas.
-bool QuicFramer::AppendAckFramePayload(
+void QuicFramer::set_version(const QuicVersion version) {
+ DCHECK(IsSupportedVersion(version));
+ quic_version_ = version;
+}
+
+bool QuicFramer::AppendAckFramePayloadAndTypeByte(
+ const QuicPacketHeader& header,
const QuicAckFrame& frame,
QuicDataWriter* writer) {
+ AckFrameInfo ack_info = GetAckFrameInfo(frame);
+ QuicPacketSequenceNumber ack_largest_observed =
+ frame.received_info.largest_observed;
+ QuicSequenceNumberLength largest_observed_length =
+ GetMinSequenceNumberLength(ack_largest_observed);
+ QuicSequenceNumberLength missing_sequence_number_length =
+ GetMinSequenceNumberLength(ack_info.max_delta);
+ // Determine whether we need to truncate ranges.
+ size_t available_range_bytes = writer->capacity() - writer->length() -
+ GetMinAckFrameSize(quic_version_,
+ header.public_header.sequence_number_length,
+ largest_observed_length);
+ size_t max_num_ranges = available_range_bytes /
+ (missing_sequence_number_length + PACKET_1BYTE_SEQUENCE_NUMBER);
+ max_num_ranges =
+ min(static_cast<size_t>(numeric_limits<uint8>::max()), max_num_ranges);
+ bool truncated = ack_info.nack_ranges.size() > max_num_ranges;
+ DVLOG_IF(1, truncated) << "Truncating ack from "
+ << ack_info.nack_ranges.size() << " ranges to "
+ << max_num_ranges;
+
+ // Write out the type byte by setting the low order bits and doing shifts
+ // to make room for the next bit flags to be set.
+ // Whether there are any nacks.
+ uint8 type_byte = ack_info.nack_ranges.empty() ? 0 : kQuicHasNacksMask;
+
+ // truncating bit.
+ type_byte <<= kQuicAckTruncatedShift;
+ type_byte |= truncated ? kQuicAckTruncatedMask : 0;
+
+ // Largest observed sequence number length.
+ type_byte <<= kQuicSequenceNumberLengthShift;
+ type_byte |= GetSequenceNumberFlags(largest_observed_length);
+
+ // Missing sequence number length.
+ type_byte <<= kQuicSequenceNumberLengthShift;
+ type_byte |= GetSequenceNumberFlags(missing_sequence_number_length);
+
+ type_byte |= kQuicFrameTypeAckMask;
+
+ if (!writer->WriteUInt8(type_byte)) {
+ return false;
+ }
+
// TODO(satyamshekhar): Decide how often we really should send this
// entropy_hash update.
if (!writer->WriteUInt8(frame.sent_info.entropy_hash)) {
return false;
}
- if (!AppendPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER,
- frame.sent_info.least_unacked, writer)) {
+ DCHECK_GE(header.packet_sequence_number, frame.sent_info.least_unacked);
+ const QuicPacketSequenceNumber least_unacked_delta =
+ header.packet_sequence_number - frame.sent_info.least_unacked;
+ if (!AppendPacketSequenceNumber(header.public_header.sequence_number_length,
+ least_unacked_delta, writer)) {
return false;
}
- size_t received_entropy_offset = writer->length();
- if (!writer->WriteUInt8(frame.received_info.entropy_hash)) {
+ const ReceivedPacketInfo& received_info = frame.received_info;
+ QuicPacketEntropyHash ack_entropy_hash = received_info.entropy_hash;
+ NackRangeMap::reverse_iterator ack_iter = ack_info.nack_ranges.rbegin();
+ if (truncated) {
+ // Skip the nack ranges which the truncated ack won't include and set
+ // a correct largest observed for the truncated ack.
+ for (size_t i = 1; i < (ack_info.nack_ranges.size() - max_num_ranges);
+ ++i) {
+ ++ack_iter;
+ }
+ // If the last range is followed by acks, include them.
+ // If the last range is followed by another range, specify the end of the
+ // range as the largest_observed.
+ ack_largest_observed = ack_iter->first - 1;
+ // Also update the entropy so it matches the largest observed.
+ ack_entropy_hash = entropy_calculator_->EntropyHash(ack_largest_observed);
+ ++ack_iter;
+ }
+
+ if (!writer->WriteUInt8(ack_entropy_hash)) {
return false;
}
- size_t largest_observed_offset = writer->length();
- if (!AppendPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER,
- frame.received_info.largest_observed,
- writer)) {
+ if (!AppendPacketSequenceNumber(largest_observed_length,
+ ack_largest_observed, writer)) {
return false;
}
- uint32 delta_time_largest_observed_us = kInvalidDeltaTime;
- if (!frame.received_info.delta_time_largest_observed.IsInfinite()) {
+
+ uint64 delta_time_largest_observed_us = kUFloat16MaxValue;
+ if (!received_info.delta_time_largest_observed.IsInfinite()) {
+ DCHECK_LE(0u,
+ frame.received_info.delta_time_largest_observed.ToMicroseconds());
delta_time_largest_observed_us =
- frame.received_info.delta_time_largest_observed.ToMicroseconds();
+ received_info.delta_time_largest_observed.ToMicroseconds();
}
- size_t delta_time_largest_observed_offset = writer->length();
- if (!writer->WriteUInt32(delta_time_largest_observed_us)) {
+ if (!writer->WriteUFloat16(delta_time_largest_observed_us)) {
return false;
}
- // We don't check for overflowing uint8 here, because we only can fit 192 acks
- // per packet, so if we overflow we will be truncated.
- uint8 num_missing_packets = frame.received_info.missing_packets.size();
- size_t num_missing_packets_offset = writer->length();
- if (!writer->WriteBytes(&num_missing_packets, 1)) {
+ if (ack_info.nack_ranges.empty()) {
+ return true;
+ }
+
+ const uint8 num_missing_ranges =
+ min(ack_info.nack_ranges.size(), max_num_ranges);
+ if (!writer->WriteBytes(&num_missing_ranges, 1)) {
return false;
}
- SequenceNumberSet::const_iterator it =
- frame.received_info.missing_packets.begin();
- int num_missing_packets_written = 0;
- for (; it != frame.received_info.missing_packets.end(); ++it) {
- if (!AppendPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER,
- *it, writer)) {
- // We are truncating.
- QuicPacketSequenceNumber largest_observed =
- CalculateLargestObserved(frame.received_info.missing_packets, --it);
- // Overwrite entropy hash for received packets.
- writer->WriteUInt8ToOffset(
- entropy_calculator_->EntropyHash(largest_observed),
- received_entropy_offset);
- // Overwrite largest_observed.
- writer->WriteUInt48ToOffset(largest_observed & k6ByteSequenceNumberMask,
- largest_observed_offset);
- writer->WriteUInt32ToOffset(kInvalidDeltaTime,
- delta_time_largest_observed_offset);
- writer->WriteUInt8ToOffset(num_missing_packets_written,
- num_missing_packets_offset);
- return true;
+ int num_ranges_written = 0;
+ QuicPacketSequenceNumber last_sequence_written = ack_largest_observed;
+ for (; ack_iter != ack_info.nack_ranges.rend(); ++ack_iter) {
+ // Calculate the delta to the last number in the range.
+ QuicPacketSequenceNumber missing_delta =
+ last_sequence_written - (ack_iter->first + ack_iter->second);
+ if (!AppendPacketSequenceNumber(missing_sequence_number_length,
+ missing_delta, writer)) {
+ return false;
+ }
+ if (!AppendPacketSequenceNumber(PACKET_1BYTE_SEQUENCE_NUMBER,
+ ack_iter->second, writer)) {
+ return false;
}
- ++num_missing_packets_written;
- DCHECK_GE(numeric_limits<uint8>::max(), num_missing_packets_written);
+ // Subtract 1 so a missing_delta of 0 means an adjacent range.
+ last_sequence_written = ack_iter->first - 1;
+ ++num_ranges_written;
}
+ DCHECK_EQ(num_missing_ranges, num_ranges_written);
return true;
}
@@ -2020,7 +2050,6 @@ bool QuicFramer::AppendConnectionCloseFramePayload(
if (!writer->WriteStringPiece16(frame.error_details)) {
return false;
}
- AppendAckFramePayload(frame.ack_frame, writer);
return true;
}
@@ -2041,7 +2070,7 @@ bool QuicFramer::AppendGoAwayFramePayload(const QuicGoAwayFrame& frame,
}
bool QuicFramer::RaiseError(QuicErrorCode error) {
- DLOG(INFO) << detailed_error_;
+ DVLOG(1) << detailed_error_;
set_error(error);
visitor_->OnError(this);
reader_.reset(NULL);
diff --git a/chromium/net/quic/quic_framer.h b/chromium/net/quic/quic_framer.h
index 841172698df..132375200be 100644
--- a/chromium/net/quic/quic_framer.h
+++ b/chromium/net/quic/quic_framer.h
@@ -44,7 +44,7 @@ const size_t kQuicStreamPayloadLengthSize = 2;
const size_t kQuicEntropyHashSize = 1;
// Size in bytes reserved for the delta time of the largest observed
// sequence number in ack frames.
-const size_t kQuicDeltaTimeLargestObservedSize = 4;
+const size_t kQuicDeltaTimeLargestObservedSize = 2;
// Size in bytes reserved for the number of missing packets in ack frames.
const size_t kNumberOfMissingPacketsSize = 1;
@@ -82,6 +82,11 @@ class NET_EXPORT_PRIVATE QuicFramerVisitorInterface {
// before it has been processed.
virtual void OnRevivedPacket() = 0;
+ // Called when the unauthenticated portion of the header has been parsed.
+ // If OnUnauthenticatedHeader returns false, framing for this packet will
+ // cease.
+ virtual bool OnUnauthenticatedHeader(const QuicPacketHeader& header) = 0;
+
// Called when the complete header of a packet had been parsed.
// If OnPacketHeader returns false, framing for this packet will cease.
virtual bool OnPacketHeader(const QuicPacketHeader& header) = 0;
@@ -150,8 +155,10 @@ class NET_EXPORT_PRIVATE QuicReceivedEntropyHashCalculatorInterface {
class NET_EXPORT_PRIVATE QuicFramer {
public:
// Constructs a new framer that installs a kNULL QuicEncrypter and
- // QuicDecrypter for level ENCRYPTION_NONE.
- QuicFramer(QuicVersion quic_version,
+ // QuicDecrypter for level ENCRYPTION_NONE. |supported_versions| specifies the
+ // list of supported QUIC versions. |quic_version_| is set to the maximum
+ // version in |supported_versions|.
+ QuicFramer(const QuicVersionVector& supported_versions,
QuicTime creation_time,
bool is_server);
@@ -160,6 +167,9 @@ class NET_EXPORT_PRIVATE QuicFramer {
// Returns true if |version| is a supported protocol version.
bool IsSupportedVersion(const QuicVersion version) const;
+ // Returns true if the version flag is set in the public flags.
+ static bool HasVersionFlag(const QuicEncryptedPacket& packet);
+
// Calculates the largest observed packet to advertise in the case an Ack
// Frame was truncated. last_written in this case is the iterator for the
// last missing packet which fit in the outgoing ack.
@@ -182,14 +192,15 @@ class NET_EXPORT_PRIVATE QuicFramer {
fec_builder_ = builder;
}
+ const QuicVersionVector& supported_versions() const {
+ return supported_versions_;
+ }
+
QuicVersion version() const {
return quic_version_;
}
- void set_version(const QuicVersion version) {
- DCHECK(IsSupportedVersion(version));
- quic_version_ = version;
- }
+ void set_version(const QuicVersion version);
// Does not DCHECK for supported version. Used by tests to set unsupported
// version to trigger version negotiation.
@@ -230,7 +241,10 @@ class NET_EXPORT_PRIVATE QuicFramer {
QuicStreamOffset offset,
bool last_frame_in_packet);
// Size in bytes of all ack frame fields without the missing packets.
- static size_t GetMinAckFrameSize();
+ static size_t GetMinAckFrameSize(
+ QuicVersion version,
+ QuicSequenceNumberLength sequence_number_length,
+ QuicSequenceNumberLength largest_observed_length);
// Size in bytes of all reset stream frame without the error details.
static size_t GetMinRstStreamFrameSize();
// Size in bytes of all connection close frame fields without the error
@@ -239,7 +253,7 @@ class NET_EXPORT_PRIVATE QuicFramer {
// Size in bytes of all GoAway frame fields without the reason phrase.
static size_t GetMinGoAwayFrameSize();
// The maximum number of nacks which can be transmitted in a single ack packet
- // without exceeding kMaxPacketSize.
+ // without exceeding kDefaultMaxPacketSize.
static size_t GetMaxUnackedPackets(QuicPacketHeader header);
// Size in bytes required to serialize the stream id.
static size_t GetStreamIdSize(QuicStreamId stream_id);
@@ -249,13 +263,18 @@ class NET_EXPORT_PRIVATE QuicFramer {
static size_t GetVersionNegotiationPacketSize(size_t number_versions);
- static bool CanTruncate(const QuicFrame& frame, size_t free_bytes);
+ static bool CanTruncate(
+ QuicVersion version, const QuicFrame& frame, size_t free_bytes);
// Returns the number of bytes added to the packet for the specified frame,
// and 0 if the frame doesn't fit. Includes the header size for the first
// frame.
size_t GetSerializedFrameLength(
- const QuicFrame& frame, size_t free_bytes, bool first_frame);
+ const QuicFrame& frame,
+ size_t free_bytes,
+ bool first_frame,
+ bool last_frame,
+ QuicSequenceNumberLength sequence_number_length);
// Returns the associated data from the encrypted packet |encrypted| as a
// stringpiece.
@@ -336,9 +355,27 @@ class NET_EXPORT_PRIVATE QuicFramer {
static bool ReadGuidFromPacket(const QuicEncryptedPacket& packet,
QuicGuid* guid);
+ static QuicSequenceNumberLength ReadSequenceNumberLength(uint8 flags);
+
+ // The minimum sequence number length required to represent |sequence_number|.
+ static QuicSequenceNumberLength GetMinSequenceNumberLength(
+ QuicPacketSequenceNumber sequence_number);
+
private:
friend class test::QuicFramerPeer;
+ typedef std::map<QuicPacketSequenceNumber, uint8> NackRangeMap;
+
+ struct AckFrameInfo {
+ AckFrameInfo();
+ ~AckFrameInfo();
+
+ // The maximum delta between ranges.
+ QuicPacketSequenceNumber max_delta;
+ // Nack ranges starting with start sequence numbers and lengths.
+ NackRangeMap nack_ranges;
+ };
+
QuicPacketEntropyHash GetPacketEntropyHash(
const QuicPacketHeader& header) const;
@@ -349,9 +386,6 @@ class NET_EXPORT_PRIVATE QuicFramer {
bool ProcessVersionNegotiationPacket(QuicPacketPublicHeader* public_header);
- bool WritePacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* writer);
-
bool ProcessPublicHeader(QuicPacketPublicHeader* header);
bool ProcessPacketHeader(QuicPacketHeader* header,
@@ -360,11 +394,14 @@ class NET_EXPORT_PRIVATE QuicFramer {
bool ProcessPacketSequenceNumber(
QuicSequenceNumberLength sequence_number_length,
QuicPacketSequenceNumber* sequence_number);
- bool ProcessFrameData();
+ bool ProcessFrameData(const QuicPacketHeader& header);
bool ProcessStreamFrame(uint8 frame_type, QuicStreamFrame* frame);
- bool ProcessAckFrame(QuicAckFrame* frame);
- bool ProcessReceivedInfo(ReceivedPacketInfo* received_info);
- bool ProcessSentInfo(SentPacketInfo* sent_info);
+ bool ProcessAckFrame(const QuicPacketHeader& header,
+ uint8 frame_type,
+ QuicAckFrame* frame);
+ bool ProcessReceivedInfo(uint8 frame_type, ReceivedPacketInfo* received_info);
+ bool ProcessSentInfo(const QuicPacketHeader& public_header,
+ SentPacketInfo* sent_info);
bool ProcessQuicCongestionFeedbackFrame(
QuicCongestionFeedbackFrame* congestion_feedback);
bool ProcessRstStreamFrame(QuicRstStreamFrame* frame);
@@ -380,22 +417,36 @@ class NET_EXPORT_PRIVATE QuicFramer {
QuicSequenceNumberLength sequence_number_length,
QuicPacketSequenceNumber packet_sequence_number) const;
+ // Computes the wire size in bytes of the |ack| frame, assuming no truncation.
+ size_t GetAckFrameSize(const QuicAckFrame& ack,
+ QuicSequenceNumberLength sequence_number_length);
+
// Computes the wire size in bytes of the payload of |frame|.
- size_t ComputeFrameLength(const QuicFrame& frame, bool last_frame_in_packet);
+ size_t ComputeFrameLength(const QuicFrame& frame,
+ bool last_frame_in_packet,
+ QuicSequenceNumberLength sequence_number_length);
static bool AppendPacketSequenceNumber(
QuicSequenceNumberLength sequence_number_length,
QuicPacketSequenceNumber packet_sequence_number,
QuicDataWriter* writer);
+ static uint8 GetSequenceNumberFlags(
+ QuicSequenceNumberLength sequence_number_length);
+
+ static AckFrameInfo GetAckFrameInfo(const QuicAckFrame& frame);
+
+ bool AppendPacketHeader(const QuicPacketHeader& header,
+ QuicDataWriter* writer);
bool AppendTypeByte(const QuicFrame& frame,
bool last_frame_in_packet,
QuicDataWriter* writer);
bool AppendStreamFramePayload(const QuicStreamFrame& frame,
bool last_frame_in_packet,
QuicDataWriter* builder);
- bool AppendAckFramePayload(const QuicAckFrame& frame,
- QuicDataWriter* builder);
+ bool AppendAckFramePayloadAndTypeByte(const QuicPacketHeader& header,
+ const QuicAckFrame& frame,
+ QuicDataWriter* builder);
bool AppendQuicCongestionFeedbackFramePayload(
const QuicCongestionFeedbackFrame& frame,
QuicDataWriter* builder);
@@ -430,6 +481,11 @@ class NET_EXPORT_PRIVATE QuicFramer {
scoped_ptr<QuicData> decrypted_;
// Version of the protocol being used.
QuicVersion quic_version_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary).
+ QuicVersionVector supported_versions_;
// Primary decrypter used to decrypt packets during parsing.
scoped_ptr<QuicDecrypter> decrypter_;
// Alternative decrypter that can also be used to decrypt packets.
diff --git a/chromium/net/quic/quic_framer_test.cc b/chromium/net/quic/quic_framer_test.cc
index b3bdbac35f4..eef4a5894c1 100644
--- a/chromium/net/quic/quic_framer_test.cc
+++ b/chromium/net/quic/quic_framer_test.cc
@@ -25,6 +25,7 @@ using base::StringPiece;
using std::make_pair;
using std::map;
using std::numeric_limits;
+using std::pair;
using std::string;
using std::vector;
using testing::Return;
@@ -231,6 +232,11 @@ class TestQuicVisitor : public ::net::QuicFramerVisitorInterface {
return accept_packet_;
}
+ virtual bool OnUnauthenticatedHeader(
+ const QuicPacketHeader& header) OVERRIDE {
+ return true;
+ }
+
virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE {
frame_count_++;
stream_frames_.push_back(new QuicStreamFrame(frame));
@@ -309,14 +315,13 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
: encrypter_(new test::TestEncrypter()),
decrypter_(new test::TestDecrypter()),
start_(QuicTime::Zero().Add(QuicTime::Delta::FromMicroseconds(0x10))),
- framer_(QuicVersionMax(), start_, true) {
+ framer_(QuicSupportedVersions(), start_, true) {
+ version_ = GetParam();
+ framer_.set_version(version_);
framer_.SetDecrypter(decrypter_);
framer_.SetEncrypter(ENCRYPTION_NONE, encrypter_);
framer_.set_visitor(&visitor_);
framer_.set_received_entropy_calculator(&entropy_calculator_);
-
- version_ = GetParam();
- framer_.set_version(version_);
}
// Helper function to get unsigned char representation of digit in the
@@ -400,6 +405,12 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> {
EXPECT_EQ(error_code, framer_.error()) << "len: " << len;
}
+ // Checks if the supplied string matches data in the supplied StreamFrame.
+ void CheckStreamFrameData(string str, QuicStreamFrame* frame) {
+ scoped_ptr<string> frame_data(frame->GetDataAsString());
+ EXPECT_EQ(str, *frame_data);
+ }
+
void CheckStreamFrameBoundaries(unsigned char* packet,
size_t stream_id_size,
bool include_version) {
@@ -1039,8 +1050,7 @@ TEST_P(QuicFramerTest, InvalidPublicFlag) {
0x00,
// frame type (padding)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
CheckProcessingFails(packet,
@@ -1065,8 +1075,7 @@ TEST_P(QuicFramerTest, InvalidPublicFlagWithMatchingVersions) {
0x00,
// frame type (padding)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
CheckProcessingFails(packet,
@@ -1091,8 +1100,7 @@ TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
0x00,
// frame type (padding frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
@@ -1117,8 +1125,7 @@ TEST_P(QuicFramerTest, InvalidPrivateFlag) {
0x10,
// frame type (padding)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
CheckProcessingFails(packet,
@@ -1163,12 +1170,10 @@ TEST_P(QuicFramerTest, PaddingFrame) {
0x00,
// frame type (padding frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
// Ignored data (which in this case is a stream frame)
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -1212,8 +1217,7 @@ TEST_P(QuicFramerTest, StreamFrame) {
0x00,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -1241,7 +1245,7 @@ TEST_P(QuicFramerTest, StreamFrame) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
// Now test framing boundaries
CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, !kIncludeVersion);
@@ -1261,8 +1265,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
0x00,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFC : 0xFE),
+ 0xFE,
// stream id
0x04, 0x03, 0x02,
// offset
@@ -1290,7 +1293,7 @@ TEST_P(QuicFramerTest, StreamFrame3ByteStreamId) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
// Now test framing boundaries
const size_t stream_id_size = 3;
@@ -1311,8 +1314,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
0x00,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFA : 0xFD),
+ 0xFD,
// stream id
0x04, 0x03,
// offset
@@ -1340,7 +1342,7 @@ TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
// Now test framing boundaries
const size_t stream_id_size = 2;
@@ -1361,8 +1363,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
0x00,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xF8 : 0xFC),
+ 0xFC,
// stream id
0x04,
// offset
@@ -1390,7 +1391,7 @@ TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
// Now test framing boundaries
const size_t stream_id_size = 1;
@@ -1413,8 +1414,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
0x00,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -1444,7 +1444,7 @@ TEST_P(QuicFramerTest, StreamFrameWithVersion) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
// Now test framing boundaries
CheckStreamFrameBoundaries(packet, kQuicMaxStreamIdSize, kIncludeVersion);
@@ -1466,8 +1466,7 @@ TEST_P(QuicFramerTest, RejectPacket) {
0x00,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -1495,8 +1494,7 @@ TEST_P(QuicFramerTest, RejectPacket) {
TEST_P(QuicFramerTest, RevivedStreamFrame) {
unsigned char payload[] = {
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -1546,7 +1544,7 @@ TEST_P(QuicFramerTest, RevivedStreamFrame) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
}
TEST_P(QuicFramerTest, StreamFrameInFecGroup) {
@@ -1565,8 +1563,7 @@ TEST_P(QuicFramerTest, StreamFrameInFecGroup) {
0x02,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -1601,7 +1598,7 @@ TEST_P(QuicFramerTest, StreamFrameInFecGroup) {
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(GG_UINT64_C(0xBA98FEDC32107654),
visitor_.stream_frames_[0]->offset);
- EXPECT_EQ("hello world!", visitor_.stream_frames_[0]->data);
+ CheckStreamFrameData("hello world!", visitor_.stream_frames_[0]);
}
TEST_P(QuicFramerTest, AckFrame) {
@@ -1612,31 +1609,32 @@ TEST_P(QuicFramerTest, AckFrame) {
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
// packet sequence number
- 0xBC, 0x9A, 0x78, 0x56,
+ 0xA8, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // private flags
- 0x00,
+ // private flags (entropy)
+ 0x01,
// frame type (ack frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x01 : 0x40),
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
// entropy hash of sent packets till least awaiting - 1.
0xAB,
- // least packet sequence number awaiting an ack
- 0xA0, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ // least packet sequence number awaiting an ack, delta from sequence number.
+ 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
// entropy hash of all received packets.
0xBA,
// largest observed packet sequence number
0xBF, 0x9A, 0x78, 0x56,
0x34, 0x12,
- // Infinite delta time.
- 0xFF, 0xFF, 0xFF, 0xFF,
+ // Zero delta time.
+ 0x0, 0x0,
// num missing packets
0x01,
- // missing packet
- 0xBE, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
};
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
@@ -1670,15 +1668,17 @@ TEST_P(QuicFramerTest, AckFrame) {
kQuicDeltaTimeLargestObservedSize;
const size_t kMissingPacketsOffset = kNumMissingPacketOffset +
kNumberOfMissingPacketsSize;
+ const size_t kMissingPacketsRange = kMissingPacketsOffset +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
// Now test framing boundaries
- const size_t missing_packets_size = 1 * PACKET_6BYTE_SEQUENCE_NUMBER;
- for (size_t i = kQuicFrameTypeSize;
- i < QuicFramer::GetMinAckFrameSize() + missing_packets_size; ++i) {
+ const size_t ack_frame_size = kMissingPacketsRange +
+ PACKET_1BYTE_SEQUENCE_NUMBER;
+ for (size_t i = kQuicFrameTypeSize; i < ack_frame_size; ++i) {
string expected_error;
if (i < kLeastUnackedOffset) {
expected_error = "Unable to read entropy hash for sent packets.";
} else if (i < kReceivedEntropyOffset) {
- expected_error = "Unable to read least unacked.";
+ expected_error = "Unable to read least unacked delta.";
} else if (i < kLargestObservedOffset) {
expected_error = "Unable to read entropy hash for received packets.";
} else if (i < kMissingDeltaTimeOffset) {
@@ -1686,9 +1686,11 @@ TEST_P(QuicFramerTest, AckFrame) {
} else if (i < kNumMissingPacketOffset) {
expected_error = "Unable to read delta time largest observed.";
} else if (i < kMissingPacketsOffset) {
- expected_error = "Unable to read num missing packets.";
+ expected_error = "Unable to read num missing packet ranges.";
+ } else if (i < kMissingPacketsRange) {
+ expected_error = "Unable to read missing sequence number delta.";
} else {
- expected_error = "Unable to read sequence number in missing packets.";
+ expected_error = "Unable to read missing sequence number range.";
}
CheckProcessingFails(
packet,
@@ -1698,6 +1700,141 @@ TEST_P(QuicFramerTest, AckFrame) {
}
}
+TEST_P(QuicFramerTest, AckFrameNoNacks) {
+ unsigned char packet[] = {
+ // public flags (8 byte guid)
+ 0x3C,
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence number
+ 0xA8, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // private flags (entropy)
+ 0x01,
+
+ // frame type (ack frame)
+ // (no nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x4C,
+ // entropy hash of sent packets till least awaiting - 1.
+ 0xAB,
+ // least packet sequence number awaiting an ack, delta from sequence number.
+ 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ };
+
+ 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());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame* frame = visitor_.ack_frames_[0];
+ EXPECT_EQ(0xAB, frame->sent_info.entropy_hash);
+ EXPECT_EQ(0xBA, frame->received_info.entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF),
+ frame->received_info.largest_observed);
+ ASSERT_EQ(0u, frame->received_info.missing_packets.size());
+ EXPECT_EQ(GG_UINT64_C(0x0123456789AA0), frame->sent_info.least_unacked);
+
+ // Verify that the packet re-serializes identically.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame));
+ scoped_ptr<QuicPacket> data(
+ framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+ ASSERT_TRUE(data != NULL);
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
+TEST_P(QuicFramerTest, AckFrame500Nacks) {
+ unsigned char packet[] = {
+ // public flags (8 byte guid)
+ 0x3C,
+ // guid
+ 0x10, 0x32, 0x54, 0x76,
+ 0x98, 0xBA, 0xDC, 0xFE,
+ // packet sequence 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 sent packets till least awaiting - 1.
+ 0xAB,
+ // least packet sequence number awaiting an ack, delta from sequence number.
+ 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+ // entropy hash of all received packets.
+ 0xBA,
+ // largest observed packet sequence number
+ 0xBF, 0x9A, 0x78, 0x56,
+ 0x34, 0x12,
+ // Zero delta time.
+ 0x0, 0x0,
+ // 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,
+ };
+
+ 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());
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ QuicAckFrame* frame = visitor_.ack_frames_[0];
+ EXPECT_EQ(0xAB, frame->sent_info.entropy_hash);
+ EXPECT_EQ(0xBA, frame->received_info.entropy_hash);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABF),
+ frame->received_info.largest_observed);
+ ASSERT_EQ(500u, frame->received_info.missing_packets.size());
+ SequenceNumberSet::const_iterator first_missing_iter =
+ frame->received_info.missing_packets.begin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE) - 499, *first_missing_iter);
+ SequenceNumberSet::const_reverse_iterator last_missing_iter =
+ frame->received_info.missing_packets.rbegin();
+ EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *last_missing_iter);
+ EXPECT_EQ(GG_UINT64_C(0x0123456789AA0), frame->sent_info.least_unacked);
+
+ // Verify that the packet re-serializes identically.
+ QuicFrames frames;
+ frames.push_back(QuicFrame(frame));
+ scoped_ptr<QuicPacket> data(
+ framer_.BuildUnsizedDataPacket(*visitor_.header_, frames).packet);
+ ASSERT_TRUE(data != NULL);
+
+ test::CompareCharArraysWithHexError("constructed packet",
+ data->data(), data->length(),
+ AsChars(packet), arraysize(packet));
+}
+
TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) {
unsigned char packet[] = {
// public flags (8 byte guid)
@@ -1712,8 +1849,7 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameTCP) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (tcp)
0x00,
// ack_frame.feedback.tcp.accumulated_number_of_lost_packets
@@ -1770,8 +1906,7 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInterArrival) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (inter arrival)
0x01,
// accumulated_number_of_lost_packets
@@ -1867,8 +2002,7 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameFixRate) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (fix rate)
0x02,
// bitrate_in_bytes_per_second;
@@ -1920,8 +2054,7 @@ TEST_P(QuicFramerTest, CongestionFeedbackFrameInvalidFeedback) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (invalid)
0x03,
};
@@ -1946,8 +2079,7 @@ TEST_P(QuicFramerTest, RstStreamFrame) {
0x00,
// frame type (rst stream frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x27 : 0x01),
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// error code
@@ -2006,8 +2138,7 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
0x00,
// frame type (connection close frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x2F : 0x02),
+ 0x02,
// error code
0x11, 0x00, 0x00, 0x00,
@@ -2018,25 +2149,6 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
'u', 's', 'e', ' ',
'I', ' ', 'c', 'a',
'n',
-
- // Ack frame.
- // entropy hash of sent packets till least awaiting - 1.
- 0xBF,
- // least packet sequence number awaiting an ack
- 0xA0, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // entropy hash of all received packets.
- 0xEB,
- // largest observed packet sequence number
- 0xBF, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // Infinite delta time.
- 0xFF, 0xFF, 0xFF, 0xFF,
- // num missing packets
- 0x01,
- // missing packet
- 0xBE, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
};
QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
@@ -2051,21 +2163,11 @@ TEST_P(QuicFramerTest, ConnectionCloseFrame) {
EXPECT_EQ(0x11, visitor_.connection_close_frame_.error_code);
EXPECT_EQ("because I can", visitor_.connection_close_frame_.error_details);
- ASSERT_EQ(1u, visitor_.ack_frames_.size());
- const QuicAckFrame& frame = *visitor_.ack_frames_[0];
- EXPECT_EQ(0xBF, frame.sent_info.entropy_hash);
- EXPECT_EQ(GG_UINT64_C(0x0123456789AA0), frame.sent_info.least_unacked);
- EXPECT_EQ(0xEB, frame.received_info.entropy_hash);
- EXPECT_EQ(GG_UINT64_C(0x0123456789ABF), frame.received_info.largest_observed);
- ASSERT_EQ(1u, frame.received_info.missing_packets.size());
- SequenceNumberSet::const_iterator missing_iter =
- frame.received_info.missing_packets.begin();
- EXPECT_EQ(GG_UINT64_C(0x0123456789ABE), *missing_iter);
+ ASSERT_EQ(0u, visitor_.ack_frames_.size());
// Now test framing boundaries
for (size_t i = kQuicFrameTypeSize;
- i < QuicFramer::GetMinConnectionCloseFrameSize() -
- QuicFramer::GetMinAckFrameSize(); ++i) {
+ i < QuicFramer::GetMinConnectionCloseFrameSize(); ++i) {
string expected_error;
if (i < kQuicFrameTypeSize + kQuicErrorCodeSize) {
expected_error = "Unable to read connection close error code.";
@@ -2094,8 +2196,7 @@ TEST_P(QuicFramerTest, GoAwayFrame) {
0x00,
// frame type (go away frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x37 : 0x03),
+ 0x03,
// error code
0x09, 0x00, 0x00, 0x00,
// stream id
@@ -2295,8 +2396,7 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
0x00,
// frame type (padding frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
@@ -2311,7 +2411,8 @@ TEST_P(QuicFramerTest, BuildPaddingFramePacket) {
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
@@ -2342,8 +2443,7 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
0x00,
// frame type (padding frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
@@ -2358,7 +2458,8 @@ TEST_P(QuicFramerTest, Build4ByteSequenceNumberPaddingFramePacket) {
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
@@ -2389,8 +2490,7 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
0x00,
// frame type (padding frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
@@ -2405,7 +2505,8 @@ TEST_P(QuicFramerTest, Build2ByteSequenceNumberPaddingFramePacket) {
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
@@ -2436,8 +2537,7 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
0x00,
// frame type (padding frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x07 : 0x00),
+ 0x00,
0x00, 0x00, 0x00, 0x00
};
@@ -2452,7 +2552,8 @@ TEST_P(QuicFramerTest, Build1ByteSequenceNumberPaddingFramePacket) {
test::CompareCharArraysWithHexError("constructed packet",
data->data(), data->length(),
- AsChars(packet), arraysize(packet));
+ AsChars(packet),
+ arraysize(packet));
}
TEST_P(QuicFramerTest, BuildStreamFramePacket) {
@@ -2469,7 +2570,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
stream_frame.stream_id = 0x01020304;
stream_frame.fin = true;
stream_frame.offset = GG_UINT64_C(0xBA98FEDC32107654);
- stream_frame.data = "hello world!";
+ stream_frame.data = MakeIOVector("hello world!");
QuicFrames frames;
frames.push_back(QuicFrame(&stream_frame));
@@ -2487,8 +2588,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacket) {
0x01,
// frame type (stream frame with fin and no length)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xBE : 0xDF),
+ 0xDF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -2523,7 +2623,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
stream_frame.stream_id = 0x01020304;
stream_frame.fin = true;
stream_frame.offset = GG_UINT64_C(0xBA98FEDC32107654);
- stream_frame.data = "hello world!";
+ stream_frame.data = MakeIOVector("hello world!");
QuicFrames frames;
frames.push_back(QuicFrame(&stream_frame));
@@ -2543,8 +2643,7 @@ TEST_P(QuicFramerTest, BuildStreamFramePacketWithVersionFlag) {
0x01,
// frame type (stream frame with fin and no length)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xBE : 0xDF),
+ 0xDF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -2599,7 +2698,7 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) {
header.public_header.version_flag = false;
header.fec_flag = false;
header.entropy_flag = true;
- header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
+ header.packet_sequence_number = GG_UINT64_C(0x770123456789AA8);
header.fec_group = 0;
QuicAckFrame ack_frame;
@@ -2621,31 +2720,32 @@ TEST_P(QuicFramerTest, BuildAckFramePacket) {
0x10, 0x32, 0x54, 0x76,
0x98, 0xBA, 0xDC, 0xFE,
// packet sequence number
- 0xBC, 0x9A, 0x78, 0x56,
+ 0xA8, 0x9A, 0x78, 0x56,
0x34, 0x12,
// private flags (entropy)
0x01,
// frame type (ack frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x01 : 0x40),
+ // (has nacks, not truncated, 6 byte largest observed, 1 byte delta)
+ 0x6C,
// entropy hash of sent packets till least awaiting - 1.
0x14,
- // least packet sequence number awaiting an ack
- 0xA0, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ // least packet sequence number awaiting an ack, delta from sequence number.
+ 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
// entropy hash of all received packets.
0x43,
// largest observed packet sequence number
0xBF, 0x9A, 0x78, 0x56,
0x34, 0x12,
// Zero delta time.
- 0x0, 0x0, 0x0, 0x0,
- // num missing packets
+ 0x0, 0x0,
+ // num missing packet ranges
0x01,
- // missing packet
- 0xBE, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
+ // missing packet delta
+ 0x01,
+ // 0 more missing packets in range.
+ 0x00,
};
scoped_ptr<QuicPacket> data(
@@ -2688,8 +2788,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketTCP) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (TCP)
0x00,
// accumulated number of lost packets
@@ -2748,8 +2847,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketInterArrival) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (inter arrival)
0x01,
// accumulated_number_of_lost_packets
@@ -2812,8 +2910,7 @@ TEST_P(QuicFramerTest, BuildCongestionFeedbackFramePacketFixRate) {
0x00,
// frame type (congestion feedback frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x03 : 0x20),
+ 0x20,
// congestion feedback type (fix rate)
0x02,
// bitrate_in_bytes_per_second;
@@ -2879,8 +2976,7 @@ TEST_P(QuicFramerTest, BuildRstFramePacket) {
0x00,
// frame type (rst stream frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x27 : 0x01),
+ 0x01,
// stream id
0x04, 0x03, 0x02, 0x01,
// error code
@@ -2920,13 +3016,6 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
close_frame.error_code = static_cast<QuicErrorCode>(0x05060708);
close_frame.error_details = "because I can";
- QuicAckFrame* ack_frame = &close_frame.ack_frame;
- ack_frame->received_info.entropy_hash = 0x43;
- ack_frame->received_info.largest_observed = GG_UINT64_C(0x0123456789ABF);
- ack_frame->received_info.missing_packets.insert(GG_UINT64_C(0x0123456789ABE));
- ack_frame->sent_info.entropy_hash = 0xE0;
- ack_frame->sent_info.least_unacked = GG_UINT64_C(0x0123456789AA0);
-
QuicFrames frames;
frames.push_back(QuicFrame(&close_frame));
@@ -2943,8 +3032,7 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
0x01,
// frame type (connection close frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x2F : 0x02),
+ 0x02,
// error code
0x08, 0x07, 0x06, 0x05,
// error details length
@@ -2954,25 +3042,6 @@ TEST_P(QuicFramerTest, BuildCloseFramePacket) {
'u', 's', 'e', ' ',
'I', ' ', 'c', 'a',
'n',
-
- // Ack frame.
- // entropy hash of sent packets till least awaiting - 1.
- 0xE0,
- // least packet sequence number awaiting an ack
- 0xA0, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // entropy hash of all received packets.
- 0x43,
- // largest observed packet sequence number
- 0xBF, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // Infinite delta time.
- 0xFF, 0xFF, 0xFF, 0xFF,
- // num missing packets
- 0x01,
- // missing packet
- 0xBE, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
};
scoped_ptr<QuicPacket> data(
@@ -3015,8 +3084,7 @@ TEST_P(QuicFramerTest, BuildGoAwayPacket) {
0x01,
// frame type (go away frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x37 : 0x03),
+ 0x03,
// error code
0x08, 0x07, 0x06, 0x05,
// stream id
@@ -3217,20 +3285,17 @@ TEST_P(QuicFramerTest, DISABLED_Truncation) {
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
header.fec_group = 0;
- QuicConnectionCloseFrame close_frame;
- QuicAckFrame* ack_frame = &close_frame.ack_frame;
- close_frame.error_code = static_cast<QuicErrorCode>(0x05);
- close_frame.error_details = "because I can";
- ack_frame->received_info.largest_observed = 201;
- ack_frame->sent_info.least_unacked = 0;
- for (uint64 i = 1; i < ack_frame->received_info.largest_observed; ++i) {
- ack_frame->received_info.missing_packets.insert(i);
+ QuicAckFrame ack_frame;
+ ack_frame.received_info.largest_observed = 601;
+ ack_frame.sent_info.least_unacked = 0;
+ for (uint64 i = 1; i < ack_frame.received_info.largest_observed; i += 2) {
+ ack_frame.received_info.missing_packets.insert(i);
}
// Create a packet with just the ack
QuicFrame frame;
frame.type = ACK_FRAME;
- frame.ack_frame = ack_frame;
+ frame.ack_frame = &ack_frame;
QuicFrames frames;
frames.push_back(frame);
@@ -3242,25 +3307,20 @@ TEST_P(QuicFramerTest, DISABLED_Truncation) {
framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
*raw_ack_packet));
- // Create a packet with just connection close.
- frames.clear();
- frame.type = CONNECTION_CLOSE_FRAME;
- frame.connection_close_frame = &close_frame;
- frames.push_back(frame);
-
- scoped_ptr<QuicPacket> raw_close_packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
- ASSERT_TRUE(raw_close_packet != NULL);
-
- scoped_ptr<QuicEncryptedPacket> close_packet(
- framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
- *raw_close_packet));
-
// Now make sure we can turn our ack packet back into an ack frame
ASSERT_TRUE(framer_.ProcessPacket(*ack_packet));
-
- // And do the same for the close frame.
- ASSERT_TRUE(framer_.ProcessPacket(*close_packet));
+ ASSERT_EQ(1u, visitor_.ack_frames_.size());
+ const QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
+ EXPECT_EQ(0u, processed_ack_frame.sent_info.least_unacked);
+ EXPECT_TRUE(processed_ack_frame.received_info.is_truncated);
+ EXPECT_EQ(510u, processed_ack_frame.received_info.largest_observed);
+ ASSERT_EQ(255u, processed_ack_frame.received_info.missing_packets.size());
+ SequenceNumberSet::const_iterator missing_iter =
+ processed_ack_frame.received_info.missing_packets.begin();
+ EXPECT_EQ(1u, *missing_iter);
+ SequenceNumberSet::const_reverse_iterator last_missing_iter =
+ processed_ack_frame.received_info.missing_packets.rbegin();
+ EXPECT_EQ(509u, *last_missing_iter);
}
TEST_P(QuicFramerTest, CleanTruncation) {
@@ -3273,20 +3333,17 @@ TEST_P(QuicFramerTest, CleanTruncation) {
header.packet_sequence_number = GG_UINT64_C(0x123456789ABC);
header.fec_group = 0;
- QuicConnectionCloseFrame close_frame;
- QuicAckFrame* ack_frame = &close_frame.ack_frame;
- close_frame.error_code = static_cast<QuicErrorCode>(0x05);
- close_frame.error_details = "because I can";
- ack_frame->received_info.largest_observed = 201;
- ack_frame->sent_info.least_unacked = 0;
- for (uint64 i = 1; i < ack_frame->received_info.largest_observed; ++i) {
- ack_frame->received_info.missing_packets.insert(i);
+ QuicAckFrame ack_frame;
+ ack_frame.received_info.largest_observed = 201;
+ ack_frame.sent_info.least_unacked = 0;
+ for (uint64 i = 1; i < ack_frame.received_info.largest_observed; ++i) {
+ ack_frame.received_info.missing_packets.insert(i);
}
// Create a packet with just the ack
QuicFrame frame;
frame.type = ACK_FRAME;
- frame.ack_frame = ack_frame;
+ frame.ack_frame = &ack_frame;
QuicFrames frames;
frames.push_back(frame);
@@ -3298,26 +3355,9 @@ TEST_P(QuicFramerTest, CleanTruncation) {
framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
*raw_ack_packet));
- // Create a packet with just connection close.
- frames.clear();
- frame.type = CONNECTION_CLOSE_FRAME;
- frame.connection_close_frame = &close_frame;
- frames.push_back(frame);
-
- scoped_ptr<QuicPacket> raw_close_packet(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
- ASSERT_TRUE(raw_close_packet != NULL);
-
- scoped_ptr<QuicEncryptedPacket> close_packet(
- framer_.EncryptPacket(ENCRYPTION_NONE, header.packet_sequence_number,
- *raw_close_packet));
-
// Now make sure we can turn our ack packet back into an ack frame
ASSERT_TRUE(framer_.ProcessPacket(*ack_packet));
- // And do the same for the close frame.
- ASSERT_TRUE(framer_.ProcessPacket(*close_packet));
-
// Test for clean truncation of the ack by comparing the length of the
// original packets to the re-serialized packets.
frames.clear();
@@ -3330,17 +3370,7 @@ TEST_P(QuicFramerTest, CleanTruncation) {
framer_.BuildUnsizedDataPacket(header, frames).packet);
ASSERT_TRUE(raw_ack_packet != NULL);
EXPECT_EQ(original_raw_length, raw_ack_packet->length());
-
- frames.clear();
- frame.type = CONNECTION_CLOSE_FRAME;
- frame.connection_close_frame = &visitor_.connection_close_frame_;
- frames.push_back(frame);
-
- original_raw_length = raw_close_packet->length();
- raw_close_packet.reset(
- framer_.BuildUnsizedDataPacket(header, frames).packet);
ASSERT_TRUE(raw_ack_packet != NULL);
- EXPECT_EQ(original_raw_length, raw_close_packet->length());
}
TEST_P(QuicFramerTest, EntropyFlagTest) {
@@ -3357,8 +3387,7 @@ TEST_P(QuicFramerTest, EntropyFlagTest) {
0x01,
// frame type (stream frame with fin and no length)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xBE : 0xDF),
+ 0xDF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -3395,8 +3424,7 @@ TEST_P(QuicFramerTest, FecEntropyTest) {
0xFF,
// frame type (stream frame with fin and no length)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xBE : 0xDF),
+ 0xDF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -3431,8 +3459,7 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
0x01,
// frame type (stream frame with fin)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0xFE : 0xFF),
+ 0xFF,
// stream id
0x04, 0x03, 0x02, 0x01,
// offset
@@ -3446,8 +3473,7 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
'r', 'l', 'd', '!',
// frame type (ack frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x01 : 0x40),
+ 0x40,
// entropy hash of sent packets till least awaiting - 1.
0x14,
// least packet sequence number awaiting an ack
@@ -3478,64 +3504,5 @@ TEST_P(QuicFramerTest, StopPacketProcessing) {
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
}
-TEST_P(QuicFramerTest, ConnectionCloseWithInvalidAck) {
- unsigned char packet[] = {
- // public flags (8 byte guid)
- 0x3C,
- // guid
- 0x10, 0x32, 0x54, 0x76,
- 0x98, 0xBA, 0xDC, 0xFE,
- // packet sequence number
- 0xBC, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // private flags
- 0x00,
-
- // frame type (connection close frame)
- static_cast<unsigned char>(
- GetParam() < QUIC_VERSION_10 ? 0x2F : 0x02),
- // error code
- 0x11, 0x00, 0x00, 0x00,
- // error details length
- 0x0d, 0x00,
- // error details
- 'b', 'e', 'c', 'a',
- 'u', 's', 'e', ' ',
- 'I', ' ', 'c', 'a',
- 'n',
-
- // Ack frame.
- // entropy hash of sent packets till least awaiting - 1.
- 0xE0,
- // least packet sequence number awaiting an ack
- 0xA0, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // entropy hash of all received packets.
- 0x43,
- // largest observed packet sequence number
- 0xBF, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- // Infinite delta time.
- 0xFF, 0xFF, 0xFF, 0xFF,
- // num missing packets
- 0x01,
- // missing packet
- 0xBE, 0x9A, 0x78, 0x56,
- 0x34, 0x12,
- };
-
- MockFramerVisitor visitor;
- framer_.set_visitor(&visitor);
- EXPECT_CALL(visitor, OnPacket());
- EXPECT_CALL(visitor, OnPacketHeader(_));
- EXPECT_CALL(visitor, OnAckFrame(_)).WillOnce(Return(false));
- EXPECT_CALL(visitor, OnConnectionCloseFrame(_)).Times(0);
- EXPECT_CALL(visitor, OnPacketComplete());
-
- QuicEncryptedPacket encrypted(AsChars(packet), arraysize(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
-}
-
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_http_stream.cc b/chromium/net/quic/quic_http_stream.cc
index 0122c64b1ad..56dbbab13e5 100644
--- a/chromium/net/quic/quic_http_stream.cc
+++ b/chromium/net/quic/quic_http_stream.cc
@@ -24,9 +24,11 @@ namespace net {
static const size_t kHeaderBufInitialSize = 4096;
-QuicHttpStream::QuicHttpStream(const base::WeakPtr<QuicClientSession> session)
+QuicHttpStream::QuicHttpStream(const base::WeakPtr<QuicClientSession>& session)
: next_state_(STATE_NONE),
session_(session),
+ session_error_(OK),
+ was_handshake_confirmed_(session->IsCryptoHandshakeConfirmed()),
stream_(NULL),
request_info_(NULL),
request_body_stream_(NULL),
@@ -38,10 +40,13 @@ QuicHttpStream::QuicHttpStream(const base::WeakPtr<QuicClientSession> session)
user_buffer_len_(0),
weak_factory_(this) {
DCHECK(session_);
+ session_->AddObserver(this);
}
QuicHttpStream::~QuicHttpStream() {
Close(false);
+ if (session_)
+ session_->RemoveObserver(this);
}
int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info,
@@ -50,7 +55,8 @@ int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info,
const CompletionCallback& callback) {
DCHECK(!stream_);
if (!session_)
- return ERR_CONNECTION_CLOSED;
+ return was_handshake_confirmed_ ? ERR_CONNECTION_CLOSED :
+ ERR_QUIC_HANDSHAKE_FAILED;
stream_net_log_ = stream_net_log;
request_info_ = request_info;
@@ -59,19 +65,24 @@ int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info,
int rv = stream_request_.StartRequest(
session_, &stream_, base::Bind(&QuicHttpStream::OnStreamReady,
weak_factory_.GetWeakPtr()));
- if (rv == ERR_IO_PENDING)
+ if (rv == ERR_IO_PENDING) {
callback_ = callback;
-
- if (rv == OK)
+ } else if (rv == OK) {
stream_->SetDelegate(this);
+ } else if (!was_handshake_confirmed_) {
+ rv = ERR_QUIC_HANDSHAKE_FAILED;
+ }
return rv;
}
void QuicHttpStream::OnStreamReady(int rv) {
DCHECK(rv == OK || !stream_);
- if (rv == OK)
+ if (rv == OK) {
stream_->SetDelegate(this);
+ } else if (!was_handshake_confirmed_) {
+ rv = ERR_QUIC_HANDSHAKE_FAILED;
+ }
ResetAndReturn(&callback_).Run(rv);
}
@@ -88,23 +99,8 @@ int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
QuicPriority priority = ConvertRequestPriorityToQuicPriority(priority_);
stream_->set_priority(priority);
// Store the serialized request headers.
- SpdyHeaderBlock headers;
CreateSpdyHeadersFromHttpRequest(*request_info_, request_headers,
- &headers, 3, /*direct=*/true);
- if (session_->connection()->version() < QUIC_VERSION_9) {
- request_ = stream_->compressor()->CompressHeaders(headers);
- } else {
- request_ = stream_->compressor()->CompressHeadersWithPriority(priority,
- headers);
- }
- // Log the actual request with the URL Request's net log.
- stream_net_log_.AddEvent(
- NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS,
- base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
- // Also log to the QuicSession's net log.
- stream_->net_log().AddEvent(
- NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS,
- base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
+ &request_headers_, SPDY3, /*direct=*/true);
// Store the request body.
request_body_stream_ = request_info_->upload_data_stream;
@@ -211,9 +207,7 @@ void QuicHttpStream::Close(bool not_reusable) {
// Note: the not_reusable flag has no meaning for SPDY streams.
if (stream_) {
stream_->SetDelegate(NULL);
- // TODO(rch): use new CANCELLED error code here once quic 11
- // is everywhere.
- stream_->Close(QUIC_ERROR_PROCESSING_STREAM);
+ stream_->Reset(QUIC_STREAM_CANCELLED);
stream_ = NULL;
}
}
@@ -244,6 +238,11 @@ bool QuicHttpStream::IsConnectionReusable() const {
return false;
}
+int64 QuicHttpStream::GetTotalReceivedBytes() const {
+ // TODO(eustas): Implement.
+ return 0;
+}
+
bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
// TODO(mmenke): Figure out what to do here.
return true;
@@ -273,18 +272,6 @@ void QuicHttpStream::SetPriority(RequestPriority priority) {
priority_ = priority;
}
-int QuicHttpStream::OnSendData() {
- // TODO(rch): Change QUIC IO to provide notifications to the streams.
- NOTREACHED();
- return OK;
-}
-
-int QuicHttpStream::OnSendDataComplete(int status, bool* eof) {
- // TODO(rch): Change QUIC IO to provide notifications to the streams.
- NOTREACHED();
- return OK;
-}
-
int QuicHttpStream::OnDataReceived(const char* data, int length) {
DCHECK_NE(0, length);
// Are we still reading the response headers.
@@ -316,7 +303,9 @@ int QuicHttpStream::OnDataReceived(const char* data, int length) {
memcpy(user_buffer_->data(), data, user_buffer_len_);
int delta = length - user_buffer_len_;
BufferResponseBody(data + user_buffer_len_, delta);
+ length = user_buffer_len_;
}
+
user_buffer_ = NULL;
user_buffer_len_ = 0;
DoCallback(length);
@@ -325,7 +314,8 @@ int QuicHttpStream::OnDataReceived(const char* data, int length) {
void QuicHttpStream::OnClose(QuicErrorCode error) {
if (error != QUIC_NO_ERROR) {
- response_status_ = ERR_QUIC_PROTOCOL_ERROR;
+ response_status_ = was_handshake_confirmed_ ?
+ ERR_QUIC_PROTOCOL_ERROR : ERR_QUIC_HANDSHAKE_FAILED;
} else if (!response_headers_received_) {
response_status_ = ERR_ABORTED;
}
@@ -337,7 +327,8 @@ void QuicHttpStream::OnClose(QuicErrorCode error) {
void QuicHttpStream::OnError(int error) {
stream_ = NULL;
- response_status_ = error;
+ response_status_ = was_handshake_confirmed_ ?
+ error : ERR_QUIC_HANDSHAKE_FAILED;
if (!callback_.is_null())
DoCallback(response_status_);
}
@@ -346,6 +337,15 @@ bool QuicHttpStream::HasSendHeadersComplete() {
return next_state_ > STATE_SEND_HEADERS_COMPLETE;
}
+void QuicHttpStream::OnCryptoHandshakeConfirmed() {
+ was_handshake_confirmed_ = true;
+}
+
+void QuicHttpStream::OnSessionClosed(int error) {
+ session_error_ = error;
+ session_.reset();
+}
+
void QuicHttpStream::OnIOComplete(int rv) {
rv = DoLoop(rv);
@@ -406,6 +406,26 @@ int QuicHttpStream::DoSendHeaders() {
if (!stream_)
return ERR_UNEXPECTED;
+ if (request_.empty() && !stream_->CanWrite(
+ base::Bind(&QuicHttpStream::OnIOComplete,
+ weak_factory_.GetWeakPtr()))) {
+ // Do not compress headers unless it is likely that they can be sent.
+ next_state_ = STATE_SEND_HEADERS;
+ return ERR_IO_PENDING;
+ }
+ request_ = stream_->compressor()->CompressHeadersWithPriority(
+ ConvertRequestPriorityToQuicPriority(priority_), request_headers_);
+
+ // Log the actual request with the URL Request's net log.
+ stream_net_log_.AddEvent(
+ NetLog::TYPE_HTTP_TRANSACTION_SPDY_SEND_REQUEST_HEADERS,
+ base::Bind(&SpdyHeaderBlockNetLogCallback, &request_headers_));
+ // Also log to the QuicSession's net log.
+ stream_->net_log().AddEvent(
+ NetLog::TYPE_QUIC_HTTP_STREAM_SEND_REQUEST_HEADERS,
+ base::Bind(&SpdyHeaderBlockNetLogCallback, &request_headers_));
+ request_headers_.clear();
+
bool has_upload_data = request_body_stream_ != NULL;
next_state_ = STATE_SEND_HEADERS_COMPLETE;
@@ -506,7 +526,7 @@ int QuicHttpStream::ParseResponseHeaders() {
NetLog::TYPE_QUIC_HTTP_STREAM_READ_RESPONSE_HEADERS,
base::Bind(&SpdyHeaderBlockNetLogCallback, &headers));
- if (!SpdyHeadersToHttpResponse(headers, 3, response_info_)) {
+ if (!SpdyHeadersToHttpResponse(headers, SPDY3, response_info_)) {
DLOG(WARNING) << "Invalid headers";
return ERR_QUIC_PROTOCOL_ERROR;
}
diff --git a/chromium/net/quic/quic_http_stream.h b/chromium/net/quic/quic_http_stream.h
index 71fb5153352..7a96ea3d206 100644
--- a/chromium/net/quic/quic_http_stream.h
+++ b/chromium/net/quic/quic_http_stream.h
@@ -23,10 +23,11 @@ class QuicHttpStreamPeer;
// non-owning pointer to a QuicReliableClientStream which it uses to
// send and receive data.
class NET_EXPORT_PRIVATE QuicHttpStream :
+ public QuicClientSession::Observer,
public QuicReliableClientStream::Delegate,
public HttpStream {
public:
- explicit QuicHttpStream(const base::WeakPtr<QuicClientSession> session);
+ explicit QuicHttpStream(const base::WeakPtr<QuicClientSession>& session);
virtual ~QuicHttpStream();
@@ -51,6 +52,7 @@ class NET_EXPORT_PRIVATE QuicHttpStream :
virtual bool IsConnectionReused() const OVERRIDE;
virtual void SetConnectionReused() OVERRIDE;
virtual bool IsConnectionReusable() const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
@@ -61,13 +63,15 @@ class NET_EXPORT_PRIVATE QuicHttpStream :
virtual void SetPriority(RequestPriority priority) OVERRIDE;
// QuicReliableClientStream::Delegate implementation
- virtual int OnSendData() OVERRIDE;
- virtual int OnSendDataComplete(int status, bool* eof) OVERRIDE;
virtual int OnDataReceived(const char* data, int length) OVERRIDE;
virtual void OnClose(QuicErrorCode error) OVERRIDE;
virtual void OnError(int error) OVERRIDE;
virtual bool HasSendHeadersComplete() OVERRIDE;
+ // QuicClientSession::Observer implementation
+ virtual void OnCryptoHandshakeConfirmed() OVERRIDE;
+ virtual void OnSessionClosed(int error) OVERRIDE;
+
private:
friend class test::QuicHttpStreamPeer;
@@ -102,7 +106,9 @@ class NET_EXPORT_PRIVATE QuicHttpStream :
State next_state_;
- const base::WeakPtr<QuicClientSession> session_;
+ base::WeakPtr<QuicClientSession> session_;
+ int session_error_; // Error code from the connection shutdown.
+ bool was_handshake_confirmed_; // True if the crypto handshake succeeded.
QuicClientSession::StreamRequest stream_request_;
QuicReliableClientStream* stream_; // Non-owning.
@@ -124,6 +130,9 @@ class NET_EXPORT_PRIVATE QuicHttpStream :
// response.
int response_status_;
+ // Serialized request headers.
+ SpdyHeaderBlock request_headers_;
+
bool response_headers_received_;
// Serialized HTTP request.
diff --git a/chromium/net/quic/quic_http_stream_test.cc b/chromium/net/quic/quic_http_stream_test.cc
index 7ccab6d8e1e..97ae97261be 100644
--- a/chromium/net/quic/quic_http_stream_test.cc
+++ b/chromium/net/quic/quic_http_stream_test.cc
@@ -19,6 +19,7 @@
#include "net/quic/quic_client_session.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_connection_helper.h"
+#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_http_utils.h"
#include "net/quic/quic_reliable_client_stream.h"
#include "net/quic/spdy_utils.h"
@@ -51,8 +52,10 @@ class TestQuicConnection : public QuicConnection {
public:
TestQuicConnection(QuicGuid guid,
IPEndPoint address,
- QuicConnectionHelper* helper)
- : QuicConnection(guid, address, helper, false, QuicVersionMax()) {
+ QuicConnectionHelper* helper,
+ QuicPacketWriter* writer)
+ : QuicConnection(guid, address, helper, writer, false,
+ QuicSupportedVersions()) {
}
void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
@@ -132,22 +135,20 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
use_closing_stream_(false),
read_buffer_(new IOBufferWithSize(4096)),
guid_(2),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
- creator_(guid_, &framer_, &random_, false) {
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
+ random_generator_(0),
+ creator_(guid_, &framer_, &random_generator_, false) {
IPAddressNumber ip;
CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
peer_addr_ = IPEndPoint(ip, 443);
self_addr_ = IPEndPoint(ip, 8435);
- // TODO(rch): remove this.
- QuicConnection::g_acks_do_not_instigate_acks = true;
}
~QuicHttpStreamTest() {
+ session_->CloseSessionOnError(ERR_ABORTED);
for (size_t i = 0; i < writes_.size(); i++) {
delete writes_[i].packet;
}
- // TODO(rch): remove this.
- QuicConnection::g_acks_do_not_instigate_acks = false;
}
// Adds a packet to the list of expected writes.
@@ -188,7 +189,8 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
receive_algorithm_ = new TestReceiveAlgorithm(NULL);
EXPECT_CALL(*receive_algorithm_, RecordIncomingPacket(_, _, _, _)).
Times(AnyNumber());
- EXPECT_CALL(*send_algorithm_, SentPacket(_, _, _, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, _, _, _)).Times(AnyNumber());
EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
@@ -197,16 +199,20 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
Return(QuicTime::Delta::Zero()));
EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(
Return(QuicBandwidth::Zero()));
- helper_ = new QuicConnectionHelper(runner_.get(), &clock_,
- &random_generator_, socket);
- connection_ = new TestQuicConnection(guid_, peer_addr_, helper_);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)).Times(AnyNumber());
+ helper_.reset(new QuicConnectionHelper(runner_.get(), &clock_,
+ &random_generator_));
+ writer_.reset(new QuicDefaultPacketWriter(socket));
+ connection_ = new TestQuicConnection(guid_, peer_addr_, helper_.get(),
+ writer_.get());
connection_->set_visitor(&visitor_);
connection_->SetSendAlgorithm(send_algorithm_);
connection_->SetReceiveAlgorithm(receive_algorithm_);
crypto_config_.SetDefaults();
session_.reset(
new QuicClientSession(connection_,
- scoped_ptr<DatagramClientSocket>(socket), NULL,
+ scoped_ptr<DatagramClientSocket>(socket),
+ writer_.Pass(), NULL,
&crypto_client_stream_factory_,
"www.google.com", DefaultQuicConfig(),
&crypto_config_, NULL));
@@ -242,7 +248,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
bool write_priority,
RequestPriority priority) {
QuicSpdyCompressor compressor;
- if (framer_.version() >= QUIC_VERSION_9 && write_priority) {
+ if (write_priority) {
return compressor.CompressHeadersWithPriority(
ConvertRequestPriorityToQuicPriority(priority), headers);
}
@@ -257,7 +263,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
QuicStreamOffset offset,
base::StringPiece data) {
InitializeHeader(sequence_number, should_include_version);
- QuicStreamFrame frame(3, fin, offset, data);
+ QuicStreamFrame frame(3, fin, offset, MakeIOVector(data));
return ConstructPacket(header_, QuicFrame(&frame));
}
@@ -265,7 +271,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
QuicEncryptedPacket* ConstructRstStreamPacket(
QuicPacketSequenceNumber sequence_number) {
InitializeHeader(sequence_number, false);
- QuicRstStreamFrame frame(3, QUIC_ERROR_PROCESSING_STREAM);
+ QuicRstStreamFrame frame(3, QUIC_STREAM_CANCELLED);
return ConstructPacket(header_, QuicFrame(&frame));
}
@@ -300,11 +306,11 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
scoped_refptr<TestTaskRunner> runner_;
scoped_ptr<MockWrite[]> mock_writes_;
MockClock clock_;
- MockRandom random_generator_;
TestQuicConnection* connection_;
- QuicConnectionHelper* helper_;
+ scoped_ptr<QuicConnectionHelper> helper_;
testing::StrictMock<MockConnectionVisitor> visitor_;
scoped_ptr<QuicHttpStream> stream_;
+ scoped_ptr<QuicDefaultPacketWriter> writer_;
scoped_ptr<QuicClientSession> session_;
QuicCryptoClientConfig crypto_config_;
TestCompletionCallback callback_;
@@ -342,7 +348,7 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<bool> {
QuicFramer framer_;
IPEndPoint self_addr_;
IPEndPoint peer_addr_;
- MockRandom random_;
+ MockRandom random_generator_;
MockCryptoClientStreamFactory crypto_client_stream_factory_;
QuicPacketCreator creator_;
QuicPacketHeader header_;
@@ -510,7 +516,7 @@ TEST_F(QuicHttpStreamTest, SendPostRequest) {
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(
new UploadBytesElementReader(kUploadData, strlen(kUploadData)));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
request_.method = "POST";
request_.url = GURL("http://www.google.com/");
request_.upload_data_stream = &upload_data_stream;
@@ -723,6 +729,37 @@ TEST_F(QuicHttpStreamTest, CheckPriorityWithNoDelegate) {
reliable_stream->SetDelegate(delegate);
}
+TEST_F(QuicHttpStreamTest, DontCompressHeadersWhenNotWritable) {
+ SetRequestString("GET", "/", MEDIUM);
+ AddWrite(SYNCHRONOUS, ConstructDataPacket(1, true, kFin, 0, request_data_));
+
+ Initialize();
+ request_.method = "GET";
+ request_.url = GURL("http://www.google.com/");
+
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
+ WillRepeatedly(Return(QuicTime::Delta::Infinite()));
+ EXPECT_EQ(OK, stream_->InitializeStream(&request_, MEDIUM,
+ net_log_, callback_.callback()));
+ EXPECT_EQ(ERR_IO_PENDING, stream_->SendRequest(headers_, &response_,
+ callback_.callback()));
+
+ // Verify that the headers have not been compressed and buffered in
+ // the stream.
+ QuicReliableClientStream* reliable_stream =
+ QuicHttpStreamPeer::GetQuicReliableClientStream(stream_.get());
+ EXPECT_FALSE(reliable_stream->HasBufferedData());
+ EXPECT_FALSE(AtEof());
+
+ EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
+ WillRepeatedly(Return(QuicTime::Delta::Zero()));
+
+ // Data should flush out now.
+ connection_->OnCanWrite();
+ EXPECT_FALSE(reliable_stream->HasBufferedData());
+ EXPECT_TRUE(AtEof());
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_http_utils.cc b/chromium/net/quic/quic_http_utils.cc
index 4a486268547..173403d82dc 100644
--- a/chromium/net/quic/quic_http_utils.cc
+++ b/chromium/net/quic/quic_http_utils.cc
@@ -9,7 +9,7 @@ namespace net {
QuicPriority ConvertRequestPriorityToQuicPriority(
const RequestPriority priority) {
DCHECK_GE(priority, MINIMUM_PRIORITY);
- DCHECK_LT(priority, NUM_PRIORITIES);
+ DCHECK_LE(priority, MAXIMUM_PRIORITY);
return static_cast<QuicPriority>(HIGHEST - priority);
}
diff --git a/chromium/net/quic/quic_network_transaction_unittest.cc b/chromium/net/quic/quic_network_transaction_unittest.cc
index a6cbff1b81a..2e4610ce5e7 100644
--- a/chromium/net/quic/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/quic_network_transaction_unittest.cc
@@ -64,6 +64,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
compressor_(new QuicSpdyCompressor()),
auth_handler_factory_(
HttpAuthHandlerFactory::CreateDefault(&host_resolver_)),
+ random_generator_(0),
hanging_data_(NULL, 0, NULL, 0) {
request_.method = "GET";
request_.url = GURL("http://www.google.com/");
@@ -90,7 +91,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
QuicPacketSequenceNumber num,
QuicStreamId stream_id) {
QuicPacketHeader header;
- header.public_header.guid = 0xDEADBEEF;
+ header.public_header.guid = random_generator_.RandUint64();
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
header.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
@@ -107,7 +108,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
scoped_ptr<QuicEncryptedPacket> ConstructConnectionClosePacket(
QuicPacketSequenceNumber num) {
QuicPacketHeader header;
- header.public_header.guid = 0xDEADBEEF;
+ header.public_header.guid = random_generator_.RandUint64();
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
header.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
@@ -116,11 +117,9 @@ class QuicNetworkTransactionTest : public PlatformTest {
header.fec_flag = false;
header.fec_group = 0;
- QuicAckFrame ack_frame(0, QuicTime::Zero(), 0);
QuicConnectionCloseFrame close;
close.error_code = QUIC_CRYPTO_VERSION_NOT_SUPPORTED;
close.error_details = "Time to panic!";
- close.ack_frame = ack_frame;
return scoped_ptr<QuicEncryptedPacket>(
ConstructPacket(header, QuicFrame(&close)));
}
@@ -129,7 +128,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
QuicPacketSequenceNumber largest_received,
QuicPacketSequenceNumber least_unacked) {
QuicPacketHeader header;
- header.public_header.guid = 0xDEADBEEF;
+ header.public_header.guid = random_generator_.RandUint64();
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
header.public_header.sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
@@ -145,7 +144,7 @@ class QuicNetworkTransactionTest : public PlatformTest {
feedback.tcp.accumulated_number_of_lost_packets = 0;
feedback.tcp.receive_window = 256000;
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(QuicFrame(&ack));
frames.push_back(QuicFrame(&feedback));
@@ -178,11 +177,8 @@ class QuicNetworkTransactionTest : public PlatformTest {
std::string SerializeHeaderBlock(const SpdyHeaderBlock& headers) {
QuicSpdyCompressor compressor;
- if (QuicVersionMax() >= QUIC_VERSION_9) {
- return compressor.CompressHeadersWithPriority(
- ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY), headers);
- }
- return compressor.CompressHeaders(headers);
+ return compressor.CompressHeadersWithPriority(
+ ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY), headers);
}
// Returns a newly created packet to send kData on stream 1.
@@ -194,14 +190,14 @@ class QuicNetworkTransactionTest : public PlatformTest {
QuicStreamOffset offset,
base::StringPiece data) {
InitializeHeader(sequence_number, should_include_version);
- QuicStreamFrame frame(stream_id, fin, offset, data);
+ QuicStreamFrame frame(stream_id, fin, offset, MakeIOVector(data));
return ConstructPacket(header_, QuicFrame(&frame)).release();
}
scoped_ptr<QuicEncryptedPacket> ConstructPacket(
const QuicPacketHeader& header,
const QuicFrame& frame) {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
@@ -456,7 +452,7 @@ TEST_F(QuicNetworkTransactionTest, DoNotForceQuicForHttps) {
}
TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -509,7 +505,7 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
params_.origin_to_force_quic_on =
HostPortPair::FromString("www.google.com:443");
params_.enable_quic_https = true;
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
MockRead http_reads[] = {
MockRead("HTTP/1.1 200 OK\r\n"),
@@ -559,7 +555,7 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
}
TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START);
@@ -618,7 +614,7 @@ TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
}
TEST_F(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
scoped_ptr<QuicEncryptedPacket> req(
ConstructDataPacket(1, 3, true, true, 0,
@@ -655,7 +651,7 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
}
TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
scoped_ptr<QuicEncryptedPacket> req(
ConstructDataPacket(1, 3, true, true, 0,
@@ -702,7 +698,7 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
}
TEST_F(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
scoped_ptr<QuicEncryptedPacket> req(
ConstructDataPacket(1, 3, true, true, 0,
@@ -761,7 +757,7 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithConfirmationRequired) {
}
TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
// Alternate-protocol job
scoped_ptr<QuicEncryptedPacket> close(ConstructConnectionClosePacket(1));
@@ -792,7 +788,7 @@ TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocol) {
}
TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
// Alternate-protocol job
MockRead quic_reads[] = {
@@ -822,7 +818,7 @@ TEST_F(QuicNetworkTransactionTest, BrokenAlternateProtocolReadError) {
}
TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+ HttpStreamFactory::EnableNpnSpdy3(); // Enables QUIC too.
// Alternate-protocol job
MockRead quic_reads[] = {
@@ -834,18 +830,28 @@ TEST_F(QuicNetworkTransactionTest, FailedZeroRttBrokenAlternateProtocol) {
AddHangingNonAlternateProtocolSocketData();
+ // Final job that will proceed when the QUIC job fails.
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n\r\n"),
+ MockRead("hello from http"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)
+ };
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+ NULL, 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+
CreateSession();
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);
- EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
+ SendRequestAndExpectHttpResponse("hello from http");
ExpectBrokenAlternateProtocolMapping();
+
+ EXPECT_TRUE(quic_data.at_read_eof());
+ EXPECT_TRUE(quic_data.at_write_eof());
}
} // namespace test
diff --git a/chromium/net/quic/quic_packet_creator.cc b/chromium/net/quic/quic_packet_creator.cc
index 609ebcbd734..cb37cc271de 100644
--- a/chromium/net/quic/quic_packet_creator.cc
+++ b/chromium/net/quic/quic_packet_creator.cc
@@ -19,13 +19,48 @@ using std::vector;
namespace net {
+// A QuicRandom wrapper that gets a bucket of entropy and distributes it
+// bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this
+// class if single bit randomness is needed elsewhere.
+class QuicRandomBoolSource {
+ public:
+ // random: Source of entropy. Not owned.
+ explicit QuicRandomBoolSource(QuicRandom* random)
+ : random_(random),
+ bit_bucket_(0),
+ bit_mask_(0) {}
+
+ ~QuicRandomBoolSource() {}
+
+ // Returns the next random bit from the bucket.
+ bool RandBool() {
+ if (bit_mask_ == 0) {
+ bit_bucket_ = random_->RandUint64();
+ bit_mask_ = 1;
+ }
+ bool result = ((bit_bucket_ & bit_mask_) != 0);
+ bit_mask_ <<= 1;
+ return result;
+ }
+
+ private:
+ // Source of entropy.
+ QuicRandom* random_;
+ // Stored random bits.
+ uint64 bit_bucket_;
+ // The next available bit has "1" in the mask. Zero means empty bucket.
+ uint64 bit_mask_;
+
+ DISALLOW_COPY_AND_ASSIGN(QuicRandomBoolSource);
+};
+
QuicPacketCreator::QuicPacketCreator(QuicGuid guid,
QuicFramer* framer,
QuicRandom* random_generator,
bool is_server)
: guid_(guid),
framer_(framer),
- random_generator_(random_generator),
+ random_bool_source_(new QuicRandomBoolSource(random_generator)),
sequence_number_(0),
fec_group_number_(0),
is_server_(is_server),
@@ -41,6 +76,7 @@ QuicPacketCreator::~QuicPacketCreator() {
void QuicPacketCreator::OnBuiltFecProtectedPayload(
const QuicPacketHeader& header, StringPiece payload) {
if (fec_group_.get()) {
+ DCHECK_NE(0u, header.fec_group);
fec_group_->Update(header, payload);
}
}
@@ -85,15 +121,8 @@ void QuicPacketCreator::UpdateSequenceNumberLength(
bytes_per_second / options_.max_packet_length;
const uint64 delta = max(current_delta, congestion_window);
- if (delta < 1 << ((PACKET_1BYTE_SEQUENCE_NUMBER * 8) - 2)) {
- options_.send_sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER;
- } else if (delta < 1 << ((PACKET_2BYTE_SEQUENCE_NUMBER * 8) - 2)) {
- options_.send_sequence_number_length = PACKET_2BYTE_SEQUENCE_NUMBER;
- } else if (delta < 1 << ((PACKET_4BYTE_SEQUENCE_NUMBER * 8) - 2)) {
- options_.send_sequence_number_length = PACKET_4BYTE_SEQUENCE_NUMBER;
- } else {
- options_.send_sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER;
- }
+ options_.send_sequence_number_length =
+ QuicFramer::GetMinSequenceNumberLength(delta * 4);
}
bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
@@ -116,7 +145,7 @@ size_t QuicPacketCreator::StreamFramePacketOverhead(
}
size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
- StringPiece data,
+ const IOVector& data,
QuicStreamOffset offset,
bool fin,
QuicFrame* frame) {
@@ -131,47 +160,53 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
framer_->version(), id, offset, true);
}
- const size_t free_bytes = BytesFree();
- size_t bytes_consumed = 0;
-
- if (data.size() != 0) {
- // When a STREAM frame is the last frame in a packet, it consumes two fewer
- // bytes of framing overhead.
- // Anytime more data is available than fits in with the extra two bytes,
- // the frame will be the last, and up to two extra bytes are consumed.
- // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when
- // 1 byte is available, because then the STREAM frame isn't the last.
-
- // The minimum frame size(0 bytes of data) if it's not the last frame.
- size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
- framer_->version(), id, offset, false);
- // Check if it's the last frame in the packet.
- if (data.size() + min_frame_size > free_bytes) {
- // The minimum frame size(0 bytes of data) if it is the last frame.
- size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize(
- framer_->version(), id, offset, true);
- bytes_consumed =
- min<size_t>(free_bytes - min_last_frame_size, data.size());
- } else {
- DCHECK_LT(data.size(), BytesFree());
- bytes_consumed = data.size();
+ if (data.Empty()) {
+ if (!fin) {
+ LOG(DFATAL) << "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, data));
+ return 0;
+ }
- bool set_fin = fin && bytes_consumed == data.size(); // Last frame.
- StringPiece data_frame(data.data(), bytes_consumed);
- *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, data_frame));
+ const size_t free_bytes = BytesFree();
+ size_t bytes_consumed = 0;
+ const size_t data_size = data.TotalBufferSize();
+
+ // When a STREAM frame is the last frame in a packet, it consumes two fewer
+ // bytes of framing overhead.
+ // Anytime more data is available than fits in with the extra two bytes,
+ // the frame will be the last, and up to two extra bytes are consumed.
+ // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when
+ // 1 byte is available, because then the STREAM frame isn't the last.
+
+ // The minimum frame size(0 bytes of data) if it's not the last frame.
+ size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
+ framer_->version(), id, offset, false);
+ // Check if it's the last frame in the packet.
+ if (data_size + min_frame_size > free_bytes) {
+ // The minimum frame size(0 bytes of data) if it is the last frame.
+ size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize(
+ framer_->version(), id, offset, true);
+ bytes_consumed =
+ min<size_t>(free_bytes - min_last_frame_size, data_size);
} else {
- DCHECK(fin);
- // Create a new packet for the fin, if necessary.
- *frame = QuicFrame(new QuicStreamFrame(id, true, offset, ""));
+ DCHECK_LT(data_size, BytesFree());
+ bytes_consumed = data_size;
}
+ bool set_fin = fin && bytes_consumed == data_size; // Last frame.
+ IOVector frame_data;
+ frame_data.AppendIovecAtMostBytes(data.iovec(), data.Size(),
+ bytes_consumed);
+ DCHECK_EQ(frame_data.TotalBufferSize(), bytes_consumed);
+ *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, frame_data));
return bytes_consumed;
}
size_t QuicPacketCreator::CreateStreamFrameWithNotifier(
QuicStreamId id,
- StringPiece data,
+ const IOVector& data,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier* notifier,
@@ -189,18 +224,26 @@ size_t QuicPacketCreator::CreateStreamFrameWithNotifier(
SerializedPacket QuicPacketCreator::ReserializeAllFrames(
const QuicFrames& frames,
QuicSequenceNumberLength original_length) {
- // Temporarily set the sequence number length and disable FEC.
const QuicSequenceNumberLength start_length = sequence_number_length_;
const QuicSequenceNumberLength start_options_length =
options_.send_sequence_number_length;
const QuicFecGroupNumber start_fec_group = fec_group_number_;
+ const size_t start_max_packets_per_fec_group =
+ options_.max_packets_per_fec_group;
+
+ // Temporarily set the sequence number length and disable FEC.
sequence_number_length_ = original_length;
options_.send_sequence_number_length = original_length;
fec_group_number_ = 0;
+ options_.max_packets_per_fec_group = 0;
+
+ // Serialize the packet and restore the fec and sequence number length state.
SerializedPacket serialized_packet = SerializeAllFrames(frames);
sequence_number_length_ = start_length;
options_.send_sequence_number_length = start_options_length;
fec_group_number_ = start_fec_group;
+ options_.max_packets_per_fec_group = start_max_packets_per_fec_group;
+
return serialized_packet;
}
@@ -229,10 +272,20 @@ bool QuicPacketCreator::HasPendingFrames() {
size_t QuicPacketCreator::BytesFree() const {
const size_t max_plaintext_size =
framer_->GetMaxPlaintextSize(options_.max_packet_length);
- if (PacketSize() >= max_plaintext_size) {
+ DCHECK_GE(max_plaintext_size, PacketSize());
+
+ // If the last frame in the packet is a stream frame, then it can be
+ // two bytes smaller than if it were not the last. So this means that
+ // there are two fewer bytes available to the next frame in this case.
+ bool has_trailing_stream_frame =
+ !queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME;
+ size_t expanded_packet_size = PacketSize() +
+ (has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0);
+
+ if (expanded_packet_size >= max_plaintext_size) {
return 0;
}
- return max_plaintext_size - PacketSize();
+ return max_plaintext_size - expanded_packet_size;
}
size_t QuicPacketCreator::PacketSize() const {
@@ -246,7 +299,7 @@ size_t QuicPacketCreator::PacketSize() const {
packet_size_ = GetPacketHeaderSize(options_.send_guid_length,
send_version_in_packet_,
sequence_number_length_,
- fec_group_number_ == 0 ?
+ options_.max_packets_per_fec_group == 0 ?
NOT_IN_FEC_GROUP : IN_FEC_GROUP);
}
return packet_size_;
@@ -263,18 +316,29 @@ SerializedPacket QuicPacketCreator::SerializePacket() {
QuicPacketHeader header;
FillPacketHeader(fec_group_number_, false, false, &header);
+ MaybeAddPadding();
+
+ size_t max_plaintext_size =
+ framer_->GetMaxPlaintextSize(options_.max_packet_length);
+ DCHECK_GE(max_plaintext_size, packet_size_);
+ // ACK and CONNECTION_CLOSE Frames will be truncated only if they're
+ // the first frame in the packet. If truncation is to occur, then
+ // GetSerializedFrameLength will have returned all bytes free.
+ bool possibly_truncated =
+ packet_size_ != max_plaintext_size ||
+ queued_frames_.size() != 1 ||
+ (queued_frames_.back().type == ACK_FRAME ||
+ queued_frames_.back().type == CONNECTION_CLOSE_FRAME);
SerializedPacket serialized =
framer_->BuildDataPacket(header, queued_frames_, packet_size_);
-
- // Run through all the included frames and if any of them have an AckNotifier
- // registered, then inform the AckNotifier that it should be interested in
- // this packet's sequence number.
- for (QuicFrames::iterator it = queued_frames_.begin();
- it != queued_frames_.end(); ++it) {
- if (it->type == STREAM_FRAME && it->stream_frame->notifier != NULL) {
- it->stream_frame->notifier->AddSequenceNumber(serialized.sequence_number);
- }
+ if (!serialized.packet) {
+ LOG(DFATAL) << "Failed to serialize " << queued_frames_.size()
+ << " frames.";
}
+ // Because of possible truncation, we can't be confident that our
+ // packet size calculation worked correctly.
+ if (!possibly_truncated)
+ DCHECK_EQ(packet_size_, serialized.packet->length());
packet_size_ = 0;
queued_frames_.clear();
@@ -295,7 +359,10 @@ SerializedPacket QuicPacketCreator::SerializeFec() {
fec_group_.reset(NULL);
fec_group_number_ = 0;
packet_size_ = 0;
- DCHECK(serialized.packet);
+ if (!serialized.packet) {
+ LOG(DFATAL) << "Failed to serialize fec packet for group:"
+ << fec_data.fec_group;
+ }
DCHECK_GE(options_.max_packet_length, serialized.packet->length());
return serialized;
}
@@ -334,17 +401,12 @@ void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
header->public_header.sequence_number_length = sequence_number_length_;
bool entropy_flag;
- if (header->packet_sequence_number == 1) {
- DCHECK(!fec_flag);
- // TODO(satyamshekhar): No entropy in the first message.
- // For crypto tests to pass. Fix this by using deterministic QuicRandom.
- entropy_flag = 0;
- } else if (fec_flag) {
+ if (fec_flag) {
// FEC packets don't have an entropy of their own. Entropy flag for FEC
// packets is the XOR of entropy of previous packets.
entropy_flag = fec_entropy_flag;
} else {
- entropy_flag = random_generator_->RandBool();
+ entropy_flag = random_bool_source_->RandBool();
}
header->entropy_flag = entropy_flag;
header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
@@ -359,13 +421,19 @@ bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
bool save_retransmittable_frames) {
size_t frame_len = framer_->GetSerializedFrameLength(
- frame, BytesFree(), queued_frames_.empty());
+ frame, BytesFree(), queued_frames_.empty(), true,
+ options()->send_sequence_number_length);
if (frame_len == 0) {
return false;
}
DCHECK_LT(0u, packet_size_);
+ MaybeStartFEC();
packet_size_ += frame_len;
-
+ // If the last frame in the packet was a stream frame, then once we add the
+ // new frame it's serialization will be two bytes larger.
+ if (!queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME) {
+ packet_size_ += kQuicStreamPayloadLengthSize;
+ }
if (save_retransmittable_frames && ShouldRetransmit(frame)) {
if (queued_retransmittable_frames_.get() == NULL) {
queued_retransmittable_frames_.reset(new RetransmittableFrames());
@@ -383,4 +451,29 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
return true;
}
+void QuicPacketCreator::MaybeAddPadding() {
+ if (BytesFree() == 0) {
+ // Don't pad full packets.
+ return;
+ }
+
+ // If any of the frames in the current packet are on the crypto stream
+ // then they contain handshake messagses, and we should pad them.
+ bool is_handshake = false;
+ for (size_t i = 0; i < queued_frames_.size(); ++i) {
+ if (queued_frames_[i].type == STREAM_FRAME &&
+ queued_frames_[i].stream_frame->stream_id == kCryptoStreamId) {
+ is_handshake = true;
+ break;
+ }
+ }
+ if (!is_handshake) {
+ return;
+ }
+
+ QuicPaddingFrame padding;
+ bool success = AddFrame(QuicFrame(&padding), false);
+ DCHECK(success);
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_packet_creator.h b/chromium/net/quic/quic_packet_creator.h
index 68b62166fee..b6756af4059 100644
--- a/chromium/net/quic/quic_packet_creator.h
+++ b/chromium/net/quic/quic_packet_creator.h
@@ -25,21 +25,19 @@ class QuicPacketCreatorPeer;
class QuicAckNotifier;
class QuicRandom;
+class QuicRandomBoolSource;
class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
public:
// Options for controlling how packets are created.
struct Options {
Options()
- : max_packet_length(kMaxPacketSize),
- random_reorder(false),
+ : max_packet_length(kDefaultMaxPacketSize),
max_packets_per_fec_group(0),
send_guid_length(PACKET_8BYTE_GUID),
- send_sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER) {
- }
+ send_sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER) {}
size_t max_packet_length;
- bool random_reorder; // Inefficient: rewrite if used at scale.
// 0 indicates fec is disabled.
size_t max_packets_per_fec_group;
// Length of guid to send over the wire.
@@ -63,10 +61,6 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// return true if an fec group is open.
bool ShouldSendFec(bool force_close) const;
- // Starts a new FEC group with the next serialized packet, if FEC is enabled
- // and there is not already an FEC group open.
- void MaybeStartFEC();
-
// Makes the framer not serialize the protocol version in sent packets.
void StopSendingVersion();
@@ -91,7 +85,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// If data is empty and fin is true, the expected behavior is to consume the
// fin but return 0.
size_t CreateStreamFrame(QuicStreamId id,
- base::StringPiece data,
+ const IOVector& data,
QuicStreamOffset offset,
bool fin,
QuicFrame* frame);
@@ -101,7 +95,7 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// The |notifier| is not owned by the QuicPacketGenerator and must outlive the
// generated packet.
size_t CreateStreamFrameWithNotifier(QuicStreamId id,
- base::StringPiece data,
+ const IOVector& data,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier* notifier,
@@ -121,12 +115,21 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// Returns true if there are frames pending to be serialized.
bool HasPendingFrames();
- // Returns the number of bytes which are free to frames in the current packet.
+ // Returns the number of bytes which are available to be used by additional
+ // 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;
- // Returns the number of bytes in the current packet, including the header.
+ // 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;
+ // TODO(jri): AddSavedFrame calls AddFrame, which only saves the frame
+ // if it is a stream frame, not other types of frames. Fix this API;
+ // add a AddNonSavedFrame method.
// Adds |frame| to the packet creator's list of frames to be serialized.
// Returns false if the frame doesn't fit into the current packet.
bool AddSavedFrame(const QuicFrame& frame);
@@ -177,6 +180,10 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
static bool ShouldRetransmit(const QuicFrame& frame);
+ // Starts a new FEC group with the next serialized packet, if FEC is enabled
+ // and there is not already an FEC group open.
+ void MaybeStartFEC();
+
void FillPacketHeader(QuicFecGroupNumber fec_group,
bool fec_flag,
bool fec_entropy_flag,
@@ -186,10 +193,15 @@ class NET_EXPORT_PRIVATE QuicPacketCreator : public QuicFecBuilderInterface {
// Particularly useful for retransmits using SerializeAllFrames().
bool AddFrame(const QuicFrame& frame, bool save_retransmittable_frames);
+ // Adds a padding frame to the current packet only if the current packet
+ // contains a handshake message, and there is sufficient room to fit a
+ // padding frame.
+ void MaybeAddPadding();
+
Options options_;
QuicGuid guid_;
QuicFramer* framer_;
- QuicRandom* random_generator_;
+ scoped_ptr<QuicRandomBoolSource> random_bool_source_;
QuicPacketSequenceNumber sequence_number_;
QuicFecGroupNumber fec_group_number_;
scoped_ptr<QuicFecGroup> fec_group_;
diff --git a/chromium/net/quic/quic_packet_creator_test.cc b/chromium/net/quic/quic_packet_creator_test.cc
index 51133b6880e..33f2e5c3010 100644
--- a/chromium/net/quic/quic_packet_creator_test.cc
+++ b/chromium/net/quic/quic_packet_creator_test.cc
@@ -8,8 +8,8 @@
#include "net/quic/crypto/null_encrypter.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
-#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_utils.h"
+#include "net/quic/test_tools/mock_random.h"
#include "net/quic/test_tools/quic_packet_creator_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -30,12 +30,12 @@ namespace {
class QuicPacketCreatorTest : public ::testing::TestWithParam<bool> {
protected:
QuicPacketCreatorTest()
- : server_framer_(QuicVersionMax(), QuicTime::Zero(), true),
- client_framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ : server_framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
+ client_framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
sequence_number_(0),
guid_(2),
data_("foo"),
- creator_(guid_, &client_framer_, QuicRandom::GetInstance(), false) {
+ creator_(guid_, &client_framer_, &mock_random_, false) {
client_framer_.set_visitor(&framer_visitor_);
server_framer_.set_visitor(&framer_visitor_);
}
@@ -49,16 +49,47 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<bool> {
server_framer_.ProcessPacket(*encrypted);
}
- void CheckStreamFrame(const QuicFrame& frame, QuicStreamId stream_id,
- const string& data, QuicStreamOffset offset, bool fin) {
+ void CheckStreamFrame(const QuicFrame& frame,
+ QuicStreamId stream_id,
+ const string& data,
+ QuicStreamOffset offset,
+ bool fin) {
EXPECT_EQ(STREAM_FRAME, frame.type);
ASSERT_TRUE(frame.stream_frame);
EXPECT_EQ(stream_id, frame.stream_frame->stream_id);
- EXPECT_EQ(data, frame.stream_frame->data);
+ scoped_ptr<string> frame_data(frame.stream_frame->GetDataAsString());
+ EXPECT_EQ(data, *frame_data);
EXPECT_EQ(offset, frame.stream_frame->offset);
EXPECT_EQ(fin, frame.stream_frame->fin);
}
+ // Returns the number of bytes consumed by the header of packet, including
+ // the version, that is not in an FEC group.
+ size_t GetPacketHeaderOverhead() {
+ return GetPacketHeaderSize(creator_.options()->send_guid_length,
+ kIncludeVersion,
+ creator_.options()->send_sequence_number_length,
+ NOT_IN_FEC_GROUP);
+ }
+
+ // Returns the number of bytes of overhead that will be added to a packet
+ // of maximum length.
+ size_t GetEncryptionOverhead() {
+ return creator_.options()->max_packet_length -
+ client_framer_.GetMaxPlaintextSize(
+ creator_.options()->max_packet_length);
+ }
+
+ // 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() {
+ return QuicFramer::GetMinStreamFrameSize(
+ client_framer_.version(), kStreamId, kOffset, true);
+ }
+
+ static const QuicStreamId kStreamId = 1u;
+ static const QuicStreamOffset kOffset = 1u;
+
QuicFrames frames_;
QuicFramer server_framer_;
QuicFramer client_framer_;
@@ -66,15 +97,14 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<bool> {
QuicPacketSequenceNumber sequence_number_;
QuicGuid guid_;
string data_;
+ MockRandom mock_random_;
QuicPacketCreator creator_;
};
TEST_F(QuicPacketCreatorTest, SerializeFrames) {
frames_.push_back(QuicFrame(new QuicAckFrame(0u, QuicTime::Zero(), 0u)));
- frames_.push_back(QuicFrame(new QuicStreamFrame(
- 0u, false, 0u, StringPiece(""))));
- frames_.push_back(QuicFrame(new QuicStreamFrame(
- 0u, true, 0u, StringPiece(""))));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(0u, true, 0u, IOVector())));
SerializedPacket serialized = creator_.SerializeAllFrames(frames_);
delete frames_[0].ack_frame;
delete frames_[1].stream_frame;
@@ -83,6 +113,7 @@ TEST_F(QuicPacketCreatorTest, SerializeFrames) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnAckFrame(_));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
@@ -96,16 +127,15 @@ TEST_F(QuicPacketCreatorTest, SerializeFrames) {
TEST_F(QuicPacketCreatorTest, SerializeWithFEC) {
creator_.options()->max_packets_per_fec_group = 6;
ASSERT_FALSE(creator_.ShouldSendFec(false));
- creator_.MaybeStartFEC();
- frames_.push_back(QuicFrame(new QuicStreamFrame(
- 0u, false, 0u, StringPiece(""))));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
SerializedPacket serialized = creator_.SerializeAllFrames(frames_);
delete frames_[0].stream_frame;
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
@@ -123,6 +153,7 @@ TEST_F(QuicPacketCreatorTest, SerializeWithFEC) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnFecData(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -143,6 +174,7 @@ TEST_F(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnAckFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -159,6 +191,7 @@ TEST_F(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnAckFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -170,7 +203,6 @@ TEST_F(QuicPacketCreatorTest, SerializeChangingSequenceNumberLength) {
TEST_F(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) {
creator_.options()->max_packets_per_fec_group = 6;
ASSERT_FALSE(creator_.ShouldSendFec(false));
- creator_.MaybeStartFEC();
frames_.push_back(QuicFrame(new QuicAckFrame(0u, QuicTime::Zero(), 0u)));
creator_.AddSavedFrame(frames_[0]);
@@ -183,6 +215,7 @@ TEST_F(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_));
EXPECT_CALL(framer_visitor_, OnAckFrame(_));
@@ -201,6 +234,7 @@ TEST_F(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnFecData(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -211,7 +245,7 @@ TEST_F(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) {
// Ensure the next FEC group starts using the new sequence number length.
serialized = creator_.SerializeAllFrames(frames_);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER, serialized.sequence_number_length);
- delete frames_[0].stream_frame;
+ delete frames_[0].ack_frame;
delete serialized.packet;
}
@@ -223,8 +257,7 @@ TEST_F(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
PACKET_4BYTE_SEQUENCE_NUMBER;
QuicPacketCreatorPeer::SetSequenceNumberLength(&creator_,
PACKET_2BYTE_SEQUENCE_NUMBER);
- frames_.push_back(QuicFrame(new QuicStreamFrame(
- 0u, false, 0u, StringPiece(""))));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
SerializedPacket serialized =
creator_.ReserializeAllFrames(frames_, PACKET_1BYTE_SEQUENCE_NUMBER);
EXPECT_EQ(PACKET_4BYTE_SEQUENCE_NUMBER,
@@ -237,6 +270,7 @@ TEST_F(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -248,7 +282,7 @@ TEST_F(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) {
TEST_F(QuicPacketCreatorTest, SerializeConnectionClose) {
QuicConnectionCloseFrame frame;
frame.error_code = QUIC_NO_ERROR;
- frame.ack_frame = QuicAckFrame(0u, QuicTime::Zero(), 0u);
+ frame.error_details = "error";
SerializedPacket serialized = creator_.SerializeConnectionClose(&frame);
ASSERT_EQ(1u, serialized.sequence_number);
@@ -256,8 +290,8 @@ TEST_F(QuicPacketCreatorTest, SerializeConnectionClose) {
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
- EXPECT_CALL(framer_visitor_, OnAckFrame(_));
EXPECT_CALL(framer_visitor_, OnConnectionCloseFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -267,7 +301,8 @@ TEST_F(QuicPacketCreatorTest, SerializeConnectionClose) {
TEST_F(QuicPacketCreatorTest, CreateStreamFrame) {
QuicFrame frame;
- size_t consumed = creator_.CreateStreamFrame(1u, "test", 0u, false, &frame);
+ size_t consumed = creator_.CreateStreamFrame(1u, MakeIOVector("test"), 0u,
+ false, &frame);
EXPECT_EQ(4u, consumed);
CheckStreamFrame(frame, 1u, "test", 0u, false);
delete frame.stream_frame;
@@ -275,7 +310,8 @@ TEST_F(QuicPacketCreatorTest, CreateStreamFrame) {
TEST_F(QuicPacketCreatorTest, CreateStreamFrameFin) {
QuicFrame frame;
- size_t consumed = creator_.CreateStreamFrame(1u, "test", 10u, true, &frame);
+ size_t consumed = creator_.CreateStreamFrame(1u, MakeIOVector("test"), 10u,
+ true, &frame);
EXPECT_EQ(4u, consumed);
CheckStreamFrame(frame, 1u, "test", 10u, true);
delete frame.stream_frame;
@@ -283,31 +319,24 @@ TEST_F(QuicPacketCreatorTest, CreateStreamFrameFin) {
TEST_F(QuicPacketCreatorTest, CreateStreamFrameFinOnly) {
QuicFrame frame;
- size_t consumed = creator_.CreateStreamFrame(1u, "", 0u, true, &frame);
+ size_t consumed = creator_.CreateStreamFrame(1u, IOVector(), 0u, true,
+ &frame);
EXPECT_EQ(0u, consumed);
CheckStreamFrame(frame, 1u, string(), 0u, true);
delete frame.stream_frame;
}
TEST_F(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
- QuicStreamId kStreamId = 1u;
- QuicStreamOffset kOffset = 1u;
- for (int i = 0; i < 100; ++i) {
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead();
+ for (size_t i = overhead; i < overhead + 100; ++i) {
creator_.options()->max_packet_length = i;
- const size_t max_plaintext_size = client_framer_.GetMaxPlaintextSize(i);
- const bool should_have_room = max_plaintext_size >
- (QuicFramer::GetMinStreamFrameSize(
- client_framer_.version(), kStreamId, kOffset, true) +
- GetPacketHeaderSize(creator_.options()->send_guid_length,
- kIncludeVersion,
- creator_.options()->send_sequence_number_length,
- NOT_IN_FEC_GROUP));
+ const bool should_have_room = i > overhead + GetStreamFrameOverhead();
ASSERT_EQ(should_have_room,
creator_.HasRoomForStreamFrame(kStreamId, kOffset));
if (should_have_room) {
QuicFrame frame;
size_t bytes_consumed = creator_.CreateStreamFrame(
- kStreamId, "testdata", kOffset, false, &frame);
+ kStreamId, MakeIOVector("testdata"), kOffset, false, &frame);
EXPECT_LT(0u, bytes_consumed);
ASSERT_TRUE(creator_.AddSavedFrame(frame));
SerializedPacket serialized_packet = creator_.SerializePacket();
@@ -318,10 +347,99 @@ TEST_F(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
}
}
+TEST_F(QuicPacketCreatorTest, StreamFrameConsumption) {
+ // Compute the total overhead for a single frame in packet.
+ 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) {
+ string data(capacity + delta, 'A');
+ size_t bytes_free = delta > 0 ? 0 : 0 - delta;
+ QuicFrame frame;
+ size_t bytes_consumed = creator_.CreateStreamFrame(
+ kStreamId, MakeIOVector(data), kOffset, false, &frame);
+ EXPECT_EQ(capacity - bytes_free, bytes_consumed);
+
+ ASSERT_TRUE(creator_.AddSavedFrame(frame));
+ // BytesFree() returns bytes available for the next frame, which will
+ // be two bytes smaller since the stream frame would need to be grown.
+ size_t expected_bytes_free = bytes_free < 3 ? 0 : bytes_free - 2;
+ EXPECT_EQ(expected_bytes_free, creator_.BytesFree()) << "delta: " << delta;
+ SerializedPacket serialized_packet = creator_.SerializePacket();
+ ASSERT_TRUE(serialized_packet.packet);
+ delete serialized_packet.packet;
+ delete serialized_packet.retransmittable_frames;
+ }
+}
+
+TEST_F(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) {
+ // Compute the total overhead for a single frame in packet.
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead()
+ + GetStreamFrameOverhead();
+ ASSERT_GT(kMaxPacketSize, overhead);
+ 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;
+ size_t bytes_consumed = creator_.CreateStreamFrame(
+ kStreamId, MakeIOVector(data), kOffset, false, &frame);
+ EXPECT_LT(0u, bytes_consumed);
+ ASSERT_TRUE(creator_.AddSavedFrame(frame));
+ SerializedPacket serialized_packet = creator_.SerializePacket();
+ ASSERT_TRUE(serialized_packet.packet);
+ // 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(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize)
+ - bytes_free, serialized_packet.packet->length());
+ } else {
+ EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize),
+ serialized_packet.packet->length());
+ }
+ delete serialized_packet.packet;
+ delete serialized_packet.retransmittable_frames;
+ }
+}
+
+TEST_F(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) {
+ // Compute the total overhead for a single frame in packet.
+ const size_t overhead = GetPacketHeaderOverhead() + GetEncryptionOverhead()
+ + GetStreamFrameOverhead();
+ ASSERT_GT(kDefaultMaxPacketSize, overhead);
+ 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;
+ size_t bytes_consumed = creator_.CreateStreamFrame(
+ kStreamId + 2, MakeIOVector(data), kOffset, false, &frame);
+ EXPECT_LT(0u, bytes_consumed);
+ ASSERT_TRUE(creator_.AddSavedFrame(frame));
+ SerializedPacket serialized_packet = creator_.SerializePacket();
+ ASSERT_TRUE(serialized_packet.packet);
+ if (bytes_free > 0) {
+ EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize)
+ - bytes_free, serialized_packet.packet->length());
+ } else {
+ EXPECT_EQ(client_framer_.GetMaxPlaintextSize(kDefaultMaxPacketSize),
+ serialized_packet.packet->length());
+ }
+ delete serialized_packet.packet;
+ delete serialized_packet.retransmittable_frames;
+ }
+}
+
TEST_F(QuicPacketCreatorTest, SerializeVersionNegotiationPacket) {
QuicPacketCreatorPeer::SetIsServer(&creator_, true);
QuicVersionVector versions;
- versions.push_back(QuicVersionMax());
+ versions.push_back(test::QuicVersionMax());
scoped_ptr<QuicEncryptedPacket> encrypted(
creator_.SerializeVersionNegotiationPacket(versions));
@@ -380,6 +498,22 @@ TEST_F(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthBandwidth) {
creator_.options()->send_sequence_number_length);
}
+TEST_F(QuicPacketCreatorTest, CreateStreamFrameWithNotifier) {
+ // Ensure that if CreateStreamFrame does not consume any data (e.g. a FIN only
+ // frame) then any QuicAckNotifier that is passed in still gets attached to
+ // the frame.
+ MockAckNotifierDelegate delegate;
+ QuicAckNotifier notifier(&delegate);
+ QuicFrame frame;
+ IOVector empty_iovector;
+ bool fin = true;
+ size_t consumed_bytes = creator_.CreateStreamFrameWithNotifier(
+ 1u, empty_iovector, 0u, fin, &notifier, &frame);
+ EXPECT_EQ(0u, consumed_bytes);
+ EXPECT_EQ(&notifier, frame.stream_frame->notifier);
+ delete frame.stream_frame;
+}
+
INSTANTIATE_TEST_CASE_P(ToggleVersionSerialization,
QuicPacketCreatorTest,
::testing::Values(false, true));
@@ -388,8 +522,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) {
if (!GetParam()) {
creator_.StopSendingVersion();
}
- frames_.push_back(QuicFrame(new QuicStreamFrame(
- 0u, false, 0u, StringPiece(""))));
+ frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
SerializedPacket serialized = creator_.SerializeAllFrames(frames_);
delete frames_[0].stream_frame;
@@ -397,6 +530,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) {
{
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
+ EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_));
EXPECT_CALL(framer_visitor_, OnPacketHeader(_)).WillOnce(
DoAll(SaveArg<0>(&header), Return(true)));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
@@ -420,7 +554,7 @@ TEST_P(QuicPacketCreatorTest, CreateStreamFrameTooLarge) {
QuicFrame frame;
const string too_long_payload(payload_length * 2, 'a');
size_t consumed = creator_.CreateStreamFrame(
- 1u, too_long_payload, 0u, true, &frame);
+ 1u, MakeIOVector(too_long_payload), 0u, true, &frame);
EXPECT_EQ(payload_length, consumed);
const string payload(payload_length, 'a');
CheckStreamFrame(frame, 1u, payload, 0u, false);
@@ -442,7 +576,7 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) {
creator_.BytesFree());
// Add a variety of frame types and then a padding frame.
- QuicAckFrame ack_frame;
+ QuicAckFrame ack_frame(0u, QuicTime::Zero(), 0u);
EXPECT_TRUE(creator_.AddSavedFrame(QuicFrame(&ack_frame)));
EXPECT_TRUE(creator_.HasPendingFrames());
@@ -452,7 +586,8 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) {
EXPECT_TRUE(creator_.HasPendingFrames());
QuicFrame frame;
- size_t consumed = creator_.CreateStreamFrame(1u, "test", 0u, false, &frame);
+ size_t consumed = creator_.CreateStreamFrame(
+ 1u, MakeIOVector("test"), 0u, false, &frame);
EXPECT_EQ(4u, consumed);
ASSERT_TRUE(frame.stream_frame);
EXPECT_TRUE(creator_.AddSavedFrame(frame));
@@ -486,6 +621,29 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndSerialize) {
creator_.BytesFree());
}
+TEST_F(QuicPacketCreatorTest, EntropyFlag) {
+ frames_.push_back(QuicFrame(new QuicStreamFrame(0u, false, 0u, IOVector())));
+
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ SerializedPacket serialized = creator_.SerializeAllFrames(frames_);
+ // Verify both BoolSource and hash algorithm.
+ bool expected_rand_bool =
+ (mock_random_.RandUint64() & (GG_UINT64_C(1) << j)) != 0;
+ bool observed_rand_bool =
+ (serialized.entropy_hash & (1 << ((j+1) % 8))) != 0;
+ uint8 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();
+ }
+
+ delete frames_[0].stream_frame;
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_packet_generator.cc b/chromium/net/quic/quic_packet_generator.cc
index 9151cb883b3..3785f7d2f8d 100644
--- a/chromium/net/quic/quic_packet_generator.cc
+++ b/chromium/net/quic/quic_packet_generator.cc
@@ -59,16 +59,16 @@ QuicPacketGenerator::~QuicPacketGenerator() {
void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback) {
should_send_ack_ = true;
should_send_feedback_ = also_send_feedback;
- SendQueuedFrames();
+ SendQueuedFrames(false);
}
void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
queued_control_frames_.push_back(frame);
- SendQueuedFrames();
+ SendQueuedFrames(false);
}
QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
- StringPiece data,
+ const IOVector& data_to_write,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier* notifier) {
@@ -76,7 +76,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
// The caller should have flushed pending frames before sending handshake
// messages.
DCHECK(handshake == NOT_HANDSHAKE || !HasPendingFrames());
- SendQueuedFrames();
+ SendQueuedFrames(false);
size_t total_bytes_consumed = 0;
bool fin_consumed = false;
@@ -84,17 +84,20 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
if (!packet_creator_->HasRoomForStreamFrame(id, offset)) {
SerializeAndSendPacket();
}
- while (delegate_->CanWrite(NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
- handshake)) {
+
+ IOVector data = data_to_write;
+ size_t data_size = data.TotalBufferSize();
+ while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA, handshake)) {
QuicFrame frame;
size_t bytes_consumed;
if (notifier != NULL) {
// We want to track which packet this stream frame ends up in.
bytes_consumed = packet_creator_->CreateStreamFrameWithNotifier(
- id, data, offset + total_bytes_consumed, fin, notifier, &frame);
+ id, data, offset + total_bytes_consumed, fin, notifier, &frame);
} else {
bytes_consumed = packet_creator_->CreateStreamFrame(
- id, data, offset + total_bytes_consumed, fin, &frame);
+ id, data, offset + total_bytes_consumed, fin, &frame);
}
if (!AddFrame(frame)) {
LOG(DFATAL) << "Failed to add stream frame.";
@@ -105,16 +108,16 @@ QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
}
total_bytes_consumed += bytes_consumed;
- fin_consumed = fin && bytes_consumed == data.size();
- data.remove_prefix(bytes_consumed);
- DCHECK(data.empty() || packet_creator_->BytesFree() == 0u);
+ fin_consumed = fin && total_bytes_consumed == data_size;
+ data.Consume(bytes_consumed);
+ DCHECK(data.Empty() || packet_creator_->BytesFree() == 0u);
// TODO(ianswett): Restore packet reordering.
if (!InBatchMode() || !packet_creator_->HasRoomForStreamFrame(id, offset)) {
SerializeAndSendPacket();
}
- if (data.empty()) {
+ if (data.Empty()) {
// We're done writing the data. Exit the loop.
// We don't make this a precondition because we could have 0 bytes of data
// if we're simply writing a fin.
@@ -142,21 +145,21 @@ bool QuicPacketGenerator::CanSendWithNextPendingFrameAddition() const {
if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
DCHECK(!queued_control_frames_.empty()); // These are retransmittable.
}
- return delegate_->CanWrite(NOT_RETRANSMISSION, retransmittable,
- NOT_HANDSHAKE);
+ return delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, retransmittable,
+ NOT_HANDSHAKE);
}
-void QuicPacketGenerator::SendQueuedFrames() {
- packet_creator_->MaybeStartFEC();
+void QuicPacketGenerator::SendQueuedFrames(bool flush) {
// Only add pending frames if we are SURE we can then send the whole packet.
- while (HasPendingFrames() && CanSendWithNextPendingFrameAddition()) {
+ while (HasPendingFrames() &&
+ (flush || CanSendWithNextPendingFrameAddition())) {
if (!AddNextPendingFrame()) {
// Packet was full, so serialize and send it.
SerializeAndSendPacket();
}
}
- if (!InBatchMode()) {
+ if (!InBatchMode() || flush) {
if (packet_creator_->HasPendingFrames()) {
SerializeAndSendPacket();
}
@@ -167,7 +170,6 @@ void QuicPacketGenerator::SendQueuedFrames() {
SerializedPacket serialized_fec = packet_creator_->SerializeFec();
DCHECK(serialized_fec.packet);
delegate_->OnSerializedPacket(serialized_fec);
- packet_creator_->MaybeStartFEC();
}
}
}
@@ -182,7 +184,11 @@ void QuicPacketGenerator::StartBatchOperations() {
void QuicPacketGenerator::FinishBatchOperations() {
batch_mode_ = false;
- SendQueuedFrames();
+ SendQueuedFrames(false);
+}
+
+void QuicPacketGenerator::FlushAllQueuedFrames() {
+ SendQueuedFrames(true);
}
bool QuicPacketGenerator::HasQueuedFrames() const {
@@ -213,7 +219,9 @@ bool QuicPacketGenerator::AddNextPendingFrame() {
return !should_send_feedback_;
}
- DCHECK(!queued_control_frames_.empty());
+ if (queued_control_frames_.empty()) {
+ LOG(DFATAL) << "AddNextPendingFrame called with no queued control frames.";
+ }
if (!AddFrame(queued_control_frames_.back())) {
// Packet was full.
return false;
@@ -239,7 +247,6 @@ void QuicPacketGenerator::SerializeAndSendPacket() {
SerializedPacket serialized_fec = packet_creator_->SerializeFec();
DCHECK(serialized_fec.packet);
delegate_->OnSerializedPacket(serialized_fec);
- packet_creator_->MaybeStartFEC();
}
}
diff --git a/chromium/net/quic/quic_packet_generator.h b/chromium/net/quic/quic_packet_generator.h
index 940b259adf7..1ff04882ae1 100644
--- a/chromium/net/quic/quic_packet_generator.h
+++ b/chromium/net/quic/quic_packet_generator.h
@@ -64,9 +64,9 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
class NET_EXPORT_PRIVATE DelegateInterface {
public:
virtual ~DelegateInterface() {}
- virtual bool CanWrite(Retransmission retransmission,
- HasRetransmittableData retransmittable,
- IsHandshake handshake) = 0;
+ virtual bool ShouldGeneratePacket(TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake) = 0;
virtual QuicAckFrame* CreateAckFrame() = 0;
virtual QuicCongestionFeedbackFrame* CreateFeedbackFrame() = 0;
// Takes ownership of |packet.packet| and |packet.retransmittable_frames|.
@@ -106,7 +106,7 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
// QuicAckNotifier is owned by the QuicConnection. |notifier| may
// be NULL.
QuicConsumedData ConsumeData(QuicStreamId id,
- base::StringPiece data,
+ const IOVector& data,
QuicStreamOffset offset,
bool fin,
QuicAckNotifier* notifier);
@@ -115,9 +115,12 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
bool InBatchMode();
// Disables flushing.
void StartBatchOperations();
- // Enables flushing and flushes queued data.
+ // Enables flushing and flushes queued data which can be sent.
void FinishBatchOperations();
+ // Flushes all queued frames, even frames which are not sendable.
+ void FlushAllQueuedFrames();
+
bool HasQueuedFrames() const;
void set_debug_delegate(DebugDelegateInterface* debug_delegate) {
@@ -125,7 +128,7 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator {
}
private:
- void SendQueuedFrames();
+ void SendQueuedFrames(bool flush);
// Test to see if we have pending ack, feedback, or control frames.
bool HasPendingFrames() const;
diff --git a/chromium/net/quic/quic_packet_generator_test.cc b/chromium/net/quic/quic_packet_generator_test.cc
index ec8dd56a677..8907db95a12 100644
--- a/chromium/net/quic/quic_packet_generator_test.cc
+++ b/chromium/net/quic/quic_packet_generator_test.cc
@@ -33,34 +33,37 @@ class MockDelegate : public QuicPacketGenerator::DelegateInterface {
MockDelegate() {}
virtual ~MockDelegate() {}
- MOCK_METHOD3(CanWrite, bool(Retransmission retransmission,
- HasRetransmittableData retransmittable,
- IsHandshake handshake));
-
+ MOCK_METHOD3(ShouldGeneratePacket,
+ bool(TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake));
MOCK_METHOD0(CreateAckFrame, QuicAckFrame*());
MOCK_METHOD0(CreateFeedbackFrame, QuicCongestionFeedbackFrame*());
MOCK_METHOD1(OnSerializedPacket, bool(const SerializedPacket& packet));
MOCK_METHOD2(CloseConnection, void(QuicErrorCode, bool));
void SetCanWriteAnything() {
- EXPECT_CALL(*this, CanWrite(NOT_RETRANSMISSION, _, _))
+ EXPECT_CALL(*this, ShouldGeneratePacket(NOT_RETRANSMISSION, _, _))
.WillRepeatedly(Return(true));
- EXPECT_CALL(*this, CanWrite(NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA, _))
+ EXPECT_CALL(*this, ShouldGeneratePacket(NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA, _))
.WillRepeatedly(Return(true));
}
void SetCanNotWrite() {
- EXPECT_CALL(*this, CanWrite(NOT_RETRANSMISSION, _, _))
+ EXPECT_CALL(*this, ShouldGeneratePacket(NOT_RETRANSMISSION, _, _))
.WillRepeatedly(Return(false));
- EXPECT_CALL(*this, CanWrite(NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA, _))
+ EXPECT_CALL(*this, ShouldGeneratePacket(NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA, _))
.WillRepeatedly(Return(false));
}
// Use this when only ack and feedback frames should be allowed to be written.
void SetCanWriteOnlyNonRetransmittable() {
- EXPECT_CALL(*this, CanWrite(NOT_RETRANSMISSION, _, _))
+ EXPECT_CALL(*this, ShouldGeneratePacket(NOT_RETRANSMISSION, _, _))
.WillRepeatedly(Return(false));
- EXPECT_CALL(*this, CanWrite(NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA, _))
+ EXPECT_CALL(*this, ShouldGeneratePacket(NOT_RETRANSMISSION,
+ NO_RETRANSMITTABLE_DATA, _))
.WillRepeatedly(Return(true));
}
@@ -97,7 +100,7 @@ struct PacketContents {
class QuicPacketGeneratorTest : public ::testing::Test {
protected:
QuicPacketGeneratorTest()
- : framer_(QuicVersionMax(), QuicTime::Zero(), false),
+ : framer_(QuicSupportedVersions(), QuicTime::Zero(), false),
creator_(42, &framer_, &random_, false),
generator_(&delegate_, NULL, &creator_),
packet_(0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL),
@@ -191,10 +194,12 @@ class QuicPacketGeneratorTest : public ::testing::Test {
EXPECT_EQ(fec_group, simple_framer_.fec_data().fec_group);
}
- StringPiece CreateData(size_t len) {
+ IOVector CreateData(size_t len) {
data_array_.reset(new char[len]);
memset(data_array_.get(), '?', len);
- return StringPiece(data_array_.get(), len);
+ IOVector data;
+ data.Append(data_array_.get(), len);
+ return data;
}
QuicFramer framer_;
@@ -310,6 +315,25 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldNotFlush) {
EXPECT_TRUE(generator_.HasQueuedFrames());
}
+TEST_F(QuicPacketGeneratorTest, AddControlFrame_NotWritableBatchThenFlush) {
+ delegate_.SetCanNotWrite();
+ generator_.StartBatchOperations();
+
+ generator_.AddControlFrame(QuicFrame(CreateRstStreamFrame()));
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+ generator_.FinishBatchOperations();
+ EXPECT_TRUE(generator_.HasQueuedFrames());
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
+ DoAll(SaveArg<0>(&packet_), Return(true)));
+ generator_.FlushAllQueuedFrames();
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+
+ PacketContents contents;
+ contents.num_rst_stream_frames = 1;
+ CheckPacketContains(contents, packet_);
+}
+
TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
delegate_.SetCanWriteAnything();
@@ -327,7 +351,8 @@ TEST_F(QuicPacketGeneratorTest, AddControlFrame_WritableAndShouldFlush) {
TEST_F(QuicPacketGeneratorTest, ConsumeData_NotWritable) {
delegate_.SetCanNotWrite();
- QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 2, true, NULL);
+ QuicConsumedData consumed = generator_.ConsumeData(1, MakeIOVector("foo"), 2,
+ true, NULL);
EXPECT_EQ(0u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -337,7 +362,8 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldNotFlush) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
- QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 2, true, NULL);
+ QuicConsumedData consumed = generator_.ConsumeData(1, MakeIOVector("foo"), 2,
+ true, NULL);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -348,7 +374,8 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_WritableAndShouldFlush) {
EXPECT_CALL(delegate_, OnSerializedPacket(_)).WillOnce(
DoAll(SaveArg<0>(&packet_), Return(true)));
- QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 2, true, NULL);
+ QuicConsumedData consumed = generator_.ConsumeData(1, MakeIOVector("foo"), 2,
+ true, NULL);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -363,8 +390,9 @@ TEST_F(QuicPacketGeneratorTest,
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
- generator_.ConsumeData(1, "foo", 2, true, NULL);
- QuicConsumedData consumed = generator_.ConsumeData(3, "quux", 7, false, NULL);
+ generator_.ConsumeData(1, MakeIOVector("foo"), 2, true, NULL);
+ QuicConsumedData consumed = generator_.ConsumeData(3, MakeIOVector("quux"), 7,
+ false, NULL);
EXPECT_EQ(4u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -374,8 +402,9 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_BatchOperations) {
delegate_.SetCanWriteAnything();
generator_.StartBatchOperations();
- generator_.ConsumeData(1, "foo", 2, true, NULL);
- QuicConsumedData consumed = generator_.ConsumeData(3, "quux", 7, false, NULL);
+ generator_.ConsumeData(1, MakeIOVector("foo"), 2, true, NULL);
+ QuicConsumedData consumed = generator_.ConsumeData(3, MakeIOVector("quux"), 7,
+ false, NULL);
EXPECT_EQ(4u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -412,7 +441,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataFEC) {
}
// Send enough data to create 3 packets: two full and one partial.
- size_t data_len = 2 * kMaxPacketSize + 100;
+ size_t data_len = 2 * kDefaultMaxPacketSize + 100;
QuicConsumedData consumed =
generator_.ConsumeData(3, CreateData(data_len), 0, true, NULL);
EXPECT_EQ(data_len, consumed.bytes_consumed);
@@ -444,7 +473,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeDataSendsFecAtEnd) {
}
// Send enough data to create 2 packets: one full and one partial.
- size_t data_len = 1 * kMaxPacketSize + 100;
+ size_t data_len = 1 * kDefaultMaxPacketSize + 100;
QuicConsumedData consumed =
generator_.ConsumeData(3, CreateData(data_len), 0, true, NULL);
EXPECT_EQ(data_len, consumed.bytes_consumed);
@@ -480,7 +509,8 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
generator_.StartBatchOperations();
// Queue enough data to prevent a stream frame with a non-zero offset from
// fitting.
- QuicConsumedData consumed = generator_.ConsumeData(1, "foo", 0, false, NULL);
+ QuicConsumedData consumed = generator_.ConsumeData(1, MakeIOVector("foo"), 0,
+ false, NULL);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
EXPECT_TRUE(generator_.HasQueuedFrames());
@@ -488,7 +518,7 @@ TEST_F(QuicPacketGeneratorTest, ConsumeData_FramesPreviouslyQueued) {
// This frame will not fit with the existing frame, causing the queued frame
// to be serialized, and it will not fit with another frame like it, so it is
// serialized by itself.
- consumed = generator_.ConsumeData(1, "bar", 3, true, NULL);
+ consumed = generator_.ConsumeData(1, MakeIOVector("bar"), 3, true, NULL);
EXPECT_EQ(3u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -517,7 +547,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations) {
Return(CreateFeedbackFrame()));
// Send some data and a control frame
- generator_.ConsumeData(3, "quux", 7, false, NULL);
+ generator_.ConsumeData(3, MakeIOVector("quux"), 7, false, NULL);
generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
// All five frames will be flushed out in a single packet.
@@ -562,7 +592,7 @@ TEST_F(QuicPacketGeneratorTest, NotWritableThenBatchOperations2) {
}
// Send enough data to exceed one packet
- size_t data_len = kMaxPacketSize + 100;
+ size_t data_len = kDefaultMaxPacketSize + 100;
QuicConsumedData consumed =
generator_.ConsumeData(3, CreateData(data_len), 0, true, NULL);
EXPECT_EQ(data_len, consumed.bytes_consumed);
diff --git a/chromium/net/quic/quic_packet_writer.h b/chromium/net/quic/quic_packet_writer.h
new file mode 100644
index 00000000000..5df30c8fa14
--- /dev/null
+++ b/chromium/net/quic/quic_packet_writer.h
@@ -0,0 +1,41 @@
+// 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_PACKET_WRITER_H_
+#define NET_QUIC_QUIC_PACKET_WRITER_H_
+
+#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+class QuicBlockedWriterInterface;
+struct WriteResult;
+
+// An interface between writers and the entity managing the
+// socket (in our case the QuicDispatcher). This allows the Dispatcher to
+// control writes, and manage any writers who end up write blocked.
+class NET_EXPORT_PRIVATE QuicPacketWriter {
+ 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.
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) = 0;
+
+ // Returns true if the writer buffers and subsequently rewrites data
+ // when an attempt to write results in the underlying socket becoming
+ // write blocked.
+ virtual bool IsWriteBlockedDataBuffered() const = 0;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_PACKET_WRITER_H_
diff --git a/chromium/net/quic/quic_protocol.cc b/chromium/net/quic/quic_protocol.cc
index cdf3c6ce4d9..cc37c111d7e 100644
--- a/chromium/net/quic/quic_protocol.cc
+++ b/chromium/net/quic/quic_protocol.cc
@@ -95,10 +95,18 @@ QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
QuicStreamFrame::QuicStreamFrame() {}
+QuicStreamFrame::QuicStreamFrame(const QuicStreamFrame& frame)
+ : stream_id(frame.stream_id),
+ fin(frame.fin),
+ offset(frame.offset),
+ data(frame.data),
+ notifier(frame.notifier) {
+}
+
QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
bool fin,
QuicStreamOffset offset,
- StringPiece data)
+ IOVector data)
: stream_id(stream_id),
fin(fin),
offset(offset),
@@ -106,6 +114,17 @@ QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
notifier(NULL) {
}
+string* QuicStreamFrame::GetDataAsString() const {
+ string* data_string = new string();
+ data_string->reserve(data.TotalBufferSize());
+ for (size_t i = 0; i < data.Size(); ++i) {
+ data_string->append(static_cast<char*>(data.iovec()[i].iov_base),
+ data.iovec()[i].iov_len);
+ }
+ DCHECK_EQ(data_string->size(), data.TotalBufferSize());
+ return data_string;
+}
+
uint32 MakeQuicTag(char a, char b, char c, char d) {
return static_cast<uint32>(a) |
static_cast<uint32>(b) << 8 |
@@ -113,20 +132,18 @@ uint32 MakeQuicTag(char a, char b, char c, char d) {
static_cast<uint32>(d) << 24;
}
-QuicVersion QuicVersionMax() { return kSupportedQuicVersions[0]; }
-
-QuicVersion QuicVersionMin() {
- return kSupportedQuicVersions[arraysize(kSupportedQuicVersions) - 1];
+QuicVersionVector QuicSupportedVersions() {
+ QuicVersionVector supported_versions;
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ supported_versions.push_back(kSupportedQuicVersions[i]);
+ }
+ return supported_versions;
}
QuicTag QuicVersionToQuicTag(const QuicVersion version) {
switch (version) {
- case QUIC_VERSION_8:
- return MakeQuicTag('Q', '0', '0', '8');
- case QUIC_VERSION_9:
- return MakeQuicTag('Q', '0', '0', '9');
- case QUIC_VERSION_10:
- return MakeQuicTag('Q', '0', '1', '0');
+ case QUIC_VERSION_12:
+ return MakeQuicTag('Q', '0', '1', '2');
default:
// This shold be an ERROR because we should never attempt to convert an
// invalid QuicVersion to be written to the wire.
@@ -136,22 +153,15 @@ QuicTag QuicVersionToQuicTag(const QuicVersion version) {
}
QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
- const QuicTag quic_tag_v8 = MakeQuicTag('Q', '0', '0', '8');
- const QuicTag quic_tag_v9 = MakeQuicTag('Q', '0', '0', '9');
- const QuicTag quic_tag_v10 = MakeQuicTag('Q', '0', '1', '0');
-
- if (version_tag == quic_tag_v8) {
- return QUIC_VERSION_8;
- } else if (version_tag == quic_tag_v9) {
- return QUIC_VERSION_9;
- } else if (version_tag == quic_tag_v10) {
- return QUIC_VERSION_10;
- } else {
- // Reading from the client so this should not be considered an ERROR.
- DLOG(INFO) << "Unsupported QuicTag version: "
- << QuicUtils::TagToString(version_tag);
- return QUIC_VERSION_UNSUPPORTED;
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ if (version_tag == QuicVersionToQuicTag(kSupportedQuicVersions[i])) {
+ return kSupportedQuicVersions[i];
+ }
}
+ // Reading from the client so this should not be considered an ERROR.
+ DVLOG(1) << "Unsupported QuicTag version: "
+ << QuicUtils::TagToString(version_tag);
+ return QUIC_VERSION_UNSUPPORTED;
}
#define RETURN_STRING_LITERAL(x) \
@@ -160,21 +170,19 @@ return #x
string QuicVersionToString(const QuicVersion version) {
switch (version) {
- RETURN_STRING_LITERAL(QUIC_VERSION_8);
- RETURN_STRING_LITERAL(QUIC_VERSION_9);
- RETURN_STRING_LITERAL(QUIC_VERSION_10);
+ RETURN_STRING_LITERAL(QUIC_VERSION_12);
default:
return "QUIC_VERSION_UNSUPPORTED";
}
}
-string QuicVersionArrayToString(const QuicVersion versions[],
- int num_versions) {
+string QuicVersionVectorToString(const QuicVersionVector& versions) {
string result = "";
- for (int i = 0; i < num_versions; ++i) {
- const QuicVersion& version = versions[i];
- result.append(QuicVersionToString(version));
- result.append(",");
+ for (size_t i = 0; i < versions.size(); ++i) {
+ if (i != 0) {
+ result.append(",");
+ }
+ result.append(QuicVersionToString(versions[i]));
}
return result;
}
@@ -201,10 +209,10 @@ ostream& operator<<(ostream& os, const QuicPacketHeader& header) {
return os;
}
-// TODO(ianswett): Initializing largest_observed to 0 should not be necessary.
ReceivedPacketInfo::ReceivedPacketInfo()
: largest_observed(0),
- delta_time_largest_observed(QuicTime::Delta::Infinite()) {
+ delta_time_largest_observed(QuicTime::Delta::Infinite()),
+ is_truncated(false) {
}
ReceivedPacketInfo::~ReceivedPacketInfo() {}
@@ -293,13 +301,13 @@ ostream& operator<<(ostream& os,
break;
}
}
- return os;
+ return os;
}
ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) {
os << "sent info { " << ack_frame.sent_info << " } "
<< "received info { " << ack_frame.received_info << " }\n";
- return os;
+ return os;
}
CongestionFeedbackMessageFixRate::CongestionFeedbackMessageFixRate()
@@ -394,12 +402,12 @@ RetransmittableFrames::~RetransmittableFrames() {
const QuicFrame& RetransmittableFrames::AddStreamFrame(
QuicStreamFrame* stream_frame) {
- // Make an owned copy of the StringPiece.
- string* stream_data = new string(stream_frame->data.data(),
- stream_frame->data.size());
- // Ensure the frame's StringPiece points to the owned copy of the data.
- stream_frame->data = StringPiece(*stream_data);
- stream_data_.push_back(stream_data);
+ // Make an owned copy of the stream frame's data.
+ stream_data_.push_back(stream_frame->GetDataAsString());
+ // Ensure the stream frame's IOVector points to the owned copy of the data.
+ stream_frame->data.Clear();
+ stream_frame->data.Append(const_cast<char*>(stream_data_.back()->data()),
+ stream_data_.back()->size());
frames_.push_back(QuicFrame(stream_frame));
return frames_.back();
}
@@ -430,6 +438,12 @@ SerializedPacket::SerializedPacket(
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;
diff --git a/chromium/net/quic/quic_protocol.h b/chromium/net/quic/quic_protocol.h
index 26e6c027682..e97e2fc77aa 100644
--- a/chromium/net/quic/quic_protocol.h
+++ b/chromium/net/quic/quic_protocol.h
@@ -20,6 +20,7 @@
#include "base/strings/string_piece.h"
#include "net/base/int128.h"
#include "net/base/net_export.h"
+#include "net/quic/iovector.h"
#include "net/quic/quic_bandwidth.h"
#include "net/quic/quic_time.h"
@@ -45,8 +46,26 @@ typedef std::vector<QuicTag> QuicTagVector;
typedef uint32 QuicPriority;
// TODO(rch): Consider Quic specific names for these constants.
-// Maximum size in bytes of a QUIC packet.
-const QuicByteCount kMaxPacketSize = 1200;
+// Default and initial maximum size in bytes of a QUIC packet.
+const QuicByteCount kDefaultMaxPacketSize = 1200;
+// The maximum packet size of any QUIC packet, based on ethernet's max size,
+// minus the IP and UDP headers. IPv6 has a 40 byte header, UPD adds an
+// additional 8 bytes. This is a total overhead of 48 bytes. Ethernet's
+// max packet size is 1500 bytes, 1500 - 48 = 1452.
+const QuicByteCount kMaxPacketSize = 1452;
+
+// Maximum size of the initial congestion window in packets.
+const size_t kDefaultInitialWindow = 10;
+// TODO(ianswett): Temporarily changed to 10 due to a large number of clients
+// mistakenly negotiating 100 initially and suffering the consequences.
+const size_t kMaxInitialWindow = 10;
+
+// Maximum size of the congestion window, in packets, for TCP congestion control
+// algorithms.
+const size_t kMaxTcpCongestionWindow = 200;
+
+// Don't allow a client to suggest an RTT longer than 15 seconds.
+const size_t kMaxInitialRoundTripTimeUs = 15 * kNumMicrosPerSecond;
// Maximum number of open streams per connection.
const size_t kDefaultMaxStreamsPerConnection = 100;
@@ -83,9 +102,32 @@ const int64 kDefaultInitialTimeoutSecs = 120; // 2 mins.
const int64 kDefaultTimeoutSecs = 60 * 10; // 10 minutes.
const int64 kDefaultMaxTimeForCryptoHandshakeSecs = 5; // 5 secs.
-enum Retransmission {
+// We define an unsigned 16-bit floating point value, inspired by IEEE floats
+// (http://en.wikipedia.org/wiki/Half_precision_floating-point_format),
+// with 5-bit exponent (bias 1), 11-bit mantissa (effective 12 with hidden
+// bit) and denormals, but without signs, transfinites or fractions. Wire format
+// 16 bits (little-endian byte order) are split into exponent (high 5) and
+// mantissa (low 11) and decoded as:
+// uint64 value;
+// if (exponent == 0) value = mantissa;
+// else value = (mantissa | 1 << 11) << (exponent - 1)
+const int kUFloat16ExponentBits = 5;
+const int kUFloat16MaxExponent = (1 << kUFloat16ExponentBits) - 2; // 30
+const int kUFloat16MantissaBits = 16 - kUFloat16ExponentBits; // 11
+const int kUFloat16MantissaEffectiveBits = kUFloat16MantissaBits + 1; // 12
+const uint64 kUFloat16MaxValue = // 0x3FFC0000000
+ ((GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits) - 1) <<
+ kUFloat16MaxExponent;
+
+enum TransmissionType {
NOT_RETRANSMISSION,
- IS_RETRANSMISSION,
+ NACK_RETRANSMISSION,
+ RTO_RETRANSMISSION,
+};
+
+enum RetransmissionType {
+ INITIAL_ENCRYPTION_ONLY,
+ ALL_PACKETS
};
enum HasRetransmittableData {
@@ -128,6 +170,14 @@ enum QuicSequenceNumberLength {
PACKET_6BYTE_SEQUENCE_NUMBER = 6
};
+// Used to indicate a QuicSequenceNumberLength using two flag bits.
+enum QuicSequenceNumberLengthFlags {
+ PACKET_FLAGS_1BYTE_SEQUENCE = 0, // 00
+ PACKET_FLAGS_2BYTE_SEQUENCE = 1, // 01
+ PACKET_FLAGS_4BYTE_SEQUENCE = 1 << 1, // 10
+ PACKET_FLAGS_6BYTE_SEQUENCE = 1 << 1 | 1, // 11
+};
+
// The public flags are specified in one byte.
enum QuicPacketPublicFlags {
PACKET_PUBLIC_FLAGS_NONE = 0,
@@ -153,10 +203,10 @@ enum QuicPacketPublicFlags {
// --01----: 2 bytes
// --10----: 4 bytes
// --11----: 6 bytes
- PACKET_PUBLIC_FLAGS_1BYTE_SEQUENCE = 0,
- PACKET_PUBLIC_FLAGS_2BYTE_SEQUENCE = 1 << 4,
- PACKET_PUBLIC_FLAGS_4BYTE_SEQUENCE = 1 << 5,
- PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE = 1 << 5 | 1 << 4,
+ PACKET_PUBLIC_FLAGS_1BYTE_SEQUENCE = PACKET_FLAGS_1BYTE_SEQUENCE << 4,
+ PACKET_PUBLIC_FLAGS_2BYTE_SEQUENCE = PACKET_FLAGS_2BYTE_SEQUENCE << 4,
+ PACKET_PUBLIC_FLAGS_4BYTE_SEQUENCE = PACKET_FLAGS_4BYTE_SEQUENCE << 4,
+ PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE = PACKET_FLAGS_6BYTE_SEQUENCE << 4,
// All bits set (bits 6 and 7 are not currently used): 00111111
PACKET_PUBLIC_FLAGS_MAX = (1 << 6) - 1
@@ -189,25 +239,22 @@ enum QuicVersion {
// Special case to indicate unknown/unsupported QUIC version.
QUIC_VERSION_UNSUPPORTED = 0,
- QUIC_VERSION_8 = 8,
- QUIC_VERSION_9 = 9,
- QUIC_VERSION_10 = 10, // Current version.
+ QUIC_VERSION_12 = 12, // Current version.
};
// This vector contains QUIC versions which we currently support.
// This should be ordered such that the highest supported version is the first
// element, with subsequent elements in descending order (versions can be
// skipped as necessary).
-static const QuicVersion kSupportedQuicVersions[] =
- {QUIC_VERSION_10, QUIC_VERSION_9};
+//
+// IMPORTANT: if you are addding to this list, follow the instructions at
+// http://sites/quic/adding-and-removing-versions
+static const QuicVersion kSupportedQuicVersions[] = {QUIC_VERSION_12};
typedef std::vector<QuicVersion> QuicVersionVector;
-// Upper limit on versions we support.
-NET_EXPORT_PRIVATE QuicVersion QuicVersionMax();
-
-// Lower limit on versions we support.
-NET_EXPORT_PRIVATE QuicVersion QuicVersionMin();
+// Returns a vector of QUIC versions in kSupportedQuicVersions.
+NET_EXPORT_PRIVATE QuicVersionVector QuicSupportedVersions();
// QuicTag is written to and read from the wire, but we prefer to use
// the more readable QuicVersion at other levels.
@@ -219,18 +266,14 @@ NET_EXPORT_PRIVATE QuicTag QuicVersionToQuicTag(const QuicVersion version);
// Returns QUIC_VERSION_UNSUPPORTED if version_tag cannot be understood.
NET_EXPORT_PRIVATE QuicVersion QuicTagToQuicVersion(const QuicTag version_tag);
-// Returns the appropriate QuicTag for a properly formed version string
-// (e.g. Q008).
-NET_EXPORT_PRIVATE QuicTag StringToQuicTag(std::string version);
-
// Helper function which translates from a QuicVersion to a string.
// Returns strings corresponding to enum names (e.g. QUIC_VERSION_6).
NET_EXPORT_PRIVATE std::string QuicVersionToString(const QuicVersion version);
// Returns comma separated list of string representations of QuicVersion enum
-// values in the supplied QuicVersionArray.
-NET_EXPORT_PRIVATE std::string QuicVersionArrayToString(
- const QuicVersion versions[], int num_versions);
+// values in the supplied |versions| vector.
+NET_EXPORT_PRIVATE std::string QuicVersionVectorToString(
+ const QuicVersionVector& versions);
// Version and Crypto tags are written to the wire with a big-endian
// representation of the name of the tag. For example
@@ -377,6 +420,8 @@ enum QuicErrorCode {
QUIC_INVALID_CRYPTO_MESSAGE_TYPE = 33,
// A crypto message was received with an illegal parameter.
QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER = 34,
+ // An invalid channel id signature was supplied.
+ QUIC_INVALID_CHANNEL_ID_SIGNATURE = 52,
// A crypto message was received with a mandatory parameter missing.
QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND = 35,
// A crypto message was received with a parameter that has no overlap
@@ -403,9 +448,17 @@ enum QuicErrorCode {
QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT = 44,
// The server config for a server has expired.
QUIC_CRYPTO_SERVER_CONFIG_EXPIRED = 45,
+ // We failed to setup the symmetric keys for a connection.
+ QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED = 53,
+ // A handshake message arrived, but we are still validating the
+ // previous handshake message.
+ QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO = 54,
+ // This connection involved a version negotiation which appears to have been
+ // tampered with.
+ QUIC_VERSION_NEGOTIATION_MISMATCH = 55,
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 52,
+ QUIC_LAST_ERROR = 56,
};
struct NET_EXPORT_PRIVATE QuicPacketPublicHeader {
@@ -470,15 +523,20 @@ struct NET_EXPORT_PRIVATE QuicPaddingFrame {
struct NET_EXPORT_PRIVATE QuicStreamFrame {
QuicStreamFrame();
+ QuicStreamFrame(const QuicStreamFrame& frame);
QuicStreamFrame(QuicStreamId stream_id,
bool fin,
QuicStreamOffset offset,
- base::StringPiece data);
+ IOVector data);
+
+ // Returns a copy of the IOVector |data| as a heap-allocated string.
+ // Caller must take ownership of the returned string.
+ std::string* GetDataAsString() const;
QuicStreamId stream_id;
bool fin;
QuicStreamOffset offset; // Location of this data in the stream.
- base::StringPiece data;
+ IOVector data;
// If this is set, then when this packet is ACKed the AckNotifier will be
// informed.
@@ -519,6 +577,9 @@ struct NET_EXPORT_PRIVATE ReceivedPacketInfo {
// structure.
// The set of packets which we're expecting and have not received.
SequenceNumberSet missing_packets;
+
+ // Whether the ack had to be truncated when sent.
+ bool is_truncated;
};
// True if the sequence number is greater than largest_observed or is listed
@@ -620,7 +681,6 @@ struct NET_EXPORT_PRIVATE QuicRstStreamFrame {
struct NET_EXPORT_PRIVATE QuicConnectionCloseFrame {
QuicErrorCode error_code;
std::string error_details;
- QuicAckFrame ack_frame;
};
struct NET_EXPORT_PRIVATE QuicGoAwayFrame {
@@ -795,6 +855,9 @@ class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData {
QuicEncryptedPacket(char* buffer, size_t length, bool owns_buffer)
: QuicData(buffer, length, owns_buffer) {}
+ // Clones the packet into a new packet which owns the buffer.
+ QuicEncryptedPacket* Clone() const;
+
// By default, gtest prints the raw bytes of an object. The bool data
// member (in the base class QuicData) causes this object to have padding
// bytes, which causes the default gtest object printer to read
@@ -870,6 +933,26 @@ struct QuicConsumedData {
bool fin_consumed;
};
+enum WriteStatus {
+ WRITE_STATUS_OK,
+ WRITE_STATUS_BLOCKED,
+ WRITE_STATUS_ERROR,
+};
+
+// A struct used to return the result of write calls including either the number
+// of bytes written or the error code, depending upon the status.
+struct NET_EXPORT_PRIVATE WriteResult {
+ WriteResult(WriteStatus status, int bytes_written_or_error_code) :
+ status(status), bytes_written(bytes_written_or_error_code) {
+ }
+
+ WriteStatus status;
+ union {
+ int bytes_written; // only valid when status is OK
+ int error_code; // only valid when status is ERROR
+ };
+};
+
} // namespace net
#endif // NET_QUIC_QUIC_PROTOCOL_H_
diff --git a/chromium/net/quic/quic_protocol_test.cc b/chromium/net/quic/quic_protocol_test.cc
index 52ed6645c94..bf1fece981c 100644
--- a/chromium/net/quic/quic_protocol_test.cc
+++ b/chromium/net/quic/quic_protocol_test.cc
@@ -56,14 +56,14 @@ TEST(QuicProtocolTest, QuicVersionToQuicTag) {
#endif
// Explicitly test a specific version.
- EXPECT_EQ(MakeQuicTag('Q', '0', '1', '0'),
- QuicVersionToQuicTag(QUIC_VERSION_10));
+ EXPECT_EQ(MakeQuicTag('Q', '0', '1', '2'),
+ QuicVersionToQuicTag(QUIC_VERSION_12));
// Loop over all supported versions and make sure that we never hit the
// default case (i.e. all supported versions should be successfully converted
// to valid QuicTags).
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- const QuicVersion& version = kSupportedQuicVersions[i];
+ QuicVersion version = kSupportedQuicVersions[i];
EXPECT_LT(0u, QuicVersionToQuicTag(version));
}
}
@@ -95,11 +95,11 @@ TEST(QuicProtocolTest, QuicTagToQuicVersion) {
#endif
// Explicitly test specific versions.
- EXPECT_EQ(QUIC_VERSION_10,
- QuicTagToQuicVersion(MakeQuicTag('Q', '0', '1', '0')));
+ EXPECT_EQ(QUIC_VERSION_12,
+ QuicTagToQuicVersion(MakeQuicTag('Q', '0', '1', '2')));
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
- const QuicVersion& version = kSupportedQuicVersions[i];
+ QuicVersion version = kSupportedQuicVersions[i];
// Get the tag from the version (we can loop over QuicVersions easily).
QuicTag tag = QuicVersionToQuicTag(version);
@@ -127,19 +127,30 @@ TEST(QuicProtocolTest, QuicTagToQuicVersionUnsupported) {
}
TEST(QuicProtocolTest, QuicVersionToString) {
- EXPECT_EQ("QUIC_VERSION_8",
- QuicVersionToString(QUIC_VERSION_8));
+ EXPECT_EQ("QUIC_VERSION_12", QuicVersionToString(QUIC_VERSION_12));
EXPECT_EQ("QUIC_VERSION_UNSUPPORTED",
QuicVersionToString(QUIC_VERSION_UNSUPPORTED));
- QuicVersion single_version[] = {QUIC_VERSION_8};
- EXPECT_EQ("QUIC_VERSION_8,", QuicVersionArrayToString(
- single_version, arraysize(single_version)));
- QuicVersion multiple_versions[] =
- {QUIC_VERSION_10, QUIC_VERSION_9, QUIC_VERSION_8};
- EXPECT_EQ("QUIC_VERSION_10,QUIC_VERSION_9,QUIC_VERSION_8,",
- QuicVersionArrayToString(multiple_versions,
- arraysize(multiple_versions)));
+ QuicVersion single_version[] = {QUIC_VERSION_12};
+ QuicVersionVector versions_vector;
+ for (size_t i = 0; i < arraysize(single_version); ++i) {
+ versions_vector.push_back(single_version[i]);
+ }
+ EXPECT_EQ("QUIC_VERSION_12", QuicVersionVectorToString(versions_vector));
+
+ QuicVersion multiple_versions[] = {QUIC_VERSION_UNSUPPORTED, QUIC_VERSION_12};
+ versions_vector.clear();
+ for (size_t i = 0; i < arraysize(multiple_versions); ++i) {
+ versions_vector.push_back(multiple_versions[i]);
+ }
+ EXPECT_EQ("QUIC_VERSION_UNSUPPORTED,QUIC_VERSION_12",
+ QuicVersionVectorToString(versions_vector));
+
+ // Make sure that all supported versions are present in QuicVersionToString.
+ for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
+ QuicVersion version = kSupportedQuicVersions[i];
+ EXPECT_NE("QUIC_VERSION_UNSUPPORTED", QuicVersionToString(version));
+ }
}
} // namespace
diff --git a/chromium/net/quic/quic_received_packet_manager.cc b/chromium/net/quic/quic_received_packet_manager.cc
index 9a136db5202..b24ac7c671e 100644
--- a/chromium/net/quic/quic_received_packet_manager.cc
+++ b/chromium/net/quic/quic_received_packet_manager.cc
@@ -5,6 +5,7 @@
#include "net/quic/quic_received_packet_manager.h"
#include "base/logging.h"
+#include "base/stl_util.h"
#include "net/base/linked_hash_map.h"
using std::make_pair;
@@ -13,13 +14,26 @@ using std::min;
namespace net {
-QuicReceivedPacketManager::QuicReceivedPacketManager()
+namespace {
+
+// The maximum number of packets to ack immediately after a missing packet for
+// fast retransmission to kick in at the sender. This limit is created to
+// reduce the number of acks sent that have no benefit for fast retransmission.
+// Set to the number of nacks needed for fast retransmit plus one for protection
+// against an ack loss
+const size_t kMaxPacketsAfterNewMissing = 4;
+
+}
+
+QuicReceivedPacketManager::QuicReceivedPacketManager(
+ CongestionFeedbackType congestion_type)
: packets_entropy_hash_(0),
largest_sequence_number_(0),
peer_largest_observed_packet_(0),
least_packet_awaited_by_peer_(1),
peer_least_packet_awaiting_ack_(0),
- time_largest_observed_(QuicTime::Zero()) {
+ time_largest_observed_(QuicTime::Zero()),
+ receive_algorithm_(ReceiveAlgorithmInterface::Create(congestion_type)) {
received_info_.largest_observed = 0;
received_info_.entropy_hash = 0;
}
@@ -27,7 +41,10 @@ QuicReceivedPacketManager::QuicReceivedPacketManager()
QuicReceivedPacketManager::~QuicReceivedPacketManager() {}
void QuicReceivedPacketManager::RecordPacketReceived(
- const QuicPacketHeader& header, QuicTime receipt_time) {
+ QuicByteCount bytes,
+ const QuicPacketHeader& header,
+ QuicTime receipt_time,
+ bool revived) {
QuicPacketSequenceNumber sequence_number = header.packet_sequence_number;
DCHECK(IsAwaitingPacket(sequence_number));
@@ -47,6 +64,17 @@ void QuicReceivedPacketManager::RecordPacketReceived(
time_largest_observed_ = receipt_time;
}
RecordPacketEntropyHash(sequence_number, header.entropy_hash);
+
+ // Don't update the receive algorithm for revived packets.
+ if (!revived) {
+ receive_algorithm_->RecordIncomingPacket(
+ bytes, sequence_number, receipt_time, revived);
+ }
+}
+
+bool QuicReceivedPacketManager::IsMissing(
+ QuicPacketSequenceNumber sequence_number) {
+ return ContainsKey(received_info_.missing_packets, sequence_number);
}
bool QuicReceivedPacketManager::IsAwaitingPacket(
@@ -55,26 +83,32 @@ bool QuicReceivedPacketManager::IsAwaitingPacket(
}
void QuicReceivedPacketManager::UpdateReceivedPacketInfo(
- ReceivedPacketInfo* received_info, QuicTime approximate_now) {
+ ReceivedPacketInfo* received_info,
+ QuicTime approximate_now) {
*received_info = received_info_;
received_info->entropy_hash = EntropyHash(received_info_.largest_observed);
+
if (time_largest_observed_ == QuicTime::Zero()) {
- // We have not received any new higher sequence numbers since we sent our
- // last ACK.
+ // We have received no packets.
received_info->delta_time_largest_observed = QuicTime::Delta::Infinite();
- } else {
- received_info->delta_time_largest_observed =
- approximate_now.Subtract(time_largest_observed_);
+ return;
+ }
- time_largest_observed_ = QuicTime::Zero();
+ if (approximate_now < time_largest_observed_) {
+ // Approximate now may well be "in the past".
+ received_info->delta_time_largest_observed = QuicTime::Delta::Zero();
+ return;
}
+
+ received_info->delta_time_largest_observed =
+ approximate_now.Subtract(time_largest_observed_);
}
void QuicReceivedPacketManager::RecordPacketEntropyHash(
QuicPacketSequenceNumber sequence_number,
QuicPacketEntropyHash entropy_hash) {
if (sequence_number < largest_sequence_number_) {
- DLOG(INFO) << "Ignoring received packet entropy for sequence_number:"
+ DVLOG(1) << "Ignoring received packet entropy for sequence_number:"
<< sequence_number << " less than largest_peer_sequence_number:"
<< largest_sequence_number_;
return;
@@ -87,6 +121,11 @@ void QuicReceivedPacketManager::RecordPacketEntropyHash(
<< " entropy hash: " << static_cast<int>(entropy_hash);
}
+bool QuicReceivedPacketManager::GenerateCongestionFeedback(
+ QuicCongestionFeedbackFrame* feedback) {
+ return receive_algorithm_->GenerateCongestionFeedback(feedback);
+}
+
QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
QuicPacketSequenceNumber sequence_number) const {
DCHECK_LE(sequence_number, received_info_.largest_observed);
@@ -98,11 +137,13 @@ QuicPacketEntropyHash QuicReceivedPacketManager::EntropyHash(
ReceivedEntropyMap::const_iterator it =
packets_entropy_.upper_bound(sequence_number);
// When this map is empty we should only query entropy for
- // |largest_received_sequence_number_|.
+ // received_info_.largest_observed, since no other entropy can be correctly
+ // calculated, because we're not storing the entropy for any prior packets.
// TODO(rtenneti): add support for LOG_IF_EVERY_N_SEC to chromium.
- // LOG_IF_EVERY_N_SEC(WARNING, it != packets_entropy_.end(), 10)
- LOG_IF(WARNING, it != packets_entropy_.end())
- << "largest_received: " << received_info_.largest_observed
+ // LOG_IF_EVERY_N_SEC(DFATAL, it == packets_entropy_.end(), 10)
+ LOG_IF(DFATAL, it == packets_entropy_.end())
+ << "EntropyHash may be unknown. largest_received: "
+ << received_info_.largest_observed
<< " sequence_number: " << sequence_number;
// TODO(satyamshekhar): Make this O(1).
@@ -118,7 +159,7 @@ void QuicReceivedPacketManager::RecalculateEntropyHash(
QuicPacketEntropyHash entropy_hash) {
DCHECK_LE(peer_least_unacked, received_info_.largest_observed);
if (peer_least_unacked < largest_sequence_number_) {
- DLOG(INFO) << "Ignoring received peer_least_unacked:" << peer_least_unacked
+ DVLOG(1) << "Ignoring received peer_least_unacked:" << peer_least_unacked
<< " less than largest_peer_sequence_number:"
<< largest_sequence_number_;
return;
@@ -185,4 +226,14 @@ void QuicReceivedPacketManager::UpdatePacketInformationSentByPeer(
peer_least_packet_awaiting_ack_);
}
+bool QuicReceivedPacketManager::HasMissingPackets() {
+ return !received_info_.missing_packets.empty();
+}
+
+bool QuicReceivedPacketManager::HasNewMissingPackets() {
+ return HasMissingPackets() &&
+ (received_info_.largest_observed -
+ *received_info_.missing_packets.rbegin()) <= kMaxPacketsAfterNewMissing;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_received_packet_manager.h b/chromium/net/quic/quic_received_packet_manager.h
index a762ae804c7..9e2fb59c241 100644
--- a/chromium/net/quic/quic_received_packet_manager.h
+++ b/chromium/net/quic/quic_received_packet_manager.h
@@ -8,12 +8,14 @@
#ifndef NET_QUIC_QUIC_RECEIVED_PACKET_MANAGER_H_
#define NET_QUIC_QUIC_RECEIVED_PACKET_MANAGER_H_
+#include "net/quic/congestion_control/receive_algorithm_interface.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_protocol.h"
namespace net {
namespace test {
+class QuicConnectionPeer;
class QuicReceivedPacketManagerPeer;
} // namespace test
@@ -23,12 +25,22 @@ class QuicReceivedPacketManagerPeer;
class NET_EXPORT_PRIVATE QuicReceivedPacketManager :
public QuicReceivedEntropyHashCalculatorInterface {
public:
- QuicReceivedPacketManager();
+ explicit QuicReceivedPacketManager(CongestionFeedbackType congestion_type);
virtual ~QuicReceivedPacketManager();
- // Updates the internal state concerning which packets have been acked.
- void RecordPacketReceived(const QuicPacketHeader& header,
- QuicTime receipt_time);
+ // Updates the internal state concerning which packets have been received.
+ // bytes: the packet size in bytes including Quic Headers.
+ // header: the packet header.
+ // timestamp: the arrival time of the packet.
+ // revived: true if the packet was lost and then recovered with help of a
+ // FEC packet.
+ void RecordPacketReceived(QuicByteCount bytes,
+ const QuicPacketHeader& header,
+ QuicTime receipt_time,
+ bool revived);
+
+ // Checks whether |sequence_number| is missing and less than largest observed.
+ bool IsMissing(QuicPacketSequenceNumber sequence_number);
// Checks if we're still waiting for the packet with |sequence_number|.
bool IsAwaitingPacket(QuicPacketSequenceNumber sequence_number);
@@ -37,6 +49,13 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager :
void UpdateReceivedPacketInfo(ReceivedPacketInfo* received_info,
QuicTime approximate_now);
+ // Should be called before sending an ACK packet, to decide if we need
+ // to attach a QuicCongestionFeedbackFrame block.
+ // Returns false if no QuicCongestionFeedbackFrame block is needed.
+ // Otherwise fills in feedback and returns true.
+ virtual bool GenerateCongestionFeedback(
+ QuicCongestionFeedbackFrame* feedback);
+
// QuicReceivedEntropyHashCalculatorInterface
// Called by QuicFramer, when the outgoing ack gets truncated, to recalculate
// the received entropy hash for the truncated ack frame.
@@ -50,6 +69,13 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager :
// Updates internal state based on |incoming_ack.sent_info|.
void UpdatePacketInformationSentByPeer(const QuicAckFrame& incoming_ack);
+ // Returns whether the peer is missing packets.
+ bool HasMissingPackets();
+
+ // Returns true when there are new missing packets to be reported within 3
+ // packets of the largest observed.
+ bool HasNewMissingPackets();
+
QuicPacketSequenceNumber peer_largest_observed_packet() {
return peer_largest_observed_packet_;
}
@@ -63,6 +89,7 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager :
}
private:
+ friend class test::QuicConnectionPeer;
friend class test::QuicReceivedPacketManagerPeer;
typedef std::map<QuicPacketSequenceNumber,
@@ -117,6 +144,8 @@ class NET_EXPORT_PRIVATE QuicReceivedPacketManager :
// no sequence numbers have been received since UpdateReceivedPacketInfo.
// Needed for calculating delta_time_largest_observed.
QuicTime time_largest_observed_;
+
+ scoped_ptr<ReceiveAlgorithmInterface> receive_algorithm_;
};
} // namespace net
diff --git a/chromium/net/quic/quic_received_packet_manager_test.cc b/chromium/net/quic/quic_received_packet_manager_test.cc
index 76be470c265..9d11129f0ff 100644
--- a/chromium/net/quic/quic_received_packet_manager_test.cc
+++ b/chromium/net/quic/quic_received_packet_manager_test.cc
@@ -21,12 +21,14 @@ namespace {
class QuicReceivedPacketManagerTest : public ::testing::Test {
protected:
+ QuicReceivedPacketManagerTest() : received_manager_(kTCP) { }
+
void RecordPacketEntropyHash(QuicPacketSequenceNumber sequence_number,
QuicPacketEntropyHash entropy_hash) {
QuicPacketHeader header;
header.packet_sequence_number = sequence_number;
header.entropy_hash = entropy_hash;
- received_manager_.RecordPacketReceived(header, QuicTime::Zero());;
+ received_manager_.RecordPacketReceived(0u, header, QuicTime::Zero(), false);
}
QuicReceivedPacketManager received_manager_;
@@ -103,9 +105,9 @@ TEST_F(QuicReceivedPacketManagerTest, RecalculateEntropyHash) {
TEST_F(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) {
QuicPacketHeader header;
header.packet_sequence_number = 2u;
- received_manager_.RecordPacketReceived(header, QuicTime::Zero());
+ received_manager_.RecordPacketReceived(0u, header, QuicTime::Zero(), false);
header.packet_sequence_number = 7u;
- received_manager_.RecordPacketReceived(header, QuicTime::Zero());
+ received_manager_.RecordPacketReceived(0u, header, QuicTime::Zero(), false);
EXPECT_TRUE(received_manager_.IsAwaitingPacket(3u));
EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u));
EXPECT_TRUE(QuicReceivedPacketManagerPeer::DontWaitForPacketsBefore(
@@ -114,6 +116,26 @@ TEST_F(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) {
EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u));
}
+TEST_F(QuicReceivedPacketManagerTest, UpdateReceivedPacketInfo) {
+ QuicPacketHeader header;
+ header.packet_sequence_number = 2u;
+ QuicTime two_ms = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(2));
+ received_manager_.RecordPacketReceived(0u, header, two_ms, false);
+
+ ReceivedPacketInfo info;
+ received_manager_.UpdateReceivedPacketInfo(&info, QuicTime::Zero());
+ // 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(), info.delta_time_largest_observed);
+
+ QuicTime four_ms = QuicTime::Zero().Add(QuicTime::Delta::FromMilliseconds(4));
+ received_manager_.UpdateReceivedPacketInfo(&info, four_ms);
+ // When UpdateReceivedPacketInfo after not having received a new packet,
+ // the delta should still be accurate.
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
+ info.delta_time_largest_observed);
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_reliable_client_stream.cc b/chromium/net/quic/quic_reliable_client_stream.cc
index 06b3178cdad..af12b8b222b 100644
--- a/chromium/net/quic/quic_reliable_client_stream.cc
+++ b/chromium/net/quic/quic_reliable_client_stream.cc
@@ -14,7 +14,7 @@ namespace net {
QuicReliableClientStream::QuicReliableClientStream(QuicStreamId id,
QuicSession* session,
const BoundNetLog& net_log)
- : ReliableQuicStream(id, session),
+ : QuicDataStream(id, session),
net_log_(net_log),
delegate_(NULL) {
}
@@ -33,18 +33,18 @@ uint32 QuicReliableClientStream::ProcessData(const char* data,
int rv = delegate_->OnDataReceived(data, data_len);
if (rv != OK) {
DLOG(ERROR) << "Delegate refused data, rv: " << rv;
- Close(QUIC_BAD_APPLICATION_PAYLOAD);
+ Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return 0;
}
return data_len;
}
-void QuicReliableClientStream::TerminateFromPeer(bool half_close) {
+void QuicReliableClientStream::OnFinRead() {
if (delegate_) {
delegate_->OnClose(connection_error());
delegate_ = NULL;
}
- ReliableQuicStream::TerminateFromPeer(half_close);
+ ReliableQuicStream::OnFinRead();
}
void QuicReliableClientStream::OnCanWrite() {
@@ -57,7 +57,7 @@ void QuicReliableClientStream::OnCanWrite() {
QuicPriority QuicReliableClientStream::EffectivePriority() const {
if (delegate_ && delegate_->HasSendHeadersComplete()) {
- return ReliableQuicStream::EffectivePriority();
+ return QuicDataStream::EffectivePriority();
}
return kHighestPriority;
}
@@ -69,7 +69,7 @@ int QuicReliableClientStream::WriteStreamData(
// We should not have data buffered.
DCHECK(!HasBufferedData());
// Writes the data, or buffers it.
- WriteData(data, fin);
+ WriteOrBufferData(data, fin);
if (!HasBufferedData()) {
return OK;
}
@@ -92,4 +92,16 @@ void QuicReliableClientStream::OnError(int error) {
}
}
+bool QuicReliableClientStream::CanWrite(const CompletionCallback& callback) {
+ bool can_write = session()->connection()->CanWrite(
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA,
+ id() == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE);
+ if (!can_write) {
+ session()->MarkWriteBlocked(id(), EffectivePriority());
+ DCHECK(callback_.is_null());
+ callback_ = callback;
+ }
+ return can_write;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_reliable_client_stream.h b/chromium/net/quic/quic_reliable_client_stream.h
index bf3fc158d45..2d5b818b653 100644
--- a/chromium/net/quic/quic_reliable_client_stream.h
+++ b/chromium/net/quic/quic_reliable_client_stream.h
@@ -12,7 +12,7 @@
#include "net/http/http_request_info.h"
#include "net/http/http_response_info.h"
#include "net/http/http_stream.h"
-#include "net/quic/reliable_quic_stream.h"
+#include "net/quic/quic_data_stream.h"
namespace net {
@@ -20,24 +20,13 @@ class QuicClientSession;
// A client-initiated ReliableQuicStream. Instances of this class
// are owned by the QuicClientSession which created them.
-class NET_EXPORT_PRIVATE QuicReliableClientStream : public ReliableQuicStream {
+class NET_EXPORT_PRIVATE QuicReliableClientStream : public QuicDataStream {
public:
// Delegate handles protocol specific behavior of a quic stream.
class NET_EXPORT_PRIVATE Delegate {
public:
Delegate() {}
- // Called when stream is ready to send data.
- // Returns network error code. OK when it successfully sent data.
- // ERR_IO_PENDING when performing operation asynchronously.
- virtual int OnSendData() = 0;
-
- // Called when data has been sent. |status| indicates network error
- // or number of bytes that has been sent. On return, |eof| is set to true
- // if no more data is available to send.
- // Returns network error code. OK when it successfully sent data.
- virtual int OnSendDataComplete(int status, bool* eof) = 0;
-
// Called when data is received.
// Returns network error code. OK when it successfully receives data.
virtual int OnDataReceived(const char* data, int length) = 0;
@@ -64,15 +53,15 @@ class NET_EXPORT_PRIVATE QuicReliableClientStream : public ReliableQuicStream {
virtual ~QuicReliableClientStream();
- // ReliableQuicStream
+ // QuicDataStream
virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE;
- virtual void TerminateFromPeer(bool half_close) OVERRIDE;
+ virtual void OnFinRead() OVERRIDE;
virtual void OnCanWrite() OVERRIDE;
virtual QuicPriority EffectivePriority() 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.
- using ReliableQuicStream::set_priority;
+ using QuicDataStream::set_priority;
int WriteStreamData(base::StringPiece data,
bool fin,
@@ -84,8 +73,16 @@ class NET_EXPORT_PRIVATE QuicReliableClientStream : public ReliableQuicStream {
Delegate* GetDelegate() { return delegate_; }
void OnError(int error);
+ // Returns true if the stream can possible write data. (The socket may
+ // turn out to be write blocked, of course). If the stream can not write,
+ // this method returns false, and |callback| will be invoked when
+ // it becomes writable.
+ bool CanWrite(const CompletionCallback& callback);
+
const BoundNetLog& net_log() const { return net_log_; }
+ using QuicDataStream::HasBufferedData;
+
private:
BoundNetLog net_log_;
Delegate* delegate_;
diff --git a/chromium/net/quic/quic_reliable_client_stream_test.cc b/chromium/net/quic/quic_reliable_client_stream_test.cc
index aaebda27fe0..081186ec846 100644
--- a/chromium/net/quic/quic_reliable_client_stream_test.cc
+++ b/chromium/net/quic/quic_reliable_client_stream_test.cc
@@ -8,6 +8,7 @@
#include "net/base/test_completion_callback.h"
#include "net/quic/quic_client_session.h"
#include "net/quic/quic_utils.h"
+#include "net/quic/spdy_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -19,6 +20,8 @@ namespace net {
namespace test {
namespace {
+const QuicGuid kStreamId = 3;
+
class MockDelegate : public QuicReliableClientStream::Delegate {
public:
MockDelegate() {}
@@ -37,21 +40,63 @@ class MockDelegate : public QuicReliableClientStream::Delegate {
class QuicReliableClientStreamTest : public ::testing::Test {
public:
QuicReliableClientStreamTest()
- : session_(new MockConnection(1, IPEndPoint(), false), false),
- stream_(1, &session_, BoundNetLog()) {
+ : session_(new MockConnection(false)),
+ stream_(kStreamId, &session_, BoundNetLog()) {
stream_.SetDelegate(&delegate_);
}
+ void InitializeHeaders() {
+ headers_[":host"] = "www.google.com";
+ headers_[":path"] = "/index.hml";
+ headers_[":scheme"] = "https";
+ headers_["cookie"] =
+ "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; "
+ "__utmc=160408618; "
+ "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX"
+ "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX"
+ "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT"
+ "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0"
+ "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh"
+ "1zFMi5vzcns38-8_Sns; "
+ "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-"
+ "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339"
+ "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c"
+ "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%"
+ "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4"
+ "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1"
+ "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP"
+ "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6"
+ "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b"
+ "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6"
+ "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG"
+ "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk"
+ "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn"
+ "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr"
+ "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo ";
+ }
+
testing::StrictMock<MockDelegate> delegate_;
MockSession session_;
QuicReliableClientStream stream_;
QuicCryptoClientConfig crypto_config_;
+ SpdyHeaderBlock headers_;
};
-TEST_F(QuicReliableClientStreamTest, TerminateFromPeer) {
+TEST_F(QuicReliableClientStreamTest, OnFinRead) {
+ InitializeHeaders();
+ QuicSpdyCompressor compressor;
+ string compressed_headers = compressor.CompressHeaders(headers_);
+ QuicStreamFrame frame1(kStreamId, false, 0, MakeIOVector(compressed_headers));
+ string uncompressed_headers =
+ SpdyUtils::SerializeUncompressedHeaders(headers_);
+ EXPECT_CALL(delegate_, OnDataReceived(StrEq(uncompressed_headers.data()),
+ uncompressed_headers.size()));
+ stream_.OnStreamFrame(frame1);
+
+ IOVector iov;
+ QuicStreamFrame frame2(kStreamId, true, compressed_headers.length(), iov);
EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR));
-
- stream_.TerminateFromPeer(true);
+ stream_.OnStreamFrame(frame2);
}
TEST_F(QuicReliableClientStreamTest, ProcessData) {
@@ -87,7 +132,7 @@ TEST_F(QuicReliableClientStreamTest, WriteStreamData) {
const size_t kDataLen = arraysize(kData1);
// All data written.
- EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _)).WillOnce(
+ EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen, true)));
TestCompletionCallback callback;
EXPECT_EQ(OK, stream_.WriteStreamData(base::StringPiece(kData1, kDataLen),
@@ -102,7 +147,7 @@ TEST_F(QuicReliableClientStreamTest, WriteStreamDataAsync) {
const size_t kDataLen = arraysize(kData1);
// No data written.
- EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _)).WillOnce(
+ EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _, _)).WillOnce(
Return(QuicConsumedData(0, false)));
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
@@ -111,7 +156,7 @@ TEST_F(QuicReliableClientStreamTest, WriteStreamDataAsync) {
ASSERT_FALSE(callback.have_result());
// All data written.
- EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _)).WillOnce(
+ EXPECT_CALL(session_, WritevData(stream_.id(), _, _, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen, true)));
stream_.OnCanWrite();
ASSERT_TRUE(callback.have_result());
diff --git a/chromium/net/quic/quic_sent_packet_manager.cc b/chromium/net/quic/quic_sent_packet_manager.cc
index a8960f07aa0..bda30c72a1f 100644
--- a/chromium/net/quic/quic_sent_packet_manager.cc
+++ b/chromium/net/quic/quic_sent_packet_manager.cc
@@ -6,10 +6,53 @@
#include "base/logging.h"
#include "base/stl_util.h"
+#include "net/quic/congestion_control/pacing_sender.h"
+#include "net/quic/quic_ack_notifier_manager.h"
using std::make_pair;
+using std::min;
+
+// TODO(rtenneti): Remove this.
+// Do not flip this flag until the flakiness of the
+// net/tools/quic/end_to_end_test is fixed.
+// If true, then QUIC connections will track the retransmission history of a
+// packet so that an ack of a previous transmission will ack the data of all
+// other transmissions.
+bool FLAGS_track_retransmission_history = false;
+
+// A test-only flag to prevent the RTO from backing off when multiple sequential
+// tail drops occur.
+bool FLAGS_limit_rto_increase_for_tests = false;
+
+// Do not remove this flag until the Finch-trials described in b/11706275
+// are complete.
+// If true, QUIC connections will support the use of a pacing algorithm when
+// sending packets, in an attempt to reduce packet loss. The client must also
+// request pacing for the server to enable it.
+bool FLAGS_enable_quic_pacing = false;
namespace net {
+namespace {
+static const int kBitrateSmoothingPeriodMs = 1000;
+static const int kHistoryPeriodMs = 5000;
+
+static const int kDefaultRetransmissionTimeMs = 500;
+// TCP RFC calls for 1 second RTO however Linux differs from this default and
+// define the minimum RTO to 200ms, we will use the same until we have data to
+// support a higher or lower value.
+static const int kMinRetransmissionTimeMs = 200;
+static const int kMaxRetransmissionTimeMs = 60000;
+static const size_t kMaxRetransmissions = 10;
+
+// We only retransmit 2 packets per ack.
+static const size_t kMaxRetransmissionsPerAck = 2;
+
+// TCP retransmits after 3 nacks.
+static const size_t kNumberOfNacksBeforeRetransmission = 3;
+
+COMPILE_ASSERT(kHistoryPeriodMs >= kBitrateSmoothingPeriodMs,
+ history_must_be_longer_or_equal_to_the_smoothing_period);
+} // namespace
#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
@@ -17,185 +60,386 @@ QuicSentPacketManager::HelperInterface::~HelperInterface() {
}
QuicSentPacketManager::QuicSentPacketManager(bool is_server,
- HelperInterface* helper)
+ HelperInterface* helper,
+ const QuicClock* clock,
+ CongestionFeedbackType type)
: is_server_(is_server),
- helper_(helper) {
+ helper_(helper),
+ clock_(clock),
+ send_algorithm_(SendAlgorithmInterface::Create(clock, type)),
+ rtt_sample_(QuicTime::Delta::Infinite()),
+ consecutive_rto_count_(0),
+ using_pacing_(false) {
}
QuicSentPacketManager::~QuicSentPacketManager() {
- STLDeleteValues(&unacked_packets_);
+ for (UnackedPacketMap::iterator it = unacked_packets_.begin();
+ it != unacked_packets_.end(); ++it) {
+ delete it->second.retransmittable_frames;
+ // Only delete previous_transmissions once, for the newest packet.
+ if (it->second.previous_transmissions != NULL &&
+ it->first == *it->second.previous_transmissions->rbegin()) {
+ delete it->second.previous_transmissions;
+ }
+ }
+ STLDeleteValues(&packet_history_map_);
}
-void QuicSentPacketManager::OnSerializedPacket(
- const SerializedPacket& serialized_packet) {
- if (serialized_packet.packet->is_fec_packet()) {
- unacked_fec_packets_.insert(make_pair(
- serialized_packet.sequence_number,
- serialized_packet.retransmittable_frames));
- return;
+void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
+ if (config.initial_round_trip_time_us() > 0 &&
+ rtt_sample_.IsInfinite()) {
+ // The initial rtt should already be set on the client side.
+ DVLOG_IF(1, !is_server_)
+ << "Client did not set an initial RTT, but did negotiate one.";
+ rtt_sample_ =
+ QuicTime::Delta::FromMicroseconds(config.initial_round_trip_time_us());
+ }
+ if (config.congestion_control() == kPACE) {
+ MaybeEnablePacing();
}
+ send_algorithm_->SetFromConfig(config, is_server_);
+}
- if (serialized_packet.retransmittable_frames == NULL) {
+void QuicSentPacketManager::SetMaxPacketSize(QuicByteCount max_packet_size) {
+ send_algorithm_->SetMaxPacketSize(max_packet_size);
+}
+
+void QuicSentPacketManager::OnSerializedPacket(
+ const SerializedPacket& serialized_packet) {
+ if (serialized_packet.retransmittable_frames == NULL &&
+ !serialized_packet.packet->is_fec_packet()) {
// Don't track ack/congestion feedback packets.
return;
}
+ ack_notifier_manager_.OnSerializedPacket(serialized_packet);
+
DCHECK(unacked_packets_.empty() ||
- unacked_packets_.rbegin()->first <
- serialized_packet.sequence_number);
+ unacked_packets_.rbegin()->first < serialized_packet.sequence_number);
unacked_packets_[serialized_packet.sequence_number] =
- serialized_packet.retransmittable_frames;
- retransmission_map_[serialized_packet.sequence_number] =
- RetransmissionInfo(serialized_packet.sequence_number,
- serialized_packet.sequence_number_length);
+ TransmissionInfo(serialized_packet.retransmittable_frames,
+ serialized_packet.sequence_number_length);
}
void QuicSentPacketManager::OnRetransmittedPacket(
QuicPacketSequenceNumber old_sequence_number,
QuicPacketSequenceNumber new_sequence_number) {
DCHECK(ContainsKey(unacked_packets_, old_sequence_number));
- DCHECK(ContainsKey(retransmission_map_, old_sequence_number));
+ DCHECK(ContainsKey(pending_retransmissions_, old_sequence_number));
DCHECK(unacked_packets_.empty() ||
unacked_packets_.rbegin()->first < new_sequence_number);
- RetransmissionInfo retransmission_info(
- new_sequence_number, GetSequenceNumberLength(old_sequence_number));
- retransmission_info.number_retransmissions =
- retransmission_map_[old_sequence_number].number_retransmissions + 1;
- retransmission_map_.erase(old_sequence_number);
- retransmission_map_[new_sequence_number] = retransmission_info;
+ pending_retransmissions_.erase(old_sequence_number);
- RetransmittableFrames* frames = unacked_packets_[old_sequence_number];
+ UnackedPacketMap::iterator unacked_it =
+ unacked_packets_.find(old_sequence_number);
+ RetransmittableFrames* frames = unacked_it->second.retransmittable_frames;
DCHECK(frames);
- unacked_packets_.erase(old_sequence_number);
- unacked_packets_[new_sequence_number] = frames;
+
+ // A notifier may be waiting to hear about ACKs for the original sequence
+ // number. Inform them that the sequence number has changed.
+ ack_notifier_manager_.UpdateSequenceNumber(old_sequence_number,
+ new_sequence_number);
+
+ // We keep the old packet in the unacked packet list until it, or one of
+ // the retransmissions of it are acked.
+ unacked_it->second.retransmittable_frames = NULL;
+ unacked_packets_[new_sequence_number] =
+ TransmissionInfo(frames, GetSequenceNumberLength(old_sequence_number));
+
+ // Keep track of all sequence numbers that this packet
+ // has been transmitted as.
+ SequenceNumberSet* previous_transmissions =
+ unacked_it->second.previous_transmissions;
+ if (previous_transmissions == NULL) {
+ // This is the first retransmission of this packet, so create a new entry.
+ previous_transmissions = new SequenceNumberSet;
+ unacked_it->second.previous_transmissions = previous_transmissions;
+ previous_transmissions->insert(old_sequence_number);
+ }
+ previous_transmissions->insert(new_sequence_number);
+ unacked_packets_[new_sequence_number].previous_transmissions =
+ previous_transmissions;
+
+ DCHECK(HasRetransmittableFrames(new_sequence_number));
+}
+
+bool QuicSentPacketManager::OnIncomingAck(
+ const ReceivedPacketInfo& received_info, QuicTime ack_receive_time) {
+ // Determine if the least unacked sequence number is being acked.
+ QuicPacketSequenceNumber least_unacked_sent_before =
+ GetLeastUnackedSentPacket();
+ bool new_least_unacked = !IsAwaitingPacket(received_info,
+ least_unacked_sent_before);
+
+ HandleAckForSentPackets(received_info);
+
+ SequenceNumberSet retransmission_packets =
+ OnIncomingAckFrame(received_info, ack_receive_time);
+
+ for (SequenceNumberSet::const_iterator it = retransmission_packets.begin();
+ it != retransmission_packets.end(); ++it) {
+ DCHECK(!ContainsKey(pending_packets_, *it));
+ MarkForRetransmission(*it, NACK_RETRANSMISSION);
+ }
+
+ if (new_least_unacked) {
+ consecutive_rto_count_ = 0;
+ }
+
+ return new_least_unacked;
+}
+
+void QuicSentPacketManager::DiscardUnackedPacket(
+ QuicPacketSequenceNumber sequence_number) {
+ MarkPacketReceivedByPeer(sequence_number);
}
void QuicSentPacketManager::HandleAckForSentPackets(
- const QuicAckFrame& incoming_ack,
- SequenceNumberSet* acked_packets) {
+ const ReceivedPacketInfo& received_info) {
// 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.
UnackedPacketMap::iterator it = unacked_packets_.begin();
while (it != unacked_packets_.end()) {
QuicPacketSequenceNumber sequence_number = it->first;
- if (sequence_number > helper_->GetPeerLargestObservedPacket()) {
+ if (sequence_number > received_info.largest_observed) {
// These are very new sequence_numbers.
break;
}
- RetransmittableFrames* unacked = it->second;
- if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
- // Packet was acked, so remove it from our unacked packet list.
- DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
- acked_packets->insert(sequence_number);
- delete unacked;
- unacked_packets_.erase(it++);
- retransmission_map_.erase(sequence_number);
- } else {
- // This is a packet which we planned on retransmitting and has not been
- // seen at the time of this ack being sent out. See if it's our new
- // lowest unacked packet.
- DVLOG(1) << ENDPOINT << "still missing packet " << sequence_number;
+
+ if (IsAwaitingPacket(received_info, sequence_number)) {
++it;
- // The peer got packets after this sequence number. This is an explicit
- // nack.
- RetransmissionMap::iterator retransmission_it =
- retransmission_map_.find(sequence_number);
- if (retransmission_it == retransmission_map_.end()) {
- continue;
- }
- size_t nack_count = ++(retransmission_it->second.number_nacks);
- helper_->OnPacketNacked(sequence_number, nack_count);
+ continue;
}
+
+ // Packet was acked, so remove it from our unacked packet list.
+ DVLOG(1) << ENDPOINT <<"Got an ack for packet " << sequence_number;
+ // If data is associated with the most recent transmission of this
+ // packet, then inform the caller.
+ it = MarkPacketReceivedByPeer(sequence_number);
+
+ // The AckNotifierManager is informed of every ACKed sequence number.
+ ack_notifier_manager_.OnPacketAcked(sequence_number);
+ }
+
+ // If we have received a truncated ack, then we need to
+ // clear out some previous transmissions to allow the peer
+ // to actually ACK new packets.
+ if (received_info.is_truncated) {
+ ClearPreviousRetransmissions(received_info.missing_packets.size() / 2);
}
}
-void QuicSentPacketManager::HandleAckForSentFecPackets(
- const QuicAckFrame& incoming_ack,
- SequenceNumberSet* acked_packets) {
- UnackedPacketMap::iterator it = unacked_fec_packets_.begin();
- while (it != unacked_fec_packets_.end()) {
+void QuicSentPacketManager::ClearPreviousRetransmissions(size_t num_to_clear) {
+ UnackedPacketMap::iterator it = unacked_packets_.begin();
+ while (it != unacked_packets_.end() && num_to_clear > 0) {
QuicPacketSequenceNumber sequence_number = it->first;
- if (sequence_number > helper_->GetPeerLargestObservedPacket()) {
+ // If this is not a previous transmission then there is no point
+ // in clearing out any further packets, because it will not affect
+ // the high water mark.
+ SequenceNumberSet* previous_transmissions =
+ it->second.previous_transmissions;
+ if (previous_transmissions == NULL) {
break;
}
- if (!IsAwaitingPacket(incoming_ack.received_info, sequence_number)) {
- DVLOG(1) << ENDPOINT << "Got an ack for fec packet: " << sequence_number;
- acked_packets->insert(sequence_number);
- unacked_fec_packets_.erase(it++);
- } else {
- DVLOG(1) << ENDPOINT << "Still missing ack for fec packet: "
- << sequence_number;
- ++it;
+ QuicPacketSequenceNumber newest_transmission =
+ *previous_transmissions->rbegin();
+ if (sequence_number == newest_transmission) {
+ break;
+ }
+
+ DCHECK(it->second.retransmittable_frames == NULL);
+ previous_transmissions->erase(sequence_number);
+ if (previous_transmissions->size() == 1) {
+ unacked_packets_[newest_transmission].previous_transmissions = NULL;
+ delete previous_transmissions;
}
+ unacked_packets_.erase(it++);
+ --num_to_clear;
}
}
-void QuicSentPacketManager::DiscardPacket(
- QuicPacketSequenceNumber sequence_number) {
- UnackedPacketMap::iterator unacked_it =
- unacked_packets_.find(sequence_number);
- if (unacked_it == unacked_packets_.end()) {
- // Packet was not meant to be retransmitted.
- DCHECK(!ContainsKey(retransmission_map_, sequence_number));
+bool QuicSentPacketManager::HasRetransmittableFrames(
+ QuicPacketSequenceNumber sequence_number) const {
+ if (!ContainsKey(unacked_packets_, sequence_number)) {
+ return false;
+ }
+
+ return unacked_packets_.find(
+ sequence_number)->second.retransmittable_frames != NULL;
+}
+
+void QuicSentPacketManager::RetransmitUnackedPackets(
+ RetransmissionType retransmission_type) {
+ if (unacked_packets_.empty()) {
return;
}
- // Delete the unacked packet.
- delete unacked_it->second;
- unacked_packets_.erase(unacked_it);
- retransmission_map_.erase(sequence_number);
+ for (UnackedPacketMap::const_iterator unacked_it = unacked_packets_.begin();
+ unacked_it != unacked_packets_.end(); ++unacked_it) {
+ const RetransmittableFrames* frames =
+ unacked_it->second.retransmittable_frames;
+ if (frames == NULL) {
+ continue;
+ }
+ if (retransmission_type == ALL_PACKETS ||
+ frames->encryption_level() == ENCRYPTION_INITIAL) {
+ // TODO(satyamshekhar): Think about congestion control here.
+ // Specifically, about the retransmission count of packets being sent
+ // proactively to achieve 0 (minimal) RTT.
+ OnPacketAbandoned(unacked_it->first);
+ if (!MarkForRetransmission(unacked_it->first, NACK_RETRANSMISSION)) {
+ DiscardUnackedPacket(unacked_it->first);
+ }
+ }
+ }
}
-bool QuicSentPacketManager::IsRetransmission(
- QuicPacketSequenceNumber sequence_number) const {
- RetransmissionMap::const_iterator it =
- retransmission_map_.find(sequence_number);
- return it != retransmission_map_.end() &&
- it->second.number_retransmissions > 0;
+bool QuicSentPacketManager::MarkForRetransmission(
+ QuicPacketSequenceNumber sequence_number,
+ TransmissionType transmission_type) {
+ DCHECK(ContainsKey(unacked_packets_, sequence_number));
+ if (!HasRetransmittableFrames(sequence_number)) {
+ return false;
+ }
+ // If it's already in the retransmission map, don't add it again, just let
+ // the prior retransmission request win out.
+ if (ContainsKey(pending_retransmissions_, sequence_number)) {
+ return true;
+ }
+
+ pending_retransmissions_[sequence_number] = transmission_type;
+ return true;
}
-size_t QuicSentPacketManager::GetRetransmissionCount(
- QuicPacketSequenceNumber sequence_number) const {
- DCHECK(ContainsKey(retransmission_map_, sequence_number));
- RetransmissionMap::const_iterator it =
- retransmission_map_.find(sequence_number);
- return it->second.number_retransmissions;
+bool QuicSentPacketManager::HasPendingRetransmissions() const {
+ return !pending_retransmissions_.empty();
}
-bool QuicSentPacketManager::IsUnacked(
- QuicPacketSequenceNumber sequence_number) const {
- return ContainsKey(unacked_packets_, sequence_number);
+QuicSentPacketManager::PendingRetransmission
+ QuicSentPacketManager::NextPendingRetransmission() {
+ DCHECK(!pending_retransmissions_.empty());
+ QuicPacketSequenceNumber sequence_number =
+ pending_retransmissions_.begin()->first;
+ DCHECK(ContainsKey(unacked_packets_, sequence_number));
+ const RetransmittableFrames* retransmittable_frames =
+ unacked_packets_[sequence_number].retransmittable_frames;
+ DCHECK(retransmittable_frames);
+
+ return PendingRetransmission(sequence_number,
+ pending_retransmissions_.begin()->second,
+ *retransmittable_frames,
+ GetSequenceNumberLength(sequence_number));
}
-bool QuicSentPacketManager::IsFecUnacked(
+bool QuicSentPacketManager::IsPreviousTransmission(
QuicPacketSequenceNumber sequence_number) const {
- return ContainsKey(unacked_fec_packets_, sequence_number);
+ DCHECK(ContainsKey(unacked_packets_, sequence_number));
+
+ UnackedPacketMap::const_iterator it = unacked_packets_.find(sequence_number);
+ if (it->second.previous_transmissions == NULL) {
+ return false;
+ }
+
+ SequenceNumberSet* previous_transmissions = it->second.previous_transmissions;
+ DCHECK(!previous_transmissions->empty());
+ return *previous_transmissions->rbegin() != sequence_number;
}
-const RetransmittableFrames& QuicSentPacketManager::GetRetransmittableFrames(
- QuicPacketSequenceNumber sequence_number) const {
+QuicSentPacketManager::UnackedPacketMap::iterator
+QuicSentPacketManager::MarkPacketReceivedByPeer(
+ QuicPacketSequenceNumber sequence_number) {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
- DCHECK(ContainsKey(retransmission_map_, sequence_number));
- return *unacked_packets_.find(sequence_number)->second;
+ // If this packet has never been retransmitted, then simply drop it.
+ UnackedPacketMap::const_iterator previous_it =
+ unacked_packets_.find(sequence_number);
+ if (previous_it->second.previous_transmissions == NULL) {
+ UnackedPacketMap::iterator next_unacked =
+ unacked_packets_.find(sequence_number);
+ ++next_unacked;
+ DiscardPacket(sequence_number);
+ return next_unacked;
+ }
+
+ SequenceNumberSet* previous_transmissions =
+ previous_it->second.previous_transmissions;
+ DCHECK(!previous_transmissions->empty());
+ SequenceNumberSet::reverse_iterator previous_transmissions_it =
+ previous_transmissions->rbegin();
+ QuicPacketSequenceNumber newest_transmission = *previous_transmissions_it;
+ if (newest_transmission == sequence_number) {
+ DiscardPacket(newest_transmission);
+ } else {
+ // If we have received an ack for a previous transmission of a packet,
+ // we want to keep the "new" transmission of the packet unacked,
+ // but prevent the data from being retransmitted.
+ delete unacked_packets_[newest_transmission].retransmittable_frames;
+ unacked_packets_[newest_transmission].retransmittable_frames = NULL;
+ unacked_packets_[newest_transmission].previous_transmissions = NULL;
+ pending_retransmissions_.erase(newest_transmission);
+ }
+
+ // Clear out information all previous transmissions.
+ ++previous_transmissions_it;
+ while (previous_transmissions_it != previous_transmissions->rend()) {
+ QuicPacketSequenceNumber previous_transmission = *previous_transmissions_it;
+ ++previous_transmissions_it;
+ DiscardPacket(previous_transmission);
+ }
+
+ delete previous_transmissions;
+
+ UnackedPacketMap::iterator next_unacked = unacked_packets_.begin();
+ while (next_unacked != unacked_packets_.end() &&
+ next_unacked->first < sequence_number) {
+ ++next_unacked;
+ }
+ return next_unacked;
+}
+
+void QuicSentPacketManager::DiscardPacket(
+ QuicPacketSequenceNumber sequence_number) {
+ UnackedPacketMap::iterator unacked_it =
+ unacked_packets_.find(sequence_number);
+ // Packet was not meant to be retransmitted.
+ if (unacked_it == unacked_packets_.end()) {
+ return;
+ }
+
+ // Delete the retransmittable frames.
+ delete unacked_it->second.retransmittable_frames;
+ unacked_packets_.erase(unacked_it);
+ pending_retransmissions_.erase(sequence_number);
+ return;
+}
+
+bool QuicSentPacketManager::IsUnacked(
+ QuicPacketSequenceNumber sequence_number) const {
+ return ContainsKey(unacked_packets_, sequence_number);
}
QuicSequenceNumberLength QuicSentPacketManager::GetSequenceNumberLength(
QuicPacketSequenceNumber sequence_number) const {
DCHECK(ContainsKey(unacked_packets_, sequence_number));
- DCHECK(ContainsKey(retransmission_map_, sequence_number));
- return retransmission_map_.find(
- sequence_number)->second.sequence_number_length;
+ return unacked_packets_.find(sequence_number)->second.sequence_number_length;
}
bool QuicSentPacketManager::HasUnackedPackets() const {
return !unacked_packets_.empty();
}
-size_t QuicSentPacketManager::GetNumUnackedPackets() const {
- return unacked_packets_.size();
+size_t QuicSentPacketManager::GetNumRetransmittablePackets() const {
+ size_t num_unacked_packets = 0;
+ for (UnackedPacketMap::const_iterator it = unacked_packets_.begin();
+ it != unacked_packets_.end(); ++it) {
+ QuicPacketSequenceNumber sequence_number = it->first;
+ if (HasRetransmittableFrames(sequence_number)) {
+ ++num_unacked_packets;
+ }
+ }
+ return num_unacked_packets;
}
QuicPacketSequenceNumber
@@ -218,4 +462,316 @@ SequenceNumberSet QuicSentPacketManager::GetUnackedPackets() const {
return unacked_packets;
}
+void QuicSentPacketManager::OnPacketSent(
+ QuicPacketSequenceNumber sequence_number,
+ QuicTime sent_time,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData has_retransmittable_data) {
+ DCHECK_LT(0u, sequence_number);
+ DCHECK(!ContainsKey(pending_packets_, sequence_number));
+ if (ContainsKey(unacked_packets_, sequence_number)) {
+ unacked_packets_[sequence_number].sent_time = sent_time;
+ }
+
+ // Only track packets the send algorithm wants us to track.
+ if (!send_algorithm_->OnPacketSent(sent_time, sequence_number, bytes,
+ transmission_type,
+ has_retransmittable_data)) {
+ return;
+ }
+ packet_history_map_[sequence_number] = new SendAlgorithmInterface::SentPacket(
+ bytes, sent_time, has_retransmittable_data);
+ pending_packets_.insert(sequence_number);
+ CleanupPacketHistory();
+}
+
+void QuicSentPacketManager::OnRetransmissionTimeout() {
+ // Abandon all pending packets to ensure the congestion window
+ // opens up before we attempt to retransmit packets.
+ QuicTime::Delta retransmission_delay = GetRetransmissionDelay();
+ QuicTime max_send_time =
+ clock_->ApproximateNow().Subtract(retransmission_delay);
+ for (SequenceNumberSet::iterator it = pending_packets_.begin();
+ it != pending_packets_.end();) {
+ QuicPacketSequenceNumber sequence_number = *it;
+ DCHECK(ContainsKey(packet_history_map_, sequence_number));
+ DCHECK(ContainsKey(unacked_packets_, sequence_number));
+ const TransmissionInfo& transmission_info =
+ unacked_packets_.find(sequence_number)->second;
+ // Abandon retransmittable packet and old non-retransmittable packets.
+ if (transmission_info.retransmittable_frames ||
+ transmission_info.sent_time <= max_send_time) {
+ pending_packets_.erase(it++);
+ send_algorithm_->OnPacketAbandoned(
+ sequence_number, packet_history_map_[sequence_number]->bytes_sent());
+ } else {
+ ++it;
+ }
+ }
+
+ // Attempt to send all the unacked packets when the RTO fires, let the
+ // congestion manager decide how many to send immediately and the remaining
+ // packets will be queued for future sending.
+ DVLOG(1) << "OnRetransmissionTimeout() fired with "
+ << unacked_packets_.size() << " unacked packets.";
+
+ // Retransmit any packet with retransmittable frames.
+ bool packets_retransmitted = false;
+ for (UnackedPacketMap::const_iterator it = unacked_packets_.begin();
+ it != unacked_packets_.end(); ++it) {
+ if (it->second.retransmittable_frames != NULL) {
+ packets_retransmitted = true;
+ MarkForRetransmission(it->first, RTO_RETRANSMISSION);
+ }
+ }
+
+ // Only inform the sent packet manager of an RTO if data was retransmitted.
+ if (packets_retransmitted) {
+ ++consecutive_rto_count_;
+ send_algorithm_->OnRetransmissionTimeout();
+ }
+}
+
+void QuicSentPacketManager::OnPacketAbandoned(
+ QuicPacketSequenceNumber sequence_number) {
+ SequenceNumberSet::iterator it = pending_packets_.find(sequence_number);
+ if (it != pending_packets_.end()) {
+ DCHECK(ContainsKey(packet_history_map_, sequence_number));
+ send_algorithm_->OnPacketAbandoned(
+ sequence_number, packet_history_map_[sequence_number]->bytes_sent());
+ pending_packets_.erase(it);
+ }
+}
+
+void QuicSentPacketManager::OnIncomingQuicCongestionFeedbackFrame(
+ const QuicCongestionFeedbackFrame& frame,
+ const QuicTime& feedback_receive_time) {
+ send_algorithm_->OnIncomingQuicCongestionFeedbackFrame(
+ frame, feedback_receive_time, packet_history_map_);
+}
+
+SequenceNumberSet QuicSentPacketManager::OnIncomingAckFrame(
+ const ReceivedPacketInfo& received_info,
+ const QuicTime& ack_receive_time) {
+ MaybeUpdateRTT(received_info, ack_receive_time);
+
+ // We want to.
+ // * Get all packets lower(including) than largest_observed
+ // from pending_packets_.
+ // * Remove all packets no longer being waited for(ie: acked).
+ // * Send each ACK in the list to send_algorithm_.
+ SequenceNumberSet::iterator it = pending_packets_.begin();
+ SequenceNumberSet::iterator it_upper =
+ pending_packets_.upper_bound(received_info.largest_observed);
+
+ SequenceNumberSet retransmission_packets;
+ SequenceNumberSet lost_packets;
+ while (it != it_upper) {
+ QuicPacketSequenceNumber sequence_number = *it;
+ const SendAlgorithmInterface::SentPacket* sent_packet =
+ packet_history_map_[sequence_number];
+ if (!IsAwaitingPacket(received_info, sequence_number)) {
+ // Not missing, hence implicitly acked.
+ size_t bytes_sent = sent_packet->bytes_sent();
+ send_algorithm_->OnPacketAcked(sequence_number, bytes_sent, rtt_sample_);
+ pending_packets_.erase(it++); // Must be incremented post to work.
+ continue;
+ }
+
+ // The peer got packets after this sequence number. This is an explicit
+ // nack.
+ DVLOG(1) << "still missing packet " << sequence_number;
+ DCHECK(ContainsKey(packet_history_map_, sequence_number));
+ // Consider it multiple nacks when there is a gap between the missing packet
+ // and the largest observed, since the purpose of a nack threshold is to
+ // tolerate re-ordering. This handles both StretchAcks and Forward Acks.
+ // TODO(ianswett): This relies heavily on sequential reception of packets,
+ // and makes an assumption that the congestion control uses TCP style nacks.
+ size_t min_nacks = received_info.largest_observed - sequence_number;
+ packet_history_map_[sequence_number]->Nack(min_nacks);
+
+ size_t num_nacks_needed = kNumberOfNacksBeforeRetransmission;
+ // Check for early retransmit(RFC5827) when the last packet gets acked and
+ // the there are fewer than 4 pending packets.
+ if (pending_packets_.size() <= kNumberOfNacksBeforeRetransmission &&
+ sent_packet->has_retransmittable_data() == HAS_RETRANSMITTABLE_DATA &&
+ *pending_packets_.rbegin() == received_info.largest_observed) {
+ num_nacks_needed = received_info.largest_observed - sequence_number;
+ }
+
+ if (sent_packet->nack_count() < num_nacks_needed) {
+ ++it;
+ continue;
+ }
+
+ // If the number of retransmissions has maxed out, don't lose or retransmit
+ // any more packets.
+ if (retransmission_packets.size() >= kMaxRetransmissionsPerAck) {
+ ++it;
+ continue;
+ }
+
+ lost_packets.insert(sequence_number);
+ if (sent_packet->has_retransmittable_data() == HAS_RETRANSMITTABLE_DATA) {
+ retransmission_packets.insert(sequence_number);
+ }
+
+ ++it;
+ }
+ // Abandon packets after the loop over pending packets, because otherwise it
+ // changes the early retransmit logic and iteration.
+ for (SequenceNumberSet::const_iterator it = lost_packets.begin();
+ it != lost_packets.end(); ++it) {
+ // TODO(ianswett): OnPacketLost is also called from TCPCubicSender when
+ // an FEC packet is lost, but FEC loss information should be shared among
+ // congestion managers. Additionally, if it's expected the FEC packet may
+ // repair the loss, it should be recorded as a loss to the congestion
+ // manager, but not retransmitted until it's known whether the FEC packet
+ // arrived.
+ send_algorithm_->OnPacketLost(*it, ack_receive_time);
+ OnPacketAbandoned(*it);
+ }
+
+ return retransmission_packets;
+}
+
+void QuicSentPacketManager::MaybeUpdateRTT(
+ const ReceivedPacketInfo& received_info,
+ const QuicTime& ack_receive_time) {
+ // We calculate the RTT based on the highest ACKed sequence number, the lower
+ // sequence numbers will include the ACK aggregation delay.
+ SendAlgorithmInterface::SentPacketsMap::iterator history_it =
+ packet_history_map_.find(received_info.largest_observed);
+ // TODO(satyamshekhar): largest_observed might be missing.
+ if (history_it == packet_history_map_.end()) {
+ return;
+ }
+
+ QuicTime::Delta send_delta = ack_receive_time.Subtract(
+ history_it->second->send_timestamp());
+ if (send_delta > received_info.delta_time_largest_observed) {
+ rtt_sample_ = send_delta.Subtract(
+ received_info.delta_time_largest_observed);
+ } else if (rtt_sample_.IsInfinite()) {
+ // Even though we received information from the peer suggesting
+ // an invalid (negative) RTT, we can use the send delta as an
+ // approximation until we get a better estimate.
+ rtt_sample_ = send_delta;
+ }
+}
+
+QuicTime::Delta QuicSentPacketManager::TimeUntilSend(
+ QuicTime now,
+ TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake) {
+ return send_algorithm_->TimeUntilSend(now, transmission_type, retransmittable,
+ handshake);
+}
+
+// Ensures that the Delayed Ack timer is always set to a value lesser
+// than the retransmission timer's minimum value (MinRTO). We want the
+// delayed ack to get back to the QUIC peer before the sender's
+// retransmission timer triggers. Since we do not know the
+// reverse-path one-way delay, we assume equal delays for forward and
+// reverse paths, and ensure that the timer is set to less than half
+// of the MinRTO.
+// There may be a value in making this delay adaptive with the help of
+// the sender and a signaling mechanism -- if the sender uses a
+// different MinRTO, we may get spurious retransmissions. May not have
+// any benefits, but if the delayed ack becomes a significant source
+// of (likely, tail) latency, then consider such a mechanism.
+
+const QuicTime::Delta QuicSentPacketManager::DelayedAckTime() {
+ return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs/2);
+}
+
+const QuicTime::Delta QuicSentPacketManager::GetRetransmissionDelay() const {
+ size_t number_retransmissions = consecutive_rto_count_;
+ if (FLAGS_limit_rto_increase_for_tests) {
+ const size_t kTailDropWindowSize = 5;
+ const size_t kTailDropMaxRetransmissions = 4;
+ if (pending_packets_.size() <= kTailDropWindowSize) {
+ // Avoid exponential backoff of RTO when there are only a few packets
+ // outstanding. This helps avoid the situation where fake packet loss
+ // causes a packet and it's retransmission to be dropped causing
+ // test timouts.
+ if (number_retransmissions <= kTailDropMaxRetransmissions) {
+ number_retransmissions = 0;
+ } else {
+ number_retransmissions -= kTailDropMaxRetransmissions;
+ }
+ }
+ }
+
+ QuicTime::Delta retransmission_delay = send_algorithm_->RetransmissionDelay();
+ if (retransmission_delay.IsZero()) {
+ // We are in the initial state, use default timeout values.
+ retransmission_delay =
+ QuicTime::Delta::FromMilliseconds(kDefaultRetransmissionTimeMs);
+ }
+ // Calculate exponential back off.
+ retransmission_delay = QuicTime::Delta::FromMilliseconds(
+ retransmission_delay.ToMilliseconds() * static_cast<size_t>(
+ (1 << min<size_t>(number_retransmissions, kMaxRetransmissions))));
+
+ // TODO(rch): This code should move to |send_algorithm_|.
+ if (retransmission_delay.ToMilliseconds() < kMinRetransmissionTimeMs) {
+ return QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs);
+ }
+ if (retransmission_delay.ToMilliseconds() > kMaxRetransmissionTimeMs) {
+ return QuicTime::Delta::FromMilliseconds(kMaxRetransmissionTimeMs);
+ }
+ return retransmission_delay;
+}
+
+const QuicTime::Delta QuicSentPacketManager::SmoothedRtt() const {
+ return send_algorithm_->SmoothedRtt();
+}
+
+QuicBandwidth QuicSentPacketManager::BandwidthEstimate() const {
+ return send_algorithm_->BandwidthEstimate();
+}
+
+QuicByteCount QuicSentPacketManager::GetCongestionWindow() const {
+ return send_algorithm_->GetCongestionWindow();
+}
+
+void QuicSentPacketManager::CleanupPacketHistory() {
+ const QuicTime::Delta kHistoryPeriod =
+ QuicTime::Delta::FromMilliseconds(kHistoryPeriodMs);
+ QuicTime now = clock_->ApproximateNow();
+
+ SendAlgorithmInterface::SentPacketsMap::iterator history_it =
+ packet_history_map_.begin();
+ for (; history_it != packet_history_map_.end(); ++history_it) {
+ if (now.Subtract(history_it->second->send_timestamp()) <= kHistoryPeriod) {
+ return;
+ }
+ // Don't remove packets which have not been acked.
+ if (ContainsKey(pending_packets_, history_it->first)) {
+ continue;
+ }
+ delete history_it->second;
+ packet_history_map_.erase(history_it);
+ history_it = packet_history_map_.begin();
+ }
+}
+
+void QuicSentPacketManager::MaybeEnablePacing() {
+ if (!FLAGS_enable_quic_pacing) {
+ return;
+ }
+
+ if (using_pacing_) {
+ return;
+ }
+
+ using_pacing_ = true;
+ send_algorithm_.reset(
+ new PacingSender(send_algorithm_.release(),
+ QuicTime::Delta::FromMicroseconds(1)));
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_sent_packet_manager.h b/chromium/net/quic/quic_sent_packet_manager.h
index 355ea498b65..71c61e93c03 100644
--- a/chromium/net/quic/quic_sent_packet_manager.h
+++ b/chromium/net/quic/quic_sent_packet_manager.h
@@ -15,26 +15,68 @@
#include "base/containers/hash_tables.h"
#include "net/base/linked_hash_map.h"
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/quic_ack_notifier_manager.h"
#include "net/quic/quic_protocol.h"
+NET_EXPORT_PRIVATE extern bool FLAGS_track_retransmission_history;
+NET_EXPORT_PRIVATE extern bool FLAGS_limit_rto_increase_for_tests;
+NET_EXPORT_PRIVATE extern bool FLAGS_enable_quic_pacing;
+
namespace net {
+namespace test {
+class QuicConnectionPeer;
+class QuicSentPacketManagerPeer;
+} // namespace test
+
+class QuicClock;
+class QuicConfig;
+
+// Class which tracks the set of packets sent on a QUIC connection and contains
+// a send algorithm to decide when to send new packets. It keeps track of any
+// retransmittable data associated with each packet. If a packet is
+// retransmitted, it will keep track of each version of a packet so that if a
+// previous transmission is acked, the data will not be retransmitted.
class NET_EXPORT_PRIVATE QuicSentPacketManager {
public:
+ // Struct to store the pending retransmission information.
+ struct PendingRetransmission {
+ PendingRetransmission(QuicPacketSequenceNumber sequence_number,
+ TransmissionType transmission_type,
+ const RetransmittableFrames& retransmittable_frames,
+ QuicSequenceNumberLength sequence_number_length)
+ : sequence_number(sequence_number),
+ transmission_type(transmission_type),
+ retransmittable_frames(retransmittable_frames),
+ sequence_number_length(sequence_number_length) {
+ }
+
+ QuicPacketSequenceNumber sequence_number;
+ TransmissionType transmission_type;
+ const RetransmittableFrames& retransmittable_frames;
+ QuicSequenceNumberLength sequence_number_length;
+ };
+
+ // Interface which provides callbacks that the manager needs.
class NET_EXPORT_PRIVATE HelperInterface {
public:
- virtual QuicPacketSequenceNumber GetPeerLargestObservedPacket() = 0;
- virtual QuicPacketSequenceNumber GetNextPacketSequenceNumber() = 0;
-
- // Called when a packet has been explicitly NACKd
- virtual void OnPacketNacked(QuicPacketSequenceNumber sequence_number,
- size_t nack_count) = 0;
virtual ~HelperInterface();
+
+ // Called to return the sequence number of the next packet to be sent.
+ virtual QuicPacketSequenceNumber GetNextPacketSequenceNumber() = 0;
};
- QuicSentPacketManager(bool is_server, HelperInterface* helper);
+ QuicSentPacketManager(bool is_server,
+ HelperInterface* helper,
+ const QuicClock* clock,
+ CongestionFeedbackType congestion_type);
virtual ~QuicSentPacketManager();
+ virtual void SetFromConfig(const QuicConfig& config);
+
+ virtual void SetMaxPacketSize(QuicByteCount max_packet_size);
+
// Called when a new packet is serialized. If the packet contains
// retransmittable data, it will be added to the unacked packet map.
void OnSerializedPacket(const SerializedPacket& serialized_packet);
@@ -45,93 +87,217 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager {
void OnRetransmittedPacket(QuicPacketSequenceNumber old_sequence_number,
QuicPacketSequenceNumber new_sequence_number);
- // Process the incoming ack looking for newly ack'd data packets.
- void HandleAckForSentPackets(const QuicAckFrame& incoming_ack,
- SequenceNumberSet* acked_packets);
-
- // Process the incoming ack looking for newly ack'd FEC packets.
- void HandleAckForSentFecPackets(const QuicAckFrame& incoming_ack,
- SequenceNumberSet* acked_packets);
-
- // Discards all information about packet |sequence_number|.
- void DiscardPacket(QuicPacketSequenceNumber sequence_number);
-
- // Returns true if |sequence_number| is a retransmission of a packet.
- bool IsRetransmission(QuicPacketSequenceNumber sequence_number) const;
+ // Processes the incoming ack and returns true if the retransmission or ack
+ // alarm should be reset.
+ bool OnIncomingAck(const ReceivedPacketInfo& received_info,
+ QuicTime ack_receive_time);
- // Returns the number of times the data in the packet |sequence_number|
- // has been transmitted.
- size_t GetRetransmissionCount(
- QuicPacketSequenceNumber sequence_number) const;
+ // Discards any information for the packet corresponding to |sequence_number|.
+ // If this packet has been retransmitted, information on those packets
+ // will be discarded as well.
+ void DiscardUnackedPacket(QuicPacketSequenceNumber sequence_number);
// Returns true if the non-FEC packet |sequence_number| is unacked.
bool IsUnacked(QuicPacketSequenceNumber sequence_number) const;
- // Returns true if the FEC packet |sequence_number| is unacked.
- bool IsFecUnacked(QuicPacketSequenceNumber sequence_number) const;
+ // Requests retransmission of all unacked packets of |retransmission_type|.
+ void RetransmitUnackedPackets(RetransmissionType retransmission_type);
- // Returns the RetransmittableFrames for |sequence_number|.
- const RetransmittableFrames& GetRetransmittableFrames(
- QuicPacketSequenceNumber sequence_number) const;
+ // Returns true if the unacked packet |sequence_number| has retransmittable
+ // frames. This will only return false if the packet has been acked, if a
+ // previous transmission of this packet was ACK'd, or if this packet has been
+ // retransmitted as with different sequence number.
+ bool HasRetransmittableFrames(QuicPacketSequenceNumber sequence_number) const;
- // Returns the length of the serialized sequence number for
- // the packet |sequence_number|.
- QuicSequenceNumberLength GetSequenceNumberLength(
- QuicPacketSequenceNumber sequence_number) const;
+ // Returns true if there are pending retransmissions.
+ bool HasPendingRetransmissions() const;
+
+ // Retrieves the next pending retransmission.
+ PendingRetransmission NextPendingRetransmission();
- // Returns true if there are any unacked packets.
bool HasUnackedPackets() const;
- // Returns the number of unacked packets.
- size_t GetNumUnackedPackets() const;
+ // Returns the number of unacked packets which have retransmittable frames.
+ size_t GetNumRetransmittablePackets() const;
- // Returns the smallest sequence number of a sent packet which has not
- // been acked by the peer. If all packets have been acked, returns the
+ // Returns the smallest sequence number of a sent packet which has not been
+ // acked by the peer. Excludes any packets which have been retransmitted
+ // with a new sequence number. If all packets have been acked, returns the
// sequence number of the next packet that will be sent.
QuicPacketSequenceNumber GetLeastUnackedSentPacket() const;
- // Returns the set of unacked packet sequence numbers.
+ // Returns the set of sequence numbers of all unacked packets.
+ // Test only.
SequenceNumberSet GetUnackedPackets() const;
+ // Returns true if |sequence_number| is a previous transmission of packet.
+ bool IsPreviousTransmission(QuicPacketSequenceNumber sequence_number) const;
+
+ // TODO(ianswett): Combine the congestion control related methods below with
+ // some of the methods above and cleanup the resulting code.
+ // Called when we have received an ack frame from peer.
+ // Returns a set containing all the sequence numbers to be nack retransmitted
+ // as a result of the ack.
+ virtual SequenceNumberSet OnIncomingAckFrame(
+ const ReceivedPacketInfo& received_info,
+ const QuicTime& ack_receive_time);
+
+ // Called when a congestion feedback frame is received from peer.
+ virtual void OnIncomingQuicCongestionFeedbackFrame(
+ const QuicCongestionFeedbackFrame& frame,
+ const QuicTime& feedback_receive_time);
+
+ // Called when we have sent bytes to the peer. This informs the manager both
+ // the number of bytes sent and if they were retransmitted.
+ virtual void OnPacketSent(QuicPacketSequenceNumber sequence_number,
+ QuicTime sent_time,
+ QuicByteCount bytes,
+ TransmissionType transmission_type,
+ HasRetransmittableData has_retransmittable_data);
+
+ // Called when the retransmission timer expires.
+ virtual void OnRetransmissionTimeout();
+
+ // Called when a packet is timed out, such as an RTO. Removes the bytes from
+ // the congestion manager, but does not change the congestion window size.
+ virtual void OnPacketAbandoned(QuicPacketSequenceNumber sequence_number);
+
+ // Calculate the time until we can send the next packet to the wire.
+ // Note 1: When kUnknownWaitTime is returned, there is no need to poll
+ // TimeUntilSend again until we receive an OnIncomingAckFrame event.
+ // Note 2: Send algorithms may or may not use |retransmit| in their
+ // calculations.
+ virtual QuicTime::Delta TimeUntilSend(QuicTime now,
+ TransmissionType transmission_type,
+ HasRetransmittableData retransmittable,
+ IsHandshake handshake);
+
+ // Returns amount of time for delayed ack timer.
+ const QuicTime::Delta DelayedAckTime();
+
+ // Returns the current RTO delay.
+ const QuicTime::Delta GetRetransmissionDelay() const;
+
+ // Returns the estimated smoothed RTT calculated by the congestion algorithm.
+ const QuicTime::Delta SmoothedRtt() const;
+
+ // Returns the estimated bandwidth calculated by the congestion algorithm.
+ QuicBandwidth BandwidthEstimate() const;
+
+ // Returns the size of the current congestion window in bytes. Note, this is
+ // not the *available* window. Some send algorithms may not use a congestion
+ // window and will return 0.
+ QuicByteCount GetCongestionWindow() const;
+
+ // Enables pacing if it has not already been enabled, and if
+ // FLAGS_enable_quic_pacing is set.
+ void MaybeEnablePacing();
+
+ bool using_pacing() const { return using_pacing_; }
+
+
private:
- struct RetransmissionInfo {
- RetransmissionInfo() {}
- explicit RetransmissionInfo(QuicPacketSequenceNumber sequence_number,
- QuicSequenceNumberLength sequence_number_length)
- : sequence_number(sequence_number),
+ friend class test::QuicConnectionPeer;
+ friend class test::QuicSentPacketManagerPeer;
+
+ struct TransmissionInfo {
+ TransmissionInfo()
+ : retransmittable_frames(NULL),
+ sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER),
+ sent_time(QuicTime::Zero()),
+ previous_transmissions(NULL) { }
+ TransmissionInfo(RetransmittableFrames* retransmittable_frames,
+ QuicSequenceNumberLength sequence_number_length)
+ : retransmittable_frames(retransmittable_frames),
sequence_number_length(sequence_number_length),
- number_nacks(0),
- number_retransmissions(0) {
+ sent_time(QuicTime::Zero()),
+ previous_transmissions(NULL) {
}
- QuicPacketSequenceNumber sequence_number;
+ RetransmittableFrames* retransmittable_frames;
QuicSequenceNumberLength sequence_number_length;
- size_t number_nacks;
- size_t number_retransmissions;
+ // Zero when the packet is serialized, non-zero once it's sent.
+ QuicTime sent_time;
+ // Stores all previous transmissions if the packet has been retransmitted,
+ // and is NULL otherwise.
+ SequenceNumberSet* previous_transmissions;
};
typedef linked_hash_map<QuicPacketSequenceNumber,
- RetransmittableFrames*> UnackedPacketMap;
- typedef base::hash_map<QuicPacketSequenceNumber,
- RetransmissionInfo> RetransmissionMap;
+ TransmissionInfo> UnackedPacketMap;
+ typedef linked_hash_map<QuicPacketSequenceNumber,
+ TransmissionType> PendingRetransmissionMap;
+ typedef base::hash_map<QuicPacketSequenceNumber, SequenceNumberSet*>
+ PreviousTransmissionMap;
- // When new packets are created which may be retransmitted, they are added
- // to this map, which contains owning pointers to the contained frames.
- UnackedPacketMap unacked_packets_;
+ // Process the incoming ack looking for newly ack'd data packets.
+ void HandleAckForSentPackets(const ReceivedPacketInfo& received_info);
+
+ // Update the RTT if the ack is for the largest acked sequence number.
+ void MaybeUpdateRTT(const ReceivedPacketInfo& received_info,
+ const QuicTime& ack_receive_time);
- // Pending fec packets that have not been acked yet. These packets need to be
- // cleared out of the cgst_window after a timeout since FEC packets are never
- // retransmitted.
- // TODO(satyamshekhar): What should be the timeout for these packets?
- UnackedPacketMap unacked_fec_packets_;
+ // Marks |sequence_number| as having been seen by the peer. Returns an
+ // iterator to the next remaining unacked packet.
+ UnackedPacketMap::iterator MarkPacketReceivedByPeer(
+ QuicPacketSequenceNumber sequence_number);
- // Map from sequence number to the retransmission info.
- RetransmissionMap retransmission_map_;
+ // Simply removes the entries, if any, from the unacked packet map
+ // and the retransmission map.
+ void DiscardPacket(QuicPacketSequenceNumber sequence_number);
+
+ // Request that |sequence_number| be retransmitted after the other pending
+ // retransmissions. Returns false if there are no retransmittable frames for
+ // |sequence_number| and true if it will be retransmitted.
+ bool MarkForRetransmission(QuicPacketSequenceNumber sequence_number,
+ TransmissionType transmission_type);
+
+ // Returns the length of the serialized sequence number for
+ // the packet |sequence_number|.
+ QuicSequenceNumberLength GetSequenceNumberLength(
+ QuicPacketSequenceNumber sequence_number) const;
+
+ // Clears up to |num_to_clear| previous transmissions in order to make room
+ // in the ack frame for new acks.
+ void ClearPreviousRetransmissions(size_t num_to_clear);
+
+ void CleanupPacketHistory();
+
+ // Newly serialized retransmittable and fec 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 NULL, while
+ // the new packet's entry will contain the frames to retransmit.
+ // If the old packet is acked before the new packet, then the old entry will
+ // be removed from the map and the new entry's retransmittable frames will be
+ // set to NULL.
+ UnackedPacketMap unacked_packets_;
+
+ // Pending retransmissions which have not been packetized and sent yet.
+ PendingRetransmissionMap pending_retransmissions_;
// Tracks if the connection was created by the server.
bool is_server_;
+
HelperInterface* helper_;
+ // An AckNotifier can register to be informed when ACKs have been received for
+ // all packets that a given block of data was sent in. The AckNotifierManager
+ // maintains the currently active notifiers.
+ AckNotifierManager ack_notifier_manager_;
+
+ const QuicClock* clock_;
+ scoped_ptr<SendAlgorithmInterface> send_algorithm_;
+ // Tracks the send time, size, and nack count of sent packets. Packets are
+ // removed after 5 seconds and they've been removed from pending_packets_.
+ SendAlgorithmInterface::SentPacketsMap packet_history_map_;
+ // Packets that are outstanding and have not been abandoned or lost.
+ SequenceNumberSet pending_packets_;
+ QuicTime::Delta rtt_sample_; // RTT estimate from the most recent ACK.
+ // Number of times the RTO timer has fired in a row without receiving an ack.
+ size_t consecutive_rto_count_;
+ bool using_pacing_;
+
DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManager);
};
diff --git a/chromium/net/quic/quic_sent_packet_manager_test.cc b/chromium/net/quic/quic_sent_packet_manager_test.cc
index 8f5cb3d19d4..168cbf378cf 100644
--- a/chromium/net/quic/quic_sent_packet_manager_test.cc
+++ b/chromium/net/quic/quic_sent_packet_manager_test.cc
@@ -4,10 +4,13 @@
#include "net/quic/quic_sent_packet_manager.h"
+#include "base/stl_util.h"
+#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using std::vector;
using testing::_;
using testing::Return;
using testing::StrictMock;
@@ -18,63 +21,876 @@ namespace {
class MockHelper : public QuicSentPacketManager::HelperInterface {
public:
- MOCK_METHOD0(GetPeerLargestObservedPacket, QuicPacketSequenceNumber());
MOCK_METHOD0(GetNextPacketSequenceNumber, QuicPacketSequenceNumber());
- MOCK_METHOD2(OnPacketNacked, void(QuicPacketSequenceNumber sequence_number,
- size_t nack_count));
};
-class QuicSentPacketManagerTest : public ::testing::Test {
+class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> {
protected:
QuicSentPacketManagerTest()
- : manager_(true, &helper_) {
+ : manager_(true, &helper_, &clock_, kFixRate),
+ send_algorithm_(new StrictMock<MockSendAlgorithm>) {
+ QuicSentPacketManagerPeer::SetSendAlgorithm(&manager_, send_algorithm_);
+ }
+
+ ~QuicSentPacketManagerTest() {
+ STLDeleteElements(&packets_);
+ }
+
+ void VerifyUnackedPackets(QuicPacketSequenceNumber* packets,
+ size_t num_packets) {
+ if (num_packets == 0) {
+ EXPECT_FALSE(manager_.HasUnackedPackets());
+ EXPECT_EQ(0u, manager_.GetNumRetransmittablePackets());
+ return;
+ }
+
+ EXPECT_TRUE(manager_.HasUnackedPackets());
+ EXPECT_EQ(packets[0], manager_.GetLeastUnackedSentPacket());
+ for (size_t i = 0; i < num_packets; ++i) {
+ EXPECT_TRUE(manager_.IsUnacked(packets[i])) << packets[i];
+ }
+ }
+
+ void VerifyRetransmittablePackets(QuicPacketSequenceNumber* packets,
+ size_t num_packets) {
+ SequenceNumberSet unacked = manager_.GetUnackedPackets();
+ for (size_t i = 0; i < num_packets; ++i) {
+ EXPECT_TRUE(ContainsKey(unacked, packets[i])) << packets[i];
+ }
+ size_t num_retransmittable = 0;
+ for (SequenceNumberSet::const_iterator it = unacked.begin();
+ it != unacked.end(); ++it) {
+ if (manager_.HasRetransmittableFrames(*it)) {
+ ++num_retransmittable;
+ }
+ }
+ EXPECT_EQ(num_packets, manager_.GetNumRetransmittablePackets());
+ EXPECT_EQ(num_packets, num_retransmittable);
+ }
+
+ void VerifyAckedPackets(QuicPacketSequenceNumber* expected,
+ size_t num_expected,
+ const SequenceNumberSet& actual) {
+ if (num_expected == 0) {
+ EXPECT_TRUE(actual.empty());
+ return;
+ }
+
+ EXPECT_EQ(num_expected, actual.size());
+ for (size_t i = 0; i < num_expected; ++i) {
+ EXPECT_TRUE(ContainsKey(actual, expected[i])) << expected[i];
+ }
+ }
+
+ void RetransmitPacket(QuicPacketSequenceNumber old_sequence_number,
+ QuicPacketSequenceNumber new_sequence_number) {
+ QuicSentPacketManagerPeer::MarkForRetransmission(
+ &manager_, old_sequence_number, NACK_RETRANSMISSION);
+ EXPECT_TRUE(manager_.HasPendingRetransmissions());
+ QuicSentPacketManager::PendingRetransmission next_retransmission =
+ manager_.NextPendingRetransmission();
+ EXPECT_EQ(old_sequence_number, next_retransmission.sequence_number);
+ EXPECT_EQ(NACK_RETRANSMISSION, next_retransmission.transmission_type);
+ manager_.OnRetransmittedPacket(old_sequence_number, new_sequence_number);
+ EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(
+ &manager_, new_sequence_number));
+ }
+
+ SerializedPacket CreatePacket(QuicPacketSequenceNumber sequence_number) {
+ packets_.push_back(QuicPacket::NewDataPacket(
+ NULL, 0, false, PACKET_8BYTE_GUID, false,
+ PACKET_6BYTE_SEQUENCE_NUMBER));
+ return SerializedPacket(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
+ packets_.back(), 0u, new RetransmittableFrames());
+ }
+
+ SerializedPacket CreateFecPacket(QuicPacketSequenceNumber sequence_number) {
+ packets_.push_back(QuicPacket::NewFecPacket(
+ NULL, 0, false, PACKET_8BYTE_GUID, false,
+ PACKET_6BYTE_SEQUENCE_NUMBER));
+ return SerializedPacket(sequence_number, PACKET_6BYTE_SEQUENCE_NUMBER,
+ packets_.back(), 0u, NULL);
+ }
+
+ void SendDataPacket(QuicPacketSequenceNumber sequence_number) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, sequence_number, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ SerializedPacket packet(CreatePacket(sequence_number));
+ manager_.OnSerializedPacket(packet);
+ manager_.OnPacketSent(sequence_number, clock_.ApproximateNow(),
+ packet.packet->length(), NOT_RETRANSMISSION,
+ HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Based on QuicConnection's WritePendingRetransmissions.
+ void RetransmitNextPacket(
+ QuicPacketSequenceNumber retransmission_sequence_number) {
+ EXPECT_TRUE(manager_.HasPendingRetransmissions());
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, retransmission_sequence_number, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ const QuicSentPacketManager::PendingRetransmission pending =
+ manager_.NextPendingRetransmission();
+ manager_.OnRetransmittedPacket(
+ pending.sequence_number, retransmission_sequence_number);
+ manager_.OnPacketSent(retransmission_sequence_number,
+ clock_.ApproximateNow(), 1000,
+ pending.transmission_type, HAS_RETRANSMITTABLE_DATA);
}
testing::StrictMock<MockHelper> helper_;
QuicSentPacketManager manager_;
+ vector<QuicPacket*> packets_;
+ MockClock clock_;
+ MockSendAlgorithm* send_algorithm_;
};
+TEST_F(QuicSentPacketManagerTest, IsUnacked) {
+ VerifyUnackedPackets(NULL, 0);
+
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+
+ QuicPacketSequenceNumber unacked[] = { 1 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 1 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+}
+
+TEST_F(QuicSentPacketManagerTest, IsUnAckedRetransmit) {
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+ RetransmitPacket(1, 2);
+
+ EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2));
+ QuicPacketSequenceNumber unacked[] = { 1, 2 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 2 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+}
+
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAck) {
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+ RetransmitPacket(1, 2);
+
+ // Ack 2 but not 1.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 2;
+ received_info.missing_packets.insert(1);
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ // No unacked packets remain.
+ VerifyUnackedPackets(NULL, 0);
+ VerifyRetransmittablePackets(NULL, 0);
+}
+
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckBeforeSend) {
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+ QuicSentPacketManagerPeer::MarkForRetransmission(
+ &manager_, 1, NACK_RETRANSMISSION);
+ EXPECT_TRUE(manager_.HasPendingRetransmissions());
+
+ // Ack 1.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 1;
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ // There should no longer be a pending retransmission.
+ EXPECT_FALSE(manager_.HasPendingRetransmissions());
+
+ // No unacked packets remain.
+ VerifyUnackedPackets(NULL, 0);
+ VerifyRetransmittablePackets(NULL, 0);
+}
+
+TEST_F(QuicSentPacketManagerTest, RetransmitThenAckPrevious) {
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+ RetransmitPacket(1, 2);
+
+ // Ack 1 but not 2.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 1;
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ // 2 remains unacked, but no packets have retransmittable data.
+ QuicPacketSequenceNumber unacked[] = { 2 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ VerifyRetransmittablePackets(NULL, 0);
+
+ // Verify that if the retransmission alarm does fire to abandon packet 2,
+ // the sent packet manager is not notified, since there is no retransmittable
+ // data outstanding.
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillOnce(Return(QuicTime::Delta::FromMilliseconds(1)));
+ manager_.OnRetransmissionTimeout();
+}
+
+TEST_F(QuicSentPacketManagerTest, RetransmitTwiceThenAckFirst) {
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+ RetransmitPacket(1, 2);
+ RetransmitPacket(2, 3);
+
+ // Ack 1 but not 2 or 3.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 1;
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ // 3 remains unacked, but no packets have retransmittable data.
+ QuicPacketSequenceNumber unacked[] = { 3 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ VerifyRetransmittablePackets(NULL, 0);
+
+ // Verify that if the retransmission alarm does fire to abandon packet 3,
+ // the sent packet manager is not notified, since there is no retransmittable
+ // data outstanding.
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillOnce(Return(QuicTime::Delta::FromMilliseconds(1)));
+ manager_.OnRetransmissionTimeout();
+}
+
+TEST_F(QuicSentPacketManagerTest, TruncatedAck) {
+ SerializedPacket serialized_packet(CreatePacket(1));
+
+ manager_.OnSerializedPacket(serialized_packet);
+ RetransmitPacket(1, 2);
+ RetransmitPacket(2, 3);
+ RetransmitPacket(3, 4);
+
+ // Truncated ack with 2 NACKs
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 2;
+ received_info.missing_packets.insert(1);
+ received_info.missing_packets.insert(2);
+ received_info.is_truncated = true;
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ // High water mark will be raised.
+ QuicPacketSequenceNumber unacked[] = { 2, 3, 4 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 4 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+}
+
+TEST_F(QuicSentPacketManagerTest, SendDropAckRetransmitManyPackets) {
+ manager_.OnSerializedPacket(CreatePacket(1));
+ manager_.OnSerializedPacket(CreatePacket(2));
+ manager_.OnSerializedPacket(CreatePacket(3));
+
+ {
+ // Ack packets 1 and 3.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 3;
+ received_info.missing_packets.insert(2);
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ QuicPacketSequenceNumber unacked[] = { 2 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 2 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+ }
+
+ manager_.OnSerializedPacket(CreatePacket(4));
+ manager_.OnSerializedPacket(CreatePacket(5));
+
+ {
+ // Ack packets 5.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 5;
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(4);
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ QuicPacketSequenceNumber unacked[] = { 2, 4 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 2, 4 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+ }
+
+ manager_.OnSerializedPacket(CreatePacket(6));
+ manager_.OnSerializedPacket(CreatePacket(7));
+
+ {
+ // Ack packets 7.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 7;
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(4);
+ received_info.missing_packets.insert(6);
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ QuicPacketSequenceNumber unacked[] = { 2, 4, 6 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 2, 4, 6 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+ }
+
+ RetransmitPacket(2, 8);
+ manager_.OnSerializedPacket(CreatePacket(9));
+ manager_.OnSerializedPacket(CreatePacket(10));
+
+ {
+ // Ack packet 10.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 10;
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(4);
+ received_info.missing_packets.insert(6);
+ received_info.missing_packets.insert(8);
+ received_info.missing_packets.insert(9);
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ QuicPacketSequenceNumber unacked[] = { 2, 4, 6, 8, 9 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 4, 6, 8, 9 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+ }
+
+
+ RetransmitPacket(4, 11);
+ manager_.OnSerializedPacket(CreatePacket(12));
+ manager_.OnSerializedPacket(CreatePacket(13));
+
+ {
+ // Ack packet 13.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 13;
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(4);
+ received_info.missing_packets.insert(6);
+ received_info.missing_packets.insert(8);
+ received_info.missing_packets.insert(9);
+ received_info.missing_packets.insert(11);
+ received_info.missing_packets.insert(12);
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ QuicPacketSequenceNumber unacked[] = { 2, 4, 6, 8, 9, 11, 12 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 6, 8, 9, 11, 12 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+ }
+
+ RetransmitPacket(6, 14);
+ manager_.OnSerializedPacket(CreatePacket(15));
+ manager_.OnSerializedPacket(CreatePacket(16));
+
+ {
+ // Ack packet 16.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 13;
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(4);
+ received_info.missing_packets.insert(6);
+ received_info.missing_packets.insert(8);
+ received_info.missing_packets.insert(9);
+ received_info.missing_packets.insert(11);
+ received_info.missing_packets.insert(12);
+ received_info.is_truncated = true;
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ // Truncated ack raises the high water mark by clearing out 2, 4, and 6.
+ QuicPacketSequenceNumber unacked[] = { 8, 9, 11, 12, 14, 15, 16 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ QuicPacketSequenceNumber retransmittable[] = { 8, 9, 11, 12, 14, 15, 16 };
+ VerifyRetransmittablePackets(retransmittable, arraysize(retransmittable));
+ }
+}
+
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacket) {
EXPECT_CALL(helper_, GetNextPacketSequenceNumber()).WillOnce(Return(1u));
EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
}
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacketUnacked) {
- scoped_ptr<QuicPacket> packet(QuicPacket::NewDataPacket(
- NULL, 0, false, PACKET_8BYTE_GUID, false, PACKET_6BYTE_SEQUENCE_NUMBER));
- SerializedPacket serialized_packet(1u, PACKET_6BYTE_SEQUENCE_NUMBER,
- packet.get(), 7u,
- new RetransmittableFrames());
+ SerializedPacket serialized_packet(CreatePacket(1));
manager_.OnSerializedPacket(serialized_packet);
EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
}
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacketUnackedFec) {
- scoped_ptr<QuicPacket> packet(QuicPacket::NewFecPacket(
- NULL, 0, false, PACKET_8BYTE_GUID, false, PACKET_6BYTE_SEQUENCE_NUMBER));
- SerializedPacket serialized_packet(1u, PACKET_6BYTE_SEQUENCE_NUMBER,
- packet.get(), 7u, NULL);
+ SerializedPacket serialized_packet(CreateFecPacket(1));
manager_.OnSerializedPacket(serialized_packet);
- // FEC packets do not count as "unacked".
- EXPECT_CALL(helper_, GetNextPacketSequenceNumber()).WillOnce(Return(2u));
- EXPECT_EQ(2u, manager_.GetLeastUnackedSentPacket());
+ EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
}
TEST_F(QuicSentPacketManagerTest, GetLeastUnackedSentPacketDiscardUnacked) {
- scoped_ptr<QuicPacket> packet(QuicPacket::NewDataPacket(
- NULL, 0, false, PACKET_8BYTE_GUID, false, PACKET_6BYTE_SEQUENCE_NUMBER));
- SerializedPacket serialized_packet(1u, PACKET_6BYTE_SEQUENCE_NUMBER,
- packet.get(), 7u,
- new RetransmittableFrames());
+ SerializedPacket serialized_packet(CreatePacket(1));
manager_.OnSerializedPacket(serialized_packet);
- manager_.DiscardPacket(1u);
+ manager_.DiscardUnackedPacket(1u);
EXPECT_CALL(helper_, GetNextPacketSequenceNumber()).WillOnce(Return(2u));
EXPECT_EQ(2u, manager_.GetLeastUnackedSentPacket());
}
+TEST_F(QuicSentPacketManagerTest, GetLeastUnackedPacketAndDiscard) {
+ VerifyUnackedPackets(NULL, 0);
+
+ SerializedPacket serialized_packet(CreateFecPacket(1));
+ manager_.OnSerializedPacket(serialized_packet);
+ EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
+
+ SerializedPacket serialized_packet2(CreateFecPacket(2));
+ manager_.OnSerializedPacket(serialized_packet2);
+ EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
+
+ SerializedPacket serialized_packet3(CreateFecPacket(3));
+ manager_.OnSerializedPacket(serialized_packet3);
+ EXPECT_EQ(1u, manager_.GetLeastUnackedSentPacket());
+
+ QuicPacketSequenceNumber unacked[] = { 1, 2, 3 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ VerifyRetransmittablePackets(NULL, 0);
+
+ manager_.DiscardUnackedPacket(1);
+ EXPECT_EQ(2u, manager_.GetLeastUnackedSentPacket());
+
+ // Ack 2.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = 2;
+ manager_.OnIncomingAck(received_info, QuicTime::Zero());
+
+ EXPECT_EQ(3u, manager_.GetLeastUnackedSentPacket());
+
+ // Discard the 3rd packet and ensure there are no FEC packets.
+ manager_.DiscardUnackedPacket(3);
+ EXPECT_FALSE(manager_.HasUnackedPackets());
+}
+
+TEST_F(QuicSentPacketManagerTest, GetSentTime) {
+ VerifyUnackedPackets(NULL, 0);
+
+ SerializedPacket serialized_packet(CreateFecPacket(1));
+ manager_.OnSerializedPacket(serialized_packet);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 1, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(
+ 1, QuicTime::Zero(), 0, NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ SerializedPacket serialized_packet2(CreateFecPacket(2));
+ QuicTime sent_time = QuicTime::Zero().Add(QuicTime::Delta::FromSeconds(1));
+ manager_.OnSerializedPacket(serialized_packet2);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, 2, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(
+ 2, sent_time, 0, NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+
+ QuicPacketSequenceNumber unacked[] = { 1, 2 };
+ VerifyUnackedPackets(unacked, arraysize(unacked));
+ VerifyRetransmittablePackets(NULL, 0);
+
+ EXPECT_TRUE(manager_.HasUnackedPackets());
+ EXPECT_EQ(QuicTime::Zero(),
+ QuicSentPacketManagerPeer::GetSentTime(&manager_, 1));
+ EXPECT_EQ(sent_time, QuicSentPacketManagerPeer::GetSentTime(&manager_, 2));
+}
+
+TEST_F(QuicSentPacketManagerTest, NackRetransmit1Packet) {
+ const size_t kNumSentPackets = 4;
+ // Transmit 4 packets.
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 3 times with increasing largest observed.
+ ReceivedPacketInfo received_info;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ received_info.missing_packets.insert(1);
+ for (QuicPacketSequenceNumber i = 1; i <= 3; ++i) {
+ received_info.largest_observed = i + 1;
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(i + 1, _, _)).Times(1);
+ if (i == 3) {
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ }
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(i == 3 ? 1u : 0u, retransmissions.size());
+ EXPECT_EQ(i, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+ }
+}
+
+// A stretch ack is an ack that covers more than 1 packet of previously
+// unacknowledged data.
+TEST_F(QuicSentPacketManagerTest, NackRetransmit1PacketWith1StretchAck) {
+ const size_t kNumSentPackets = 4;
+ // Transmit 4 packets.
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 3 times in a single StretchAck.
+ ReceivedPacketInfo received_info;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ received_info.missing_packets.insert(1);
+ received_info.largest_observed = kNumSentPackets;
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(_, _, _)).Times(3);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(1u, retransmissions.size());
+ EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+}
+
+// Ack a packet 3 packets ahead, causing a retransmit.
+TEST_F(QuicSentPacketManagerTest, NackRetransmit1PacketSingleAck) {
+ const size_t kNumSentPackets = 4;
+ // Transmit 4 packets.
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 3 times in an AckFrame with three missing packets.
+ ReceivedPacketInfo received_info;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ received_info.missing_packets.insert(1);
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(3);
+ received_info.largest_observed = kNumSentPackets;
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(1u, retransmissions.size());
+ EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+}
+
+TEST_F(QuicSentPacketManagerTest, EarlyRetransmit1Packet) {
+ const size_t kNumSentPackets = 2;
+ // Transmit 2 packets.
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Early retransmit when the final packet gets acked and the first is nacked.
+ ReceivedPacketInfo received_info;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ received_info.missing_packets.insert(1);
+ received_info.largest_observed = kNumSentPackets;
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(1u, retransmissions.size());
+ EXPECT_EQ(1u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+}
+
+TEST_F(QuicSentPacketManagerTest, DontEarlyRetransmitPacket) {
+ const size_t kNumSentPackets = 4;
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Fast retransmit when the final packet gets acked, but don't early
+ // retransmit as well, because there are 4 packets outstanding when the ack
+ // arrives.
+ ReceivedPacketInfo received_info;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ received_info.missing_packets.insert(1);
+ received_info.missing_packets.insert(2);
+ received_info.missing_packets.insert(3);
+ received_info.largest_observed = kNumSentPackets;
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(1, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(1, _)).Times(1);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(1u, retransmissions.size());
+ EXPECT_EQ(3u, QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+}
+
+TEST_F(QuicSentPacketManagerTest, NackRetransmit2Packets) {
+ const size_t kNumSentPackets = 20;
+ // Transmit 20 packets.
+ for (QuicPacketSequenceNumber i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first 19 packets 3 times.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = kNumSentPackets;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ for (size_t i = 1; i < kNumSentPackets; ++i) {
+ received_info.missing_packets.insert(i);
+ }
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAcked(kNumSentPackets, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(2u, retransmissions.size());
+ for (size_t i = 1; i < kNumSentPackets; ++i) {
+ EXPECT_EQ(kNumSentPackets - i,
+ QuicSentPacketManagerPeer::GetNackCount(&manager_, i));
+ }
+}
+
+TEST_F(QuicSentPacketManagerTest, NackRetransmit2PacketsAlternateAcks) {
+ const size_t kNumSentPackets = 30;
+ // Transmit 15 packets of data and 15 ack packets. The send algorithm will
+ // inform the congestion manager not to save the acks by returning false.
+ for (QuicPacketSequenceNumber i = 1; i <= kNumSentPackets; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(i % 2 == 0 ? false : true));
+ manager_.OnPacketSent(
+ i, clock_.Now(), 1000, NOT_RETRANSMISSION,
+ i % 2 == 0 ? NO_RETRANSMITTABLE_DATA : HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first 29 packets 3 times.
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = kNumSentPackets;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ for (size_t i = 1; i < kNumSentPackets; ++i) {
+ received_info.missing_packets.insert(i);
+ }
+ // We never actually get an ack call, since the kNumSentPackets packet was
+ // not saved.
+ EXPECT_CALL(*send_algorithm_, OnPacketLost(_, _)).Times(2);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(2);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(2u, retransmissions.size());
+ // Only non-ack packets have a nack count.
+ for (size_t i = 1; i < kNumSentPackets; i += 2) {
+ EXPECT_EQ(kNumSentPackets - i,
+ QuicSentPacketManagerPeer::GetNackCount(&manager_, i));
+ }
+
+ // Ensure only the odd packets were retransmitted, since the others were not
+ // retransmittable(ie: acks).
+ for (SequenceNumberSet::const_iterator it = retransmissions.begin();
+ it != retransmissions.end(); ++it) {
+ EXPECT_EQ(1u, *it % 2);
+ }
+}
+
+TEST_F(QuicSentPacketManagerTest, NackTwiceThenAck) {
+ // Transmit 4 packets.
+ for (QuicPacketSequenceNumber i = 1; i <= 4; ++i) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ manager_.OnPacketSent(i, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ }
+
+ // Nack the first packet 2 times, then ack it.
+ ReceivedPacketInfo received_info;
+ received_info.missing_packets.insert(1);
+ for (size_t i = 1; i <= 3; ++i) {
+ if (i == 3) {
+ received_info.missing_packets.clear();
+ }
+ received_info.largest_observed = i + 1;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAcked(_, _, _)).Times(i == 3 ? 2 : 1);
+ SequenceNumberSet retransmissions =
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(0u, retransmissions.size());
+ // The nack count remains at 2 when the packet is acked.
+ EXPECT_EQ(i == 3 ? 2u : i,
+ QuicSentPacketManagerPeer::GetNackCount(&manager_, 1));
+ }
+}
+
+TEST_F(QuicSentPacketManagerTest, Rtt) {
+ QuicPacketSequenceNumber sequence_number = 1;
+ QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(15);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
+
+ manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
+
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = sequence_number;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(5);
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
+}
+
+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
+ // and is hence invalid.
+ QuicPacketSequenceNumber sequence_number = 1;
+ QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
+
+ manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = sequence_number;
+ received_info.delta_time_largest_observed =
+ QuicTime::Delta::FromMilliseconds(11);
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
+}
+
+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.
+ QuicPacketSequenceNumber sequence_number = 1;
+ QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketAcked(sequence_number, _, expected_rtt)).Times(1);
+
+ manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = sequence_number;
+ received_info.delta_time_largest_observed = QuicTime::Delta::Infinite();
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
+}
+
+TEST_F(QuicSentPacketManagerTest, RttZeroDelta) {
+ // Expect that the RTT is the time between send and receive since the
+ // delta_time_largest_observed is zero.
+ QuicPacketSequenceNumber sequence_number = 1;
+ QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(1).WillOnce(Return(true));
+ EXPECT_CALL(*send_algorithm_, OnPacketAcked(sequence_number, _, expected_rtt))
+ .Times(1);
+
+ manager_.OnPacketSent(sequence_number, clock_.Now(), 1000,
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
+ clock_.AdvanceTime(expected_rtt);
+
+ ReceivedPacketInfo received_info;
+ received_info.largest_observed = sequence_number;
+ received_info.delta_time_largest_observed = QuicTime::Delta::Zero();
+ manager_.OnIncomingAckFrame(received_info, clock_.Now());
+ EXPECT_EQ(expected_rtt, QuicSentPacketManagerPeer::rtt(&manager_));
+}
+
+TEST_F(QuicSentPacketManagerTest, RetransmissionTimeout) {
+ // Send 100 packets and then ensure all are abandoned when the RTO fires.
+ const size_t kNumSentPackets = 100;
+ for (size_t i = 1; i <= kNumSentPackets; ++i) {
+ SendDataPacket(i);
+ }
+
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(_, _)).Times(kNumSentPackets);
+
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillOnce(Return(QuicTime::Delta::FromMilliseconds(1)));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ manager_.OnRetransmissionTimeout();
+}
+
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMin) {
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillOnce(Return(QuicTime::Delta::FromMilliseconds(1)));
+
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
+ manager_.GetRetransmissionDelay());
+}
+
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelayMax) {
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillOnce(Return(QuicTime::Delta::FromSeconds(500)));
+
+ EXPECT_EQ(QuicTime::Delta::FromSeconds(60),
+ manager_.GetRetransmissionDelay());
+}
+
+TEST_F(QuicSentPacketManagerTest, GetTransmissionDelay) {
+ SendDataPacket(1);
+ QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillRepeatedly(Return(delay));
+
+ // Delay should back off exponentially.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_EQ(delay, manager_.GetRetransmissionDelay());
+ delay = delay.Add(delay);
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(i + 1, _));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ manager_.OnRetransmissionTimeout();
+ RetransmitNextPacket(i + 2);
+ }
+}
+
+TEST_F(QuicSentPacketManagerTest, GetTestTransmissionDelayTailDrop) {
+ FLAGS_limit_rto_increase_for_tests = true;
+
+ SendDataPacket(1);
+ QuicTime::Delta delay = QuicTime::Delta::FromMilliseconds(500);
+ EXPECT_CALL(*send_algorithm_, RetransmissionDelay())
+ .WillRepeatedly(Return(delay));
+
+ // No backoff for the first 5 retransmissions.
+ for (int i = 0; i < 5; ++i) {
+ EXPECT_EQ(delay, manager_.GetRetransmissionDelay());
+ EXPECT_CALL(*send_algorithm_, OnPacketAbandoned(i + 1, _));
+ EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout());
+ manager_.OnRetransmissionTimeout();
+ RetransmitNextPacket(i + 2);
+ }
+
+ // Then backoff starts
+ EXPECT_EQ(delay.Add(delay), manager_.GetRetransmissionDelay());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_session.cc b/chromium/net/quic/quic_session.cc
index 9389af403ca..67cdf54d1d1 100644
--- a/chromium/net/quic/quic_session.cc
+++ b/chromium/net/quic/quic_session.cc
@@ -20,7 +20,7 @@ namespace net {
const size_t kMaxPrematurelyClosedStreamsTracked = 20;
const size_t kMaxZombieStreams = 20;
-#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
+#define ENDPOINT (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
@@ -59,8 +59,13 @@ class VisitorShim : public QuicConnectionVisitorInterface {
session_->OnSuccessfulVersionNegotiation(version);
}
- virtual void ConnectionClose(QuicErrorCode error, bool from_peer) OVERRIDE {
- session_->ConnectionClose(error, from_peer);
+ virtual void OnConfigNegotiated() OVERRIDE {
+ session_->OnConfigNegotiated();
+ }
+
+ virtual void OnConnectionClosed(QuicErrorCode error,
+ bool from_peer) OVERRIDE {
+ session_->OnConnectionClosed(error, from_peer);
// The session will go away, so don't bother with cleanup.
}
@@ -73,14 +78,12 @@ class VisitorShim : public QuicConnectionVisitorInterface {
};
QuicSession::QuicSession(QuicConnection* connection,
- const QuicConfig& config,
- bool is_server)
+ const QuicConfig& config)
: connection_(connection),
visitor_shim_(new VisitorShim(this)),
config_(config),
max_open_streams_(config_.max_streams_per_connection()),
- next_stream_id_(is_server ? 2 : 3),
- is_server_(is_server),
+ next_stream_id_(is_server() ? 2 : 3),
largest_peer_created_stream_id_(0),
error_(QUIC_NO_ERROR),
goaway_received_(false),
@@ -88,12 +91,11 @@ QuicSession::QuicSession(QuicConnection* connection,
has_pending_handshake_(false) {
connection_->set_visitor(visitor_shim_.get());
- connection_->SetIdleNetworkTimeout(config_.idle_connection_state_lifetime());
+ connection_->SetFromConfig(config_);
if (connection_->connected()) {
connection_->SetOverallConnectionTimeout(
config_.max_time_before_crypto_handshake());
}
- // TODO(satyamshekhar): Set congestion control and ICSL also.
}
QuicSession::~QuicSession() {
@@ -133,11 +135,11 @@ bool QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
}
stream->OnStreamFrame(frames[i]);
- // If the stream had been prematurely closed, and the
+ // If the stream is a data stream had been prematurely closed, and the
// headers are now decompressed, then we are finally finished
// with this stream.
if (ContainsKey(zombie_streams_, stream_id) &&
- stream->headers_decompressed()) {
+ static_cast<QuicDataStream*>(stream)->headers_decompressed()) {
CloseZombieStream(stream_id);
}
}
@@ -149,7 +151,7 @@ bool QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
}
QuicStreamId stream_id = decompression_blocked_streams_.begin()->second;
decompression_blocked_streams_.erase(header_id);
- ReliableQuicStream* stream = GetStream(stream_id);
+ QuicDataStream* stream = GetDataStream(stream_id);
if (!stream) {
connection()->SendConnectionClose(
QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED);
@@ -161,7 +163,13 @@ bool QuicSession::OnStreamFrames(const vector<QuicStreamFrame>& frames) {
}
void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
- ReliableQuicStream* stream = GetStream(frame.stream_id);
+ if (frame.stream_id == kCryptoStreamId) {
+ connection()->SendConnectionCloseWithDetails(
+ QUIC_INVALID_STREAM_ID,
+ "Attempt to reset the crypto stream");
+ return;
+ }
+ QuicDataStream* stream = GetDataStream(frame.stream_id);
if (!stream) {
return; // Errors are handled by GetStream.
}
@@ -175,6 +183,10 @@ void QuicSession::OnRstStream(const QuicRstStreamFrame& frame) {
AddPrematurelyClosedStream(frame.stream_id);
return;
}
+ if (stream->stream_bytes_read() > 0 && !stream->headers_decompressed()) {
+ connection()->SendConnectionClose(
+ QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED);
+ }
stream->OnStreamReset(frame.error_code);
}
@@ -183,19 +195,20 @@ void QuicSession::OnGoAway(const QuicGoAwayFrame& frame) {
goaway_received_ = true;
}
-void QuicSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
+void QuicSession::OnConnectionClosed(QuicErrorCode error, bool from_peer) {
DCHECK(!connection_->connected());
if (error_ == QUIC_NO_ERROR) {
error_ = error;
}
- while (stream_map_.size() != 0) {
- ReliableStreamMap::iterator it = stream_map_.begin();
+ while (!stream_map_.empty()) {
+ DataStreamMap::iterator it = stream_map_.begin();
QuicStreamId id = it->first;
- it->second->ConnectionClose(error, from_peer);
- // The stream should call CloseStream as part of ConnectionClose.
+ it->second->OnConnectionClosed(error, from_peer);
+ // The stream should call CloseStream as part of OnConnectionClosed.
if (stream_map_.find(id) != stream_map_.end()) {
- LOG(DFATAL) << ENDPOINT << "Stream failed to close under ConnectionClose";
+ LOG(DFATAL) << ENDPOINT
+ << "Stream failed to close under OnConnectionClosed";
CloseStream(id);
}
}
@@ -209,12 +222,12 @@ bool QuicSession::OnCanWrite() {
while (!connection_->HasQueuedData() &&
remaining_writes > 0) {
DCHECK(write_blocked_streams_.HasWriteBlockedStreams());
- int index = write_blocked_streams_.GetHighestPriorityWriteBlockedList();
- if (index == -1) {
+ if (!write_blocked_streams_.HasWriteBlockedStreams()) {
LOG(DFATAL) << "WriteBlockedStream is missing";
connection_->CloseConnection(QUIC_INTERNAL_ERROR, false);
return true; // We have no write blocked streams.
}
+ int index = write_blocked_streams_.GetHighestPriorityWriteBlockedList();
QuicStreamId stream_id = write_blocked_streams_.PopFront(index);
if (stream_id == kCryptoStreamId) {
has_pending_handshake_ = false; // We just popped it.
@@ -235,12 +248,17 @@ bool QuicSession::HasPendingHandshake() const {
return has_pending_handshake_;
}
-QuicConsumedData QuicSession::WritevData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin) {
- return connection_->SendvStreamData(id, iov, iov_count, offset, fin);
+QuicConsumedData QuicSession::WritevData(
+ QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
+ IOVector data;
+ data.AppendIovec(iov, iov_count);
+ return connection_->SendStreamData(id, data, offset, fin,
+ ack_notifier_delegate);
}
void QuicSession::SendRstStream(QuicStreamId id,
@@ -260,20 +278,20 @@ void QuicSession::CloseStream(QuicStreamId stream_id) {
void QuicSession::CloseStreamInner(QuicStreamId stream_id,
bool locally_reset) {
- DLOG(INFO) << ENDPOINT << "Closing stream " << stream_id;
+ DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
- ReliableStreamMap::iterator it = stream_map_.find(stream_id);
+ DataStreamMap::iterator it = stream_map_.find(stream_id);
if (it == stream_map_.end()) {
- DLOG(INFO) << ENDPOINT << "Stream is already closed: " << stream_id;
+ DVLOG(1) << ENDPOINT << "Stream is already closed: " << stream_id;
return;
}
- ReliableQuicStream* stream = it->second;
+ QuicDataStream* stream = it->second;
if (connection_->connected() && !stream->headers_decompressed()) {
// If the stream is being closed locally (for example a client cancelling
// a request before receiving the response) then we need to make sure that
// we keep the stream alive long enough to process any response or
// RST_STREAM frames.
- if (locally_reset && !is_server_) {
+ if (locally_reset && !is_server()) {
AddZombieStream(stream_id);
return;
}
@@ -310,7 +328,7 @@ void QuicSession::AddZombieStream(QuicStreamId stream_id) {
void QuicSession::CloseZombieStream(QuicStreamId stream_id) {
DCHECK(ContainsKey(zombie_streams_, stream_id));
zombie_streams_.erase(stream_id);
- ReliableQuicStream* stream = GetStream(stream_id);
+ QuicDataStream* stream = GetDataStream(stream_id);
if (!stream) {
return;
}
@@ -335,6 +353,10 @@ bool QuicSession::IsCryptoHandshakeConfirmed() {
return GetCryptoStream()->handshake_confirmed();
}
+void QuicSession::OnConfigNegotiated() {
+ connection_->SetFromConfig(config_);
+}
+
void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
switch (event) {
// TODO(satyamshekhar): Move the logic of setting the encrypter/decrypter
@@ -345,15 +367,12 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
case ENCRYPTION_REESTABLISHED:
// Retransmit originally packets that were sent, since they can't be
// decrypted by the peer.
- connection_->RetransmitUnackedPackets(
- QuicConnection::INITIAL_ENCRYPTION_ONLY);
+ connection_->RetransmitUnackedPackets(INITIAL_ENCRYPTION_ONLY);
break;
case HANDSHAKE_CONFIRMED:
LOG_IF(DFATAL, !config_.negotiated()) << ENDPOINT
<< "Handshake confirmed without parameter negotiation.";
- connection_->SetIdleNetworkTimeout(
- config_.idle_connection_state_lifetime());
connection_->SetOverallConnectionTimeout(QuicTime::Delta::Infinite());
max_open_streams_ = config_.max_streams_per_connection();
break;
@@ -375,8 +394,8 @@ QuicConfig* QuicSession::config() {
return &config_;
}
-void QuicSession::ActivateStream(ReliableQuicStream* stream) {
- DLOG(INFO) << ENDPOINT << "num_streams: " << stream_map_.size()
+void QuicSession::ActivateStream(QuicDataStream* stream) {
+ DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
<< ". activating " << stream->id();
DCHECK_EQ(stream_map_.count(stream->id()), 0u);
stream_map_[stream->id()] = stream;
@@ -392,8 +411,16 @@ ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
if (stream_id == kCryptoStreamId) {
return GetCryptoStream();
}
+ return GetDataStream(stream_id);
+}
+
+QuicDataStream* QuicSession::GetDataStream(const QuicStreamId stream_id) {
+ if (stream_id == kCryptoStreamId) {
+ DLOG(FATAL) << "Attempt to call GetDataStream with the crypto stream id";
+ return NULL;
+ }
- ReliableStreamMap::iterator it = stream_map_.find(stream_id);
+ DataStreamMap::iterator it = stream_map_.find(stream_id);
if (it != stream_map_.end()) {
return it->second;
}
@@ -412,7 +439,7 @@ ReliableQuicStream* QuicSession::GetStream(const QuicStreamId stream_id) {
return GetIncomingReliableStream(stream_id);
}
-ReliableQuicStream* QuicSession::GetIncomingReliableStream(
+QuicDataStream* QuicSession::GetIncomingReliableStream(
QuicStreamId stream_id) {
if (IsClosedStream(stream_id)) {
return NULL;
@@ -441,7 +468,7 @@ ReliableQuicStream* QuicSession::GetIncomingReliableStream(
}
largest_peer_created_stream_id_ = stream_id;
}
- ReliableQuicStream* stream = CreateIncomingReliableStream(stream_id);
+ QuicDataStream* stream = CreateIncomingDataStream(stream_id);
if (stream == NULL) {
return NULL;
}
@@ -489,6 +516,11 @@ void QuicSession::MarkWriteBlocked(QuicStreamId id, QuicPriority priority) {
write_blocked_streams_.PushBack(id, priority);
}
+bool QuicSession::HasQueuedData() const {
+ return write_blocked_streams_.NumBlockedStreams() ||
+ connection_->HasQueuedData();
+}
+
void QuicSession::MarkDecompressionBlocked(QuicHeaderId header_id,
QuicStreamId stream_id) {
decompression_blocked_streams_[header_id] = stream_id;
diff --git a/chromium/net/quic/quic_session.h b/chromium/net/quic/quic_session.h
index b58feb27426..083990b55f6 100644
--- a/chromium/net/quic/quic_session.h
+++ b/chromium/net/quic/quic_session.h
@@ -15,6 +15,7 @@
#include "net/base/linked_hash_map.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_crypto_stream.h"
+#include "net/quic/quic_data_stream.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_spdy_compressor.h"
@@ -53,8 +54,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
};
QuicSession(QuicConnection* connection,
- const QuicConfig& config,
- bool is_server);
+ const QuicConfig& config);
virtual ~QuicSession();
@@ -63,9 +63,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
const std::vector<QuicStreamFrame>& frames) OVERRIDE;
virtual void OnRstStream(const QuicRstStreamFrame& frame) OVERRIDE;
virtual void OnGoAway(const QuicGoAwayFrame& frame) OVERRIDE;
- virtual void ConnectionClose(QuicErrorCode error, bool from_peer) OVERRIDE;
+ virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE;
virtual void OnSuccessfulVersionNegotiation(
- const QuicVersion& version) OVERRIDE{}
+ const QuicVersion& version) OVERRIDE {}
+ virtual void OnConfigNegotiated() OVERRIDE;
// Not needed for HTTP.
virtual bool OnCanWrite() OVERRIDE;
virtual bool HasPendingHandshake() const OVERRIDE;
@@ -75,11 +76,16 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// 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.
- virtual QuicConsumedData WritevData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin);
+ // If provided, |ack_notifier_delegate| will be registered to be notified when
+ // we have seen ACKs for all packets resulting from this call. Not owned by
+ // this class.
+ virtual QuicConsumedData WritevData(
+ QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckNotifier::DelegateInterface* ack_notifier_delegate);
// Called by streams when they want to close the stream in both directions.
virtual void SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error);
@@ -141,6 +147,10 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
void MarkWriteBlocked(QuicStreamId id, QuicPriority priority);
+ // Returns true if the session has data to be sent, either queued in the
+ // connection, or in a write-blocked stream.
+ bool HasQueuedData() const;
+
// Marks that |stream_id| is blocked waiting to decompress the
// headers identified by |decompression_id|.
void MarkDecompressionBlocked(QuicHeaderId decompression_id,
@@ -162,26 +172,32 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
QuicErrorCode error() const { return error_; }
+ bool is_server() const { return connection_->is_server(); }
+
protected:
+ typedef base::hash_map<QuicStreamId, QuicDataStream*> DataStreamMap;
+
// Creates a new stream, owned by the caller, to handle a peer-initiated
// stream. Returns NULL and does error handling if the stream can not be
// created.
- virtual ReliableQuicStream* CreateIncomingReliableStream(QuicStreamId id) = 0;
+ virtual QuicDataStream* CreateIncomingDataStream(QuicStreamId id) = 0;
// Create a new stream, owned by the caller, to handle a locally-initiated
// stream. Returns NULL if max streams have already been opened.
- virtual ReliableQuicStream* CreateOutgoingReliableStream() = 0;
+ virtual QuicDataStream* CreateOutgoingDataStream() = 0;
// Return the reserved crypto stream.
virtual QuicCryptoStream* GetCryptoStream() = 0;
// Adds 'stream' to the active stream map.
- virtual void ActivateStream(ReliableQuicStream* stream);
+ virtual void ActivateStream(QuicDataStream* stream);
// Returns the stream id for a new stream.
QuicStreamId GetNextStreamId();
- ReliableQuicStream* GetIncomingReliableStream(QuicStreamId stream_id);
+ QuicDataStream* GetIncomingReliableStream(QuicStreamId stream_id);
+
+ QuicDataStream* GetDataStream(const QuicStreamId stream_id);
ReliableQuicStream* GetStream(const QuicStreamId stream_id);
@@ -191,17 +207,15 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// operations are being done on the streams at this time)
virtual void PostProcessAfterData();
- base::hash_map<QuicStreamId, ReliableQuicStream*>* streams() {
+ base::hash_map<QuicStreamId, QuicDataStream*>* streams() {
return &stream_map_;
}
- const base::hash_map<QuicStreamId, ReliableQuicStream*>* streams() const {
+ const base::hash_map<QuicStreamId, QuicDataStream*>* streams() const {
return &stream_map_;
}
- std::vector<ReliableQuicStream*>* closed_streams() {
- return &closed_streams_;
- }
+ std::vector<QuicDataStream*>* closed_streams() { return &closed_streams_; }
size_t get_max_open_streams() const {
return max_open_streams_;
@@ -211,8 +225,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
friend class test::QuicSessionPeer;
friend class VisitorShim;
- typedef base::hash_map<QuicStreamId, ReliableQuicStream*> ReliableStreamMap;
-
// Performs the work required to close |stream_id|. If |locally_reset|
// then the stream has been reset by this endpoint, not by the peer. This
// means the stream may become a zombie stream which needs to stay
@@ -248,7 +260,7 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// deletions.
scoped_ptr<VisitorShim> visitor_shim_;
- std::vector<ReliableQuicStream*> closed_streams_;
+ std::vector<QuicDataStream*> closed_streams_;
QuicSpdyDecompressor decompressor_;
QuicSpdyCompressor compressor_;
@@ -259,9 +271,8 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
size_t max_open_streams_;
// Map from StreamId to pointers to streams that are owned by the caller.
- ReliableStreamMap stream_map_;
+ DataStreamMap stream_map_;
QuicStreamId next_stream_id_;
- bool is_server_;
// Set of stream ids that have been "implicitly created" by receipt
// of a stream id larger than the next expected stream id.
diff --git a/chromium/net/quic/quic_session_test.cc b/chromium/net/quic/quic_session_test.cc
index e90b20f81c6..ecbafb5c6a2 100644
--- a/chromium/net/quic/quic_session_test.cc
+++ b/chromium/net/quic/quic_session_test.cc
@@ -12,6 +12,7 @@
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/quic_connection_peer.h"
+#include "net/quic/test_tools/quic_data_stream_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/reliable_quic_stream_peer.h"
#include "net/spdy/spdy_framer.h"
@@ -48,16 +49,17 @@ class TestCryptoStream : public QuicCryptoStream {
const QuicErrorCode error = session()->config()->ProcessClientHello(
msg, &error_details);
EXPECT_EQ(QUIC_NO_ERROR, error);
+ session()->OnConfigNegotiated();
session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
}
MOCK_METHOD0(OnCanWrite, void());
};
-class TestStream : public ReliableQuicStream {
+class TestStream : public QuicDataStream {
public:
TestStream(QuicStreamId id, QuicSession* session)
- : ReliableQuicStream(id, session) {
+ : QuicDataStream(id, session) {
}
using ReliableQuicStream::CloseWriteSide;
@@ -88,8 +90,8 @@ class StreamBlocker {
class TestSession : public QuicSession {
public:
- TestSession(QuicConnection* connection, bool is_server)
- : QuicSession(connection, DefaultQuicConfig(), is_server),
+ explicit TestSession(QuicConnection* connection)
+ : QuicSession(connection, DefaultQuicConfig()),
crypto_stream_(this) {
}
@@ -97,13 +99,13 @@ class TestSession : public QuicSession {
return &crypto_stream_;
}
- virtual TestStream* CreateOutgoingReliableStream() OVERRIDE {
+ virtual TestStream* CreateOutgoingDataStream() OVERRIDE {
TestStream* stream = new TestStream(GetNextStreamId(), this);
ActivateStream(stream);
return stream;
}
- virtual TestStream* CreateIncomingReliableStream(QuicStreamId id) OVERRIDE {
+ virtual TestStream* CreateIncomingDataStream(QuicStreamId id) OVERRIDE {
return new TestStream(id, this);
}
@@ -111,7 +113,7 @@ class TestSession : public QuicSession {
return QuicSession::IsClosedStream(id);
}
- ReliableQuicStream* GetIncomingReliableStream(QuicStreamId stream_id) {
+ QuicDataStream* GetIncomingReliableStream(QuicStreamId stream_id) {
return QuicSession::GetIncomingReliableStream(stream_id);
}
@@ -121,9 +123,8 @@ class TestSession : public QuicSession {
class QuicSessionTest : public ::testing::Test {
protected:
QuicSessionTest()
- : guid_(1),
- connection_(new MockConnection(guid_, IPEndPoint(), false)),
- session_(connection_, true) {
+ : connection_(new MockConnection(true)),
+ session_(connection_) {
headers_[":host"] = "www.google.com";
headers_[":path"] = "/index.hml";
headers_[":scheme"] = "http";
@@ -168,7 +169,6 @@ class QuicSessionTest : public ::testing::Test {
closed_streams_.insert(id);
}
- QuicGuid guid_;
MockConnection* connection_;
TestSession session_;
set<QuicStreamId> closed_streams_;
@@ -176,7 +176,7 @@ class QuicSessionTest : public ::testing::Test {
};
TEST_F(QuicSessionTest, PeerAddress) {
- EXPECT_EQ(IPEndPoint(), session_.peer_address());
+ EXPECT_EQ(IPEndPoint(Loopback4(), kTestPort), session_.peer_address());
}
TEST_F(QuicSessionTest, IsCryptoHandshakeConfirmed) {
@@ -203,12 +203,12 @@ TEST_F(QuicSessionTest, ImplicitlyCreatedStreams) {
}
TEST_F(QuicSessionTest, IsClosedStreamLocallyCreated) {
- TestStream* stream2 = session_.CreateOutgoingReliableStream();
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
EXPECT_EQ(2u, stream2->id());
- ReliableQuicStreamPeer::SetHeadersDecompressed(stream2, true);
- TestStream* stream4 = session_.CreateOutgoingReliableStream();
+ QuicDataStreamPeer::SetHeadersDecompressed(stream2, true);
+ TestStream* stream4 = session_.CreateOutgoingDataStream();
EXPECT_EQ(4u, stream4->id());
- ReliableQuicStreamPeer::SetHeadersDecompressed(stream4, true);
+ QuicDataStreamPeer::SetHeadersDecompressed(stream4, true);
CheckClosedStreams();
CloseStream(4);
@@ -218,18 +218,18 @@ TEST_F(QuicSessionTest, IsClosedStreamLocallyCreated) {
}
TEST_F(QuicSessionTest, IsClosedStreamPeerCreated) {
- ReliableQuicStream* stream3 = session_.GetIncomingReliableStream(3);
- ReliableQuicStreamPeer::SetHeadersDecompressed(stream3, true);
- ReliableQuicStream* stream5 = session_.GetIncomingReliableStream(5);
- ReliableQuicStreamPeer::SetHeadersDecompressed(stream5, true);
+ QuicDataStream* stream3 = session_.GetIncomingReliableStream(3);
+ QuicDataStreamPeer::SetHeadersDecompressed(stream3, true);
+ QuicDataStream* stream5 = session_.GetIncomingReliableStream(5);
+ QuicDataStreamPeer::SetHeadersDecompressed(stream5, true);
CheckClosedStreams();
CloseStream(3);
CheckClosedStreams();
CloseStream(5);
// Create stream id 9, and implicitly 7
- ReliableQuicStream* stream9 = session_.GetIncomingReliableStream(9);
- ReliableQuicStreamPeer::SetHeadersDecompressed(stream9, true);
+ QuicDataStream* stream9 = session_.GetIncomingReliableStream(9);
+ QuicDataStreamPeer::SetHeadersDecompressed(stream9, true);
CheckClosedStreams();
// Close 9, but make sure 7 is still not closed
CloseStream(9);
@@ -246,6 +246,7 @@ TEST_F(QuicSessionTest, DecompressionError) {
ReliableQuicStream* stream = session_.GetIncomingReliableStream(3);
EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE));
const char data[] =
+ "\0\0\0\0" // priority
"\1\0\0\0" // headers id
"\0\0\0\4" // length
"abcd"; // invalid compressed data
@@ -253,9 +254,9 @@ TEST_F(QuicSessionTest, DecompressionError) {
}
TEST_F(QuicSessionTest, OnCanWrite) {
- TestStream* stream2 = session_.CreateOutgoingReliableStream();
- TestStream* stream4 = session_.CreateOutgoingReliableStream();
- TestStream* stream6 = session_.CreateOutgoingReliableStream();
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
+ TestStream* stream4 = session_.CreateOutgoingDataStream();
+ TestStream* stream6 = session_.CreateOutgoingDataStream();
session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
@@ -276,12 +277,12 @@ TEST_F(QuicSessionTest, BufferedHandshake) {
EXPECT_FALSE(session_.HasPendingHandshake()); // Default value.
// Test that blocking other streams does not change our status.
- TestStream* stream2 = session_.CreateOutgoingReliableStream();
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
StreamBlocker stream2_blocker(&session_, stream2->id());
stream2_blocker.MarkWriteBlocked();
EXPECT_FALSE(session_.HasPendingHandshake());
- TestStream* stream3 = session_.CreateOutgoingReliableStream();
+ TestStream* stream3 = session_.CreateOutgoingDataStream();
StreamBlocker stream3_blocker(&session_, stream3->id());
stream3_blocker.MarkWriteBlocked();
EXPECT_FALSE(session_.HasPendingHandshake());
@@ -290,7 +291,7 @@ TEST_F(QuicSessionTest, BufferedHandshake) {
session_.MarkWriteBlocked(kCryptoStreamId, kSomeMiddlePriority);
EXPECT_TRUE(session_.HasPendingHandshake());
- TestStream* stream4 = session_.CreateOutgoingReliableStream();
+ TestStream* stream4 = session_.CreateOutgoingDataStream();
StreamBlocker stream4_blocker(&session_, stream4->id());
stream4_blocker.MarkWriteBlocked();
EXPECT_TRUE(session_.HasPendingHandshake());
@@ -320,9 +321,9 @@ TEST_F(QuicSessionTest, BufferedHandshake) {
}
TEST_F(QuicSessionTest, OnCanWriteWithClosedStream) {
- TestStream* stream2 = session_.CreateOutgoingReliableStream();
- TestStream* stream4 = session_.CreateOutgoingReliableStream();
- TestStream* stream6 = session_.CreateOutgoingReliableStream();
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
+ TestStream* stream4 = session_.CreateOutgoingDataStream();
+ TestStream* stream6 = session_.CreateOutgoingDataStream();
session_.MarkWriteBlocked(stream2->id(), kSomeMiddlePriority);
session_.MarkWriteBlocked(stream6->id(), kSomeMiddlePriority);
@@ -342,18 +343,20 @@ TEST_F(QuicSessionTest, OutOfOrderHeaders) {
QuicPacketHeader header;
header.public_header.guid = session_.guid();
- TestStream* stream2 = session_.CreateOutgoingReliableStream();
- TestStream* stream4 = session_.CreateOutgoingReliableStream();
+ TestStream* stream2 = session_.CreateOutgoingDataStream();
+ TestStream* stream4 = session_.CreateOutgoingDataStream();
stream2->CloseWriteSide();
stream4->CloseWriteSide();
// Create frame with headers for stream2.
string compressed_headers1 = compressor.CompressHeaders(headers_);
- QuicStreamFrame frame1(stream2->id(), false, 0, compressed_headers1);
+ QuicStreamFrame frame1(
+ stream2->id(), false, 0, MakeIOVector(compressed_headers1));
// Create frame with headers for stream4.
string compressed_headers2 = compressor.CompressHeaders(headers_);
- QuicStreamFrame frame2(stream4->id(), true, 0, compressed_headers2);
+ QuicStreamFrame frame2(
+ stream4->id(), true, 0, MakeIOVector(compressed_headers2));
// Process the second frame first. This will cause the headers to
// be queued up and processed after the first frame is processed.
@@ -391,12 +394,12 @@ TEST_F(QuicSessionTest, IncreasedTimeoutAfterCryptoHandshake) {
TEST_F(QuicSessionTest, ZombieStream) {
StrictMock<MockConnection>* connection =
- new StrictMock<MockConnection>(guid_, IPEndPoint(), false);
- TestSession session(connection, /*is_server=*/ false);
+ new StrictMock<MockConnection>(false);
+ TestSession session(connection);
- TestStream* stream3 = session.CreateOutgoingReliableStream();
+ TestStream* stream3 = session.CreateOutgoingDataStream();
EXPECT_EQ(3u, stream3->id());
- TestStream* stream5 = session.CreateOutgoingReliableStream();
+ TestStream* stream5 = session.CreateOutgoingDataStream();
EXPECT_EQ(5u, stream5->id());
EXPECT_EQ(2u, session.GetNumOpenStreams());
@@ -415,7 +418,8 @@ TEST_F(QuicSessionTest, ZombieStream) {
// Create frame with headers for stream2.
QuicSpdyCompressor compressor;
string compressed_headers1 = compressor.CompressHeaders(headers_);
- QuicStreamFrame frame1(stream3->id(), false, 0, compressed_headers1);
+ QuicStreamFrame frame1(
+ stream3->id(), false, 0, MakeIOVector(compressed_headers1));
// Process the second frame first. This will cause the headers to
// be queued up and processed after the first frame is processed.
@@ -430,12 +434,12 @@ TEST_F(QuicSessionTest, ZombieStream) {
TEST_F(QuicSessionTest, ZombieStreamConnectionClose) {
StrictMock<MockConnection>* connection =
- new StrictMock<MockConnection>(guid_, IPEndPoint(), false);
- TestSession session(connection, /*is_server=*/ false);
+ new StrictMock<MockConnection>(false);
+ TestSession session(connection);
- TestStream* stream3 = session.CreateOutgoingReliableStream();
+ TestStream* stream3 = session.CreateOutgoingDataStream();
EXPECT_EQ(3u, stream3->id());
- TestStream* stream5 = session.CreateOutgoingReliableStream();
+ TestStream* stream5 = session.CreateOutgoingDataStream();
EXPECT_EQ(5u, stream5->id());
EXPECT_EQ(2u, session.GetNumOpenStreams());
@@ -453,6 +457,24 @@ TEST_F(QuicSessionTest, ZombieStreamConnectionClose) {
EXPECT_EQ(0u, session.GetNumOpenStreams());
}
+TEST_F(QuicSessionTest, RstStreamBeforeHeadersDecompressed) {
+ // Send two bytes of payload.
+ QuicStreamFrame data1(3, false, 0, MakeIOVector("HT"));
+ vector<QuicStreamFrame> frames;
+ frames.push_back(data1);
+ EXPECT_TRUE(session_.OnStreamFrames(frames));
+ EXPECT_EQ(1u, session_.GetNumOpenStreams());
+
+ // Send a reset before the headers have been decompressed. This causes
+ // an unrecoverable compression context state.
+ EXPECT_CALL(*connection_, SendConnectionClose(
+ QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED));
+
+ QuicRstStreamFrame rst1(3, QUIC_STREAM_NO_ERROR);
+ session_.OnRstStream(rst1);
+ EXPECT_EQ(0u, session_.GetNumOpenStreams());
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_spdy_compressor.cc b/chromium/net/quic/quic_spdy_compressor.cc
index 6681493b66a..55015b0b42d 100644
--- a/chromium/net/quic/quic_spdy_compressor.cc
+++ b/chromium/net/quic/quic_spdy_compressor.cc
@@ -28,7 +28,8 @@ string QuicSpdyCompressor::CompressHeadersWithPriority(
string QuicSpdyCompressor::CompressHeaders(
const SpdyHeaderBlock& headers) {
- return CompressHeadersInternal(0, headers, false);
+ // CompressHeadersInternal ignores priority when write_priority is false.
+ return CompressHeadersInternal(0 /* ignored */, headers, false);
}
string QuicSpdyCompressor::CompressHeadersInternal(
@@ -39,7 +40,7 @@ string QuicSpdyCompressor::CompressHeadersInternal(
// CreateCompressedHeaderBlock method, or some such.
SpdyStreamId stream_id = 3; // unused.
scoped_ptr<SpdyFrame> frame(spdy_framer_.CreateHeaders(
- stream_id, CONTROL_FLAG_NONE, true, &headers));
+ stream_id, CONTROL_FLAG_NONE, &headers));
// The size of the spdy HEADER frame's fixed prefix which
// needs to be stripped off from the resulting frame.
diff --git a/chromium/net/quic/quic_spdy_compressor.h b/chromium/net/quic/quic_spdy_compressor.h
index 53a70603fea..6efb73c74bd 100644
--- a/chromium/net/quic/quic_spdy_compressor.h
+++ b/chromium/net/quic/quic_spdy_compressor.h
@@ -15,6 +15,7 @@ namespace net {
// Handles the compression of request/response headers blocks. The
// serialized format is:
+// uint32 - Priority
// uint32 - Header ID
// uint32 - Compressed header length
// ... - Compressed data
diff --git a/chromium/net/quic/quic_stream_factory.cc b/chromium/net/quic/quic_stream_factory.cc
index 4e1a8eddc20..036a91d38aa 100644
--- a/chromium/net/quic/quic_stream_factory.cc
+++ b/chromium/net/quic/quic_stream_factory.cc
@@ -9,25 +9,33 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/metrics/histogram.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_verifier.h"
#include "net/dns/host_resolver.h"
#include "net/dns/single_request_host_resolver.h"
#include "net/http/http_server_properties.h"
+#include "net/quic/congestion_control/tcp_receiver.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_random.h"
+#include "net/quic/port_suggester.h"
#include "net/quic/quic_client_session.h"
#include "net/quic/quic_clock.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_connection_helper.h"
#include "net/quic/quic_crypto_client_stream_factory.h"
+#include "net/quic/quic_default_packet_writer.h"
#include "net/quic/quic_http_stream.h"
#include "net/quic/quic_protocol.h"
#include "net/socket/client_socket_factory.h"
+using std::string;
+using std::vector;
+
namespace net {
// Responsible for creating a new QUIC session to the specified server, and
@@ -95,7 +103,8 @@ QuicStreamFactory::Job::Job(
host_port_proxy_pair_(host_port_proxy_pair),
is_https_(is_https),
cert_verifier_(cert_verifier),
- net_log_(net_log) {
+ net_log_(net_log),
+ session_(NULL) {
}
QuicStreamFactory::Job::~Job() {
@@ -214,10 +223,16 @@ scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() {
int QuicStreamFactory::Job::DoConnect() {
io_state_ = STATE_CONNECT_COMPLETE;
- session_ = factory_->CreateSession(host_port_proxy_pair_, is_https_,
- cert_verifier_, address_list_, net_log_);
+ int rv = factory_->CreateSession(host_port_proxy_pair_, is_https_,
+ cert_verifier_, address_list_, net_log_, &session_);
+ if (rv != OK) {
+ DCHECK(rv != ERR_IO_PENDING);
+ DCHECK(!session_);
+ return rv;
+ }
+
session_->StartReading();
- int rv = session_->CryptoConnect(
+ rv = session_->CryptoConnect(
factory_->require_confirmation() || is_https_,
base::Bind(&QuicStreamFactory::Job::OnIOComplete,
base::Unretained(this)));
@@ -240,7 +255,8 @@ QuicStreamFactory::QuicStreamFactory(
base::WeakPtr<HttpServerProperties> http_server_properties,
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
QuicRandom* random_generator,
- QuicClock* clock)
+ QuicClock* clock,
+ size_t max_packet_length)
: require_confirmation_(true),
host_resolver_(host_resolver),
client_socket_factory_(client_socket_factory),
@@ -248,14 +264,20 @@ QuicStreamFactory::QuicStreamFactory(
quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
random_generator_(random_generator),
clock_(clock),
- weak_factory_(this) {
+ max_packet_length_(max_packet_length),
+ weak_factory_(this),
+ port_seed_(random_generator_->RandUint64()) {
config_.SetDefaults();
config_.set_idle_connection_state_lifetime(
QuicTime::Delta::FromSeconds(30),
QuicTime::Delta::FromSeconds(30));
+
+ cannoncial_suffixes_.push_back(string(".c.youtube.com"));
+ cannoncial_suffixes_.push_back(string(".googlevideo.com"));
}
QuicStreamFactory::~QuicStreamFactory() {
+ CloseAllSessions(ERR_ABORTED);
STLDeleteElements(&all_sessions_);
STLDeleteValues(&active_jobs_);
STLDeleteValues(&all_crypto_configs_);
@@ -329,20 +351,20 @@ scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists(
const HostPortProxyPair& host_port_proxy_pair,
const BoundNetLog& net_log) {
if (!HasActiveSession(host_port_proxy_pair)) {
- DLOG(INFO) << "No active session";
+ DVLOG(1) << "No active session";
return scoped_ptr<QuicHttpStream>();
}
QuicClientSession* session = active_sessions_[host_port_proxy_pair];
DCHECK(session);
- return scoped_ptr<QuicHttpStream>(new QuicHttpStream(session->GetWeakPtr()));
+ return scoped_ptr<QuicHttpStream>(
+ new QuicHttpStream(session->GetWeakPtr()));
}
void QuicStreamFactory::OnIdleSession(QuicClientSession* session) {
}
-void QuicStreamFactory::OnSessionClose(QuicClientSession* session) {
- DCHECK_EQ(0u, session->GetNumOpenStreams());
+void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) {
const AliasSet& aliases = session_aliases_[session];
for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end();
++it) {
@@ -357,8 +379,13 @@ void QuicStreamFactory::OnSessionClose(QuicClientSession* session) {
http_server_properties_->SetBrokenAlternateProtocol(it->first);
}
}
- all_sessions_.erase(session);
session_aliases_.erase(session);
+}
+
+void QuicStreamFactory::OnSessionClosed(QuicClientSession* session) {
+ DCHECK_EQ(0u, session->GetNumOpenStreams());
+ OnSessionGoingAway(session);
+ all_sessions_.erase(session);
delete session;
}
@@ -401,60 +428,102 @@ void QuicStreamFactory::OnIPAddressChanged() {
require_confirmation_ = true;
}
+void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
+ CloseAllSessions(ERR_CERT_DATABASE_CHANGED);
+}
+
+void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) {
+ // We should flush the sessions if we removed trust from a
+ // cert, because a previously trusted server may have become
+ // untrusted.
+ //
+ // We should not flush the sessions if we added trust to a 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);
+}
+
bool QuicStreamFactory::HasActiveSession(
const HostPortProxyPair& host_port_proxy_pair) {
return ContainsKey(active_sessions_, host_port_proxy_pair);
}
-QuicClientSession* QuicStreamFactory::CreateSession(
+int QuicStreamFactory::CreateSession(
const HostPortProxyPair& host_port_proxy_pair,
bool is_https,
CertVerifier* cert_verifier,
const AddressList& address_list,
- const BoundNetLog& net_log) {
+ const BoundNetLog& net_log,
+ QuicClientSession** session) {
QuicGuid guid = random_generator_->RandUint64();
IPEndPoint addr = *address_list.begin();
+ scoped_refptr<PortSuggester> port_suggester =
+ new PortSuggester(host_port_proxy_pair.first, port_seed_);
+ DatagramSocket::BindType bind_type = DatagramSocket::RANDOM_BIND;
+#if defined(OS_WIN)
+ // TODO(jar)bug=329255 Provide better implementation to avoid pop-up warning.
+ bind_type = DatagramSocket::DEFAULT_BIND;
+#endif
scoped_ptr<DatagramClientSocket> socket(
client_socket_factory_->CreateDatagramClientSocket(
- DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt),
+ bind_type,
+ base::Bind(&PortSuggester::SuggestPort, port_suggester),
net_log.net_log(), net_log.source()));
- socket->Connect(addr);
+ int rv = socket->Connect(addr);
+ if (rv != OK)
+ return rv;
+ UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested",
+ port_suggester->call_count());
+
+#if defined(OS_WIN)
+ // TODO(jar)bug=329255 Provide better implementation to avoid pop-up warning.
+ DCHECK_EQ(0u, port_suggester->call_count());
+#else
+ DCHECK_LE(1u, port_suggester->call_count());
+#endif
// We should adaptively set this buffer size, but for now, we'll use a size
- // that is more than large enough for a 100 packet congestion window, and yet
+ // that is more than large enough for a full receive window, and yet
// does not consume "too much" memory. If we see bursty packet loss, we may
// revisit this setting and test for its impact.
- const int32 kSocketBufferSize(kMaxPacketSize * 100); // Support 100 packets.
+ const int32 kSocketBufferSize(TcpReceiver::kReceiveWindowTCP);
socket->SetReceiveBufferSize(kSocketBufferSize);
// Set a buffer large enough to contain the initial CWND's worth of packet
// to work around the problem with CHLO packets being sent out with the
// wrong encryption level, when the send buffer is full.
socket->SetSendBufferSize(kMaxPacketSize * 20); // Support 20 packets.
- QuicConnectionHelper* helper = new QuicConnectionHelper(
- base::MessageLoop::current()->message_loop_proxy().get(),
- clock_.get(),
- random_generator_,
- socket.get());
+ scoped_ptr<QuicDefaultPacketWriter> writer(
+ new QuicDefaultPacketWriter(socket.get()));
- QuicConnection* connection = new QuicConnection(guid, addr, helper, false,
- QuicVersionMax());
+ if (!helper_.get()) {
+ helper_.reset(new QuicConnectionHelper(
+ base::MessageLoop::current()->message_loop_proxy().get(),
+ clock_.get(), random_generator_));
+ }
+
+ QuicConnection* connection = new QuicConnection(guid, addr, helper_.get(),
+ writer.get(), false,
+ QuicSupportedVersions());
+ writer->SetConnection(connection);
+ connection->options()->max_packet_length = max_packet_length_;
QuicCryptoClientConfig* crypto_config =
GetOrCreateCryptoConfig(host_port_proxy_pair);
DCHECK(crypto_config);
- QuicClientSession* session =
- new QuicClientSession(connection, socket.Pass(), this,
- quic_crypto_client_stream_factory_,
- host_port_proxy_pair.first.host(), config_,
- crypto_config, net_log.net_log());
- all_sessions_.insert(session); // owning pointer
+ *session = new QuicClientSession(
+ connection, socket.Pass(), writer.Pass(), this,
+ quic_crypto_client_stream_factory_, host_port_proxy_pair.first.host(),
+ config_, crypto_config, net_log.net_log());
+ all_sessions_.insert(*session); // owning pointer
if (is_https) {
crypto_config->SetProofVerifier(
new ProofVerifierChromium(cert_verifier, net_log));
}
- return session;
+ return OK;
}
bool QuicStreamFactory::HasActiveJob(
@@ -473,15 +542,58 @@ void QuicStreamFactory::ActivateSession(
QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig(
const HostPortProxyPair& host_port_proxy_pair) {
QuicCryptoClientConfig* crypto_config;
+
if (ContainsKey(all_crypto_configs_, host_port_proxy_pair)) {
crypto_config = all_crypto_configs_[host_port_proxy_pair];
DCHECK(crypto_config);
} else {
+ // TODO(rtenneti): if two quic_sessions for the same host_port_proxy_pair
+ // share the same crypto_config, will it cause issues?
crypto_config = new QuicCryptoClientConfig();
crypto_config->SetDefaults();
all_crypto_configs_[host_port_proxy_pair] = crypto_config;
+ PopulateFromCanonicalConfig(host_port_proxy_pair, crypto_config);
}
return crypto_config;
}
+void QuicStreamFactory::PopulateFromCanonicalConfig(
+ const HostPortProxyPair& host_port_proxy_pair,
+ QuicCryptoClientConfig* crypto_config) {
+ const string server_hostname = host_port_proxy_pair.first.host();
+
+ unsigned i = 0;
+ for (; i < cannoncial_suffixes_.size(); ++i) {
+ if (EndsWith(server_hostname, cannoncial_suffixes_[i], false)) {
+ break;
+ }
+ }
+ if (i == cannoncial_suffixes_.size())
+ return;
+
+ HostPortPair canonical_host_port(cannoncial_suffixes_[i],
+ host_port_proxy_pair.first.port());
+ if (!ContainsKey(canonical_hostname_to_origin_map_, canonical_host_port)) {
+ // This is the first host we've seen which matches the suffix, so make it
+ // canonical.
+ canonical_hostname_to_origin_map_[canonical_host_port] =
+ host_port_proxy_pair;
+ return;
+ }
+
+ const HostPortProxyPair& canonical_host_port_proxy_pair =
+ canonical_hostname_to_origin_map_[canonical_host_port];
+ QuicCryptoClientConfig* canonical_crypto_config =
+ all_crypto_configs_[canonical_host_port_proxy_pair];
+ DCHECK(canonical_crypto_config);
+
+ // Copy the CachedState for the canonical server from canonical_crypto_config
+ // as the initial CachedState for the server_hostname in crypto_config.
+ crypto_config->InitializeFrom(server_hostname,
+ canonical_host_port_proxy_pair.first.host(),
+ canonical_crypto_config);
+ // Update canonical version to point at the "most recent" crypto_config.
+ canonical_hostname_to_origin_map_[canonical_host_port] = host_port_proxy_pair;
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_stream_factory.h b/chromium/net/quic/quic_stream_factory.h
index 2319e728ed8..e55c83c3cbe 100644
--- a/chromium/net/quic/quic_stream_factory.h
+++ b/chromium/net/quic/quic_stream_factory.h
@@ -7,6 +7,7 @@
#include <map>
#include <string>
+#include <vector>
#include "base/memory/weak_ptr.h"
#include "net/base/address_list.h"
@@ -14,6 +15,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/net_log.h"
#include "net/base/network_change_notifier.h"
+#include "net/cert/cert_database.h"
#include "net/proxy/proxy_server.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_crypto_stream.h"
@@ -28,10 +30,15 @@ class HostResolver;
class HttpServerProperties;
class QuicClock;
class QuicClientSession;
+class QuicConnectionHelper;
class QuicCryptoClientStreamFactory;
class QuicRandom;
class QuicStreamFactory;
+namespace test {
+class QuicStreamFactoryPeer;
+} // namespace test
+
// Encapsulates a pending request for a QuicHttpStream.
// If the request is still pending when it is destroyed, it will
// cancel the request with the factory.
@@ -72,7 +79,8 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
// A factory for creating new QuicHttpStreams on top of a pool of
// QuicClientSessions.
class NET_EXPORT_PRIVATE QuicStreamFactory
- : public NetworkChangeNotifier::IPAddressObserver {
+ : public NetworkChangeNotifier::IPAddressObserver,
+ public CertDatabase::Observer {
public:
QuicStreamFactory(
HostResolver* host_resolver,
@@ -80,7 +88,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
base::WeakPtr<HttpServerProperties> http_server_properties,
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
QuicRandom* random_generator,
- QuicClock* clock);
+ QuicClock* clock,
+ size_t max_packet_length);
virtual ~QuicStreamFactory();
// Creates a new QuicHttpStream to |host_port_proxy_pair| which will be
@@ -105,8 +114,12 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// Called by a session when it becomes idle.
void OnIdleSession(QuicClientSession* session);
+ // Called by a session when it is going away and no more streams should be
+ // created on it.
+ void OnSessionGoingAway(QuicClientSession* session);
+
// Called by a session after it shuts down.
- void OnSessionClose(QuicClientSession* session);
+ void OnSessionClosed(QuicClientSession* session);
// Cancels a pending request.
void CancelRequest(QuicStreamRequest* request);
@@ -122,20 +135,30 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// IP address changes.
virtual void OnIPAddressChanged() OVERRIDE;
+ // CertDatabase::Observer methods:
+
+ // We close all sessions when certificate database is changed.
+ virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE;
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;
+
bool require_confirmation() const { return require_confirmation_; }
void set_require_confirmation(bool require_confirmation) {
require_confirmation_ = require_confirmation;
}
+ QuicConnectionHelper* helper() { return helper_.get(); }
+
private:
class Job;
+ friend class test::QuicStreamFactoryPeer;
typedef std::map<HostPortProxyPair, QuicClientSession*> SessionMap;
typedef std::set<HostPortProxyPair> AliasSet;
typedef std::map<QuicClientSession*, AliasSet> SessionAliasMap;
typedef std::set<QuicClientSession*> SessionSet;
typedef std::map<HostPortProxyPair, QuicCryptoClientConfig*> CryptoConfigMap;
+ typedef std::map<HostPortPair, HostPortProxyPair> CanonicalHostMap;
typedef std::map<HostPortProxyPair, Job*> JobMap;
typedef std::map<QuicStreamRequest*, Job*> RequestMap;
typedef std::set<QuicStreamRequest*> RequestSet;
@@ -144,18 +167,26 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
void OnJobComplete(Job* job, int rv);
bool HasActiveSession(const HostPortProxyPair& host_port_proxy_pair);
bool HasActiveJob(const HostPortProxyPair& host_port_proxy_pair);
- QuicClientSession* CreateSession(
- const HostPortProxyPair& host_port_proxy_pair,
- bool is_https,
- CertVerifier* cert_verifier,
- const AddressList& address_list,
- const BoundNetLog& net_log);
+ int CreateSession(const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
+ const AddressList& address_list,
+ const BoundNetLog& net_log,
+ QuicClientSession** session);
void ActivateSession(const HostPortProxyPair& host_port_proxy_pair,
QuicClientSession* session);
QuicCryptoClientConfig* GetOrCreateCryptoConfig(
const HostPortProxyPair& host_port_proxy_pair);
+ // If |host_port_proxy_pair| suffix contains ".c.youtube.com" (in future we
+ // could support other suffixes), then populate |crypto_config| with a
+ // canonical server config data from |canonical_hostname_to_origin_map_| for
+ // that suffix.
+ void PopulateFromCanonicalConfig(
+ const HostPortProxyPair& host_port_proxy_pair,
+ QuicCryptoClientConfig* crypto_config);
+
bool require_confirmation_;
HostResolver* host_resolver_;
ClientSocketFactory* client_socket_factory_;
@@ -163,6 +194,10 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_;
QuicRandom* random_generator_;
scoped_ptr<QuicClock> clock_;
+ const size_t max_packet_length_;
+
+ // The helper used for all connections.
+ scoped_ptr<QuicConnectionHelper> helper_;
// Contains owning pointers to all sessions that currently exist.
SessionSet all_sessions_;
@@ -177,6 +212,16 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// clear the data in the map.
CryptoConfigMap all_crypto_configs_;
+ // Contains a map of servers which could share the same server config. Map
+ // from a Canonical host/port (host is some postfix of host names) to an
+ // actual origin, which has a plausible set of initial certificates (or at
+ // least server public key).
+ CanonicalHostMap canonical_hostname_to_origin_map_;
+
+ // Contains list of suffixes (for exmaple ".c.youtube.com",
+ // ".googlevideo.com") of cannoncial hostnames.
+ std::vector<std::string> cannoncial_suffixes_;
+
QuicConfig config_;
JobMap active_jobs_;
@@ -185,6 +230,14 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
base::WeakPtrFactory<QuicStreamFactory> weak_factory_;
+ // Each profile will (probably) have a unique port_seed_ value. This value is
+ // used to help seed a pseudo-random number generator (PortSuggester) so that
+ // we consistently (within this profile) suggest the same ephemeral port when
+ // we re-connect to any given server/port. The differences between profiles
+ // (probablistically) prevent two profiles from colliding in their ephemeral
+ // port requests.
+ uint64 port_seed_;
+
DISALLOW_COPY_AND_ASSIGN(QuicStreamFactory);
};
diff --git a/chromium/net/quic/quic_stream_factory_test.cc b/chromium/net/quic/quic_stream_factory_test.cc
index a546d874ea1..03cc6f7e8bc 100644
--- a/chromium/net/quic/quic_stream_factory_test.cc
+++ b/chromium/net/quic/quic_stream_factory_test.cc
@@ -11,6 +11,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/quic_http_stream.h"
@@ -21,17 +22,54 @@
#include "net/socket/socket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+using base::StringPiece;
+using std::string;
+using std::vector;
+
namespace net {
namespace test {
+class QuicStreamFactoryPeer {
+ public:
+ static QuicCryptoClientConfig* GetOrCreateCryptoConfig(
+ QuicStreamFactory* factory,
+ const HostPortProxyPair& host_port_proxy_pair) {
+ return factory->GetOrCreateCryptoConfig(host_port_proxy_pair);
+ }
+
+ static bool HasActiveSession(QuicStreamFactory* factory,
+ const HostPortProxyPair& host_port_proxy_pair) {
+ return factory->HasActiveSession(host_port_proxy_pair);
+ }
+
+ static QuicClientSession* GetActiveSession(
+ QuicStreamFactory* factory,
+ const HostPortProxyPair& host_port_proxy_pair) {
+ DCHECK(factory->HasActiveSession(host_port_proxy_pair));
+ return factory->active_sessions_[host_port_proxy_pair];
+ }
+
+ static bool IsLiveSession(QuicStreamFactory* factory,
+ QuicClientSession* session) {
+ for (QuicStreamFactory::SessionSet::iterator it =
+ factory->all_sessions_.begin();
+ it != factory->all_sessions_.end(); ++it) {
+ if (*it == session)
+ return true;
+ }
+ return false;
+ }
+};
+
class QuicStreamFactoryTest : public ::testing::Test {
protected:
QuicStreamFactoryTest()
- : clock_(new MockClock()),
+ : random_generator_(0),
+ clock_(new MockClock()),
factory_(&host_resolver_, &socket_factory_,
base::WeakPtr<HttpServerProperties>(),
&crypto_client_stream_factory_,
- &random_generator_, clock_),
+ &random_generator_, clock_, kDefaultMaxPacketSize),
host_port_proxy_pair_(HostPortPair("www.google.com", 443),
ProxyServer::Direct()),
is_https_(false),
@@ -43,7 +81,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
QuicPacketSequenceNumber num,
QuicStreamId stream_id) {
QuicPacketHeader header;
- header.public_header.guid = 0xDEADBEEF;
+ header.public_header.guid = random_generator_.RandUint64();
header.public_header.reset_flag = false;
header.public_header.version_flag = true;
header.packet_sequence_number = num;
@@ -52,7 +90,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
header.fec_flag = false;
header.fec_group = 0;
- QuicRstStreamFrame rst(stream_id, QUIC_ERROR_PROCESSING_STREAM);
+ QuicRstStreamFrame rst(stream_id, QUIC_STREAM_CANCELLED);
return scoped_ptr<QuicEncryptedPacket>(
ConstructPacket(header, QuicFrame(&rst)));
}
@@ -61,7 +99,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
QuicPacketSequenceNumber largest_received,
QuicPacketSequenceNumber least_unacked) {
QuicPacketHeader header;
- header.public_header.guid = 0xDEADBEEF;
+ header.public_header.guid = random_generator_.RandUint64();
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
header.packet_sequence_number = 2;
@@ -75,7 +113,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
feedback.tcp.accumulated_number_of_lost_packets = 0;
feedback.tcp.receive_window = 16000;
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(QuicFrame(&ack));
frames.push_back(QuicFrame(&feedback));
@@ -89,7 +127,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
scoped_ptr<QuicEncryptedPacket> ConstructFeedbackPacket(
QuicPacketSequenceNumber sequence_number) {
QuicPacketHeader header;
- header.public_header.guid = 0xDEADBEEF;
+ header.public_header.guid = random_generator_.RandUint64();
header.public_header.reset_flag = false;
header.public_header.version_flag = false;
header.packet_sequence_number = sequence_number;
@@ -109,7 +147,7 @@ class QuicStreamFactoryTest : public ::testing::Test {
scoped_ptr<QuicEncryptedPacket> ConstructPacket(
const QuicPacketHeader& header,
const QuicFrame& frame) {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicFrames frames;
frames.push_back(frame);
scoped_ptr<QuicPacket> packet(
@@ -170,6 +208,76 @@ TEST_F(QuicStreamFactoryTest, Create) {
EXPECT_TRUE(socket_data.at_write_eof());
}
+TEST_F(QuicStreamFactoryTest, FailedCreate) {
+ MockConnect connect(SYNCHRONOUS, ERR_ADDRESS_IN_USE);
+ DeterministicSocketData socket_data(NULL, 0, NULL, 0);
+ socket_data.set_connect_data(connect);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ socket_data.StopAfter(1);
+
+ QuicStreamRequest request(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(ERR_ADDRESS_IN_USE, callback_.WaitForResult());
+}
+
+TEST_F(QuicStreamFactoryTest, Goaway) {
+ MockRead reads[] = {
+ MockRead(ASYNC, OK, 0) // EOF
+ };
+ DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+ socket_data.StopAfter(1);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ DeterministicSocketData socket_data2(reads, arraysize(reads), NULL, 0);
+ socket_data2.StopAfter(1);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+
+ QuicStreamRequest request(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ EXPECT_TRUE(stream.get());
+
+ // Mark the session as going away. Ensure that while it is still alive
+ // that it is no longer active.
+ QuicClientSession* session = QuicStreamFactoryPeer::GetActiveSession(
+ &factory_, host_port_proxy_pair_);
+ factory_.OnSessionGoingAway(session);
+ EXPECT_EQ(true, QuicStreamFactoryPeer::IsLiveSession(&factory_, session));
+ EXPECT_FALSE(QuicStreamFactoryPeer::HasActiveSession(&factory_,
+ host_port_proxy_pair_));
+ EXPECT_EQ(NULL, factory_.CreateIfSessionExists(host_port_proxy_pair_,
+ net_log_).get());
+
+ // Create a new request for the same destination and verify that a
+ // new session is created.
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ EXPECT_TRUE(stream2.get());
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(&factory_,
+ host_port_proxy_pair_));
+ EXPECT_NE(session,
+ QuicStreamFactoryPeer::GetActiveSession(
+ &factory_, host_port_proxy_pair_));
+ EXPECT_EQ(true, QuicStreamFactoryPeer::IsLiveSession(&factory_, session));
+
+ stream2.reset();
+ stream.reset();
+
+ EXPECT_TRUE(socket_data.at_read_eof());
+ EXPECT_TRUE(socket_data.at_write_eof());
+}
+
TEST_F(QuicStreamFactoryTest, MaxOpenStream) {
MockRead reads[] = {
MockRead(ASYNC, OK, 0) // EOF
@@ -370,5 +478,190 @@ TEST_F(QuicStreamFactoryTest, OnIPAddressChanged) {
EXPECT_TRUE(socket_data2.at_write_eof());
}
+TEST_F(QuicStreamFactoryTest, OnCertAdded) {
+ MockRead reads[] = {
+ MockRead(ASYNC, 0, 0) // EOF
+ };
+ DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ socket_data.StopAfter(1);
+
+ MockRead reads2[] = {
+ MockRead(ASYNC, 0, 0) // EOF
+ };
+ DeterministicSocketData socket_data2(reads2, arraysize(reads2), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+ socket_data2.StopAfter(1);
+
+ QuicStreamRequest request(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info,
+ DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Add a cert and verify that stream saw the event.
+ factory_.OnCertAdded(NULL);
+ EXPECT_EQ(ERR_CERT_DATABASE_CHANGED,
+ stream->ReadResponseHeaders(callback_.callback()));
+ EXPECT_FALSE(factory_.require_confirmation());
+
+ // Now attempting to request a stream to the same origin should create
+ // a new session.
+
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ stream = request2.ReleaseStream();
+ stream.reset(); // Will reset stream 3.
+
+ EXPECT_TRUE(socket_data.at_read_eof());
+ EXPECT_TRUE(socket_data.at_write_eof());
+ EXPECT_TRUE(socket_data2.at_read_eof());
+ EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_F(QuicStreamFactoryTest, OnCACertChanged) {
+ MockRead reads[] = {
+ MockRead(ASYNC, 0, 0) // EOF
+ };
+ DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ socket_data.StopAfter(1);
+
+ MockRead reads2[] = {
+ MockRead(ASYNC, 0, 0) // EOF
+ };
+ DeterministicSocketData socket_data2(reads2, arraysize(reads2), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+ socket_data2.StopAfter(1);
+
+ QuicStreamRequest request(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ HttpRequestInfo request_info;
+ EXPECT_EQ(OK, stream->InitializeStream(&request_info,
+ DEFAULT_PRIORITY,
+ net_log_, CompletionCallback()));
+
+ // Change the CA cert and verify that stream saw the event.
+ factory_.OnCACertChanged(NULL);
+ EXPECT_EQ(ERR_CERT_DATABASE_CHANGED,
+ stream->ReadResponseHeaders(callback_.callback()));
+ EXPECT_FALSE(factory_.require_confirmation());
+
+ // Now attempting to request a stream to the same origin should create
+ // a new session.
+
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+
+ EXPECT_EQ(OK, callback_.WaitForResult());
+ stream = request2.ReleaseStream();
+ stream.reset(); // Will reset stream 3.
+
+ EXPECT_TRUE(socket_data.at_read_eof());
+ EXPECT_TRUE(socket_data.at_write_eof());
+ EXPECT_TRUE(socket_data2.at_read_eof());
+ EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_F(QuicStreamFactoryTest, SharedCryptoConfig) {
+ vector<string> cannoncial_suffixes;
+ cannoncial_suffixes.push_back(string(".c.youtube.com"));
+ cannoncial_suffixes.push_back(string(".googlevideo.com"));
+
+ for (unsigned i = 0; i < cannoncial_suffixes.size(); ++i) {
+ string r1_host_name("r1");
+ string r2_host_name("r2");
+ r1_host_name.append(cannoncial_suffixes[i]);
+ r2_host_name.append(cannoncial_suffixes[i]);
+
+ HostPortProxyPair host_port_proxy_pair1(HostPortPair(r1_host_name, 80),
+ ProxyServer::Direct());
+
+ QuicCryptoClientConfig* crypto_config1 =
+ QuicStreamFactoryPeer::GetOrCreateCryptoConfig(&factory_,
+ host_port_proxy_pair1);
+ DCHECK(crypto_config1);
+ QuicCryptoClientConfig::CachedState* cached1 =
+ crypto_config1->LookupOrCreate(host_port_proxy_pair1.first.host());
+ EXPECT_FALSE(cached1->proof_valid());
+ EXPECT_TRUE(cached1->source_address_token().empty());
+
+ // Mutate the cached1 to have different data.
+ // TODO(rtenneti): mutate other members of CachedState.
+ cached1->set_source_address_token(r1_host_name);
+ cached1->SetProofValid();
+
+ HostPortProxyPair host_port_proxy_pair2(HostPortPair(r2_host_name, 80),
+ ProxyServer::Direct());
+ QuicCryptoClientConfig* crypto_config2 =
+ QuicStreamFactoryPeer::GetOrCreateCryptoConfig(&factory_,
+ host_port_proxy_pair2);
+ DCHECK(crypto_config2);
+ QuicCryptoClientConfig::CachedState* cached2 =
+ crypto_config2->LookupOrCreate(host_port_proxy_pair2.first.host());
+ EXPECT_EQ(cached1->source_address_token(), cached2->source_address_token());
+ EXPECT_TRUE(cached2->proof_valid());
+ }
+}
+
+TEST_F(QuicStreamFactoryTest, CryptoConfigWhenProofIsInvalid) {
+ vector<string> cannoncial_suffixes;
+ cannoncial_suffixes.push_back(string(".c.youtube.com"));
+ cannoncial_suffixes.push_back(string(".googlevideo.com"));
+
+ for (unsigned i = 0; i < cannoncial_suffixes.size(); ++i) {
+ string r3_host_name("r3");
+ string r4_host_name("r4");
+ r3_host_name.append(cannoncial_suffixes[i]);
+ r4_host_name.append(cannoncial_suffixes[i]);
+
+ HostPortProxyPair host_port_proxy_pair1(HostPortPair(r3_host_name, 80),
+ ProxyServer::Direct());
+
+ QuicCryptoClientConfig* crypto_config1 =
+ QuicStreamFactoryPeer::GetOrCreateCryptoConfig(&factory_,
+ host_port_proxy_pair1);
+ DCHECK(crypto_config1);
+ QuicCryptoClientConfig::CachedState* cached1 =
+ crypto_config1->LookupOrCreate(host_port_proxy_pair1.first.host());
+ EXPECT_FALSE(cached1->proof_valid());
+ EXPECT_TRUE(cached1->source_address_token().empty());
+
+ // Mutate the cached1 to have different data.
+ // TODO(rtenneti): mutate other members of CachedState.
+ cached1->set_source_address_token(r3_host_name);
+ cached1->SetProofInvalid();
+
+ HostPortProxyPair host_port_proxy_pair2(HostPortPair(r4_host_name, 80),
+ ProxyServer::Direct());
+ QuicCryptoClientConfig* crypto_config2 =
+ QuicStreamFactoryPeer::GetOrCreateCryptoConfig(&factory_,
+ host_port_proxy_pair2);
+ DCHECK(crypto_config2);
+ QuicCryptoClientConfig::CachedState* cached2 =
+ crypto_config2->LookupOrCreate(host_port_proxy_pair2.first.host());
+ EXPECT_NE(cached1->source_address_token(), cached2->source_address_token());
+ EXPECT_TRUE(cached2->source_address_token().empty());
+ EXPECT_FALSE(cached2->proof_valid());
+ }
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/quic_stream_sequencer.cc b/chromium/net/quic/quic_stream_sequencer.cc
index a57c05f83c4..02fec67f200 100644
--- a/chromium/net/quic/quic_stream_sequencer.cc
+++ b/chromium/net/quic/quic_stream_sequencer.cc
@@ -39,7 +39,7 @@ QuicStreamSequencer::~QuicStreamSequencer() {
bool QuicStreamSequencer::WillAcceptStreamFrame(
const QuicStreamFrame& frame) const {
- size_t data_len = frame.data.size();
+ size_t data_len = frame.data.TotalBufferSize();
DCHECK_LE(data_len, max_frame_memory_);
if (IsDuplicate(frame)) {
@@ -75,32 +75,37 @@ bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
}
QuicStreamOffset byte_offset = frame.offset;
- const char* data = frame.data.data();
- size_t data_len = frame.data.size();
-
+ size_t data_len = frame.data.TotalBufferSize();
if (data_len == 0 && !frame.fin) {
// Stream frames must have data or a fin flag.
- stream_->ConnectionClose(QUIC_INVALID_STREAM_FRAME, false);
+ stream_->CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME,
+ "Empty stream frame without FIN set.");
return false;
}
if (frame.fin) {
- CloseStreamAtOffset(frame.offset + frame.data.size());
+ CloseStreamAtOffset(frame.offset + data_len);
if (data_len == 0) {
return true;
}
}
+ IOVector data;
+ data.AppendIovec(frame.data.iovec(), frame.data.Size());
if (byte_offset == num_bytes_consumed_) {
DVLOG(1) << "Processing byte offset " << byte_offset;
- size_t bytes_consumed = stream_->ProcessRawData(data, data_len);
+ size_t bytes_consumed = 0;
+ for (size_t i = 0; i < data.Size(); ++i) {
+ bytes_consumed += stream_->ProcessRawData(
+ static_cast<char*>(data.iovec()[i].iov_base),
+ data.iovec()[i].iov_len);
+ }
num_bytes_consumed_ += bytes_consumed;
-
if (MaybeCloseStream()) {
return true;
}
if (bytes_consumed > data_len) {
- stream_->Close(QUIC_ERROR_PROCESSING_STREAM);
+ stream_->Reset(QUIC_ERROR_PROCESSING_STREAM);
return false;
} else if (bytes_consumed == data_len) {
FlushBufferedFrames();
@@ -108,12 +113,17 @@ bool QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) {
} else {
// Set ourselves up to buffer what's left
data_len -= bytes_consumed;
- data += bytes_consumed;
+ data.Consume(bytes_consumed);
byte_offset += bytes_consumed;
}
}
- DVLOG(1) << "Buffering packet at offset " << byte_offset;
- frames_.insert(make_pair(byte_offset, string(data, data_len)));
+ for (size_t i = 0; i < data.Size(); ++i) {
+ DVLOG(1) << "Buffering stream data at offset " << byte_offset;
+ frames_.insert(make_pair(byte_offset, string(
+ static_cast<char*>(data.iovec()[i].iov_base),
+ data.iovec()[i].iov_len)));
+ byte_offset += data.iovec()[i].iov_len;
+ }
return true;
}
@@ -123,7 +133,7 @@ void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) {
// If we have a scheduled termination or close, any new offset should match
// it.
if (close_offset_ != kMaxOffset && offset != close_offset_) {
- stream_->Close(QUIC_MULTIPLE_TERMINATION_OFFSETS);
+ stream_->Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS);
return;
}
@@ -133,13 +143,13 @@ void QuicStreamSequencer::CloseStreamAtOffset(QuicStreamOffset offset) {
}
bool QuicStreamSequencer::MaybeCloseStream() {
- if (IsHalfClosed()) {
+ if (IsClosed()) {
DVLOG(1) << "Passing up termination, as we've processed "
<< num_bytes_consumed_ << " of " << close_offset_
<< " bytes.";
// Technically it's an error if num_bytes_consumed isn't exactly
// equal, but error handling seems silly at this point.
- stream_->TerminateFromPeer(true);
+ stream_->OnFinRead();
return true;
}
return false;
@@ -215,7 +225,7 @@ void QuicStreamSequencer::MarkConsumed(size_t num_bytes_consumed) {
<< " end_offset: " << end_offset
<< " offset: " << it->first
<< " length: " << it->second.length();
- stream_->Close(QUIC_ERROR_PROCESSING_STREAM);
+ stream_->Reset(QUIC_ERROR_PROCESSING_STREAM);
return;
}
@@ -241,7 +251,7 @@ bool QuicStreamSequencer::HasBytesToRead() const {
return it != frames_.end() && it->first == num_bytes_consumed_;
}
-bool QuicStreamSequencer::IsHalfClosed() const {
+bool QuicStreamSequencer::IsClosed() const {
return num_bytes_consumed_ >= close_offset_;
}
@@ -266,7 +276,7 @@ void QuicStreamSequencer::FlushBufferedFrames() {
return;
}
if (bytes_consumed > data->size()) {
- stream_->Close(QUIC_ERROR_PROCESSING_STREAM); // Programming error
+ stream_->Reset(QUIC_ERROR_PROCESSING_STREAM); // Programming error
return;
} else if (bytes_consumed == data->size()) {
frames_.erase(it);
diff --git a/chromium/net/quic/quic_stream_sequencer.h b/chromium/net/quic/quic_stream_sequencer.h
index a450bef988d..e2601246059 100644
--- a/chromium/net/quic/quic_stream_sequencer.h
+++ b/chromium/net/quic/quic_stream_sequencer.h
@@ -65,8 +65,8 @@ class NET_EXPORT_PRIVATE QuicStreamSequencer {
// Returns true if the sequncer has bytes available for reading.
bool HasBytesToRead() const;
- // Returns true if the sequencer has delivered a half close.
- bool IsHalfClosed() const;
+ // Returns true if the sequencer has delivered the fin.
+ bool IsClosed() const;
// Returns true if the sequencer has received this frame before.
bool IsDuplicate(const QuicStreamFrame& frame) const;
@@ -91,7 +91,7 @@ class NET_EXPORT_PRIVATE QuicStreamSequencer {
FrameMap frames_; // sequence number -> frame
size_t max_frame_memory_; // the maximum memory the sequencer can buffer.
// The offset, if any, we got a stream termination for. When this many bytes
- // have been processed, the stream will be half closed.
+ // have been processed, the sequencer will be closed.
QuicStreamOffset close_offset_;
};
diff --git a/chromium/net/quic/quic_stream_sequencer_test.cc b/chromium/net/quic/quic_stream_sequencer_test.cc
index 21568d60653..f898e6611f7 100644
--- a/chromium/net/quic/quic_stream_sequencer_test.cc
+++ b/chromium/net/quic/quic_stream_sequencer_test.cc
@@ -8,7 +8,9 @@
#include <vector>
#include "base/rand_util.h"
+#include "net/base/ip_endpoint.h"
#include "net/quic/reliable_quic_stream.h"
+#include "net/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,22 +37,20 @@ class QuicStreamSequencerPeer : public QuicStreamSequencer {
: QuicStreamSequencer(max_mem, stream) {
}
- virtual bool OnFinFrame(QuicStreamOffset byte_offset,
- const char* data) {
+ virtual bool OnFinFrame(QuicStreamOffset byte_offset, const char* data) {
QuicStreamFrame frame;
frame.stream_id = 1;
frame.offset = byte_offset;
- frame.data = StringPiece(data);
+ frame.data.Append(const_cast<char*>(data), strlen(data));
frame.fin = true;
return OnStreamFrame(frame);
}
- virtual bool OnFrame(QuicStreamOffset byte_offset,
- const char* data) {
+ virtual bool OnFrame(QuicStreamOffset byte_offset, const char* data) {
QuicStreamFrame frame;
frame.stream_id = 1;
frame.offset = byte_offset;
- frame.data = StringPiece(data);
+ frame.data.Append(const_cast<char*>(data), strlen(data));
frame.fin = false;
return OnStreamFrame(frame);
}
@@ -69,11 +69,15 @@ class MockStream : public ReliableQuicStream {
: ReliableQuicStream(id, session) {
}
- MOCK_METHOD1(TerminateFromPeer, void(bool half_close));
- MOCK_METHOD2(ProcessData, uint32(const char* data, uint32 data_len));
- MOCK_METHOD2(ConnectionClose, void(QuicErrorCode error, bool from_peer));
- MOCK_METHOD1(Close, void(QuicRstStreamErrorCode error));
+ MOCK_METHOD0(OnFinRead, void());
+ MOCK_METHOD2(ProcessRawData, uint32(const char* data, uint32 data_len));
+ MOCK_METHOD2(CloseConnectionWithDetails, void(QuicErrorCode error,
+ const string& details));
+ MOCK_METHOD1(Reset, void(QuicRstStreamErrorCode error));
MOCK_METHOD0(OnCanWrite, void());
+ virtual QuicPriority EffectivePriority() const {
+ return QuicUtils::HighestPriority();
+ }
};
namespace {
@@ -84,8 +88,9 @@ static const char kPayload[] =
class QuicStreamSequencerTest : public ::testing::Test {
protected:
QuicStreamSequencerTest()
- : session_(NULL),
- stream_(session_, 1),
+ : connection_(new MockConnection(false)),
+ session_(connection_),
+ stream_(&session_, 1),
sequencer_(new QuicStreamSequencerPeer(&stream_)) {
}
@@ -127,13 +132,14 @@ class QuicStreamSequencerTest : public ::testing::Test {
return true;
}
- QuicSession* session_;
+ MockConnection* connection_;
+ MockSession session_;
testing::StrictMock<MockStream> stream_;
scoped_ptr<QuicStreamSequencerPeer> sequencer_;
};
TEST_F(QuicStreamSequencerTest, RejectOldFrame) {
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3))
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3))
.WillOnce(Return(3));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
@@ -163,7 +169,7 @@ TEST_F(QuicStreamSequencerTest, DropFramePastBuffering) {
}
TEST_F(QuicStreamSequencerTest, RejectBufferedFrame) {
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_EQ(1u, sequencer_->frames()->size());
@@ -175,7 +181,7 @@ TEST_F(QuicStreamSequencerTest, RejectBufferedFrame) {
}
TEST_F(QuicStreamSequencerTest, FullFrameConsumed) {
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_EQ(0u, sequencer_->frames()->size());
@@ -183,21 +189,22 @@ TEST_F(QuicStreamSequencerTest, FullFrameConsumed) {
}
TEST_F(QuicStreamSequencerTest, EmptyFrame) {
- EXPECT_CALL(stream_, ConnectionClose(QUIC_INVALID_STREAM_FRAME, false));
+ EXPECT_CALL(stream_,
+ CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _));
EXPECT_FALSE(sequencer_->OnFrame(0, ""));
EXPECT_EQ(0u, sequencer_->frames()->size());
EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
}
TEST_F(QuicStreamSequencerTest, EmptyFinFrame) {
- EXPECT_CALL(stream_, TerminateFromPeer(true));
+ EXPECT_CALL(stream_, OnFinRead());
EXPECT_TRUE(sequencer_->OnFinFrame(0, ""));
EXPECT_EQ(0u, sequencer_->frames()->size());
EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
}
TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) {
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(2));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(2));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_EQ(1u, sequencer_->frames()->size());
@@ -206,7 +213,7 @@ TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) {
}
TEST_F(QuicStreamSequencerTest, NextxFrameNotConsumed) {
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(0));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_EQ(1u, sequencer_->frames()->size());
@@ -232,9 +239,9 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("ghi"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("def"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("ghi"), 3)).WillOnce(Return(3));
// Ack right away
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
@@ -254,7 +261,7 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderFramesProcessedWithBuffering) {
EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
// Ack right away
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
@@ -264,9 +271,9 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderFramesProcessedWithBuffering) {
EXPECT_TRUE(sequencer_->OnFrame(9, "jkl"));
EXPECT_EQ(3u, sequencer_->num_bytes_consumed());
- EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("ghi"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("jkl"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("def"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("ghi"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("jkl"), 3)).WillOnce(Return(3));
EXPECT_TRUE(sequencer_->OnFrame(3, "def"));
EXPECT_EQ(12u, sequencer_->num_bytes_consumed());
@@ -293,9 +300,9 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderFramesBlockignWithReadv) {
// Push pqr - process
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(0));
- EXPECT_CALL(stream_, ProcessData(StrEq("pqr"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("def"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("pqr"), 3)).WillOnce(Return(3));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_TRUE(sequencer_->OnFrame(3, "def"));
@@ -323,9 +330,9 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderFramesBlockignWithGetReadableRegion) {
sequencer_->SetMemoryLimit(9);
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(0));
- EXPECT_CALL(stream_, ProcessData(StrEq("pqr"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("def"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("pqr"), 3)).WillOnce(Return(3));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_TRUE(sequencer_->OnFrame(3, "def"));
@@ -357,7 +364,7 @@ TEST_F(QuicStreamSequencerTest, MarkConsumed) {
sequencer_->SetMemoryLimit(9);
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(0));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_TRUE(sequencer_->OnFrame(3, "def"));
@@ -389,7 +396,7 @@ TEST_F(QuicStreamSequencerTest, MarkConsumed) {
TEST_F(QuicStreamSequencerTest, MarkConsumedError) {
// TODO(rch): enable when chromium supports EXPECT_DFATAL.
/*
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(0));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_TRUE(sequencer_->OnFrame(9, "jklmnopqrstuvwxyz"));
@@ -401,7 +408,7 @@ TEST_F(QuicStreamSequencerTest, MarkConsumedError) {
// Now, attempt to mark consumed more data than was readable
// and expect the stream to be closed.
- EXPECT_CALL(stream_, Close(QUIC_ERROR_PROCESSING_STREAM));
+ EXPECT_CALL(stream_, Reset(QUIC_ERROR_PROCESSING_STREAM));
EXPECT_DFATAL(sequencer_->MarkConsumed(4),
"Invalid argument to MarkConsumed. num_bytes_consumed_: 3 "
"end_offset: 4 offset: 9 length: 17");
@@ -410,7 +417,7 @@ TEST_F(QuicStreamSequencerTest, MarkConsumedError) {
TEST_F(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) {
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(0));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
EXPECT_TRUE(sequencer_->OnFrame(3, "def"));
@@ -426,8 +433,8 @@ TEST_F(QuicStreamSequencerTest, MarkConsumedWithMissingPacket) {
TEST_F(QuicStreamSequencerTest, BasicHalfCloseOrdered) {
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, TerminateFromPeer(true));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, OnFinRead());
EXPECT_TRUE(sequencer_->OnFinFrame(0, "abc"));
EXPECT_EQ(3u, sequencer_->close_offset());
@@ -437,9 +444,9 @@ TEST_F(QuicStreamSequencerTest, BasicHalfCloseUnorderedWithFlush) {
sequencer_->OnFinFrame(6, "");
EXPECT_EQ(6u, sequencer_->close_offset());
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, TerminateFromPeer(true));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("def"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, OnFinRead());
EXPECT_TRUE(sequencer_->OnFrame(3, "def"));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
@@ -449,8 +456,8 @@ TEST_F(QuicStreamSequencerTest, BasicHalfUnordered) {
sequencer_->OnFinFrame(3, "");
EXPECT_EQ(3u, sequencer_->close_offset());
InSequence s;
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
- EXPECT_CALL(stream_, TerminateFromPeer(true));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, OnFinRead());
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
}
@@ -461,26 +468,26 @@ TEST_F(QuicStreamSequencerTest, TerminateWithReadv) {
sequencer_->OnFinFrame(3, "");
EXPECT_EQ(3u, sequencer_->close_offset());
- EXPECT_FALSE(sequencer_->IsHalfClosed());
+ EXPECT_FALSE(sequencer_->IsClosed());
- EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessRawData(StrEq("abc"), 3)).WillOnce(Return(0));
EXPECT_TRUE(sequencer_->OnFrame(0, "abc"));
iovec iov = { &buffer[0], 3 };
int bytes_read = sequencer_->Readv(&iov, 1);
EXPECT_EQ(3, bytes_read);
- EXPECT_TRUE(sequencer_->IsHalfClosed());
+ EXPECT_TRUE(sequencer_->IsClosed());
}
TEST_F(QuicStreamSequencerTest, MutipleOffsets) {
sequencer_->OnFinFrame(3, "");
EXPECT_EQ(3u, sequencer_->close_offset());
- EXPECT_CALL(stream_, Close(QUIC_MULTIPLE_TERMINATION_OFFSETS));
+ EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS));
sequencer_->OnFinFrame(5, "");
EXPECT_EQ(3u, sequencer_->close_offset());
- EXPECT_CALL(stream_, Close(QUIC_MULTIPLE_TERMINATION_OFFSETS));
+ EXPECT_CALL(stream_, Reset(QUIC_MULTIPLE_TERMINATION_OFFSETS));
sequencer_->OnFinFrame(1, "");
EXPECT_EQ(3u, sequencer_->close_offset());
@@ -531,11 +538,11 @@ TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
InSequence s;
for (size_t i = 0; i < list_.size(); ++i) {
string* data = &list_[i].second;
- EXPECT_CALL(stream_, ProcessData(StrEq(*data), data->size()))
+ EXPECT_CALL(stream_, ProcessRawData(StrEq(*data), data->size()))
.WillOnce(Return(data->size()));
}
- while (list_.size() != 0) {
+ while (!list_.empty()) {
int index = OneToN(list_.size()) - 1;
LOG(ERROR) << "Sending index " << index << " "
<< list_[index].second.data();
@@ -554,11 +561,11 @@ TEST_F(QuicSequencerRandomTest, RandomFramesDroppingNoBackup) {
InSequence s;
for (size_t i = 0; i < list_.size(); ++i) {
string* data = &list_[i].second;
- EXPECT_CALL(stream_, ProcessData(StrEq(*data), data->size()))
+ EXPECT_CALL(stream_, ProcessRawData(StrEq(*data), data->size()))
.WillOnce(Return(data->size()));
}
- while (list_.size() != 0) {
+ while (!list_.empty()) {
int index = OneToN(list_.size()) - 1;
LOG(ERROR) << "Sending index " << index << " "
<< list_[index].second.data();
diff --git a/chromium/net/quic/quic_utils.cc b/chromium/net/quic/quic_utils.cc
index cfb3cb7db5c..0aff3772c26 100644
--- a/chromium/net/quic/quic_utils.cc
+++ b/chromium/net/quic/quic_utils.cc
@@ -6,10 +6,13 @@
#include <ctype.h>
+#include <algorithm>
+
#include "base/logging.h"
#include "base/port.h"
#include "base/strings/stringprintf.h"
#include "base/strings/string_number_conversions.h"
+#include "net/spdy/write_blocked_list.h"
using base::StringPiece;
using std::string;
@@ -111,6 +114,15 @@ void QuicUtils::SerializeUint128(uint128 v, uint8* out) {
memcpy(out + sizeof(lo), &hi, sizeof(hi));
}
+// static
+void QuicUtils::SerializeUint128Short(uint128 v, uint8* out) {
+ const uint64 lo = Uint128Low64(v);
+ const uint64 hi = Uint128High64(v);
+ // This assumes that the system is little-endian.
+ memcpy(out, &lo, sizeof(lo));
+ memcpy(out + sizeof(lo), &hi, sizeof(hi) / 2);
+}
+
#define RETURN_STRING_LITERAL(x) \
case x: \
return #x;
@@ -188,6 +200,10 @@ const char* QuicUtils::ErrorToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG);
RETURN_STRING_LITERAL(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT);
RETURN_STRING_LITERAL(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED);
+ RETURN_STRING_LITERAL(QUIC_INVALID_CHANNEL_ID_SIGNATURE);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED);
+ RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO);
+ RETURN_STRING_LITERAL(QUIC_VERSION_NEGOTIATION_MISMATCH);
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.
@@ -217,7 +233,7 @@ string QuicUtils::TagToString(QuicTag tag) {
for (size_t i = 0; i < sizeof(chars); i++) {
chars[i] = tag;
- if (chars[i] == 0 && i == 3) {
+ if ((chars[i] == 0 || chars[i] == '\xff') && i == 3) {
chars[i] = ' ';
}
if (!isprint(static_cast<unsigned char>(chars[i]))) {
@@ -266,4 +282,14 @@ string QuicUtils::StringToHexASCIIDump(StringPiece in_buffer) {
return s;
}
+// static
+QuicPriority QuicUtils::LowestPriority() {
+ return static_cast<QuicPriority>(kLowestPriority);
+}
+
+// static
+QuicPriority QuicUtils::HighestPriority() {
+ return static_cast<QuicPriority>(kHighestPriority);
+}
+
} // namespace net
diff --git a/chromium/net/quic/quic_utils.h b/chromium/net/quic/quic_utils.h
index 37eb9d208ac..23f3b53a611 100644
--- a/chromium/net/quic/quic_utils.h
+++ b/chromium/net/quic/quic_utils.h
@@ -46,6 +46,10 @@ class NET_EXPORT_PRIVATE QuicUtils {
// SerializeUint128 writes |v| in little-endian form to |out|.
static void SerializeUint128(uint128 v, uint8* out);
+ // SerializeUint128 writes the first 96 bits of |v| in little-endian form
+ // to |out|.
+ static void SerializeUint128Short(uint128 v, uint8* out);
+
// Returns the name of the QuicRstStreamErrorCode as a char*
static const char* StreamErrorToString(QuicRstStreamErrorCode error);
@@ -71,8 +75,19 @@ class NET_EXPORT_PRIVATE QuicUtils {
static char* AsChars(unsigned char* data) {
return reinterpret_cast<char*>(data);
}
+
+ static QuicPriority LowestPriority();
+
+ static QuicPriority HighestPriority();
};
+// Utility function that returns an IOVector object wrapped around |str|.
+inline IOVector MakeIOVector(base::StringPiece str) {
+ IOVector iov;
+ iov.Append(const_cast<char*>(str.data()), str.size());
+ return iov;
+}
+
} // namespace net
#endif // NET_QUIC_QUIC_UTILS_H_
diff --git a/chromium/net/quic/quic_utils_test.cc b/chromium/net/quic/quic_utils_test.cc
index 0e50aec0ec1..0a0355f7d25 100644
--- a/chromium/net/quic/quic_utils_test.cc
+++ b/chromium/net/quic/quic_utils_test.cc
@@ -4,6 +4,7 @@
#include "net/quic/quic_utils.h"
+#include "net/quic/crypto/crypto_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -68,6 +69,21 @@ TEST(QuicUtilsTest, StringToHexASCIIDumpSuccess) {
string(reinterpret_cast<const char*>(kString), sizeof(kString))));
}
+TEST(QuicUtilsTest, TagToString) {
+ EXPECT_EQ("SCFG",
+ QuicUtils::TagToString(kSCFG));
+ EXPECT_EQ("SNO ",
+ QuicUtils::TagToString(kServerNonceTag));
+ EXPECT_EQ("CRT ",
+ QuicUtils::TagToString(kCertificateTag));
+ EXPECT_EQ("CHLO",
+ QuicUtils::TagToString(MakeQuicTag('C', 'H', 'L', 'O')));
+ // A tag that contains a non-printing character will be printed as a decimal
+ // number.
+ EXPECT_EQ("525092931",
+ QuicUtils::TagToString(MakeQuicTag('C', 'H', 'L', '\x1f')));
+}
+
} // namespace
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/reliable_quic_stream.cc b/chromium/net/quic/reliable_quic_stream.cc
index 41cb4576b58..5d9c3cce49c 100644
--- a/chromium/net/quic/reliable_quic_stream.cc
+++ b/chromium/net/quic/reliable_quic_stream.cc
@@ -13,32 +13,14 @@ using std::min;
namespace net {
+#define ENDPOINT (is_server_ ? "Server: " : " Client: ")
+
namespace {
-// This is somewhat arbitrary. It's possible, but unlikely, we will either fail
-// to set a priority client-side, or cancel a stream before stripping the
-// priority from the wire server-side. In either case, start out with a
-// priority in the middle.
-QuicPriority kDefaultPriority = 3;
-
-// Appends bytes from data into partial_data_buffer. Once partial_data_buffer
-// reaches 4 bytes, copies the data into 'result' and clears
-// partial_data_buffer.
-// Returns the number of bytes consumed.
-uint32 StripUint32(const char* data, uint32 data_len,
- string* partial_data_buffer,
- uint32* result) {
- DCHECK_GT(4u, partial_data_buffer->length());
- size_t missing_size = 4 - partial_data_buffer->length();
- if (data_len < missing_size) {
- StringPiece(data, data_len).AppendToString(partial_data_buffer);
- return data_len;
- }
- StringPiece(data, missing_size).AppendToString(partial_data_buffer);
- DCHECK_EQ(4u, partial_data_buffer->length());
- memcpy(result, partial_data_buffer->data(), 4);
- partial_data_buffer->clear();
- return missing_size;
+struct iovec MakeIovec(StringPiece data) {
+ struct iovec iov = {const_cast<char*>(data.data()),
+ static_cast<size_t>(data.size())};
+ return iov;
}
} // namespace
@@ -48,20 +30,15 @@ ReliableQuicStream::ReliableQuicStream(QuicStreamId id,
: sequencer_(this),
id_(id),
session_(session),
- visitor_(NULL),
stream_bytes_read_(0),
stream_bytes_written_(0),
- headers_decompressed_(false),
- priority_(kDefaultPriority),
- headers_id_(0),
- decompression_failed_(false),
stream_error_(QUIC_STREAM_NO_ERROR),
connection_error_(QUIC_NO_ERROR),
read_side_closed_(false),
write_side_closed_(false),
- priority_parsed_(false),
fin_buffered_(false),
- fin_sent_(false) {
+ fin_sent_(false),
+ is_server_(session_->is_server()) {
}
ReliableQuicStream::~ReliableQuicStream() {
@@ -82,12 +59,12 @@ bool ReliableQuicStream::WillAcceptStreamFrame(
bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
DCHECK_EQ(frame.stream_id, id_);
if (read_side_closed_) {
- DLOG(INFO) << "Ignoring frame " << frame.stream_id;
+ DVLOG(1) << ENDPOINT << "Ignoring frame " << frame.stream_id;
// We don't want to be reading: blackhole the data.
return true;
}
// Note: This count include duplicate data received.
- stream_bytes_read_ += frame.data.length();
+ stream_bytes_read_ += frame.data.TotalBufferSize();
bool accepted = sequencer_.OnStreamFrame(frame);
@@ -96,10 +73,12 @@ bool ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) {
void ReliableQuicStream::OnStreamReset(QuicRstStreamErrorCode error) {
stream_error_ = error;
- TerminateFromPeer(false); // Full close.
+ CloseWriteSide();
+ CloseReadSide();
}
-void ReliableQuicStream::ConnectionClose(QuicErrorCode error, bool from_peer) {
+void ReliableQuicStream::OnConnectionClosed(QuicErrorCode error,
+ bool from_peer) {
if (read_side_closed_ && write_side_closed_) {
return;
}
@@ -108,106 +87,45 @@ void ReliableQuicStream::ConnectionClose(QuicErrorCode error, bool from_peer) {
connection_error_ = error;
}
- if (from_peer) {
- TerminateFromPeer(false);
- } else {
- CloseWriteSide();
- CloseReadSide();
- }
+ CloseWriteSide();
+ CloseReadSide();
}
-void ReliableQuicStream::TerminateFromPeer(bool half_close) {
- if (!half_close) {
- CloseWriteSide();
- }
+void ReliableQuicStream::OnFinRead() {
+ DCHECK(sequencer_.IsClosed());
CloseReadSide();
}
-void ReliableQuicStream::Close(QuicRstStreamErrorCode error) {
+void ReliableQuicStream::Reset(QuicRstStreamErrorCode error) {
+ DCHECK_NE(QUIC_STREAM_NO_ERROR, error);
stream_error_ = error;
- if (error != QUIC_STREAM_NO_ERROR) {
- // Sending a RstStream results in calling CloseStream.
- session()->SendRstStream(id(), error);
- } else {
- session_->CloseStream(id());
- }
-}
-
-size_t ReliableQuicStream::Readv(const struct iovec* iov, size_t iov_len) {
- if (headers_decompressed_ && decompressed_headers_.empty()) {
- return sequencer_.Readv(iov, iov_len);
- }
- size_t bytes_consumed = 0;
- size_t iov_index = 0;
- while (iov_index < iov_len &&
- decompressed_headers_.length() > bytes_consumed) {
- size_t bytes_to_read = min(iov[iov_index].iov_len,
- decompressed_headers_.length() - bytes_consumed);
- char* iov_ptr = static_cast<char*>(iov[iov_index].iov_base);
- memcpy(iov_ptr,
- decompressed_headers_.data() + bytes_consumed, bytes_to_read);
- bytes_consumed += bytes_to_read;
- ++iov_index;
- }
- decompressed_headers_.erase(0, bytes_consumed);
- return bytes_consumed;
+ // Sending a RstStream results in calling CloseStream.
+ session()->SendRstStream(id(), error);
}
-int ReliableQuicStream::GetReadableRegions(iovec* iov, size_t iov_len) {
- if (headers_decompressed_ && decompressed_headers_.empty()) {
- return sequencer_.GetReadableRegions(iov, iov_len);
- }
- if (iov_len == 0) {
- return 0;
- }
- iov[0].iov_base = static_cast<void*>(
- const_cast<char*>(decompressed_headers_.data()));
- iov[0].iov_len = decompressed_headers_.length();
- return 1;
-}
-
-bool ReliableQuicStream::IsHalfClosed() const {
- if (!headers_decompressed_ || !decompressed_headers_.empty()) {
- return false;
- }
- return sequencer_.IsHalfClosed();
+void ReliableQuicStream::CloseConnection(QuicErrorCode error) {
+ session()->connection()->SendConnectionClose(error);
}
-bool ReliableQuicStream::HasBytesToRead() const {
- return !decompressed_headers_.empty() || sequencer_.HasBytesToRead();
+void ReliableQuicStream::CloseConnectionWithDetails(QuicErrorCode error,
+ const string& details) {
+ session()->connection()->SendConnectionCloseWithDetails(error, details);
}
-const IPEndPoint& ReliableQuicStream::GetPeerAddress() const {
- return session_->peer_address();
+QuicVersion ReliableQuicStream::version() {
+ return session()->connection()->version();
}
-QuicSpdyCompressor* ReliableQuicStream::compressor() {
- return session_->compressor();
-}
-
-bool ReliableQuicStream::GetSSLInfo(SSLInfo* ssl_info) {
- return session_->GetSSLInfo(ssl_info);
-}
-
-QuicConsumedData ReliableQuicStream::WriteData(StringPiece data, bool fin) {
+void ReliableQuicStream::WriteOrBufferData(StringPiece data, bool fin) {
DCHECK(data.size() > 0 || fin);
- return WriteOrBuffer(data, fin);
-}
-
-
-void ReliableQuicStream::set_priority(QuicPriority priority) {
- DCHECK_EQ(0u, stream_bytes_written_);
- priority_ = priority;
-}
-
-QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
DCHECK(!fin_buffered_);
QuicConsumedData consumed_data(0, false);
fin_buffered_ = fin;
if (queued_data_.empty()) {
- consumed_data = WriteDataInternal(string(data.data(), data.length()), fin);
+ struct iovec iov(MakeIovec(data));
+ consumed_data = WritevData(&iov, 1, fin, NULL);
DCHECK_LE(consumed_data.bytes_consumed, data.length());
}
@@ -218,8 +136,6 @@ QuicConsumedData ReliableQuicStream::WriteOrBuffer(StringPiece data, bool fin) {
string(data.data() + consumed_data.bytes_consumed,
data.length() - consumed_data.bytes_consumed));
}
-
- return QuicConsumedData(data.size(), true);
}
void ReliableQuicStream::OnCanWrite() {
@@ -229,7 +145,8 @@ void ReliableQuicStream::OnCanWrite() {
if (queued_data_.size() == 1 && fin_buffered_) {
fin = true;
}
- QuicConsumedData consumed_data = WriteDataInternal(data, fin);
+ struct iovec iov(MakeIovec(data));
+ QuicConsumedData consumed_data = WritevData(&iov, 1, fin, NULL);
if (consumed_data.bytes_consumed == data.size() &&
fin == consumed_data.fin_consumed) {
queued_data_.pop_front();
@@ -240,18 +157,13 @@ void ReliableQuicStream::OnCanWrite() {
}
}
-QuicConsumedData ReliableQuicStream::WriteDataInternal(
- StringPiece data, bool fin) {
- struct iovec iov = {const_cast<char*>(data.data()),
- static_cast<size_t>(data.size())};
- return WritevDataInternal(&iov, 1, fin);
-}
-
-QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov,
- int iov_count,
- bool fin) {
+QuicConsumedData ReliableQuicStream::WritevData(
+ const struct iovec* iov,
+ int iov_count,
+ bool fin,
+ QuicAckNotifier::DelegateInterface* ack_notifier_delegate) {
if (write_side_closed_) {
- DLOG(ERROR) << "Attempt to write when the write side is closed";
+ DLOG(ERROR) << ENDPOINT << "Attempt to write when the write side is closed";
return QuicConsumedData(0, false);
}
@@ -259,8 +171,8 @@ QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov,
for (int i = 0; i < iov_count; ++i) {
write_length += iov[i].iov_len;
}
- QuicConsumedData consumed_data =
- session()->WritevData(id(), iov, iov_count, stream_bytes_written_, fin);
+ QuicConsumedData consumed_data = session()->WritevData(
+ id(), iov, iov_count, stream_bytes_written_, fin, ack_notifier_delegate);
stream_bytes_written_ += consumed_data.bytes_consumed;
if (consumed_data.bytes_consumed == write_length) {
if (fin && consumed_data.fin_consumed) {
@@ -275,189 +187,28 @@ QuicConsumedData ReliableQuicStream::WritevDataInternal(const struct iovec* iov,
return consumed_data;
}
-QuicPriority ReliableQuicStream::EffectivePriority() const {
- return priority();
-}
-
void ReliableQuicStream::CloseReadSide() {
if (read_side_closed_) {
return;
}
- DLOG(INFO) << "Done reading from stream " << id();
+ DVLOG(1) << ENDPOINT << "Done reading from stream " << id();
read_side_closed_ = true;
if (write_side_closed_) {
- DLOG(INFO) << "Closing stream: " << id();
+ DVLOG(1) << ENDPOINT << "Closing stream: " << id();
session_->CloseStream(id());
}
}
-uint32 ReliableQuicStream::ProcessRawData(const char* data, uint32 data_len) {
- DCHECK_NE(0u, data_len);
- if (id() == kCryptoStreamId) {
- // The crypto stream does not use compression.
- return ProcessData(data, data_len);
- }
-
- uint32 total_bytes_consumed = 0;
- if (headers_id_ == 0u) {
- total_bytes_consumed += StripPriorityAndHeaderId(data, data_len);
- data += total_bytes_consumed;
- data_len -= total_bytes_consumed;
- if (data_len == 0 || !session_->connection()->connected()) {
- return total_bytes_consumed;
- }
- }
- DCHECK_NE(0u, headers_id_);
-
- // Once the headers are finished, we simply pass the data through.
- if (headers_decompressed_) {
- // Some buffered header data remains.
- if (!decompressed_headers_.empty()) {
- ProcessHeaderData();
- }
- if (decompressed_headers_.empty()) {
- DVLOG(1) << "Delegating procesing to ProcessData";
- total_bytes_consumed += ProcessData(data, data_len);
- }
- return total_bytes_consumed;
- }
-
- QuicHeaderId current_header_id =
- session_->decompressor()->current_header_id();
- // Ensure that this header id looks sane.
- if (headers_id_ < current_header_id ||
- headers_id_ > kMaxHeaderIdDelta + current_header_id) {
- DVLOG(1) << "Invalid headers for stream: " << id()
- << " header_id: " << headers_id_
- << " current_header_id: " << current_header_id;
- session_->connection()->SendConnectionClose(QUIC_INVALID_HEADER_ID);
- return total_bytes_consumed;
- }
-
- // If we are head-of-line blocked on decompression, then back up.
- if (current_header_id != headers_id_) {
- session_->MarkDecompressionBlocked(headers_id_, id());
- DVLOG(1) << "Unable to decompress header data for stream: " << id()
- << " header_id: " << headers_id_;
- return total_bytes_consumed;
- }
-
- // Decompressed data will be delivered to decompressed_headers_.
- size_t bytes_consumed = session_->decompressor()->DecompressData(
- StringPiece(data, data_len), this);
- DCHECK_NE(0u, bytes_consumed);
- if (bytes_consumed > data_len) {
- DCHECK(false) << "DecompressData returned illegal value";
- OnDecompressionError();
- return total_bytes_consumed;
- }
- total_bytes_consumed += bytes_consumed;
- data += bytes_consumed;
- data_len -= bytes_consumed;
-
- if (decompression_failed_) {
- // The session will have been closed in OnDecompressionError.
- return total_bytes_consumed;
- }
-
- // Headers are complete if the decompressor has moved on to the
- // next stream.
- headers_decompressed_ =
- session_->decompressor()->current_header_id() != headers_id_;
- if (!headers_decompressed_) {
- DCHECK_EQ(0u, data_len);
- }
-
- ProcessHeaderData();
-
- if (!headers_decompressed_ || !decompressed_headers_.empty()) {
- return total_bytes_consumed;
- }
-
- // We have processed all of the decompressed data but we might
- // have some more raw data to process.
- if (data_len > 0) {
- total_bytes_consumed += ProcessData(data, data_len);
- }
-
- // The sequencer will push any additional buffered frames if this data
- // has been completely consumed.
- return total_bytes_consumed;
-}
-
-uint32 ReliableQuicStream::ProcessHeaderData() {
- if (decompressed_headers_.empty()) {
- return 0;
- }
-
- size_t bytes_processed = ProcessData(decompressed_headers_.data(),
- decompressed_headers_.length());
- if (bytes_processed == decompressed_headers_.length()) {
- decompressed_headers_.clear();
- } else {
- decompressed_headers_ = decompressed_headers_.erase(0, bytes_processed);
- }
- return bytes_processed;
-}
-
-void ReliableQuicStream::OnDecompressorAvailable() {
- DCHECK_EQ(headers_id_,
- session_->decompressor()->current_header_id());
- DCHECK(!headers_decompressed_);
- DCHECK(!decompression_failed_);
- DCHECK_EQ(0u, decompressed_headers_.length());
-
- while (!headers_decompressed_) {
- struct iovec iovec;
- if (sequencer_.GetReadableRegions(&iovec, 1) == 0) {
- return;
- }
-
- size_t bytes_consumed = session_->decompressor()->DecompressData(
- StringPiece(static_cast<char*>(iovec.iov_base),
- iovec.iov_len),
- this);
- DCHECK_LE(bytes_consumed, iovec.iov_len);
- if (decompression_failed_) {
- return;
- }
- sequencer_.MarkConsumed(bytes_consumed);
-
- headers_decompressed_ =
- session_->decompressor()->current_header_id() != headers_id_;
- }
-
- // Either the headers are complete, or the all data as been consumed.
- ProcessHeaderData(); // Unprocessed headers remain in decompressed_headers_.
- if (IsHalfClosed()) {
- TerminateFromPeer(true);
- } else if (headers_decompressed_ && decompressed_headers_.empty()) {
- sequencer_.FlushBufferedFrames();
- }
-}
-
-bool ReliableQuicStream::OnDecompressedData(StringPiece data) {
- data.AppendToString(&decompressed_headers_);
- return true;
-}
-
-void ReliableQuicStream::OnDecompressionError() {
- DCHECK(!decompression_failed_);
- decompression_failed_ = true;
- session_->connection()->SendConnectionClose(QUIC_DECOMPRESSION_FAILURE);
-}
-
-
void ReliableQuicStream::CloseWriteSide() {
if (write_side_closed_) {
return;
}
- DLOG(INFO) << "Done writing to stream " << id();
+ DVLOG(1) << ENDPOINT << "Done writing to stream " << id();
write_side_closed_ = true;
if (read_side_closed_) {
- DLOG(INFO) << "Closing stream: " << id();
+ DVLOG(1) << ENDPOINT << "Closing stream: " << id();
session_->CloseStream(id());
}
}
@@ -469,46 +220,6 @@ bool ReliableQuicStream::HasBufferedData() {
void ReliableQuicStream::OnClose() {
CloseReadSide();
CloseWriteSide();
-
- if (visitor_) {
- Visitor* visitor = visitor_;
- // Calling Visitor::OnClose() may result the destruction of the visitor,
- // so we need to ensure we don't call it again.
- visitor_ = NULL;
- visitor->OnClose(this);
- }
-}
-
-uint32 ReliableQuicStream::StripPriorityAndHeaderId(
- const char* data, uint32 data_len) {
- uint32 total_bytes_parsed = 0;
-
- if (!priority_parsed_ &&
- session_->connection()->version() >= QUIC_VERSION_9 &&
- session_->connection()->is_server()) {
- QuicPriority temporary_priority = priority_;
- total_bytes_parsed = StripUint32(
- data, data_len, &headers_id_and_priority_buffer_, &temporary_priority);
- if (total_bytes_parsed > 0 && headers_id_and_priority_buffer_.size() == 0) {
- priority_parsed_ = true;
- // Spdy priorities are inverted, so the highest numerical value is the
- // lowest legal priority.
- if (temporary_priority > static_cast<QuicPriority>(kLowestPriority)) {
- session_->connection()->SendConnectionClose(QUIC_INVALID_PRIORITY);
- return 0;
- }
- priority_ = temporary_priority;
- }
- data += total_bytes_parsed;
- data_len -= total_bytes_parsed;
- }
- if (data_len > 0 && headers_id_ == 0u) {
- // The headers ID has not yet been read. Strip it from the beginning of
- // the data stream.
- total_bytes_parsed += StripUint32(
- data, data_len, &headers_id_and_priority_buffer_, &headers_id_);
- }
- return total_bytes_parsed;
}
} // namespace net
diff --git a/chromium/net/quic/reliable_quic_stream.h b/chromium/net/quic/reliable_quic_stream.h
index 807882ca2de..7b0a79068d5 100644
--- a/chromium/net/quic/reliable_quic_stream.h
+++ b/chromium/net/quic/reliable_quic_stream.h
@@ -14,8 +14,9 @@
#include "base/strings/string_piece.h"
#include "net/base/iovec.h"
#include "net/base/net_export.h"
+#include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_protocol.h"
#include "net/quic/quic_spdy_compressor.h"
-#include "net/quic/quic_spdy_decompressor.h"
#include "net/quic/quic_stream_sequencer.h"
namespace net {
@@ -28,78 +29,51 @@ class IPEndPoint;
class QuicSession;
class SSLInfo;
-// All this does right now is send data to subclasses via the sequencer.
-class NET_EXPORT_PRIVATE ReliableQuicStream : public
- QuicSpdyDecompressor::Visitor {
+class NET_EXPORT_PRIVATE ReliableQuicStream {
public:
- // Visitor receives callbacks from the stream.
- class Visitor {
- public:
- Visitor() {}
-
- // Called when the stream is closed.
- virtual void OnClose(ReliableQuicStream* stream) = 0;
-
- protected:
- virtual ~Visitor() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Visitor);
- };
-
ReliableQuicStream(QuicStreamId id,
QuicSession* session);
virtual ~ReliableQuicStream();
bool WillAcceptStreamFrame(const QuicStreamFrame& frame) const;
+
+ // Called when a (potentially duplicate) stream frame has been received
+ // for this stream. Returns false if this frame can not be accepted
+ // because there is too much data already buffered.
virtual bool OnStreamFrame(const QuicStreamFrame& frame);
+ // Called when the connection becomes writeable to allow the stream
+ // to write any pending data.
virtual void OnCanWrite();
// Called by the session just before the stream is deleted.
virtual void OnClose();
- // Called when we get a stream reset from the client.
+ // Called when we get a stream reset from the peer.
virtual void OnStreamReset(QuicRstStreamErrorCode error);
// Called when we get or send a connection close, and should immediately
// close the stream. This is not passed through the sequencer,
// but is handled immediately.
- virtual void ConnectionClose(QuicErrorCode error, bool from_peer);
-
- // Called when we should process a stream termination or
- // stream close from the peer.
- virtual void TerminateFromPeer(bool half_close);
-
- virtual uint32 ProcessRawData(const char* data, uint32 data_len);
- virtual uint32 ProcessHeaderData();
-
- virtual uint32 ProcessData(const char* data, uint32 data_len) = 0;
+ virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer);
- virtual bool OnDecompressedData(base::StringPiece data) OVERRIDE;
- virtual void OnDecompressionError() OVERRIDE;
+ // Called when the final data has been read.
+ virtual void OnFinRead();
- // Called to close the stream from this end.
- virtual void Close(QuicRstStreamErrorCode error);
+ virtual uint32 ProcessRawData(const char* data, uint32 data_len) = 0;
- // This block of functions wraps the sequencer's functions of the same
- // name. These methods return uncompressed data until that has
- // been fully processed. Then they simply delegate to the sequencer.
- virtual size_t Readv(const struct iovec* iov, size_t iov_len);
- virtual int GetReadableRegions(iovec* iov, size_t iov_len);
- virtual bool IsHalfClosed() const;
- virtual bool HasBytesToRead() const;
+ // Called to reset the stream from this end.
+ virtual void Reset(QuicRstStreamErrorCode error);
- // Called by the session when a decompression blocked stream
- // becomes unblocked.
- virtual void OnDecompressorAvailable();
+ // Called to close the entire connection from this end.
+ virtual void CloseConnection(QuicErrorCode error);
+ virtual void CloseConnectionWithDetails(QuicErrorCode error,
+ const string& details);
- // By default, this is the same as priority(), however it allows streams
- // to temporarily alter effective priority. For example if a SPDY stream has
- // compressed but not written headers it can write the headers with a higher
- // priority.
- virtual QuicPriority EffectivePriority() const;
+ // Returns the effective priority for the stream. This value may change
+ // during the life of the stream.
+ virtual QuicPriority EffectivePriority() const = 0;
QuicStreamId id() const { return id_; }
@@ -112,27 +86,23 @@ class NET_EXPORT_PRIVATE ReliableQuicStream : public
uint64 stream_bytes_read() { return stream_bytes_read_; }
uint64 stream_bytes_written() { return stream_bytes_written_; }
- const IPEndPoint& GetPeerAddress() const;
-
- void set_visitor(Visitor* visitor) { visitor_ = visitor; }
-
- QuicSpdyCompressor* compressor();
-
- // Gets the SSL connection information.
- bool GetSSLInfo(SSLInfo* ssl_info);
-
- bool headers_decompressed() const { return headers_decompressed_; }
+ QuicVersion version();
protected:
- // 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.
- //
- // The default implementation always consumed all bytes and any fin, but
- // this behavior is not guaranteed for subclasses so callers should check the
- // return value.
- virtual QuicConsumedData WriteData(base::StringPiece data, bool fin);
+ // Sends as much of 'data' to the connection as the connection will consume,
+ // and then buffers any remaining data in queued_data_.
+ void WriteOrBufferData(base::StringPiece data, bool fin);
+
+ // Sends as many bytes in the first |count| buffers of |iov| to the connection
+ // as the connection will consume.
+ // If |ack_notifier_delegate| is provided, then it will be notified once all
+ // the ACKs for this write have been received.
+ // Returns the number of bytes consumed by the connection.
+ QuicConsumedData WritevData(
+ const struct iovec* iov,
+ int iov_count,
+ bool fin,
+ QuicAckNotifier::DelegateInterface* ack_notifier_delegate);
// Close the read side of the socket. Further frames will not be accepted.
virtual void CloseReadSide();
@@ -146,61 +116,22 @@ class NET_EXPORT_PRIVATE ReliableQuicStream : public
QuicSession* session() { return session_; }
- // Sets priority_ to priority. This should only be called before bytes are
- // written to the server.
- void set_priority(QuicPriority priority);
- // This is protected because external classes should use EffectivePriority
- // instead.
- QuicPriority priority() const { return priority_; }
-
- // Sends as much of 'data' to the connection as the connection will consume,
- // and then buffers any remaining data in queued_data_.
- // Returns (data.size(), true) as it always consumed all data: it returns for
- // convenience to have the same return type as WriteDataInternal.
- QuicConsumedData WriteOrBuffer(base::StringPiece data, bool fin);
-
- // Sends as much of 'data' to the connection as the connection will consume.
- // Returns the number of bytes consumed by the connection.
- QuicConsumedData WriteDataInternal(base::StringPiece data, bool fin);
-
- // Sends as many bytes in the first |count| buffers of |iov| to the connection
- // as the connection will consume.
- // Returns the number of bytes consumed by the connection.
- QuicConsumedData WritevDataInternal(const struct iovec* iov,
- int iov_count,
- bool fin);
+ const QuicStreamSequencer* sequencer() const { return &sequencer_; }
+ QuicStreamSequencer* sequencer() { return &sequencer_; }
private:
friend class test::ReliableQuicStreamPeer;
friend class QuicStreamUtils;
- uint32 StripPriorityAndHeaderId(const char* data, uint32 data_len);
-
std::list<string> queued_data_;
QuicStreamSequencer sequencer_;
QuicStreamId id_;
QuicSession* session_;
- // Optional visitor of this stream to be notified when the stream is closed.
- Visitor* visitor_;
// Bytes read and written refer to payload bytes only: they do not include
// framing, encryption overhead etc.
uint64 stream_bytes_read_;
uint64 stream_bytes_written_;
- // True if the headers have been completely decompresssed.
- bool headers_decompressed_;
- // The priority of the stream, once parsed.
- QuicPriority priority_;
- // ID of the header block sent by the peer, once parsed.
- QuicHeaderId headers_id_;
- // Buffer into which we write bytes from priority_ and headers_id_
- // until each is fully parsed.
- string headers_id_and_priority_buffer_;
- // Contains a copy of the decompressed headers_ until they are consumed
- // via ProcessData or Readv.
- string decompressed_headers_;
- // True if an error was encountered during decompression.
- bool decompression_failed_;
// Stream error code received from a RstStreamFrame or error code sent by the
// visitor or sequencer in the RstStreamFrame.
@@ -215,10 +146,13 @@ class NET_EXPORT_PRIVATE ReliableQuicStream : public
// True if the write side is closed, and further writes should fail.
bool write_side_closed_;
- // True if the priority has been read, false otherwise.
- bool priority_parsed_;
bool fin_buffered_;
bool fin_sent_;
+
+ // True if the session this stream is running under is a server session.
+ bool is_server_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReliableQuicStream);
};
} // namespace net
diff --git a/chromium/net/quic/reliable_quic_stream_test.cc b/chromium/net/quic/reliable_quic_stream_test.cc
index 063554d82c9..7e82f533142 100644
--- a/chromium/net/quic/reliable_quic_stream_test.cc
+++ b/chromium/net/quic/reliable_quic_stream_test.cc
@@ -4,6 +4,7 @@
#include "net/quic/reliable_quic_stream.h"
+#include "net/quic/quic_ack_notifier.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_spdy_compressor.h"
#include "net/quic/quic_spdy_decompressor.h"
@@ -29,7 +30,6 @@ namespace {
const char kData1[] = "FooAndBar";
const char kData2[] = "EepAndBaz";
const size_t kDataLen = 9;
-const QuicGuid kGuid = 42;
const QuicGuid kStreamId = 3;
const bool kIsServer = true;
const bool kShouldProcessData = true;
@@ -37,20 +37,23 @@ const bool kShouldProcessData = true;
class TestStream : public ReliableQuicStream {
public:
TestStream(QuicStreamId id,
- QuicSession* session,
- bool should_process_data)
+ QuicSession* session,
+ bool should_process_data)
: ReliableQuicStream(id, session),
- should_process_data_(should_process_data) {
- }
+ should_process_data_(should_process_data) {}
- virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE {
+ virtual uint32 ProcessRawData(const char* data, uint32 data_len) OVERRIDE {
EXPECT_NE(0u, data_len);
DVLOG(1) << "ProcessData data_len: " << data_len;
data_ += string(data, data_len);
return should_process_data_ ? data_len : 0;
}
- using ReliableQuicStream::WriteData;
+ virtual QuicPriority EffectivePriority() const OVERRIDE {
+ return QuicUtils::HighestPriority();
+ }
+
+ using ReliableQuicStream::WriteOrBufferData;
using ReliableQuicStream::CloseReadSide;
using ReliableQuicStream::CloseWriteSide;
@@ -94,10 +97,8 @@ class ReliableQuicStreamTest : public ::testing::TestWithParam<bool> {
}
void Initialize(bool stream_should_process_data) {
- connection_ = new testing::StrictMock<MockConnection>(
- kGuid, IPEndPoint(), kIsServer);
- session_.reset(new testing::StrictMock<MockSession>(
- connection_, kIsServer));
+ connection_ = new StrictMock<MockConnection>(kIsServer);
+ session_.reset(new StrictMock<MockSession>(connection_));
stream_.reset(new TestStream(kStreamId, session_.get(),
stream_should_process_data));
stream2_.reset(new TestStream(kStreamId + 2, session_.get(),
@@ -126,9 +127,9 @@ TEST_F(ReliableQuicStreamTest, WriteAllData) {
1 + QuicPacketCreator::StreamFramePacketOverhead(
connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
- EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
+ EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen, true)));
- EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed);
+ stream_->WriteOrBufferData(kData1, false);
EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams());
}
@@ -140,9 +141,9 @@ TEST_F(ReliableQuicStreamTest, NoBlockingIfNoDataOrFin) {
// Write no data and no fin. If we consume nothing we should not be write
// blocked.
EXPECT_DEBUG_DEATH({
- EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _)).WillOnce(
+ EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _, _)).WillOnce(
Return(QuicConsumedData(0, false)));
- stream_->WriteData(StringPiece(), false);
+ stream_->WriteOrBufferData(StringPiece(), false);
EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams());
}, "");
}
@@ -153,10 +154,10 @@ 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(kStreamId, _, 1, _, _)).WillOnce(
+ EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _, _)).WillOnce(
Return(QuicConsumedData(1, false)));
- stream_->WriteData(StringPiece(kData1, 2), false);
- ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams());
+ stream_->WriteOrBufferData(StringPiece(kData1, 2), false);
+ ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
@@ -167,10 +168,10 @@ 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(kStreamId, _, 1, _, _)).WillOnce(
+ EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _, _)).WillOnce(
Return(QuicConsumedData(2, false)));
- stream_->WriteData(StringPiece(kData1, 2), true);
- ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams());
+ stream_->WriteOrBufferData(StringPiece(kData1, 2), true);
+ ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
TEST_F(ReliableQuicStreamTest, BlockIfSoloFinNotConsumed) {
@@ -178,13 +179,13 @@ 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(kStreamId, _, 1, _, _)).WillOnce(
+ EXPECT_CALL(*session_, WritevData(kStreamId, _, 1, _, _, _)).WillOnce(
Return(QuicConsumedData(0, false)));
- stream_->WriteData(StringPiece(), true);
- ASSERT_EQ(1, write_blocked_list_->NumBlockedStreams());
+ stream_->WriteOrBufferData(StringPiece(), true);
+ ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams());
}
-TEST_F(ReliableQuicStreamTest, WriteData) {
+TEST_F(ReliableQuicStreamTest, WriteOrBufferData) {
Initialize(kShouldProcessData);
EXPECT_FALSE(write_blocked_list_->HasWriteBlockedStreams());
@@ -192,25 +193,24 @@ TEST_F(ReliableQuicStreamTest, WriteData) {
1 + QuicPacketCreator::StreamFramePacketOverhead(
connection_->version(), PACKET_8BYTE_GUID, !kIncludeVersion,
PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP);
- EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).WillOnce(
+ EXPECT_CALL(*session_, WritevData(_, _, 1, _, _, _)).WillOnce(
Return(QuicConsumedData(kDataLen - 1, false)));
- // The return will be kDataLen, because the last byte gets buffered.
- EXPECT_EQ(kDataLen, stream_->WriteData(kData1, false).bytes_consumed);
+ stream_->WriteOrBufferData(kData1, false);
EXPECT_TRUE(write_blocked_list_->HasWriteBlockedStreams());
// Queue a bytes_consumed write.
- EXPECT_EQ(kDataLen, stream_->WriteData(kData2, false).bytes_consumed);
+ stream_->WriteOrBufferData(kData2, false);
// Make sure we get the tail of the first write followed by the bytes_consumed
InSequence s;
- EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
+ EXPECT_CALL(*session_, WritevData(_, _, 1, _, _, _)).
WillOnce(Return(QuicConsumedData(1, false)));
- EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
+ EXPECT_CALL(*session_, WritevData(_, _, 1, _, _, _)).
WillOnce(Return(QuicConsumedData(kDataLen - 2, false)));
stream_->OnCanWrite();
// And finally the end of the bytes_consumed.
- EXPECT_CALL(*session_, WritevData(_, _, 1, _, _)).
+ EXPECT_CALL(*session_, WritevData(_, _, 1, _, _, _)).
WillOnce(Return(QuicConsumedData(2, true)));
stream_->OnCanWrite();
}
@@ -222,325 +222,11 @@ TEST_F(ReliableQuicStreamTest, ConnectionCloseAfterStreamClose) {
stream_->CloseWriteSide();
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
- stream_->ConnectionClose(QUIC_INTERNAL_ERROR, false);
+ stream_->OnConnectionClosed(QUIC_INTERNAL_ERROR, false);
EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error());
EXPECT_EQ(QUIC_NO_ERROR, stream_->connection_error());
}
-TEST_F(ReliableQuicStreamTest, ProcessHeaders) {
- Initialize(kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
-
- stream_->OnStreamFrame(frame);
- EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_), stream_->data());
- EXPECT_EQ(static_cast<QuicPriority>(kHighestPriority),
- stream_->EffectivePriority());
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersWithInvalidHeaderId) {
- Initialize(kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- compressed_headers.replace(4, 1, 1, '\xFF'); // Illegal header id.
- QuicStreamFrame frame(kStreamId, false, 0, compressed_headers);
-
- EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID));
- stream_->OnStreamFrame(frame);
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBody) {
- Initialize(kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- string body = "this is the body";
- string data = compressed_headers + body;
- QuicStreamFrame frame(kStreamId, false, 0, data);
-
- stream_->OnStreamFrame(frame);
- EXPECT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
- stream_->data());
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyFragments) {
- Initialize(kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kLowestPriority, headers_);
- string body = "this is the body";
- string data = compressed_headers + body;
-
- for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
- Initialize(kShouldProcessData);
- for (size_t offset = 0; offset < data.size(); offset += fragment_size) {
- size_t remaining_data = data.length() - offset;
- StringPiece fragment(data.data() + offset,
- min(fragment_size, remaining_data));
- QuicStreamFrame frame(kStreamId, false, offset, fragment);
-
- stream_->OnStreamFrame(frame);
- }
- ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
- stream_->data()) << "fragment_size: " << fragment_size;
- }
-
- for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
- Initialize(kShouldProcessData);
-
- StringPiece fragment1(data.data(), split_point);
- QuicStreamFrame frame1(kStreamId, false, 0, fragment1);
- stream_->OnStreamFrame(frame1);
-
- StringPiece fragment2(data.data() + split_point, data.size() - split_point);
- QuicStreamFrame frame2(kStreamId, false, split_point, fragment2);
- stream_->OnStreamFrame(frame2);
-
- ASSERT_EQ(SpdyUtils::SerializeUncompressedHeaders(headers_) + body,
- stream_->data()) << "split_point: " << split_point;
- }
- EXPECT_EQ(static_cast<QuicPriority>(kLowestPriority),
- stream_->EffectivePriority());
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyReadv) {
- Initialize(!kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- string body = "this is the body";
- string data = compressed_headers + body;
- QuicStreamFrame frame(kStreamId, false, 0, data);
- string uncompressed_headers =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
- string uncompressed_data = uncompressed_headers + body;
-
- stream_->OnStreamFrame(frame);
- EXPECT_EQ(uncompressed_headers, stream_->data());
-
- char buffer[2048];
- ASSERT_LT(data.length(), arraysize(buffer));
- struct iovec vec;
- vec.iov_base = buffer;
- vec.iov_len = arraysize(buffer);
-
- size_t bytes_read = stream_->Readv(&vec, 1);
- EXPECT_EQ(uncompressed_headers.length(), bytes_read);
- EXPECT_EQ(uncompressed_headers, string(buffer, bytes_read));
-
- bytes_read = stream_->Readv(&vec, 1);
- EXPECT_EQ(body.length(), bytes_read);
- EXPECT_EQ(body, string(buffer, bytes_read));
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersAndBodyIncrementalReadv) {
- Initialize(!kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- string body = "this is the body";
- string data = compressed_headers + body;
- QuicStreamFrame frame(kStreamId, false, 0, data);
- string uncompressed_headers =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
- string uncompressed_data = uncompressed_headers + body;
-
- stream_->OnStreamFrame(frame);
- EXPECT_EQ(uncompressed_headers, stream_->data());
-
- char buffer[1];
- struct iovec vec;
- vec.iov_base = buffer;
- vec.iov_len = arraysize(buffer);
- for (size_t i = 0; i < uncompressed_data.length(); ++i) {
- size_t bytes_read = stream_->Readv(&vec, 1);
- ASSERT_EQ(1u, bytes_read);
- EXPECT_EQ(uncompressed_data.data()[i], buffer[0]);
- }
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersUsingReadvWithMultipleIovecs) {
- Initialize(!kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- string body = "this is the body";
- string data = compressed_headers + body;
- QuicStreamFrame frame(kStreamId, false, 0, data);
- string uncompressed_headers =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
- string uncompressed_data = uncompressed_headers + body;
-
- stream_->OnStreamFrame(frame);
- EXPECT_EQ(uncompressed_headers, stream_->data());
-
- char buffer1[1];
- char buffer2[1];
- struct iovec vec[2];
- vec[0].iov_base = buffer1;
- vec[0].iov_len = arraysize(buffer1);
- vec[1].iov_base = buffer2;
- vec[1].iov_len = arraysize(buffer2);
- for (size_t i = 0; i < uncompressed_data.length(); i += 2) {
- size_t bytes_read = stream_->Readv(vec, 2);
- ASSERT_EQ(2u, bytes_read) << i;
- ASSERT_EQ(uncompressed_data.data()[i], buffer1[0]) << i;
- ASSERT_EQ(uncompressed_data.data()[i + 1], buffer2[0]) << i;
- }
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessCorruptHeadersEarly) {
- Initialize(kShouldProcessData);
-
- string compressed_headers1 =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
- string decompressed_headers1 =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- headers_["content-type"] = "text/plain";
- string compressed_headers2 =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- // Corrupt the compressed data.
- compressed_headers2[compressed_headers2.length() - 1] ^= 0xA1;
- QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2);
- string decompressed_headers2 =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- // Deliver frame2 to stream2 out of order. The decompressor is not
- // available yet, so no data will be processed. The compressed data
- // will be buffered until OnDecompressorAvailable() is called
- // to process it.
- stream2_->OnStreamFrame(frame2);
- EXPECT_EQ("", stream2_->data());
-
- // Now deliver frame1 to stream1. The decompressor is available so
- // the data will be processed, and the decompressor will become
- // available for stream2.
- stream_->OnStreamFrame(frame1);
- EXPECT_EQ(decompressed_headers1, stream_->data());
-
- // Verify that the decompressor is available, and inform stream2
- // that it can now decompress the buffered compressed data. Since
- // the compressed data is corrupt, the stream will shutdown the session.
- EXPECT_EQ(2u, session_->decompressor()->current_header_id());
- EXPECT_CALL(*connection_, SendConnectionClose(QUIC_DECOMPRESSION_FAILURE));
- stream2_->OnDecompressorAvailable();
- EXPECT_EQ("", stream2_->data());
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessPartialHeadersEarly) {
- Initialize(kShouldProcessData);
-
- string compressed_headers1 =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
- string decompressed_headers1 =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- headers_["content-type"] = "text/plain";
- string compressed_headers2 =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- string partial_compressed_headers =
- compressed_headers2.substr(0, compressed_headers2.length() / 2);
- QuicStreamFrame frame2(stream2_->id(), false, 0, partial_compressed_headers);
- string decompressed_headers2 =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- // Deliver frame2 to stream2 out of order. The decompressor is not
- // available yet, so no data will be processed. The compressed data
- // will be buffered until OnDecompressorAvailable() is called
- // to process it.
- stream2_->OnStreamFrame(frame2);
- EXPECT_EQ("", stream2_->data());
-
- // Now deliver frame1 to stream1. The decompressor is available so
- // the data will be processed, and the decompressor will become
- // available for stream2.
- stream_->OnStreamFrame(frame1);
- EXPECT_EQ(decompressed_headers1, stream_->data());
-
- // Verify that the decompressor is available, and inform stream2
- // that it can now decompress the buffered compressed data. Since
- // the compressed data is incomplete it will not be passed to
- // the stream.
- EXPECT_EQ(2u, session_->decompressor()->current_header_id());
- stream2_->OnDecompressorAvailable();
- EXPECT_EQ("", stream2_->data());
-
- // Now send remaining data and verify that we have now received the
- // compressed headers.
- string remaining_compressed_headers =
- compressed_headers2.substr(partial_compressed_headers.length());
-
- QuicStreamFrame frame3(stream2_->id(), false,
- partial_compressed_headers.length(),
- remaining_compressed_headers);
- stream2_->OnStreamFrame(frame3);
- EXPECT_EQ(decompressed_headers2, stream2_->data());
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersEarly) {
- Initialize(kShouldProcessData);
-
- string compressed_headers1 =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers1);
- string decompressed_headers1 =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- headers_["content-type"] = "text/plain";
- string compressed_headers2 =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- QuicStreamFrame frame2(stream2_->id(), false, 0, compressed_headers2);
- string decompressed_headers2 =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- // Deliver frame2 to stream2 out of order. The decompressor is not
- // available yet, so no data will be processed. The compressed data
- // will be buffered until OnDecompressorAvailable() is called
- // to process it.
- stream2_->OnStreamFrame(frame2);
- EXPECT_EQ("", stream2_->data());
-
- // Now deliver frame1 to stream1. The decompressor is available so
- // the data will be processed, and the decompressor will become
- // available for stream2.
- stream_->OnStreamFrame(frame1);
- EXPECT_EQ(decompressed_headers1, stream_->data());
-
- // Verify that the decompressor is available, and inform stream2
- // that it can now decompress the buffered compressed data.
- EXPECT_EQ(2u, session_->decompressor()->current_header_id());
- stream2_->OnDecompressorAvailable();
- EXPECT_EQ(decompressed_headers2, stream2_->data());
-}
-
-TEST_F(ReliableQuicStreamTest, ProcessHeadersDelay) {
- Initialize(!kShouldProcessData);
-
- string compressed_headers =
- compressor_->CompressHeadersWithPriority(kHighestPriority, headers_);
- QuicStreamFrame frame1(stream_->id(), false, 0, compressed_headers);
- string decompressed_headers =
- SpdyUtils::SerializeUncompressedHeaders(headers_);
-
- // Send the headers to the stream and verify they were decompressed.
- stream_->OnStreamFrame(frame1);
- EXPECT_EQ(2u, session_->decompressor()->current_header_id());
-
- // Verify that we are now able to handle the body data,
- // even though the stream has not processed the headers.
- EXPECT_CALL(*connection_, SendConnectionClose(QUIC_INVALID_HEADER_ID))
- .Times(0);
- QuicStreamFrame frame2(stream_->id(), false, compressed_headers.length(),
- "body data");
- stream_->OnStreamFrame(frame2);
-}
-
} // namespace
} // namespace test
} // 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 73b5bab080a..a6b6cc1ed85 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils.cc
+++ b/chromium/net/quic/test_tools/crypto_test_utils.cc
@@ -7,7 +7,7 @@
#include "net/quic/crypto/channel_id.h"
#include "net/quic/crypto/common_cert_set.h"
#include "net/quic/crypto/crypto_handshake.h"
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/crypto/quic_random.h"
@@ -20,6 +20,8 @@
#include "net/quic/test_tools/simple_quic_framer.h"
using base::StringPiece;
+using std::make_pair;
+using std::pair;
using std::string;
using std::vector;
@@ -84,7 +86,8 @@ void MovePackets(PacketSavingConnection* source_conn,
for (vector<QuicStreamFrame>::const_iterator
i = framer.stream_frames().begin();
i != framer.stream_frames().end(); ++i) {
- ASSERT_TRUE(crypto_framer.ProcessInput(i->data));
+ scoped_ptr<string> frame_data(i->GetDataAsString());
+ ASSERT_TRUE(crypto_framer.ProcessInput(*frame_data));
ASSERT_FALSE(crypto_visitor.error());
}
}
@@ -130,13 +133,8 @@ CryptoTestUtils::FakeClientOptions::FakeClientOptions()
int CryptoTestUtils::HandshakeWithFakeServer(
PacketSavingConnection* client_conn,
QuicCryptoClientStream* client) {
- QuicGuid guid(1);
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
- IPEndPoint addr = IPEndPoint(ip, 1);
- PacketSavingConnection* server_conn =
- new PacketSavingConnection(guid, addr, true);
- TestSession server_session(server_conn, QuicConfig(), true);
+ PacketSavingConnection* server_conn = new PacketSavingConnection(true);
+ TestSession server_session(server_conn, DefaultQuicConfig());
QuicCryptoServerConfig crypto_config(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance());
@@ -163,13 +161,8 @@ int CryptoTestUtils::HandshakeWithFakeClient(
PacketSavingConnection* server_conn,
QuicCryptoServerStream* server,
const FakeClientOptions& options) {
- QuicGuid guid(1);
- IPAddressNumber ip;
- CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
- IPEndPoint addr = IPEndPoint(ip, 1);
- PacketSavingConnection* client_conn =
- new PacketSavingConnection(guid, addr, false);
- TestSession client_session(client_conn, QuicConfig(), false);
+ PacketSavingConnection* client_conn = new PacketSavingConnection(false);
+ TestSession client_session(client_conn, DefaultQuicConfig());
QuicCryptoClientConfig crypto_config;
client_session.config()->SetDefaults();
@@ -237,6 +230,27 @@ void CryptoTestUtils::CommunicateHandshakeMessages(
}
}
+pair<size_t, size_t> CryptoTestUtils::AdvanceHandshake(
+ PacketSavingConnection* a_conn,
+ QuicCryptoStream* a,
+ size_t a_i,
+ PacketSavingConnection* b_conn,
+ QuicCryptoStream* b,
+ size_t b_i) {
+ LOG(INFO) << "Processing " << a_conn->packets_.size() - a_i
+ << " packets a->b";
+ MovePackets(a_conn, &a_i, b, b_conn);
+
+ LOG(INFO) << "Processing " << b_conn->packets_.size() - b_i
+ << " packets b->a";
+ if (b_conn->packets_.size() - b_i == 2) {
+ LOG(INFO) << "here";
+ }
+ MovePackets(b_conn, &b_i, a, a_conn);
+
+ return make_pair(a_i, b_i);
+}
+
// static
string CryptoTestUtils::GetValueForTag(const CryptoHandshakeMessage& message,
QuicTag tag) {
diff --git a/chromium/net/quic/test_tools/crypto_test_utils.h b/chromium/net/quic/test_tools/crypto_test_utils.h
index 7b0c95274d5..60674a9e63d 100644
--- a/chromium/net/quic/test_tools/crypto_test_utils.h
+++ b/chromium/net/quic/test_tools/crypto_test_utils.h
@@ -7,6 +7,7 @@
#include <stdarg.h>
+#include <utility>
#include <vector>
#include "base/logging.h"
@@ -74,6 +75,16 @@ class CryptoTestUtils {
PacketSavingConnection* b_conn,
QuicCryptoStream* b);
+ // AdvanceHandshake attempts to moves messages from |a| to |b| and |b| to |a|.
+ // Returns the number of messages moved.
+ static std::pair<size_t, size_t> AdvanceHandshake(
+ PacketSavingConnection* a_conn,
+ QuicCryptoStream* a,
+ size_t a_i,
+ PacketSavingConnection* b_conn,
+ QuicCryptoStream* b,
+ size_t b_i);
+
// Returns the value for the tag |tag| in the tag value map of |message|.
static std::string GetValueForTag(const CryptoHandshakeMessage& message,
QuicTag tag);
diff --git a/chromium/net/quic/test_tools/delayed_verify_strike_register_client.cc b/chromium/net/quic/test_tools/delayed_verify_strike_register_client.cc
new file mode 100644
index 00000000000..eec16b16e8d
--- /dev/null
+++ b/chromium/net/quic/test_tools/delayed_verify_strike_register_client.cc
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/test_tools/delayed_verify_strike_register_client.h"
+
+using base::StringPiece;
+using std::string;
+using std::vector;
+
+namespace net {
+namespace test {
+
+DelayedVerifyStrikeRegisterClient::DelayedVerifyStrikeRegisterClient(
+ unsigned max_entries,
+ uint32 current_time_external,
+ uint32 window_secs,
+ const uint8 orbit[8],
+ StrikeRegister::StartupType startup)
+ : LocalStrikeRegisterClient(max_entries, current_time_external,
+ window_secs, orbit, startup),
+ delay_verifications_(false) {
+}
+
+DelayedVerifyStrikeRegisterClient::~DelayedVerifyStrikeRegisterClient() {}
+
+void DelayedVerifyStrikeRegisterClient::VerifyNonceIsValidAndUnique(
+ StringPiece nonce,
+ QuicWallTime now,
+ ResultCallback* cb) {
+ if (delay_verifications_) {
+ pending_verifications_.push_back(VerifyArgs(nonce.as_string(), now, cb));
+ } else {
+ LocalStrikeRegisterClient::VerifyNonceIsValidAndUnique(nonce, now, cb);
+ }
+}
+
+int DelayedVerifyStrikeRegisterClient::PendingVerifications() const {
+ return pending_verifications_.size();
+}
+
+void DelayedVerifyStrikeRegisterClient::RunPendingVerifications() {
+ vector<VerifyArgs> pending;
+ pending_verifications_.swap(pending);
+ for (vector<VerifyArgs>::const_iterator it = pending.begin(),
+ end = pending.end(); it != end; ++it) {
+ LocalStrikeRegisterClient::VerifyNonceIsValidAndUnique(
+ it->nonce, it->now, it->cb);
+ }
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/test_tools/delayed_verify_strike_register_client.h b/chromium/net/quic/test_tools/delayed_verify_strike_register_client.h
new file mode 100644
index 00000000000..69de1d077d3
--- /dev/null
+++ b/chromium/net/quic/test_tools/delayed_verify_strike_register_client.h
@@ -0,0 +1,63 @@
+// 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_TEST_TOOLS_DELAYED_VERIFY_STRIKE_REGISTER_CLIENT_H_
+#define NET_QUIC_TEST_TOOLS_DELAYED_VERIFY_STRIKE_REGISTER_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+#include "net/quic/crypto/local_strike_register_client.h"
+
+namespace net {
+namespace test {
+
+// Test helper that allows delaying execution of nonce verification
+// callbacks until a later time.
+class DelayedVerifyStrikeRegisterClient : public LocalStrikeRegisterClient {
+ public:
+ DelayedVerifyStrikeRegisterClient(unsigned max_entries,
+ uint32 current_time_external,
+ uint32 window_secs,
+ const uint8 orbit[8],
+ StrikeRegister::StartupType startup);
+ virtual ~DelayedVerifyStrikeRegisterClient();
+
+ virtual void VerifyNonceIsValidAndUnique(base::StringPiece nonce,
+ QuicWallTime now,
+ ResultCallback* cb) OVERRIDE;
+
+ // Start queueing verifications instead of executing them immediately.
+ void StartDelayingVerification() {
+ delay_verifications_ = true;
+ }
+ // Number of verifications that are queued.
+ int PendingVerifications() const;
+ // Run all pending verifications.
+ void RunPendingVerifications();
+
+ private:
+ struct VerifyArgs {
+ VerifyArgs(base::StringPiece in_nonce,
+ QuicWallTime in_now,
+ ResultCallback* in_cb)
+ : nonce(in_nonce.as_string()), now(in_now), cb(in_cb) {
+ }
+
+ std::string nonce;
+ QuicWallTime now;
+ ResultCallback* cb;
+ };
+
+ bool delay_verifications_;
+ std::vector<VerifyArgs> pending_verifications_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelayedVerifyStrikeRegisterClient);
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_DELAYED_VERIFY_STRIKE_REGISTER_CLIENT_H_
diff --git a/chromium/net/quic/test_tools/mock_random.cc b/chromium/net/quic/test_tools/mock_random.cc
index 19a2832bbaa..ab71d1634c8 100644
--- a/chromium/net/quic/test_tools/mock_random.cc
+++ b/chromium/net/quic/test_tools/mock_random.cc
@@ -7,7 +7,13 @@
namespace net {
MockRandom::MockRandom()
- : increment_(0) {
+ : base_(0xDEADBEEF),
+ increment_(0) {
+}
+
+MockRandom::MockRandom(uint32 base)
+ : base_(base),
+ increment_(0) {
}
void MockRandom::RandBytes(void* data, size_t len) {
@@ -15,11 +21,7 @@ void MockRandom::RandBytes(void* data, size_t len) {
}
uint64 MockRandom::RandUint64() {
- return 0xDEADBEEF + increment_;
-}
-
-bool MockRandom::RandBool() {
- return false;
+ return base_ + increment_;
}
void MockRandom::Reseed(const void* additional_entropy, size_t entropy_len) {
diff --git a/chromium/net/quic/test_tools/mock_random.h b/chromium/net/quic/test_tools/mock_random.h
index 544f5ce048a..3a3c87f4497 100644
--- a/chromium/net/quic/test_tools/mock_random.h
+++ b/chromium/net/quic/test_tools/mock_random.h
@@ -12,15 +12,15 @@ namespace net {
class MockRandom : public QuicRandom {
public:
+ // Initializes base_ to 0xDEADBEEF.
MockRandom();
+ MockRandom(uint32 base);
// QuicRandom:
// Fills the |data| buffer with a repeating byte, initially 'r'.
virtual void RandBytes(void* data, size_t len) OVERRIDE;
- // Returns 0xDEADBEEF + the current increment.
+ // Returns base + the current increment.
virtual uint64 RandUint64() OVERRIDE;
- // Returns false.
- virtual bool RandBool() OVERRIDE;
// Does nothing.
virtual void Reseed(const void* additional_entropy,
size_t entropy_len) OVERRIDE;
@@ -30,6 +30,7 @@ class MockRandom : public QuicRandom {
void ChangeValue();
private:
+ uint32 base_;
uint8 increment_;
};
diff --git a/chromium/net/quic/test_tools/quic_connection_peer.cc b/chromium/net/quic/test_tools/quic_connection_peer.cc
index 5d715db4ef5..54410b3bec1 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/quic/test_tools/quic_connection_peer.cc
@@ -5,11 +5,14 @@
#include "net/quic/test_tools/quic_connection_peer.h"
#include "base/stl_util.h"
-#include "net/quic/congestion_control/quic_congestion_manager.h"
#include "net/quic/congestion_control/receive_algorithm_interface.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"
+#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
+#include "net/quic/test_tools/quic_test_writer.h"
namespace net {
namespace test {
@@ -23,14 +26,15 @@ void QuicConnectionPeer::SendAck(QuicConnection* connection) {
void QuicConnectionPeer::SetReceiveAlgorithm(
QuicConnection* connection,
ReceiveAlgorithmInterface* receive_algorithm) {
- connection->congestion_manager_.receive_algorithm_.reset(receive_algorithm);
+ connection->received_packet_manager_.receive_algorithm_.reset(
+ receive_algorithm);
}
// static
void QuicConnectionPeer::SetSendAlgorithm(
QuicConnection* connection,
SendAlgorithmInterface* send_algorithm) {
- connection->congestion_manager_.send_algorithm_.reset(send_algorithm);
+ connection->sent_packet_manager_.send_algorithm_.reset(send_algorithm);
}
// static
@@ -50,14 +54,10 @@ QuicPacketCreator* QuicConnectionPeer::GetPacketCreator(
return &connection->packet_creator_;
}
-bool QuicConnectionPeer::GetReceivedTruncatedAck(QuicConnection* connection) {
- return connection->received_truncated_ack_;
-}
-
// static
-size_t QuicConnectionPeer::GetNumRetransmissionTimeouts(
+QuicReceivedPacketManager* QuicConnectionPeer::GetReceivedPacketManager(
QuicConnection* connection) {
- return connection->retransmission_timeouts_.size();
+ return &connection->received_packet_manager_;
}
// static
@@ -70,18 +70,21 @@ QuicTime::Delta QuicConnectionPeer::GetNetworkTimeout(
bool QuicConnectionPeer::IsSavedForRetransmission(
QuicConnection* connection,
QuicPacketSequenceNumber sequence_number) {
- return connection->sent_packet_manager_.IsUnacked(sequence_number);
+ return connection->sent_packet_manager_.IsUnacked(sequence_number) &&
+ connection->sent_packet_manager_.HasRetransmittableFrames(
+ sequence_number);
}
// static
-size_t QuicConnectionPeer::GetRetransmissionCount(
+bool QuicConnectionPeer::IsRetransmission(
QuicConnection* connection,
QuicPacketSequenceNumber sequence_number) {
- return connection->sent_packet_manager_.GetRetransmissionCount(
- sequence_number);
+ return QuicSentPacketManagerPeer::IsRetransmission(
+ &connection->sent_packet_manager_, sequence_number);
}
// static
+// TODO(ianswett): Create a GetSentEntropyHash which accepts an AckFrame.
QuicPacketEntropyHash QuicConnectionPeer::GetSentEntropyHash(
QuicConnection* connection,
QuicPacketSequenceNumber sequence_number) {
@@ -107,6 +110,17 @@ QuicPacketEntropyHash QuicConnectionPeer::ReceivedEntropyHash(
}
// static
+bool QuicConnectionPeer::IsWriteBlocked(QuicConnection* connection) {
+ return connection->write_blocked_;
+}
+
+// static
+void QuicConnectionPeer::SetIsWriteBlocked(QuicConnection* connection,
+ bool write_blocked) {
+ connection->write_blocked_ = write_blocked;
+}
+
+// static
bool QuicConnectionPeer::IsServer(QuicConnection* connection) {
return connection->is_server_;
}
@@ -137,16 +151,9 @@ void QuicConnectionPeer::SwapCrypters(QuicConnection* connection,
}
// static
-void QuicConnectionPeer:: SetMaxPacketsPerRetransmissionAlarm(
- QuicConnection* connection,
- int max_packets) {
- connection->max_packets_per_retransmission_alarm_ = max_packets;
-}
-
-// static
QuicConnectionHelperInterface* QuicConnectionPeer::GetHelper(
QuicConnection* connection) {
- return connection->helper_.get();
+ return connection->helper_;
}
// static
@@ -177,9 +184,26 @@ QuicAlarm* QuicConnectionPeer::GetSendAlarm(QuicConnection* connection) {
}
// static
+QuicAlarm* QuicConnectionPeer::GetResumeWritesAlarm(
+ QuicConnection* connection) {
+ return connection->resume_writes_alarm_.get();
+}
+
+// static
QuicAlarm* QuicConnectionPeer::GetTimeoutAlarm(QuicConnection* connection) {
return connection->timeout_alarm_.get();
}
+// static
+QuicPacketWriter* QuicConnectionPeer::GetWriter(QuicConnection* connection) {
+ return connection->writer_;
+}
+
+// static
+void QuicConnectionPeer::SetWriter(QuicConnection* connection,
+ QuicTestWriter* writer) {
+ connection->writer_ = writer;
+}
+
} // namespace test
} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_connection_peer.h b/chromium/net/quic/test_tools/quic_connection_peer.h
index 13ff14dc420..fd43661dae5 100644
--- a/chromium/net/quic/test_tools/quic_connection_peer.h
+++ b/chromium/net/quic/test_tools/quic_connection_peer.h
@@ -21,11 +21,15 @@ class QuicConnectionVisitorInterface;
class QuicFecGroup;
class QuicFramer;
class QuicPacketCreator;
+class QuicPacketWriter;
+class QuicReceivedPacketManager;
class ReceiveAlgorithmInterface;
class SendAlgorithmInterface;
namespace test {
+class QuicTestWriter;
+
// Peer to make public a number of otherwise private QuicConnection methods.
class QuicConnectionPeer {
public:
@@ -44,9 +48,8 @@ class QuicConnectionPeer {
static QuicPacketCreator* GetPacketCreator(QuicConnection* connection);
- static bool GetReceivedTruncatedAck(QuicConnection* connection);
-
- static size_t GetNumRetransmissionTimeouts(QuicConnection* connection);
+ static QuicReceivedPacketManager* GetReceivedPacketManager(
+ QuicConnection* connection);
static QuicTime::Delta GetNetworkTimeout(QuicConnection* connection);
@@ -54,9 +57,8 @@ class QuicConnectionPeer {
QuicConnection* connection,
QuicPacketSequenceNumber sequence_number);
- static size_t GetRetransmissionCount(
- QuicConnection* connection,
- QuicPacketSequenceNumber sequence_number);
+ static bool IsRetransmission(QuicConnection* connection,
+ QuicPacketSequenceNumber sequence_number);
static QuicPacketEntropyHash GetSentEntropyHash(
QuicConnection* connection,
@@ -71,6 +73,10 @@ class QuicConnectionPeer {
QuicConnection* connection,
QuicPacketSequenceNumber sequence_number);
+ static bool IsWriteBlocked(QuicConnection* connection);
+
+ static void SetIsWriteBlocked(QuicConnection* connection, bool write_blocked);
+
static bool IsServer(QuicConnection* connection);
static void SetIsServer(QuicConnection* connection, bool is_server);
@@ -83,9 +89,6 @@ class QuicConnectionPeer {
static void SwapCrypters(QuicConnection* connection, QuicFramer* framer);
- static void SetMaxPacketsPerRetransmissionAlarm(QuicConnection* connection,
- int max_packets);
-
static QuicConnectionHelperInterface* GetHelper(QuicConnection* connection);
static QuicFramer* GetFramer(QuicConnection* connection);
@@ -96,8 +99,12 @@ class QuicConnectionPeer {
static QuicAlarm* GetAckAlarm(QuicConnection* connection);
static QuicAlarm* GetRetransmissionAlarm(QuicConnection* connection);
static QuicAlarm* GetSendAlarm(QuicConnection* connection);
+ static QuicAlarm* GetResumeWritesAlarm(QuicConnection* connection);
static QuicAlarm* GetTimeoutAlarm(QuicConnection* connection);
+ static QuicPacketWriter* GetWriter(QuicConnection* connection);
+ static void SetWriter(QuicConnection* connection, QuicTestWriter* writer);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicConnectionPeer);
};
diff --git a/chromium/net/quic/test_tools/quic_data_stream_peer.cc b/chromium/net/quic/test_tools/quic_data_stream_peer.cc
new file mode 100644
index 00000000000..61656753104
--- /dev/null
+++ b/chromium/net/quic/test_tools/quic_data_stream_peer.cc
@@ -0,0 +1,19 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/test_tools/quic_data_stream_peer.h"
+
+#include "net/quic/quic_data_stream.h"
+
+namespace net {
+namespace test {
+
+// static
+void QuicDataStreamPeer::SetHeadersDecompressed(QuicDataStream* stream,
+ bool headers_decompressed) {
+ stream->headers_decompressed_ = headers_decompressed;
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_data_stream_peer.h b/chromium/net/quic/test_tools/quic_data_stream_peer.h
new file mode 100644
index 00000000000..bfaf826dcdc
--- /dev/null
+++ b/chromium/net/quic/test_tools/quic_data_stream_peer.h
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_TEST_TOOLS_QUIC_DATA_STREAM_PEER_H_
+#define NET_QUIC_TEST_TOOLS_QUIC_DATA_STREAM_PEER_H_
+
+#include "base/basictypes.h"
+#include "net/quic/quic_protocol.h"
+
+namespace net {
+
+class QuicDataStream;
+
+namespace test {
+
+class QuicDataStreamPeer {
+ public:
+ static void SetHeadersDecompressed(QuicDataStream* stream,
+ bool headers_decompressed);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicDataStreamPeer);
+};
+
+} // namespace test
+
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_QUIC_DATA_STREAM_PEER_H_
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
new file mode 100644
index 00000000000..e2e7c02c1a2
--- /dev/null
+++ b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/test_tools/quic_sent_packet_manager_peer.h"
+
+#include "base/stl_util.h"
+#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_sent_packet_manager.h"
+
+namespace net {
+namespace test {
+
+// static
+void QuicSentPacketManagerPeer::SetSendAlgorithm(
+ QuicSentPacketManager* sent_packet_manager,
+ SendAlgorithmInterface* send_algorithm) {
+ sent_packet_manager->send_algorithm_.reset(send_algorithm);
+}
+
+// static
+size_t QuicSentPacketManagerPeer::GetNackCount(
+ const QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number) {
+ return sent_packet_manager->packet_history_map_.find(
+ sequence_number)->second->nack_count();
+}
+
+// static
+QuicTime QuicSentPacketManagerPeer::GetSentTime(
+ const QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number) {
+ DCHECK(ContainsKey(sent_packet_manager->unacked_packets_, sequence_number));
+
+ return sent_packet_manager->unacked_packets_
+ .find(sequence_number)->second.sent_time;
+}
+
+// static
+QuicTime::Delta QuicSentPacketManagerPeer::rtt(
+ QuicSentPacketManager* sent_packet_manager) {
+ return sent_packet_manager->rtt_sample_;
+}
+
+// static
+bool QuicSentPacketManagerPeer::IsRetransmission(
+ QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number) {
+ DCHECK(sent_packet_manager->HasRetransmittableFrames(sequence_number));
+ return sent_packet_manager->HasRetransmittableFrames(sequence_number) &&
+ sent_packet_manager->
+ unacked_packets_[sequence_number].previous_transmissions != NULL;
+}
+
+// static
+void QuicSentPacketManagerPeer::MarkForRetransmission(
+ QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number,
+ TransmissionType transmission_type) {
+ sent_packet_manager->MarkForRetransmission(sequence_number,
+ transmission_type);
+}
+
+} // namespace test
+} // namespace net
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
new file mode 100644
index 00000000000..2ed9b218621
--- /dev/null
+++ b/chromium/net/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -0,0 +1,47 @@
+// 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_TEST_TOOLS_QUIC_SENT_PACKET_MANAGER_PEER_H_
+#define NET_QUIC_TEST_TOOLS_QUIC_SENT_PACKET_MANAGER_PEER_H_
+
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_sent_packet_manager.h"
+
+namespace net {
+
+class SendAlgorithmInterface;
+
+namespace test {
+
+class QuicSentPacketManagerPeer {
+ public:
+ static void SetSendAlgorithm(QuicSentPacketManager* sent_packet_manager,
+ SendAlgorithmInterface* send_algorithm);
+
+ static size_t GetNackCount(
+ const QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number);
+
+ static QuicTime GetSentTime(const QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number);
+
+ static QuicTime::Delta rtt(QuicSentPacketManager* sent_packet_manager);
+
+ // Returns true if |sequence_number| is a retransmission of a packet.
+ static bool IsRetransmission(QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number);
+
+ static void MarkForRetransmission(QuicSentPacketManager* sent_packet_manager,
+ QuicPacketSequenceNumber sequence_number,
+ TransmissionType transmission_type);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicSentPacketManagerPeer);
+};
+
+} // namespace test
+
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_QUIC_SENT_PACKET_MANAGER_PEER_H_
diff --git a/chromium/net/quic/test_tools/quic_test_utils.cc b/chromium/net/quic/test_tools/quic_test_utils.cc
index 8ba46b8f4ac..d85f92fa07e 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/quic/test_tools/quic_test_utils.cc
@@ -5,6 +5,7 @@
#include "net/quic/test_tools/quic_test_utils.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/crypto/crypto_utils.h"
@@ -13,6 +14,7 @@
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/spdy/spdy_frame_builder.h"
using base::StringPiece;
@@ -44,6 +46,9 @@ MockFramerVisitor::MockFramerVisitor() {
.WillByDefault(testing::Return(false));
// By default, we want to accept packets.
+ ON_CALL(*this, OnUnauthenticatedHeader(_))
+ .WillByDefault(testing::Return(true));
+
ON_CALL(*this, OnPacketHeader(_))
.WillByDefault(testing::Return(true));
@@ -73,6 +78,11 @@ bool NoOpFramerVisitor::OnProtocolVersionMismatch(QuicVersion version) {
return false;
}
+bool NoOpFramerVisitor::OnUnauthenticatedHeader(
+ const QuicPacketHeader& header) {
+ return true;
+}
+
bool NoOpFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) {
return true;
}
@@ -108,6 +118,19 @@ FramerVisitorCapturingFrames::FramerVisitorCapturingFrames() : frame_count_(0) {
}
FramerVisitorCapturingFrames::~FramerVisitorCapturingFrames() {
+ Reset();
+}
+
+void FramerVisitorCapturingFrames::Reset() {
+ STLDeleteElements(&stream_data_);
+ stream_frames_.clear();
+ frame_count_ = 0;
+ ack_.reset();
+ feedback_.reset();
+ rst_.reset();
+ close_.reset();
+ goaway_.reset();
+ version_negotiation_packet_.reset();
}
bool FramerVisitorCapturingFrames::OnPacketHeader(
@@ -118,9 +141,14 @@ bool FramerVisitorCapturingFrames::OnPacketHeader(
}
bool FramerVisitorCapturingFrames::OnStreamFrame(const QuicStreamFrame& frame) {
- // TODO(ianswett): Own the underlying string, so it will not exist outside
- // this callback.
- stream_frames_.push_back(frame);
+ // Make a copy of the frame and store a copy of underlying string, since
+ // frame.data may not exist outside this callback.
+ stream_data_.push_back(frame.GetDataAsString());
+ QuicStreamFrame frame_copy = frame;
+ frame_copy.data.Clear();
+ frame_copy.data.Append(const_cast<char*>(stream_data_.back()->data()),
+ stream_data_.back()->size());
+ stream_frames_.push_back(frame_copy);
++frame_count_;
return true;
}
@@ -203,35 +231,46 @@ void MockHelper::AdvanceTime(QuicTime::Delta delta) {
clock_.AdvanceTime(delta);
}
-MockConnection::MockConnection(QuicGuid guid,
- IPEndPoint address,
+MockConnection::MockConnection(bool is_server)
+ : QuicConnection(kTestGuid,
+ IPEndPoint(Loopback4(), kTestPort),
+ new testing::NiceMock<MockHelper>(),
+ new testing::NiceMock<MockPacketWriter>(),
+ is_server, QuicSupportedVersions()),
+ writer_(QuicConnectionPeer::GetWriter(this)),
+ helper_(helper()) {
+}
+
+MockConnection::MockConnection(IPEndPoint address,
bool is_server)
- : QuicConnection(guid, address, new testing::NiceMock<MockHelper>(),
- is_server, QuicVersionMax()),
- has_mock_helper_(true) {
+ : QuicConnection(kTestGuid, address,
+ new testing::NiceMock<MockHelper>(),
+ new testing::NiceMock<MockPacketWriter>(),
+ is_server, QuicSupportedVersions()),
+ writer_(QuicConnectionPeer::GetWriter(this)),
+ helper_(helper()) {
}
MockConnection::MockConnection(QuicGuid guid,
- IPEndPoint address,
- QuicConnectionHelperInterface* helper,
bool is_server)
- : QuicConnection(guid, address, helper, is_server, QuicVersionMax()),
- has_mock_helper_(false) {
+ : QuicConnection(guid,
+ IPEndPoint(Loopback4(), kTestPort),
+ new testing::NiceMock<MockHelper>(),
+ new testing::NiceMock<MockPacketWriter>(),
+ is_server, QuicSupportedVersions()),
+ writer_(QuicConnectionPeer::GetWriter(this)),
+ helper_(helper()) {
}
MockConnection::~MockConnection() {
}
void MockConnection::AdvanceTime(QuicTime::Delta delta) {
- CHECK(has_mock_helper_) << "Cannot advance time unless a MockClock is being"
- " used";
static_cast<MockHelper*>(helper())->AdvanceTime(delta);
}
-PacketSavingConnection::PacketSavingConnection(QuicGuid guid,
- IPEndPoint address,
- bool is_server)
- : MockConnection(guid, address, is_server) {
+PacketSavingConnection::PacketSavingConnection(bool is_server)
+ : MockConnection(is_server) {
}
PacketSavingConnection::~PacketSavingConnection() {
@@ -241,21 +280,18 @@ PacketSavingConnection::~PacketSavingConnection() {
bool PacketSavingConnection::SendOrQueuePacket(
EncryptionLevel level,
- QuicPacketSequenceNumber sequence_number,
- QuicPacket* packet,
- QuicPacketEntropyHash /* entropy_hash */,
- HasRetransmittableData /* retransmittable */,
- Force /* forced */) {
- packets_.push_back(packet);
+ const SerializedPacket& packet,
+ TransmissionType transmission_type) {
+ packets_.push_back(packet.packet);
QuicEncryptedPacket* encrypted =
- framer_.EncryptPacket(level, sequence_number, *packet);
+ framer_.EncryptPacket(level, packet.sequence_number, *packet.packet);
encrypted_packets_.push_back(encrypted);
return true;
}
-MockSession::MockSession(QuicConnection* connection, bool is_server)
- : QuicSession(connection, DefaultQuicConfig(), is_server) {
- ON_CALL(*this, WritevData(_, _, _, _, _))
+MockSession::MockSession(QuicConnection* connection)
+ : QuicSession(connection, DefaultQuicConfig()) {
+ ON_CALL(*this, WritevData(_, _, _, _, _, _))
.WillByDefault(testing::Return(QuicConsumedData(0, false)));
}
@@ -263,9 +299,8 @@ MockSession::~MockSession() {
}
TestSession::TestSession(QuicConnection* connection,
- const QuicConfig& config,
- bool is_server)
- : QuicSession(connection, config, is_server),
+ const QuicConfig& config)
+ : QuicSession(connection, config),
crypto_stream_(NULL) {
}
@@ -279,6 +314,12 @@ QuicCryptoStream* TestSession::GetCryptoStream() {
return crypto_stream_;
}
+MockPacketWriter::MockPacketWriter() {
+}
+
+MockPacketWriter::~MockPacketWriter() {
+}
+
MockSendAlgorithm::MockSendAlgorithm() {
}
@@ -332,12 +373,23 @@ string HexDumpWithMarks(const char* data, int length,
} // namespace
+QuicVersion QuicVersionMax() { return QuicSupportedVersions().front(); }
+
+QuicVersion QuicVersionMin() { return QuicSupportedVersions().back(); }
+
+IPAddressNumber Loopback4() {
+ net::IPAddressNumber addr;
+ CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr));
+ return addr;
+}
+
void CompareCharArraysWithHexError(
const string& description,
const char* actual,
const int actual_len,
const char* expected,
const int expected_len) {
+ EXPECT_EQ(actual_len, expected_len);
const int min_len = min(actual_len, expected_len);
const int max_len = max(actual_len, expected_len);
scoped_ptr<bool[]> marks(new bool[max_len]);
@@ -363,13 +415,25 @@ void CompareCharArraysWithHexError(
<< HexDumpWithMarks(actual, actual_len, marks.get(), max_len);
}
+bool DecodeHexString(const base::StringPiece& hex, std::string* bytes) {
+ bytes->clear();
+ if (hex.empty())
+ return true;
+ std::vector<uint8> v;
+ if (!base::HexStringToBytes(hex.as_string(), &v))
+ return false;
+ if (!v.empty())
+ bytes->assign(reinterpret_cast<const char*>(&v[0]), v.size());
+ return true;
+}
+
static QuicPacket* ConstructPacketFromHandshakeMessage(
QuicGuid guid,
const CryptoHandshakeMessage& message,
bool should_include_version) {
CryptoFramer crypto_framer;
scoped_ptr<QuicData> data(crypto_framer.ConstructHandshakeMessage(message));
- QuicFramer quic_framer(QuicVersionMax(), QuicTime::Zero(), false);
+ QuicFramer quic_framer(QuicSupportedVersions(), QuicTime::Zero(), false);
QuicPacketHeader header;
header.public_header.guid = guid;
@@ -382,7 +446,7 @@ static QuicPacket* ConstructPacketFromHandshakeMessage(
header.fec_group = 0;
QuicStreamFrame stream_frame(kCryptoStreamId, false, 0,
- data->AsStringPiece());
+ MakeIOVector(data->AsStringPiece()));
QuicFrame frame(&stream_frame);
QuicFrames frames;
@@ -409,7 +473,8 @@ size_t GetPacketLengthForOneStream(
version, PACKET_8BYTE_GUID, include_version,
sequence_number_length, is_in_fec_group);
const size_t ack_length = NullEncrypter().GetCiphertextSize(
- QuicFramer::GetMinAckFrameSize()) +
+ QuicFramer::GetMinAckFrameSize(
+ version, sequence_number_length, PACKET_1BYTE_SEQUENCE_NUMBER)) +
GetPacketHeaderSize(PACKET_8BYTE_GUID, include_version,
sequence_number_length, is_in_fec_group);
if (stream_length < ack_length) {
@@ -428,11 +493,19 @@ size_t GetMinStreamFrameSize(QuicVersion version) {
return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize;
}
+TestEntropyCalculator::TestEntropyCalculator() { }
+
+TestEntropyCalculator::~TestEntropyCalculator() { }
+
QuicPacketEntropyHash TestEntropyCalculator::EntropyHash(
QuicPacketSequenceNumber sequence_number) const {
return 1u;
}
+MockEntropyCalculator::MockEntropyCalculator() { }
+
+MockEntropyCalculator::~MockEntropyCalculator() { }
+
QuicConfig DefaultQuicConfig() {
QuicConfig config;
config.SetDefaults();
diff --git a/chromium/net/quic/test_tools/quic_test_utils.h b/chromium/net/quic/test_tools/quic_test_utils.h
index 64a9d30ada2..06c343189b5 100644
--- a/chromium/net/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/quic/test_tools/quic_test_utils.h
@@ -12,6 +12,7 @@
#include "base/strings/string_piece.h"
#include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/quic_ack_notifier.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_session.h"
@@ -25,12 +26,26 @@ namespace net {
namespace test {
+static const QuicGuid kTestGuid = 42;
+static const int kTestPort = 123;
+
+// Upper limit on versions we support.
+QuicVersion QuicVersionMax();
+
+// Lower limit on versions we support.
+QuicVersion QuicVersionMin();
+
+// Returns an address for 127.0.0.1.
+IPAddressNumber Loopback4();
+
void CompareCharArraysWithHexError(const std::string& description,
const char* actual,
const int actual_len,
const char* expected,
const int expected_len);
+bool DecodeHexString(const base::StringPiece& hex, std::string* bytes);
+
// Returns the length of a QuicPacket that is capable of holding either a
// stream frame or a minimal ack frame. Sets |*payload_length| to the number
// of bytes of stream data that will fit in such a packet.
@@ -48,6 +63,25 @@ size_t GetMinStreamFrameSize(QuicVersion version);
// Returns QuicConfig set to default values.
QuicConfig DefaultQuicConfig();
+template<typename SaveType>
+class ValueRestore {
+ public:
+ ValueRestore(SaveType* name, SaveType value)
+ : name_(name),
+ value_(*name) {
+ *name_ = value;
+ }
+ ~ValueRestore() {
+ *name_ = value_;
+ }
+
+ private:
+ SaveType* name_;
+ SaveType value_;
+
+ DISALLOW_COPY_AND_ASSIGN(ValueRestore);
+};
+
class MockFramerVisitor : public QuicFramerVisitorInterface {
public:
MockFramerVisitor();
@@ -62,6 +96,7 @@ class MockFramerVisitor : public QuicFramerVisitorInterface {
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));
MOCK_METHOD1(OnPacketHeader, bool(const QuicPacketHeader& header));
MOCK_METHOD1(OnFecProtectedPayload, void(base::StringPiece payload));
MOCK_METHOD1(OnStreamFrame, bool(const QuicStreamFrame& frame));
@@ -91,6 +126,7 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface {
const QuicVersionNegotiationPacket& packet) OVERRIDE {}
virtual void OnRevivedPacket() OVERRIDE {}
virtual bool OnProtocolVersionMismatch(QuicVersion version) OVERRIDE;
+ virtual bool OnUnauthenticatedHeader(const QuicPacketHeader& header) OVERRIDE;
virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
virtual void OnFecProtectedPayload(base::StringPiece payload) OVERRIDE {}
virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
@@ -129,6 +165,9 @@ class FramerVisitorCapturingFrames : public NoOpFramerVisitor {
FramerVisitorCapturingFrames();
virtual ~FramerVisitorCapturingFrames();
+ // Reset the visitor to it's initial state.
+ void Reset();
+
// NoOpFramerVisitor
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) OVERRIDE;
@@ -147,6 +186,9 @@ class FramerVisitorCapturingFrames : public NoOpFramerVisitor {
const std::vector<QuicStreamFrame>* stream_frames() const {
return &stream_frames_;
}
+ const std::vector<string*>& stream_data() const {
+ return stream_data_;
+ }
QuicAckFrame* ack() { return ack_.get(); }
QuicCongestionFeedbackFrame* feedback() { return feedback_.get(); }
QuicRstStreamFrame* rst() { return rst_.get(); }
@@ -160,6 +202,7 @@ class FramerVisitorCapturingFrames : public NoOpFramerVisitor {
size_t frame_count_;
QuicPacketHeader header_;
std::vector<QuicStreamFrame> stream_frames_;
+ std::vector<std::string*> stream_data_;
scoped_ptr<QuicAckFrame> ack_;
scoped_ptr<QuicCongestionFeedbackFrame> feedback_;
scoped_ptr<QuicRstStreamFrame> rst_;
@@ -178,11 +221,12 @@ class MockConnectionVisitor : public QuicConnectionVisitorInterface {
MOCK_METHOD1(OnStreamFrames, bool(const std::vector<QuicStreamFrame>& frame));
MOCK_METHOD1(OnRstStream, void(const QuicRstStreamFrame& frame));
MOCK_METHOD1(OnGoAway, void(const QuicGoAwayFrame& frame));
- MOCK_METHOD2(ConnectionClose, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
MOCK_METHOD0(OnCanWrite, bool());
MOCK_CONST_METHOD0(HasPendingHandshake, bool());
MOCK_METHOD1(OnSuccessfulVersionNegotiation,
void(const QuicVersion& version));
+ MOCK_METHOD0(OnConfigNegotiated, void());
private:
DISALLOW_COPY_AND_ASSIGN(MockConnectionVisitor);
@@ -197,10 +241,6 @@ class MockHelper : public QuicConnectionHelperInterface {
const QuicClock* GetClock() const;
QuicRandom* GetRandomGenerator();
void AdvanceTime(QuicTime::Delta delta);
- MOCK_METHOD2(WritePacketToWire, int(const QuicEncryptedPacket& packet,
- int* error));
- MOCK_METHOD0(IsWriteBlockedDataBuffered, bool());
- MOCK_METHOD1(IsWriteBlocked, bool(int stream_id));
virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate);
private:
@@ -210,12 +250,17 @@ class MockHelper : public QuicConnectionHelperInterface {
class MockConnection : public QuicConnection {
public:
- // Uses a MockHelper.
- MockConnection(QuicGuid guid, IPEndPoint address, bool is_server);
+ // Uses a MockHelper, GUID of 42, and 127.0.0.1:123.
+ explicit MockConnection(bool is_server);
+
+ // Uses a MockHelper, GUID of 42.
+ MockConnection(IPEndPoint address,
+ bool is_server);
+
+ // Uses a MockHelper, and 127.0.0.1:123
MockConnection(QuicGuid guid,
- IPEndPoint address,
- QuicConnectionHelperInterface* helper,
bool is_server);
+
virtual ~MockConnection();
// If the constructor that uses a MockHelper has been used then this method
@@ -247,23 +292,20 @@ class MockConnection : public QuicConnection {
}
private:
- const bool has_mock_helper_;
+ scoped_ptr<QuicPacketWriter> writer_;
+ scoped_ptr<QuicConnectionHelperInterface> helper_;
DISALLOW_COPY_AND_ASSIGN(MockConnection);
};
class PacketSavingConnection : public MockConnection {
public:
- PacketSavingConnection(QuicGuid guid, IPEndPoint address, bool is_server);
+ explicit PacketSavingConnection(bool is_server);
virtual ~PacketSavingConnection();
- virtual bool SendOrQueuePacket(
- EncryptionLevel level,
- QuicPacketSequenceNumber sequence_number,
- QuicPacket* packet,
- QuicPacketEntropyHash entropy_hash,
- HasRetransmittableData has_retransmittable_data,
- Force forced) OVERRIDE;
+ virtual bool SendOrQueuePacket(EncryptionLevel level,
+ const SerializedPacket& packet,
+ TransmissionType transmission_type) OVERRIDE;
std::vector<QuicPacket*> packets_;
std::vector<QuicEncryptedPacket*> encrypted_packets_;
@@ -274,24 +316,26 @@ class PacketSavingConnection : public MockConnection {
class MockSession : public QuicSession {
public:
- MockSession(QuicConnection* connection, bool is_server);
+ explicit MockSession(QuicConnection* connection);
virtual ~MockSession();
MOCK_METHOD4(OnPacket, bool(const IPEndPoint& self_address,
const IPEndPoint& peer_address,
const QuicPacketHeader& header,
const std::vector<QuicStreamFrame>& frame));
- MOCK_METHOD2(ConnectionClose, void(QuicErrorCode error, bool from_peer));
- MOCK_METHOD1(CreateIncomingReliableStream,
- ReliableQuicStream*(QuicStreamId id));
+ MOCK_METHOD2(OnConnectionClosed, void(QuicErrorCode error, bool from_peer));
+ MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
- MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
- MOCK_METHOD5(WritevData, QuicConsumedData(QuicStreamId id,
- const struct iovec* iov,
- int count,
- QuicStreamOffset offset,
- bool fin));
+ MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
+ MOCK_METHOD6(WritevData,
+ QuicConsumedData(QuicStreamId id,
+ const struct iovec* iov,
+ int count,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckNotifier::DelegateInterface*));
MOCK_METHOD0(IsHandshakeComplete, bool());
+ MOCK_METHOD0(IsCryptoHandshakeConfirmed, bool());
private:
DISALLOW_COPY_AND_ASSIGN(MockSession);
@@ -299,14 +343,11 @@ class MockSession : public QuicSession {
class TestSession : public QuicSession {
public:
- TestSession(QuicConnection* connection,
- const QuicConfig& config,
- bool is_server);
+ TestSession(QuicConnection* connection, const QuicConfig& config);
virtual ~TestSession();
- MOCK_METHOD1(CreateIncomingReliableStream,
- ReliableQuicStream*(QuicStreamId id));
- MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
+ MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
+ MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
void SetCryptoStream(QuicCryptoStream* stream);
@@ -317,29 +358,47 @@ class TestSession : public QuicSession {
DISALLOW_COPY_AND_ASSIGN(TestSession);
};
+class MockPacketWriter : public QuicPacketWriter {
+ public:
+ MockPacketWriter();
+ virtual ~MockPacketWriter();
+
+ MOCK_METHOD5(WritePacket,
+ WriteResult(const char* buffer,
+ size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer));
+ MOCK_CONST_METHOD0(IsWriteBlockedDataBuffered, bool());
+};
+
class MockSendAlgorithm : public SendAlgorithmInterface {
public:
MockSendAlgorithm();
virtual ~MockSendAlgorithm();
+ MOCK_METHOD2(SetFromConfig, void(const QuicConfig& config, bool is_server));
+ MOCK_METHOD1(SetMaxPacketSize, void(QuicByteCount max_packet_size));
MOCK_METHOD3(OnIncomingQuicCongestionFeedbackFrame,
void(const QuicCongestionFeedbackFrame&,
QuicTime feedback_receive_time,
const SentPacketsMap&));
- MOCK_METHOD3(OnIncomingAck,
+ MOCK_METHOD3(OnPacketAcked,
void(QuicPacketSequenceNumber, QuicByteCount, QuicTime::Delta));
- MOCK_METHOD1(OnIncomingLoss, void(QuicTime));
- MOCK_METHOD5(SentPacket,
+ MOCK_METHOD2(OnPacketLost, void(QuicPacketSequenceNumber, QuicTime));
+ MOCK_METHOD5(OnPacketSent,
bool(QuicTime sent_time, QuicPacketSequenceNumber, QuicByteCount,
- Retransmission, HasRetransmittableData));
- MOCK_METHOD2(AbandoningPacket, void(QuicPacketSequenceNumber sequence_number,
+ TransmissionType, HasRetransmittableData));
+ MOCK_METHOD0(OnRetransmissionTimeout, void());
+ MOCK_METHOD2(OnPacketAbandoned, void(QuicPacketSequenceNumber sequence_number,
QuicByteCount abandoned_bytes));
- MOCK_METHOD4(TimeUntilSend, QuicTime::Delta(QuicTime now, Retransmission,
+ MOCK_METHOD4(TimeUntilSend, QuicTime::Delta(QuicTime now, TransmissionType,
HasRetransmittableData,
IsHandshake));
- MOCK_METHOD0(BandwidthEstimate, QuicBandwidth(void));
- MOCK_METHOD0(SmoothedRtt, QuicTime::Delta(void));
- MOCK_METHOD0(RetransmissionDelay, QuicTime::Delta(void));
+ MOCK_CONST_METHOD0(BandwidthEstimate, QuicBandwidth(void));
+ MOCK_CONST_METHOD0(SmoothedRtt, QuicTime::Delta(void));
+ MOCK_CONST_METHOD0(RetransmissionDelay, QuicTime::Delta(void));
+ MOCK_CONST_METHOD0(GetCongestionWindow, QuicByteCount());
private:
DISALLOW_COPY_AND_ASSIGN(MockSendAlgorithm);
@@ -348,13 +407,23 @@ class MockSendAlgorithm : public SendAlgorithmInterface {
class TestEntropyCalculator :
public QuicReceivedEntropyHashCalculatorInterface {
public:
- TestEntropyCalculator() { }
- virtual ~TestEntropyCalculator() { }
+ TestEntropyCalculator();
+ virtual ~TestEntropyCalculator();
virtual QuicPacketEntropyHash EntropyHash(
QuicPacketSequenceNumber sequence_number) const OVERRIDE;
};
+class MockEntropyCalculator : public TestEntropyCalculator {
+ public:
+ MockEntropyCalculator();
+ virtual ~MockEntropyCalculator();
+
+ MOCK_CONST_METHOD1(
+ EntropyHash,
+ QuicPacketEntropyHash(QuicPacketSequenceNumber sequence_number));
+};
+
class TestDecompressorVisitor : public QuicSpdyDecompressor::Visitor {
public:
virtual ~TestDecompressorVisitor() {}
diff --git a/chromium/net/quic/test_tools/quic_test_writer.cc b/chromium/net/quic/test_tools/quic_test_writer.cc
new file mode 100644
index 00000000000..6755b2cfa8c
--- /dev/null
+++ b/chromium/net/quic/test_tools/quic_test_writer.cc
@@ -0,0 +1,23 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/test_tools/quic_test_writer.h"
+
+namespace net {
+namespace test {
+
+QuicTestWriter::QuicTestWriter() {}
+
+QuicTestWriter::~QuicTestWriter() {}
+
+QuicPacketWriter* QuicTestWriter::writer() {
+ return writer_.get();
+}
+
+void QuicTestWriter::set_writer(QuicPacketWriter* writer) {
+ writer_.reset(writer);
+}
+
+} // namespace test
+} // namespace net
diff --git a/chromium/net/quic/test_tools/quic_test_writer.h b/chromium/net/quic/test_tools/quic_test_writer.h
new file mode 100644
index 00000000000..ee33b7abe2a
--- /dev/null
+++ b/chromium/net/quic/test_tools/quic_test_writer.h
@@ -0,0 +1,33 @@
+// 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_TEST_TOOLS_QUIC_TEST_WRITER_H_
+#define NET_QUIC_TEST_TOOLS_QUIC_TEST_WRITER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/quic_packet_writer.h"
+
+namespace net {
+namespace test {
+
+// Allows setting a writer for a QuicConnection, to allow
+// fine-grained control of writes.
+class QuicTestWriter : public QuicPacketWriter {
+ public:
+ QuicTestWriter();
+ virtual ~QuicTestWriter();
+ // Takes ownership of |writer|.
+ void set_writer(QuicPacketWriter* writer);
+
+ protected:
+ QuicPacketWriter* writer();
+
+ private:
+ scoped_ptr<QuicPacketWriter> writer_;
+};
+
+} // namespace test
+} // namespace net
+
+#endif // NET_QUIC_TEST_TOOLS_QUIC_TEST_WRITER_H_
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 31a64e94a45..5119d035faa 100644
--- a/chromium/net/quic/test_tools/reliable_quic_stream_peer.cc
+++ b/chromium/net/quic/test_tools/reliable_quic_stream_peer.cc
@@ -22,11 +22,5 @@ void ReliableQuicStreamPeer::SetStreamBytesWritten(
stream->stream_bytes_written_ = stream_bytes_written;
}
-void ReliableQuicStreamPeer::SetHeadersDecompressed(
- ReliableQuicStream* stream,
- bool headers_decompressed) {
- stream->headers_decompressed_ = headers_decompressed;
-}
-
} // namespace test
} // namespace net
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 346a9b46411..da229da44e0 100644
--- a/chromium/net/quic/test_tools/reliable_quic_stream_peer.h
+++ b/chromium/net/quic/test_tools/reliable_quic_stream_peer.h
@@ -19,8 +19,6 @@ class ReliableQuicStreamPeer {
static void SetWriteSideClosed(bool value, ReliableQuicStream* stream);
static void SetStreamBytesWritten(QuicStreamOffset stream_bytes_written,
ReliableQuicStream* stream);
- static void SetHeadersDecompressed(ReliableQuicStream* stream,
- bool headers_decompressed);
private:
DISALLOW_COPY_AND_ASSIGN(ReliableQuicStreamPeer);
diff --git a/chromium/net/quic/test_tools/simple_quic_framer.cc b/chromium/net/quic/test_tools/simple_quic_framer.cc
index 46be3a83c5a..7d6439d2dcb 100644
--- a/chromium/net/quic/test_tools/simple_quic_framer.cc
+++ b/chromium/net/quic/test_tools/simple_quic_framer.cc
@@ -4,6 +4,7 @@
#include "net/quic/test_tools/simple_quic_framer.h"
+#include "base/stl_util.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
@@ -21,6 +22,10 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
: error_(QUIC_NO_ERROR) {
}
+ virtual ~SimpleFramerVisitor() {
+ STLDeleteElements(&stream_data_);
+ }
+
virtual void OnError(QuicFramer* framer) OVERRIDE {
error_ = framer->error();
}
@@ -42,14 +47,21 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
return true;
}
+ virtual bool OnUnauthenticatedHeader(
+ const QuicPacketHeader& header) OVERRIDE {
+ return true;
+ }
+
virtual void OnFecProtectedPayload(StringPiece payload) OVERRIDE {}
virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE {
// Save a copy of the data so it is valid after the packet is processed.
- stream_data_.push_back(frame.data.as_string());
+ stream_data_.push_back(frame.GetDataAsString());
QuicStreamFrame stream_frame(frame);
// Make sure that the stream frame points to this data.
- stream_frame.data = stream_data_.back();
+ stream_frame.data.Clear();
+ stream_frame.data.Append(const_cast<char*>(stream_data_.back()->data()),
+ stream_data_.back()->size());
stream_frames_.push_back(stream_frame);
return true;
}
@@ -122,13 +134,13 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface {
vector<QuicRstStreamFrame> rst_stream_frames_;
vector<QuicGoAwayFrame> goaway_frames_;
vector<QuicConnectionCloseFrame> connection_close_frames_;
- vector<string> stream_data_;
+ vector<string*> stream_data_;
DISALLOW_COPY_AND_ASSIGN(SimpleFramerVisitor);
};
SimpleQuicFramer::SimpleQuicFramer()
- : framer_(QuicVersionMax(), QuicTime::Zero(), true) {
+ : framer_(QuicSupportedVersions(), QuicTime::Zero(), true) {
}
SimpleQuicFramer::~SimpleQuicFramer() {
diff --git a/chromium/net/server/http_server_unittest.cc b/chromium/net/server/http_server_unittest.cc
index ede5066c3cd..0c3c97f0a90 100644
--- a/chromium/net/server/http_server_unittest.cc
+++ b/chromium/net/server/http_server_unittest.cc
@@ -188,7 +188,7 @@ TEST_F(HttpServerTest, RequestWithHeaders) {
{"HeaderWithColon", ": ", "1:1"},
{"EmptyHeader", ":", ""},
{"EmptyHeaderWithWhitespace", ": \t ", ""},
- {"HeaderWithNonASCII", ": ", "\u00f7"},
+ {"HeaderWithNonASCII", ": ", "\xf7"},
};
std::string headers;
for (size_t i = 0; i < arraysize(kHeaders); ++i) {
diff --git a/chromium/net/socket/buffered_write_stream_socket.cc b/chromium/net/socket/buffered_write_stream_socket.cc
index cf13c5e439a..87d3c337e24 100644
--- a/chromium/net/socket/buffered_write_stream_socket.cc
+++ b/chromium/net/socket/buffered_write_stream_socket.cc
@@ -27,10 +27,10 @@ BufferedWriteStreamSocket::BufferedWriteStreamSocket(
: wrapped_socket_(socket_to_wrap.Pass()),
io_buffer_(new GrowableIOBuffer()),
backup_buffer_(new GrowableIOBuffer()),
- weak_factory_(this),
callback_pending_(false),
wrapped_write_in_progress_(false),
- error_(0) {
+ error_(0),
+ weak_factory_(this) {
}
BufferedWriteStreamSocket::~BufferedWriteStreamSocket() {
diff --git a/chromium/net/socket/buffered_write_stream_socket.h b/chromium/net/socket/buffered_write_stream_socket.h
index aad5736d0b0..803018eefe3 100644
--- a/chromium/net/socket/buffered_write_stream_socket.h
+++ b/chromium/net/socket/buffered_write_stream_socket.h
@@ -69,11 +69,12 @@ class NET_EXPORT_PRIVATE BufferedWriteStreamSocket : public StreamSocket {
scoped_ptr<StreamSocket> wrapped_socket_;
scoped_refptr<GrowableIOBuffer> io_buffer_;
scoped_refptr<GrowableIOBuffer> backup_buffer_;
- base::WeakPtrFactory<BufferedWriteStreamSocket> weak_factory_;
bool callback_pending_;
bool wrapped_write_in_progress_;
int error_;
+ base::WeakPtrFactory<BufferedWriteStreamSocket> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(BufferedWriteStreamSocket);
};
diff --git a/chromium/net/socket/client_socket_factory.cc b/chromium/net/socket/client_socket_factory.cc
index a86688e3333..953914581fc 100644
--- a/chromium/net/socket/client_socket_factory.cc
+++ b/chromium/net/socket/client_socket_factory.cc
@@ -60,10 +60,10 @@ class DefaultClientSocketFactory : public ClientSocketFactory,
ClearSSLSessionCache();
}
- virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE {
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE {
// Per wtc, we actually only need to flush when trust is reduced.
- // Always flush now because OnCertTrustChanged does not tell us this.
- // See comments in ClientSocketPoolManager::OnCertTrustChanged.
+ // Always flush now because OnCACertChanged does not tell us this.
+ // See comments in ClientSocketPoolManager::OnCACertChanged.
ClearSSLSessionCache();
}
diff --git a/chromium/net/socket/client_socket_pool_base.cc b/chromium/net/socket/client_socket_pool_base.cc
index cec7956a0ee..1c79923a400 100644
--- a/chromium/net/socket/client_socket_pool_base.cc
+++ b/chromium/net/socket/client_socket_pool_base.cc
@@ -39,28 +39,6 @@ const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT.
// after a certain timeout has passed without receiving an ACK.
bool g_connect_backup_jobs_enabled = true;
-// Compares the effective priority of two results, and returns 1 if |request1|
-// has greater effective priority than |request2|, 0 if they have the same
-// effective priority, and -1 if |request2| has the greater effective priority.
-// Requests with |ignore_limits| set have higher effective priority than those
-// without. If both requests have |ignore_limits| set/unset, then the request
-// with the highest Pririoty has the highest effective priority. Does not take
-// into account the fact that Requests are serviced in FIFO order if they would
-// otherwise have the same priority.
-int CompareEffectiveRequestPriority(
- const internal::ClientSocketPoolBaseHelper::Request& request1,
- const internal::ClientSocketPoolBaseHelper::Request& request2) {
- if (request1.ignore_limits() && !request2.ignore_limits())
- return 1;
- if (!request1.ignore_limits() && request2.ignore_limits())
- return -1;
- if (request1.priority() > request2.priority())
- return 1;
- if (request1.priority() < request2.priority())
- return -1;
- return 0;
-}
-
} // namespace
ConnectJob::ConnectJob(const std::string& group_name,
@@ -162,7 +140,10 @@ ClientSocketPoolBaseHelper::Request::Request(
priority_(priority),
ignore_limits_(ignore_limits),
flags_(flags),
- net_log_(net_log) {}
+ net_log_(net_log) {
+ if (ignore_limits_)
+ DCHECK_EQ(priority_, MAXIMUM_PRIORITY);
+}
ClientSocketPoolBaseHelper::Request::~Request() {}
@@ -430,9 +411,8 @@ int ClientSocketPoolBaseHelper::RequestSocketInternal(
// If we don't have any sockets in this group, set a timer for potentially
// creating a new one. If the SYN is lost, this backup socket may complete
// before the slow socket, improving end user latency.
- if (connect_backup_jobs_enabled_ &&
- group->IsEmpty() && !group->HasBackupJob()) {
- group->StartBackupSocketTimer(group_name, this);
+ if (connect_backup_jobs_enabled_ && group->IsEmpty()) {
+ group->StartBackupJobTimer(group_name, this);
}
connecting_socket_count_++;
@@ -625,8 +605,9 @@ base::DictionaryValue* ClientSocketPoolBaseHelper::GetInfoAsValue(
group_dict->SetInteger("pending_request_count",
group->pending_request_count());
if (group->has_pending_requests()) {
- group_dict->SetInteger("top_pending_priority",
- group->TopPendingPriority());
+ group_dict->SetString(
+ "top_pending_priority",
+ RequestPriorityToString(group->TopPendingPriority()));
}
group_dict->SetInteger("active_socket_count", group->active_socket_count());
@@ -652,7 +633,8 @@ base::DictionaryValue* ClientSocketPoolBaseHelper::GetInfoAsValue(
group_dict->SetBoolean("is_stalled",
group->IsStalledOnPoolMaxSockets(
max_sockets_per_group_));
- group_dict->SetBoolean("has_backup_job", group->HasBackupJob());
+ group_dict->SetBoolean("backup_job_timer_is_running",
+ group->BackupJobTimerIsRunning());
all_groups_dict->SetWithoutPathExpansion(it->first, group_dict);
}
@@ -951,11 +933,6 @@ void ClientSocketPoolBaseHelper::RemoveConnectJob(ConnectJob* job,
DCHECK(group);
group->RemoveJob(job);
-
- // If we've got no more jobs for this group, then we no longer need a
- // backup job either.
- if (group->jobs().empty())
- group->CleanupBackupJob();
}
void ClientSocketPoolBaseHelper::OnAvailableSocketSlot(
@@ -1157,26 +1134,30 @@ void ClientSocketPoolBaseHelper::TryToCloseSocketsInLayeredPools() {
ClientSocketPoolBaseHelper::Group::Group()
: unassigned_job_count_(0),
- active_socket_count_(0),
- weak_factory_(this) {}
+ pending_requests_(NUM_PRIORITIES),
+ active_socket_count_(0) {}
ClientSocketPoolBaseHelper::Group::~Group() {
- CleanupBackupJob();
DCHECK_EQ(0u, unassigned_job_count_);
}
-void ClientSocketPoolBaseHelper::Group::StartBackupSocketTimer(
+void ClientSocketPoolBaseHelper::Group::StartBackupJobTimer(
const std::string& group_name,
ClientSocketPoolBaseHelper* pool) {
- // Only allow one timer pending to create a backup socket.
- if (weak_factory_.HasWeakPtrs())
+ // Only allow one timer to run at a time.
+ if (BackupJobTimerIsRunning())
return;
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&Group::OnBackupSocketTimerFired, weak_factory_.GetWeakPtr(),
- group_name, pool),
- pool->ConnectRetryInterval());
+ // Unretained here is okay because |backup_job_timer_| is
+ // automatically cancelled when it's destroyed.
+ backup_job_timer_.Start(
+ FROM_HERE, pool->ConnectRetryInterval(),
+ base::Bind(&Group::OnBackupJobTimerFired, base::Unretained(this),
+ group_name, pool));
+}
+
+bool ClientSocketPoolBaseHelper::Group::BackupJobTimerIsRunning() const {
+ return backup_job_timer_.IsRunning();
}
bool ClientSocketPoolBaseHelper::Group::TryToUseUnassignedConnectJob() {
@@ -1210,9 +1191,14 @@ void ClientSocketPoolBaseHelper::Group::RemoveJob(ConnectJob* job) {
size_t job_count = jobs_.size();
if (job_count < unassigned_job_count_)
unassigned_job_count_ = job_count;
+
+ // If we've got no more jobs for this group, then we no longer need a
+ // backup job either.
+ if (jobs_.empty())
+ backup_job_timer_.Stop();
}
-void ClientSocketPoolBaseHelper::Group::OnBackupSocketTimerFired(
+void ClientSocketPoolBaseHelper::Group::OnBackupJobTimerFired(
std::string group_name,
ClientSocketPoolBaseHelper* pool) {
// If there are no more jobs pending, there is no work to do.
@@ -1227,7 +1213,7 @@ void ClientSocketPoolBaseHelper::Group::OnBackupSocketTimerFired(
if (pool->ReachedMaxSocketsLimit() ||
!HasAvailableSocketSlot(pool->max_sockets_per_group_) ||
(*jobs_.begin())->GetLoadState() == LOAD_STATE_RESOLVING_HOST) {
- StartBackupSocketTimer(group_name, pool);
+ StartBackupJobTimer(group_name, pool);
return;
}
@@ -1236,8 +1222,8 @@ void ClientSocketPoolBaseHelper::Group::OnBackupSocketTimerFired(
scoped_ptr<ConnectJob> backup_job =
pool->connect_job_factory_->NewConnectJob(
- group_name, **pending_requests_.begin(), pool);
- backup_job->net_log().AddEvent(NetLog::TYPE_SOCKET_BACKUP_CREATED);
+ group_name, *pending_requests_.FirstMax().value(), pool);
+ backup_job->net_log().AddEvent(NetLog::TYPE_BACKUP_CONNECT_JOB_CREATED);
SIMPLE_STATS_COUNTER("socket.backup_created");
int rv = backup_job->Connect();
pool->connecting_socket_count_++;
@@ -1258,13 +1244,14 @@ void ClientSocketPoolBaseHelper::Group::RemoveAllJobs() {
STLDeleteElements(&jobs_);
unassigned_job_count_ = 0;
- // Cancel pending backup job.
- weak_factory_.InvalidateWeakPtrs();
+ // Stop backup job timer.
+ backup_job_timer_.Stop();
}
const ClientSocketPoolBaseHelper::Request*
ClientSocketPoolBaseHelper::Group::GetNextPendingRequest() const {
- return pending_requests_.empty() ? NULL : *pending_requests_.begin();
+ return
+ pending_requests_.empty() ? NULL : pending_requests_.FirstMax().value();
}
bool ClientSocketPoolBaseHelper::Group::HasConnectJobForHandle(
@@ -1273,40 +1260,45 @@ bool ClientSocketPoolBaseHelper::Group::HasConnectJobForHandle(
// If it's farther back in the deque than that, it doesn't have a
// corresponding ConnectJob.
size_t i = 0;
- for (RequestQueue::const_iterator it = pending_requests_.begin();
- it != pending_requests_.end() && i < jobs_.size(); ++it, ++i) {
- if ((*it)->handle() == handle)
+ for (RequestQueue::Pointer pointer = pending_requests_.FirstMax();
+ !pointer.is_null() && i < jobs_.size();
+ pointer = pending_requests_.GetNextTowardsLastMin(pointer), ++i) {
+ if (pointer.value()->handle() == handle)
return true;
}
return false;
}
void ClientSocketPoolBaseHelper::Group::InsertPendingRequest(
- scoped_ptr<const Request> r) {
- RequestQueue::iterator it = pending_requests_.begin();
- // TODO(mmenke): Should the network stack require requests with
- // |ignore_limits| have the highest priority?
- while (it != pending_requests_.end() &&
- CompareEffectiveRequestPriority(*r, *(*it)) <= 0) {
- ++it;
+ 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
+ // priority == MAXIMUM_PRIORITY) ahead of other requests with
+ // MAXIMUM_PRIORITY.
+ DCHECK_EQ(priority, MAXIMUM_PRIORITY);
+ pending_requests_.InsertAtFront(request.release(), priority);
+ } else {
+ pending_requests_.Insert(request.release(), priority);
}
- pending_requests_.insert(it, r.release());
}
scoped_ptr<const ClientSocketPoolBaseHelper::Request>
ClientSocketPoolBaseHelper::Group::PopNextPendingRequest() {
if (pending_requests_.empty())
return scoped_ptr<const ClientSocketPoolBaseHelper::Request>();
- return RemovePendingRequest(pending_requests_.begin());
+ return RemovePendingRequest(pending_requests_.FirstMax());
}
scoped_ptr<const ClientSocketPoolBaseHelper::Request>
ClientSocketPoolBaseHelper::Group::FindAndRemovePendingRequest(
ClientSocketHandle* handle) {
- for (RequestQueue::iterator it = pending_requests_.begin();
- it != pending_requests_.end(); ++it) {
- if ((*it)->handle() == handle) {
- scoped_ptr<const Request> request = RemovePendingRequest(it);
+ for (RequestQueue::Pointer pointer = pending_requests_.FirstMax();
+ !pointer.is_null();
+ pointer = pending_requests_.GetNextTowardsLastMin(pointer)) {
+ if (pointer.value()->handle() == handle) {
+ scoped_ptr<const Request> request = RemovePendingRequest(pointer);
return request.Pass();
}
}
@@ -1315,12 +1307,12 @@ ClientSocketPoolBaseHelper::Group::FindAndRemovePendingRequest(
scoped_ptr<const ClientSocketPoolBaseHelper::Request>
ClientSocketPoolBaseHelper::Group::RemovePendingRequest(
- const RequestQueue::iterator& it) {
- scoped_ptr<const Request> request(*it);
- pending_requests_.erase(it);
+ const RequestQueue::Pointer& pointer) {
+ scoped_ptr<const Request> request(pointer.value());
+ pending_requests_.Erase(pointer);
// If there are no more requests, kill the backup timer.
if (pending_requests_.empty())
- CleanupBackupJob();
+ backup_job_timer_.Stop();
return request.Pass();
}
diff --git a/chromium/net/socket/client_socket_pool_base.h b/chromium/net/socket/client_socket_pool_base.h
index 31ec9bf7b13..2c2ddb57abc 100644
--- a/chromium/net/socket/client_socket_pool_base.h
+++ b/chromium/net/socket/client_socket_pool_base.h
@@ -22,6 +22,7 @@
#ifndef NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
#define NET_SOCKET_CLIENT_SOCKET_POOL_BASE_H_
+#include <cstddef>
#include <deque>
#include <list>
#include <map>
@@ -43,6 +44,7 @@
#include "net/base/net_export.h"
#include "net/base/net_log.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/priority_queue.h"
#include "net/base/request_priority.h"
#include "net/socket/client_socket_pool.h"
#include "net/socket/stream_socket.h"
@@ -182,12 +184,12 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
private:
ClientSocketHandle* const handle_;
- CompletionCallback callback_;
+ const CompletionCallback callback_;
// TODO(akalin): Support reprioritization.
const RequestPriority priority_;
- bool ignore_limits_;
+ const bool ignore_limits_;
const Flags flags_;
- BoundNetLog net_log_;
+ const BoundNetLog net_log_;
DISALLOW_COPY_AND_ASSIGN(Request);
};
@@ -350,7 +352,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
base::TimeTicks start_time;
};
- typedef std::deque<const Request* > RequestQueue;
+ typedef PriorityQueue<const Request*> RequestQueue;
typedef std::map<const ClientSocketHandle*, const Request*> RequestMap;
// A Group is allocated per group_name when there are idle sockets or pending
@@ -380,19 +382,22 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
pending_requests_.size() > jobs_.size();
}
+ // 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).
RequestPriority TopPendingPriority() const {
- return pending_requests_.front()->priority();
+ // NOTE: FirstMax().value()->priority() is not the same as
+ // FirstMax().priority()!
+ return pending_requests_.FirstMax().value()->priority();
}
- bool HasBackupJob() const { return weak_factory_.HasWeakPtrs(); }
+ // Set a timer to create a backup job if it takes too long to
+ // create one and if a timer isn't already running.
+ void StartBackupJobTimer(const std::string& group_name,
+ ClientSocketPoolBaseHelper* pool);
- void CleanupBackupJob() {
- weak_factory_.InvalidateWeakPtrs();
- }
-
- // Set a timer to create a backup socket if it takes too long to create one.
- void StartBackupSocketTimer(const std::string& group_name,
- ClientSocketPoolBaseHelper* pool);
+ bool BackupJobTimerIsRunning() const;
// If there's a ConnectJob that's never been assigned to Request,
// decrements |unassigned_job_count_| and returns true.
@@ -422,7 +427,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
// Inserts the request into the queue based on priority
// order. Older requests are prioritized over requests of equal
// priority.
- void InsertPendingRequest(scoped_ptr<const Request> r);
+ void InsertPendingRequest(scoped_ptr<const Request> request);
// Gets and removes the next pending request. Returns NULL if
// there are no pending requests.
@@ -446,10 +451,10 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
// Returns the iterator's pending request after removing it from
// the queue.
scoped_ptr<const Request> RemovePendingRequest(
- const RequestQueue::iterator& it);
+ const RequestQueue::Pointer& pointer);
// Called when the backup socket timer fires.
- void OnBackupSocketTimerFired(
+ void OnBackupJobTimerFired(
std::string group_name,
ClientSocketPoolBaseHelper* pool);
@@ -469,8 +474,8 @@ class NET_EXPORT_PRIVATE ClientSocketPoolBaseHelper
std::set<ConnectJob*> jobs_;
RequestQueue pending_requests_;
int active_socket_count_; // number of active sockets used by clients
- // A factory to pin the backup_job tasks.
- base::WeakPtrFactory<Group> weak_factory_;
+ // A timer for when to start the backup job.
+ base::OneShotTimer<Group> backup_job_timer_;
};
typedef std::map<std::string, Group*> GroupMap;
diff --git a/chromium/net/socket/client_socket_pool_base_unittest.cc b/chromium/net/socket/client_socket_pool_base_unittest.cc
index bbeca2f3e11..46f4e40c0d4 100644
--- a/chromium/net/socket/client_socket_pool_base_unittest.cc
+++ b/chromium/net/socket/client_socket_pool_base_unittest.cc
@@ -45,7 +45,6 @@ namespace {
const int kDefaultMaxSockets = 4;
const int kDefaultMaxSocketsPerGroup = 2;
-const net::RequestPriority kDefaultPriority = MEDIUM;
// Make sure |handle| sets load times correctly when it has been assigned a
// reused socket.
@@ -100,18 +99,16 @@ void TestLoadTimingInfoNotConnected(const ClientSocketHandle& handle) {
class TestSocketParams : public base::RefCounted<TestSocketParams> {
public:
- TestSocketParams() : ignore_limits_(false) {}
+ explicit TestSocketParams(bool ignore_limits)
+ : ignore_limits_(ignore_limits) {}
- void set_ignore_limits(bool ignore_limits) {
- ignore_limits_ = ignore_limits;
- }
bool ignore_limits() { return ignore_limits_; }
private:
friend class base::RefCounted<TestSocketParams>;
~TestSocketParams() {}
- bool ignore_limits_;
+ const bool ignore_limits_;
};
typedef ClientSocketPoolBase<TestSocketParams> TestClientSocketPoolBase;
@@ -265,9 +262,10 @@ class TestConnectJob : public ConnectJob {
BoundNetLog::Make(net_log, NetLog::SOURCE_CONNECT_JOB)),
job_type_(job_type),
client_socket_factory_(client_socket_factory),
- weak_factory_(this),
load_state_(LOAD_STATE_IDLE),
- store_additional_error_state_(false) {}
+ store_additional_error_state_(false),
+ weak_factory_(this) {
+ }
void Signal() {
DoConnect(waiting_success_, true /* async */, false /* recoverable */);
@@ -400,10 +398,11 @@ class TestConnectJob : public ConnectJob {
bool waiting_success_;
const JobType job_type_;
MockClientSocketFactory* const client_socket_factory_;
- base::WeakPtrFactory<TestConnectJob> weak_factory_;
LoadState load_state_;
bool store_additional_error_state_;
+ base::WeakPtrFactory<TestConnectJob> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
};
@@ -663,7 +662,7 @@ class TestConnectJobDelegate : public ConnectJob::Delegate {
class ClientSocketPoolBaseTest : public testing::Test {
protected:
ClientSocketPoolBaseTest()
- : params_(new TestSocketParams()),
+ : params_(new TestSocketParams(false /* ignore_limits */)),
histograms_("ClientSocketPoolTest") {
connect_backup_jobs_enabled_ =
internal::ClientSocketPoolBaseHelper::connect_backup_jobs_enabled();
@@ -748,7 +747,7 @@ TEST_F(ClientSocketPoolBaseTest, ConnectJob_NoTimeoutOnSynchronousCompletion) {
TestConnectJobDelegate delegate;
ClientSocketHandle ignored;
TestClientSocketPoolBase::Request request(
- &ignored, CompletionCallback(), kDefaultPriority,
+ &ignored, CompletionCallback(), DEFAULT_PRIORITY,
internal::ClientSocketPoolBaseHelper::NORMAL,
false, params_, BoundNetLog());
scoped_ptr<TestConnectJob> job(
@@ -768,7 +767,7 @@ TEST_F(ClientSocketPoolBaseTest, ConnectJob_TimedOut) {
CapturingNetLog log;
TestClientSocketPoolBase::Request request(
- &ignored, CompletionCallback(), kDefaultPriority,
+ &ignored, CompletionCallback(), DEFAULT_PRIORITY,
internal::ClientSocketPoolBaseHelper::NORMAL,
false, params_, BoundNetLog());
// Deleted by TestConnectJobDelegate.
@@ -815,7 +814,7 @@ TEST_F(ClientSocketPoolBaseTest, BasicSynchronous) {
EXPECT_EQ(OK,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
log.bound()));
@@ -858,7 +857,7 @@ TEST_F(ClientSocketPoolBaseTest, InitConnectionFailure) {
EXPECT_EQ(ERR_CONNECTION_FAILED,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
log.bound()));
@@ -885,18 +884,18 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimit) {
// TODO(eroman): Check that the NetLog contains this event.
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("c", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("d", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("c", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("d", DEFAULT_PRIORITY));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count());
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("f", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("g", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("f", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("g", DEFAULT_PRIORITY));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
@@ -922,17 +921,17 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitReachedNewGroup) {
// TODO(eroman): Check that the NetLog contains this event.
// Reach all limits: max total sockets, and max sockets per group.
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
EXPECT_EQ(requests_size() - kDefaultMaxSockets, completion_count());
// Now create a new group and verify that we don't starve it.
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", DEFAULT_PRIORITY));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
@@ -1028,13 +1027,13 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitRespectsGroupLimit) {
TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("c", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("c", DEFAULT_PRIORITY));
// Create one asynchronous request.
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("d", DEFAULT_PRIORITY));
// We post all of our delayed tasks with a 2ms delay. I.e. they don't
// actually become pending until 2ms after they have been created. In order
@@ -1045,7 +1044,7 @@ TEST_F(ClientSocketPoolBaseTest, TotalLimitCountsConnectingSockets) {
// The next synchronous request should wait for its turn.
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("e", DEFAULT_PRIORITY));
ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
@@ -1066,17 +1065,17 @@ TEST_F(ClientSocketPoolBaseTest, CorrectlyCountStalledGroups) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSockets);
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("b", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", DEFAULT_PRIORITY));
EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
@@ -1098,7 +1097,7 @@ TEST_F(ClientSocketPoolBaseTest, StallAndThenCancelAndTriggerAvailableSocket) {
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1109,7 +1108,7 @@ TEST_F(ClientSocketPoolBaseTest, StallAndThenCancelAndTriggerAvailableSocket) {
EXPECT_EQ(ERR_IO_PENDING,
handles[i].Init("b",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1132,7 +1131,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelStalledSocketAtSocketLimit) {
for (int i = 0; i < kDefaultMaxSockets; ++i) {
EXPECT_EQ(OK, handles[i].Init(base::IntToString(i),
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callbacks[i].callback(),
pool_.get(),
BoundNetLog()));
@@ -1143,7 +1142,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelStalledSocketAtSocketLimit) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1171,7 +1170,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelPendingSocketAtSocketLimit) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handles[i].Init(base::IntToString(i),
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1183,7 +1182,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelPendingSocketAtSocketLimit) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1228,7 +1227,7 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
EXPECT_EQ(OK, handles[i].Init(base::StringPrintf(
"Take 2: %d", i),
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1241,7 +1240,7 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
// Now we will hit the socket limit.
EXPECT_EQ(ERR_IO_PENDING, stalled_handle.Init("foo",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1269,7 +1268,7 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
TestCompletionCallback callback;
EXPECT_EQ(OK, handle.Init(base::IntToString(i),
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1289,7 +1288,7 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
// close an idle socket though, since we should reuse the idle socket.
EXPECT_EQ(OK, handle.Init("0",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1301,8 +1300,8 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", IDLE));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
@@ -1333,8 +1332,8 @@ TEST_F(ClientSocketPoolBaseTest, PendingRequests) {
TEST_F(ClientSocketPoolBaseTest, PendingRequests_NoKeepAlive) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
@@ -1363,7 +1362,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelRequestClearGroup) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1379,7 +1378,7 @@ TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1390,7 +1389,7 @@ TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -1404,8 +1403,8 @@ TEST_F(ClientSocketPoolBaseTest, ConnectCancelConnect) {
TEST_F(ClientSocketPoolBaseTest, CancelRequest) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", LOWEST));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", MEDIUM));
EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", HIGHEST));
@@ -1478,10 +1477,11 @@ class RequestSocketCallback : public TestCompletionCallbackBase {
}
within_callback_ = true;
TestCompletionCallback next_job_callback;
- scoped_refptr<TestSocketParams> params(new TestSocketParams());
+ scoped_refptr<TestSocketParams> params(
+ new TestSocketParams(false /* ignore_limits */));
int rv = handle_->Init("a",
params,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
next_job_callback.callback(),
pool_,
BoundNetLog());
@@ -1530,7 +1530,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestPendingJobTwice) {
TestConnectJob::kMockPendingJob);
int rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -1548,7 +1548,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestPendingJobThenSynchronous) {
&handle, pool_.get(), connect_job_factory_, TestConnectJob::kMockJob);
int rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -1564,13 +1564,13 @@ TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestWithPendingRequests) {
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
// Now, kDefaultMaxSocketsPerGroup requests should be active.
// Let's cancel them.
@@ -1601,7 +1601,7 @@ TEST_F(ClientSocketPoolBaseTest, FailingActiveRequestWithPendingRequests) {
// Queue up all the requests
for (size_t i = 0; i < kNumberOfRequests; ++i)
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
for (size_t i = 0; i < kNumberOfRequests; ++i)
EXPECT_EQ(ERR_CONNECTION_FAILED, request(i)->WaitForResult());
@@ -1616,7 +1616,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
TestCompletionCallback callback;
int rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -1627,7 +1627,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelActiveRequestThenRequestSocket) {
rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -1647,14 +1647,14 @@ TEST_F(ClientSocketPoolBaseTest, GroupWithPendingRequestsIsNotEmpty) {
const RequestPriority kHighPriority = HIGHEST;
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
// This is going to be a pending request in an otherwise empty group.
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
// Reach the maximum socket limit.
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
// Create a stalled group with high priorities.
EXPECT_EQ(ERR_IO_PENDING, StartRequest("c", kHighPriority));
@@ -1732,7 +1732,7 @@ TEST_F(ClientSocketPoolBaseTest,
handle.set_ssl_error_response_info(info);
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
log.bound()));
@@ -1768,7 +1768,7 @@ TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -1776,7 +1776,7 @@ TEST_F(ClientSocketPoolBaseTest, TwoRequestsCancelOne) {
EXPECT_EQ(ERR_IO_PENDING,
handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -1828,7 +1828,7 @@ TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
TestSocketRequest req1(&request_order, &completion_count);
int rv = req1.handle()->Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
req1.callback(), pool_.get(),
BoundNetLog());
EXPECT_EQ(ERR_IO_PENDING, rv);
@@ -1841,7 +1841,7 @@ TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
TestSocketRequest req2(&request_order, &completion_count);
rv = req2.handle()->Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
req2.callback(),
pool_.get(),
BoundNetLog());
@@ -1849,7 +1849,7 @@ TEST_F(ClientSocketPoolBaseTest, ReleaseSockets) {
TestSocketRequest req3(&request_order, &completion_count);
rv = req3.handle()->Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
req3.callback(),
pool_.get(),
BoundNetLog());
@@ -1888,7 +1888,7 @@ TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
TestSocketRequest req1(&request_order, &completion_count);
int rv = req1.handle()->Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
req1.callback(),
pool_.get(),
BoundNetLog());
@@ -1897,7 +1897,7 @@ TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
TestSocketRequest req2(&request_order, &completion_count);
rv = req2.handle()->Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
req2.callback(),
pool_.get(),
BoundNetLog());
@@ -1909,7 +1909,7 @@ TEST_F(ClientSocketPoolBaseTest, PendingJobCompletionOrder) {
TestSocketRequest req3(&request_order, &completion_count);
rv = req3.handle()->Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
req3.callback(),
pool_.get(),
BoundNetLog());
@@ -1934,7 +1934,7 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateOneRequest) {
TestCompletionCallback callback;
int rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -1957,7 +1957,7 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequests) {
TestCompletionCallback callback;
int rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -1967,7 +1967,7 @@ TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequests) {
TestCompletionCallback callback2;
rv = handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog());
@@ -2050,7 +2050,7 @@ TEST_F(ClientSocketPoolBaseTest, LoadStatePoolLimit) {
TestCompletionCallback callback;
int rv = handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog());
@@ -2061,7 +2061,7 @@ TEST_F(ClientSocketPoolBaseTest, LoadStatePoolLimit) {
TestCompletionCallback callback2;
rv = handle2.Init("b",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog());
@@ -2073,7 +2073,7 @@ TEST_F(ClientSocketPoolBaseTest, LoadStatePoolLimit) {
TestCompletionCallback callback3;
rv = handle3.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog());
@@ -2107,7 +2107,7 @@ TEST_F(ClientSocketPoolBaseTest, Recoverable) {
ClientSocketHandle handle;
TestCompletionCallback callback;
EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED,
- handle.Init("a", params_, kDefaultPriority, callback.callback(),
+ handle.Init("a", params_, DEFAULT_PRIORITY, callback.callback(),
pool_.get(), BoundNetLog()));
EXPECT_TRUE(handle.is_initialized());
EXPECT_TRUE(handle.socket());
@@ -2123,7 +2123,7 @@ TEST_F(ClientSocketPoolBaseTest, AsyncRecoverable) {
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2143,7 +2143,7 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateSynchronous) {
EXPECT_EQ(ERR_CONNECTION_FAILED,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2163,7 +2163,7 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorStateAsynchronous) {
EXPECT_EQ(ERR_IO_PENDING,
handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2531,10 +2531,10 @@ TEST_F(ClientSocketPoolBaseTest,
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", kDefaultPriority));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequest("a", DEFAULT_PRIORITY));
EXPECT_EQ(OK, (*requests())[0]->WaitForResult());
EXPECT_EQ(OK, (*requests())[1]->WaitForResult());
@@ -2581,9 +2581,10 @@ class TestReleasingSocketRequest : public TestCompletionCallbackBase {
if (reset_releasing_handle_)
handle_.Reset();
- scoped_refptr<TestSocketParams> con_params(new TestSocketParams());
+ scoped_refptr<TestSocketParams> con_params(
+ new TestSocketParams(false /* ignore_limits */));
EXPECT_EQ(expected_result_,
- handle2_.Init("a", con_params, kDefaultPriority,
+ handle2_.Init("a", con_params, DEFAULT_PRIORITY,
callback2_.callback(), pool_, BoundNetLog()));
}
@@ -2600,9 +2601,9 @@ class TestReleasingSocketRequest : public TestCompletionCallbackBase {
TEST_F(ClientSocketPoolBaseTest, AdditionalErrorSocketsDontUseSlot) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("a", kDefaultPriority));
- EXPECT_EQ(OK, StartRequest("b", kDefaultPriority));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("a", DEFAULT_PRIORITY));
+ EXPECT_EQ(OK, StartRequest("b", DEFAULT_PRIORITY));
EXPECT_EQ(static_cast<int>(requests_size()),
client_socket_factory_.allocation_count());
@@ -2611,7 +2612,7 @@ TEST_F(ClientSocketPoolBaseTest, AdditionalErrorSocketsDontUseSlot) {
TestConnectJob::kMockPendingAdditionalErrorStateJob);
TestReleasingSocketRequest req(pool_.get(), OK, false);
EXPECT_EQ(ERR_IO_PENDING,
- req.handle()->Init("a", params_, kDefaultPriority, req.callback(),
+ req.handle()->Init("a", params_, DEFAULT_PRIORITY, req.callback(),
pool_.get(), BoundNetLog()));
// The next job should complete synchronously
connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
@@ -2639,7 +2640,7 @@ TEST_F(ClientSocketPoolBaseTest, CallbackThatReleasesPool) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2658,7 +2659,7 @@ TEST_F(ClientSocketPoolBaseTest, DoNotReuseSocketAfterFlush) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2672,7 +2673,7 @@ TEST_F(ClientSocketPoolBaseTest, DoNotReuseSocketAfterFlush) {
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2707,7 +2708,7 @@ class ConnectWithinCallback : public TestCompletionCallbackBase {
EXPECT_EQ(ERR_IO_PENDING,
handle_.Init(group_name_,
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
nested_callback_.callback(),
pool_,
BoundNetLog()));
@@ -2733,7 +2734,7 @@ TEST_F(ClientSocketPoolBaseTest, AbortAllRequestsOnFlush) {
ConnectWithinCallback callback("a", params_, pool_.get());
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2760,7 +2761,7 @@ TEST_F(ClientSocketPoolBaseTest, BackupSocketCancelAtMaxSockets) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2772,7 +2773,7 @@ TEST_F(ClientSocketPoolBaseTest, BackupSocketCancelAtMaxSockets) {
TestCompletionCallback callback;
EXPECT_EQ(OK, handles[i].Init("bar",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2802,7 +2803,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterCancelingAllRequests) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2832,7 +2833,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterFinishingAllRequests) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("bar",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2841,7 +2842,7 @@ TEST_F(ClientSocketPoolBaseTest, CancelBackupSocketAfterFinishingAllRequests) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle2.Init("bar",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -2871,7 +2872,7 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingWaitingForConnect) {
EXPECT_EQ(ERR_IO_PENDING,
handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2887,7 +2888,7 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingWaitingForConnect) {
EXPECT_EQ(ERR_IO_PENDING,
handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2929,7 +2930,7 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtGroupCapacity) {
EXPECT_EQ(ERR_IO_PENDING,
handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2945,7 +2946,7 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtGroupCapacity) {
EXPECT_EQ(ERR_IO_PENDING,
handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -2989,7 +2990,7 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtStall) {
EXPECT_EQ(ERR_IO_PENDING,
handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -3005,7 +3006,7 @@ TEST_F(ClientSocketPoolBaseTest, DelayedSocketBindingAtStall) {
EXPECT_EQ(ERR_IO_PENDING,
handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -3052,7 +3053,7 @@ TEST_F(ClientSocketPoolBaseTest, SynchronouslyProcessOnePendingRequest) {
EXPECT_EQ(ERR_IO_PENDING,
handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3068,7 +3069,7 @@ TEST_F(ClientSocketPoolBaseTest, SynchronouslyProcessOnePendingRequest) {
EXPECT_EQ(ERR_IO_PENDING,
handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3089,7 +3090,7 @@ TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3098,7 +3099,7 @@ TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3106,7 +3107,7 @@ TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) {
TestCompletionCallback callback3;
EXPECT_EQ(ERR_IO_PENDING, handle3.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback3.callback(),
pool_.get(),
BoundNetLog()));
@@ -3125,19 +3126,19 @@ TEST_F(ClientSocketPoolBaseTest, PreferUsedSocketToUnusedSocket) {
EXPECT_EQ(OK, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
EXPECT_EQ(OK, handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
EXPECT_EQ(OK, handle3.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback3.callback(),
pool_.get(),
BoundNetLog()));
@@ -3162,7 +3163,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSockets) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3171,7 +3172,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSockets) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3198,7 +3199,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsWhenAlreadyHaveAConnectJob) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3218,7 +3219,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsWhenAlreadyHaveAConnectJob) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3246,7 +3247,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3255,7 +3256,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3264,7 +3265,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback3;
EXPECT_EQ(ERR_IO_PENDING, handle3.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback3.callback(),
pool_.get(),
BoundNetLog()));
@@ -3346,7 +3347,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountIdleSockets) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3373,7 +3374,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsCountActiveSockets) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3450,7 +3451,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsMultipleTimesDoesNothing) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3460,7 +3461,7 @@ TEST_F(ClientSocketPoolBaseTest, RequestSocketsMultipleTimesDoesNothing) {
TestCompletionCallback callback2;
int rv = handle2.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog());
@@ -3529,7 +3530,7 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectJobsTakenByNormalRequests) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3564,7 +3565,7 @@ TEST_F(ClientSocketPoolBaseTest, ConnectedPreconnectJobsHaveNoConnectTimes) {
TestCompletionCallback callback;
EXPECT_EQ(OK, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -3592,7 +3593,7 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectClosesIdleSocketRemovesGroup) {
TestCompletionCallback callback1;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3606,13 +3607,13 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectClosesIdleSocketRemovesGroup) {
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle1.Init("b",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
EXPECT_EQ(ERR_IO_PENDING, handle2.Init("b",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3700,7 +3701,7 @@ TEST_F(ClientSocketPoolBaseTest, PreconnectWithBackupJob) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -3724,7 +3725,6 @@ class MockLayeredPool : public HigherLayeredPool {
MockLayeredPool(TestClientSocketPool* pool,
const std::string& group_name)
: pool_(pool),
- params_(new TestSocketParams),
group_name_(group_name),
can_release_connection_(true) {
pool_->AddHigherLayeredPool(this);
@@ -3735,13 +3735,16 @@ class MockLayeredPool : public HigherLayeredPool {
}
int RequestSocket(TestClientSocketPool* pool) {
- return handle_.Init(group_name_, params_, kDefaultPriority,
+ scoped_refptr<TestSocketParams> params(
+ new TestSocketParams(false /* ignore_limits */));
+ return handle_.Init(group_name_, params, DEFAULT_PRIORITY,
callback_.callback(), pool, BoundNetLog());
}
int RequestSocketWithoutLimits(TestClientSocketPool* pool) {
- params_->set_ignore_limits(true);
- return handle_.Init(group_name_, params_, kDefaultPriority,
+ scoped_refptr<TestSocketParams> params(
+ new TestSocketParams(true /* ignore_limits */));
+ return handle_.Init(group_name_, params, MAXIMUM_PRIORITY,
callback_.callback(), pool, BoundNetLog());
}
@@ -3762,7 +3765,6 @@ class MockLayeredPool : public HigherLayeredPool {
private:
TestClientSocketPool* const pool_;
- scoped_refptr<TestSocketParams> params_;
ClientSocketHandle handle_;
TestCompletionCallback callback_;
const std::string group_name_;
@@ -3807,7 +3809,7 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketsHeldByLayeredPoolWhenNeeded) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -3830,7 +3832,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback1;
EXPECT_EQ(OK, handle1.Init("group1",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3844,7 +3846,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback2;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("group2",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback2.callback(),
pool_.get(),
BoundNetLog()));
@@ -3867,7 +3869,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback1;
EXPECT_EQ(OK, handle1.Init("group1",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3884,7 +3886,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback3;
EXPECT_EQ(ERR_IO_PENDING, handle3.Init("group3",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback3.callback(),
pool_.get(),
BoundNetLog()));
@@ -3900,7 +3902,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback4;
EXPECT_EQ(ERR_IO_PENDING, handle4.Init("group3",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback4.callback(),
pool_.get(),
BoundNetLog()));
@@ -3932,7 +3934,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback1;
EXPECT_EQ(OK, handle1.Init("group1",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback1.callback(),
pool_.get(),
BoundNetLog()));
@@ -3995,7 +3997,7 @@ TEST_F(ClientSocketPoolBaseTest,
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING, handle.Init("a",
params_,
- kDefaultPriority,
+ DEFAULT_PRIORITY,
callback.callback(),
pool_.get(),
BoundNetLog()));
@@ -4007,21 +4009,21 @@ TEST_F(ClientSocketPoolBaseTest,
// instead of a request with the same priority that was issued earlier, but
// that does not have |ignore_limits| set.
TEST_F(ClientSocketPoolBaseTest, IgnoreLimits) {
- scoped_refptr<TestSocketParams> params_ignore_limits(new TestSocketParams());
- params_ignore_limits->set_ignore_limits(true);
+ 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", kDefaultPriority, params_));
+ EXPECT_EQ(OK, StartRequestWithParams("a", MAXIMUM_PRIORITY, params_));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", kDefaultPriority,
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
params_));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", kDefaultPriority,
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
params_ignore_limits));
ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -4029,76 +4031,25 @@ TEST_F(ClientSocketPoolBaseTest, IgnoreLimits) {
EXPECT_FALSE(request(1)->have_result());
}
-// Test that when a socket pool and group are at their limits, a request with
-// |ignore_limits| set triggers creation of a new socket, and gets the socket
-// instead of a request with a higher priority that was issued earlier, but
-// that does not have |ignore_limits| set.
-TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsLowPriority) {
- scoped_refptr<TestSocketParams> params_ignore_limits(new TestSocketParams());
- params_ignore_limits->set_ignore_limits(true);
- CreatePool(1, 1);
-
- // Issue a request to reach the socket pool limit.
- EXPECT_EQ(OK, StartRequestWithParams("a", HIGHEST, params_));
- EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
-
- connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
-
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", HIGHEST, params_));
- EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
-
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", LOW,
- params_ignore_limits));
- ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
-
- EXPECT_EQ(OK, request(2)->WaitForResult());
- EXPECT_FALSE(request(1)->have_result());
-}
-
-// Test that when a socket pool and group are at their limits, a request with
-// |ignore_limits| set triggers creation of a new socket, and gets the socket
-// instead of a request with a higher priority that was issued later and
-// does not have |ignore_limits| set.
-TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsLowPriority2) {
- scoped_refptr<TestSocketParams> params_ignore_limits(new TestSocketParams());
- params_ignore_limits->set_ignore_limits(true);
- CreatePool(1, 1);
-
- // Issue a request to reach the socket pool limit.
- EXPECT_EQ(OK, StartRequestWithParams("a", HIGHEST, params_));
- EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
-
- connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
-
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", LOW,
- params_ignore_limits));
- ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
-
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", HIGHEST, params_));
- EXPECT_EQ(1, pool_->NumConnectJobsInGroup("a"));
-
- EXPECT_EQ(OK, request(1)->WaitForResult());
- EXPECT_FALSE(request(2)->have_result());
-}
-
// 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.
TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsCancelOtherJob) {
- scoped_refptr<TestSocketParams> params_ignore_limits(new TestSocketParams());
- params_ignore_limits->set_ignore_limits(true);
+ 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", HIGHEST, params_));
+ EXPECT_EQ(OK, StartRequestWithParams("a", MAXIMUM_PRIORITY, params_));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", HIGHEST, params_));
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
+ params_));
EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", HIGHEST,
+ EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", MAXIMUM_PRIORITY,
params_ignore_limits));
ASSERT_EQ(1, pool_->NumConnectJobsInGroup("a"));
@@ -4111,58 +4062,6 @@ TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsCancelOtherJob) {
EXPECT_FALSE(request(1)->have_result());
}
-// More involved test of ignore limits. Issues a bunch of requests and later
-// checks the order in which they receive sockets.
-TEST_F(ClientSocketPoolBaseTest, IgnoreLimitsOrder) {
- scoped_refptr<TestSocketParams> params_ignore_limits(new TestSocketParams());
- params_ignore_limits->set_ignore_limits(true);
- CreatePool(1, 1);
-
- connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
-
- // Requests 0 and 1 do not have ignore_limits set, so they finish last. Since
- // the maximum number of sockets per pool is 1, the second requests does not
- // trigger a ConnectJob.
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", HIGHEST, params_));
- EXPECT_EQ(ERR_IO_PENDING, StartRequestWithParams("a", HIGHEST, params_));
-
- // Requests 2 and 3 have ignore_limits set, but have a low priority, so they
- // finish just before the first two.
- EXPECT_EQ(ERR_IO_PENDING,
- StartRequestWithParams("a", LOW, params_ignore_limits));
- EXPECT_EQ(ERR_IO_PENDING,
- StartRequestWithParams("a", LOW, params_ignore_limits));
-
- // Request 4 finishes first, since it is high priority and ignores limits.
- EXPECT_EQ(ERR_IO_PENDING,
- StartRequestWithParams("a", HIGHEST, params_ignore_limits));
-
- // Request 5 and 6 are cancelled right after starting. This should result in
- // creating two ConnectJobs. Since only one request (Request 1) did not
- // result in creating a ConnectJob, only one of the ConnectJobs should be
- // cancelled when the requests are.
- EXPECT_EQ(ERR_IO_PENDING,
- StartRequestWithParams("a", HIGHEST, params_ignore_limits));
- EXPECT_EQ(ERR_IO_PENDING,
- StartRequestWithParams("a", HIGHEST, params_ignore_limits));
- EXPECT_EQ(6, pool_->NumConnectJobsInGroup("a"));
- request(5)->handle()->Reset();
- EXPECT_EQ(6, pool_->NumConnectJobsInGroup("a"));
- request(6)->handle()->Reset();
- ASSERT_EQ(5, pool_->NumConnectJobsInGroup("a"));
-
- // Wait for the last request to get a socket.
- EXPECT_EQ(OK, request(1)->WaitForResult());
-
- // Check order in which requests received sockets.
- // These are 1-based indices, while request(x) uses 0-based indices.
- EXPECT_EQ(1, GetOrderOfRequest(5));
- EXPECT_EQ(2, GetOrderOfRequest(3));
- EXPECT_EQ(3, GetOrderOfRequest(4));
- EXPECT_EQ(4, GetOrderOfRequest(1));
- EXPECT_EQ(5, GetOrderOfRequest(2));
-}
-
} // namespace
} // namespace net
diff --git a/chromium/net/socket/client_socket_pool_manager.cc b/chromium/net/socket/client_socket_pool_manager.cc
index b37d2d1949c..24d6b70ced5 100644
--- a/chromium/net/socket/client_socket_pool_manager.cc
+++ b/chromium/net/socket/client_socket_pool_manager.cc
@@ -437,6 +437,31 @@ int InitSocketHandleForRawConnect(
callback);
}
+int InitSocketHandleForTlsConnect(
+ const HostPortPair& host_port_pair,
+ HttpNetworkSession* session,
+ const ProxyInfo& proxy_info,
+ const SSLConfig& ssl_config_for_origin,
+ const SSLConfig& ssl_config_for_proxy,
+ PrivacyMode privacy_mode,
+ const BoundNetLog& net_log,
+ ClientSocketHandle* socket_handle,
+ const CompletionCallback& callback) {
+ DCHECK(socket_handle);
+ // Synthesize an HttpRequestInfo.
+ GURL request_url = GURL("https://" + host_port_pair.ToString());
+ HttpRequestHeaders request_extra_headers;
+ int request_load_flags = 0;
+ RequestPriority request_priority = MEDIUM;
+
+ return InitSocketPoolHelper(
+ request_url, request_extra_headers, request_load_flags, request_priority,
+ session, proxy_info, false, false, ssl_config_for_origin,
+ ssl_config_for_proxy, true, privacy_mode, net_log, 0, socket_handle,
+ HttpNetworkSession::NORMAL_SOCKET_POOL, OnHostResolutionCallback(),
+ callback);
+}
+
int PreconnectSocketsForHttpRequest(
const GURL& request_url,
const HttpRequestHeaders& request_extra_headers,
diff --git a/chromium/net/socket/client_socket_pool_manager.h b/chromium/net/socket/client_socket_pool_manager.h
index 1b78324f233..12154809870 100644
--- a/chromium/net/socket/client_socket_pool_manager.h
+++ b/chromium/net/socket/client_socket_pool_manager.h
@@ -147,6 +147,21 @@ NET_EXPORT int InitSocketHandleForRawConnect(
ClientSocketHandle* socket_handle,
const CompletionCallback& callback);
+// A helper method that uses the passed in proxy information to initialize a
+// ClientSocketHandle with the relevant socket pool. Use this method for
+// a raw socket connection with TLS negotiation to a host-port pair (that needs
+// to tunnel through the proxies).
+NET_EXPORT int InitSocketHandleForTlsConnect(
+ const HostPortPair& host_port_pair,
+ HttpNetworkSession* session,
+ const ProxyInfo& proxy_info,
+ const SSLConfig& ssl_config_for_origin,
+ const SSLConfig& ssl_config_for_proxy,
+ PrivacyMode privacy_mode,
+ const BoundNetLog& net_log,
+ ClientSocketHandle* socket_handle,
+ const CompletionCallback& callback);
+
// Similar to InitSocketHandleForHttpRequest except that it initiates the
// desired number of preconnect streams from the relevant socket pool.
int PreconnectSocketsForHttpRequest(
diff --git a/chromium/net/socket/client_socket_pool_manager_impl.cc b/chromium/net/socket/client_socket_pool_manager_impl.cc
index b557874d011..991278d7341 100644
--- a/chromium/net/socket/client_socket_pool_manager_impl.cc
+++ b/chromium/net/socket/client_socket_pool_manager_impl.cc
@@ -40,6 +40,7 @@ ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
CertVerifier* cert_verifier,
ServerBoundCertService* server_bound_cert_service,
TransportSecurityState* transport_security_state,
+ CTVerifier* cert_transparency_verifier,
const std::string& ssl_session_cache_shard,
ProxyService* proxy_service,
SSLConfigService* ssl_config_service,
@@ -50,6 +51,7 @@ ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
cert_verifier_(cert_verifier),
server_bound_cert_service_(server_bound_cert_service),
transport_security_state_(transport_security_state),
+ cert_transparency_verifier_(cert_transparency_verifier),
ssl_session_cache_shard_(ssl_session_cache_shard),
proxy_service_(proxy_service),
ssl_config_service_(ssl_config_service),
@@ -69,6 +71,7 @@ ClientSocketPoolManagerImpl::ClientSocketPoolManagerImpl(
cert_verifier,
server_bound_cert_service,
transport_security_state,
+ cert_transparency_verifier,
ssl_session_cache_shard,
socket_factory,
transport_socket_pool_.get(),
@@ -286,6 +289,7 @@ ClientSocketPoolManagerImpl::GetSocketPoolForHTTPProxy(
cert_verifier_,
server_bound_cert_service_,
transport_security_state_,
+ cert_transparency_verifier_,
ssl_session_cache_shard_,
socket_factory_,
tcp_https_ret.first->second /* https proxy */,
@@ -326,6 +330,7 @@ SSLClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPoolForSSLWithProxy(
cert_verifier_,
server_bound_cert_service_,
transport_security_state_,
+ cert_transparency_verifier_,
ssl_session_cache_shard_,
socket_factory_,
NULL, /* no tcp pool, we always go through a proxy */
@@ -374,7 +379,7 @@ void ClientSocketPoolManagerImpl::OnCertAdded(const X509Certificate* cert) {
FlushSocketPoolsWithError(ERR_NETWORK_CHANGED);
}
-void ClientSocketPoolManagerImpl::OnCertTrustChanged(
+void ClientSocketPoolManagerImpl::OnCACertChanged(
const X509Certificate* cert) {
// We should flush the socket pools if we removed trust from a
// cert, because a previously trusted server may have become
@@ -383,8 +388,8 @@ void ClientSocketPoolManagerImpl::OnCertTrustChanged(
// We should not flush the socket pools if we added trust to a
// cert.
//
- // Since the OnCertTrustChanged method doesn't tell us what
- // kind of trust change it is, we have to flush the socket
+ // Since the OnCACertChanged method doesn't tell us what
+ // kind of change it is, we have to flush the socket
// pools to be safe.
FlushSocketPoolsWithError(ERR_NETWORK_CHANGED);
}
diff --git a/chromium/net/socket/client_socket_pool_manager_impl.h b/chromium/net/socket/client_socket_pool_manager_impl.h
index 8f6e618d2e1..06d4d244a36 100644
--- a/chromium/net/socket/client_socket_pool_manager_impl.h
+++ b/chromium/net/socket/client_socket_pool_manager_impl.h
@@ -23,6 +23,7 @@ namespace net {
class CertVerifier;
class ClientSocketFactory;
class ClientSocketPoolHistograms;
+class CTVerifier;
class HttpProxyClientSocketPool;
class HostResolver;
class NetLog;
@@ -62,6 +63,7 @@ class ClientSocketPoolManagerImpl : public base::NonThreadSafe,
CertVerifier* cert_verifier,
ServerBoundCertService* server_bound_cert_service,
TransportSecurityState* transport_security_state,
+ CTVerifier* cert_transparency_verifier,
const std::string& ssl_session_cache_shard,
ProxyService* proxy_service,
SSLConfigService* ssl_config_service,
@@ -90,7 +92,7 @@ class ClientSocketPoolManagerImpl : public base::NonThreadSafe,
// CertDatabase::Observer methods:
virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE;
- virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;
private:
typedef internal::OwnedPoolMap<HostPortPair, TransportClientSocketPool*>
@@ -108,6 +110,7 @@ class ClientSocketPoolManagerImpl : public base::NonThreadSafe,
CertVerifier* const cert_verifier_;
ServerBoundCertService* const server_bound_cert_service_;
TransportSecurityState* const transport_security_state_;
+ CTVerifier* const cert_transparency_verifier_;
const std::string ssl_session_cache_shard_;
ProxyService* const proxy_service_;
const scoped_refptr<SSLConfigService> ssl_config_service_;
diff --git a/chromium/net/socket/next_proto.h b/chromium/net/socket/next_proto.h
index 0bd307a3778..a2e5ab6902d 100644
--- a/chromium/net/socket/next_proto.h
+++ b/chromium/net/socket/next_proto.h
@@ -13,23 +13,19 @@ namespace net {
// protocols that we recognise.
enum NextProto {
kProtoUnknown = 0,
- kProtoHTTP11 = 1,
+ kProtoHTTP11,
kProtoMinimumVersion = kProtoHTTP11,
- // TODO(akalin): Stop advertising SPDY/1 and remove this.
- kProtoSPDY1 = 2,
- kProtoSPDYMinimumVersion = kProtoSPDY1,
- kProtoSPDY2 = 3,
- // TODO(akalin): Stop adverising SPDY/2.1, too.
- kProtoSPDY21 = 4,
- kProtoSPDY3 = 5,
- kProtoSPDY31 = 6,
- kProtoSPDY4a2 = 7,
+ kProtoDeprecatedSPDY2,
+ kProtoSPDYMinimumVersion = kProtoDeprecatedSPDY2,
+ kProtoSPDY3,
+ kProtoSPDY31,
+ kProtoSPDY4a2,
// We lump in HTTP/2 with the SPDY protocols for now.
- kProtoHTTP2Draft04 = 8,
+ kProtoHTTP2Draft04,
kProtoSPDYMaximumVersion = kProtoHTTP2Draft04,
- kProtoQUIC1SPDY3 = 9,
+ kProtoQUIC1SPDY3,
kProtoMaximumVersion = kProtoQUIC1SPDY3,
};
diff --git a/chromium/net/socket/nss_ssl_util.cc b/chromium/net/socket/nss_ssl_util.cc
index 7e3aee430c4..33e7e6b89ac 100644
--- a/chromium/net/socket/nss_ssl_util.cc
+++ b/chromium/net/socket/nss_ssl_util.cc
@@ -13,6 +13,7 @@
#include <string>
#include "base/bind.h"
+#include "base/cpu.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
@@ -22,16 +23,67 @@
#include "crypto/nss_util.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
+#include "net/base/nss_memio.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
#endif
+namespace {
+
+// CiphersRemove takes a zero-terminated array of cipher suite ids in
+// |to_remove| and sets every instance of them in |ciphers| to zero. It returns
+// true if it found and removed every element of |to_remove|. It assumes that
+// there are no duplicates in |ciphers| nor in |to_remove|.
+bool CiphersRemove(const uint16* to_remove, uint16* ciphers, size_t num) {
+ size_t i, found = 0;
+
+ for (i = 0; ; i++) {
+ if (to_remove[i] == 0)
+ break;
+
+ for (size_t j = 0; j < num; j++) {
+ if (to_remove[i] == ciphers[j]) {
+ ciphers[j] = 0;
+ found++;
+ break;
+ }
+ }
+ }
+
+ return found == i;
+}
+
+// CiphersCompact takes an array of cipher suite ids in |ciphers|, where some
+// entries are zero, and moves the entries so that all the non-zero elements
+// are compacted at the end of the array.
+void CiphersCompact(uint16* ciphers, size_t num) {
+ size_t j = num - 1;
+
+ for (size_t i = num - 1; i < num; i--) {
+ if (ciphers[i] == 0)
+ continue;
+ ciphers[j--] = ciphers[i];
+ }
+}
+
+// CiphersCopy copies the zero-terminated array |in| to |out|. It returns the
+// number of cipher suite ids copied.
+size_t CiphersCopy(const uint16* in, uint16* out) {
+ for (size_t i = 0; ; i++) {
+ if (in[i] == 0)
+ return i;
+ out[i] = in[i];
+ }
+}
+
+} // anonymous namespace
+
namespace net {
class NSSSSLInitSingleton {
public:
- NSSSSLInitSingleton() {
+ NSSSSLInitSingleton() : model_fd_(NULL) {
crypto::EnsureNSSInit();
NSS_SetDomesticPolicy();
@@ -81,14 +133,72 @@ class NSSSSLInitSingleton {
// Enable SSL.
SSL_OptionSetDefault(SSL_SECURITY, PR_TRUE);
+ // Calculate the order of ciphers that we'll use for NSS sockets. (Note
+ // that, even if a cipher is specified in the ordering, it must still be
+ // enabled in order to be included in a ClientHello.)
+ //
+ // Our top preference cipher suites are either forward-secret AES-GCM or
+ // forward-secret ChaCha20-Poly1305. If the local machine has AES-NI then
+ // we prefer AES-GCM, otherwise ChaCha20. The remainder of the cipher suite
+ // preference is inheriented from NSS. */
+ static const uint16 chacha_ciphers[] = {
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
+ 0,
+ };
+ static const uint16 aes_gcm_ciphers[] = {
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
+ 0,
+ };
+ scoped_ptr<uint16[]> ciphers(new uint16[num_ciphers]);
+ memcpy(ciphers.get(), ssl_ciphers, sizeof(uint16)*num_ciphers);
+
+ if (CiphersRemove(chacha_ciphers, ciphers.get(), num_ciphers) &&
+ CiphersRemove(aes_gcm_ciphers, ciphers.get(), num_ciphers)) {
+ CiphersCompact(ciphers.get(), num_ciphers);
+
+ const uint16* preference_ciphers = chacha_ciphers;
+ const uint16* other_ciphers = aes_gcm_ciphers;
+ base::CPU cpu;
+
+ if (cpu.has_aesni() && cpu.has_avx()) {
+ preference_ciphers = aes_gcm_ciphers;
+ other_ciphers = chacha_ciphers;
+ }
+ unsigned i = CiphersCopy(preference_ciphers, ciphers.get());
+ CiphersCopy(other_ciphers, &ciphers[i]);
+
+ if ((model_fd_ = memio_CreateIOLayer(1, 1)) == NULL ||
+ SSL_ImportFD(NULL, model_fd_) == NULL ||
+ SECSuccess !=
+ SSL_CipherOrderSet(model_fd_, ciphers.get(), num_ciphers)) {
+ NOTREACHED();
+ if (model_fd_) {
+ PR_Close(model_fd_);
+ model_fd_ = NULL;
+ }
+ }
+ }
+
// All other SSL options are set per-session by SSLClientSocket and
// SSLServerSocket.
}
+ PRFileDesc* GetModelSocket() {
+ return model_fd_;
+ }
+
~NSSSSLInitSingleton() {
// Have to clear the cache, or NSS_Shutdown fails with SEC_ERROR_BUSY.
SSL_ClearSessionCache();
+ if (model_fd_)
+ PR_Close(model_fd_);
}
+
+ private:
+ PRFileDesc* model_fd_;
};
static base::LazyInstance<NSSSSLInitSingleton> g_nss_ssl_init_singleton =
@@ -107,6 +217,10 @@ void EnsureNSSSSLInit() {
g_nss_ssl_init_singleton.Get();
}
+PRFileDesc* GetNSSModelSocket() {
+ return g_nss_ssl_init_singleton.Get().GetModelSocket();
+}
+
// Map a Chromium net error code to an NSS error code.
// See _MD_unix_map_default_error in the NSS source
// tree for inspiration.
@@ -237,6 +351,8 @@ int MapNSSError(PRErrorCode err) {
// was used earlier.
case SSL_ERROR_WRONG_CERTIFICATE:
return ERR_SSL_SERVER_CERT_CHANGED;
+ case SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT:
+ return ERR_SSL_INAPPROPRIATE_FALLBACK;
default: {
if (IS_SSL_ERROR(err)) {
diff --git a/chromium/net/socket/nss_ssl_util.h b/chromium/net/socket/nss_ssl_util.h
index 09ae3562cd7..3aed7bf6b4a 100644
--- a/chromium/net/socket/nss_ssl_util.h
+++ b/chromium/net/socket/nss_ssl_util.h
@@ -9,6 +9,7 @@
#define NET_SOCKET_NSS_SSL_UTIL_H_
#include <prerror.h>
+#include <prio.h>
#include "net/base/net_export.h"
@@ -27,6 +28,10 @@ void LogFailedNSSFunction(const BoundNetLog& net_log,
// Map network error code to NSS error code.
PRErrorCode MapErrorToNSS(int result);
+// GetNSSModelSocket returns either NULL, or an NSS socket that can be passed
+// to |SSL_ImportFD| in order to inherit some default options.
+PRFileDesc* GetNSSModelSocket();
+
// Map NSS error code to network error code.
int MapNSSError(PRErrorCode err);
diff --git a/chromium/net/socket/socket_descriptor.cc b/chromium/net/socket/socket_descriptor.cc
index 5a2e53cab4d..81787a29d25 100644
--- a/chromium/net/socket/socket_descriptor.cc
+++ b/chromium/net/socket/socket_descriptor.cc
@@ -12,6 +12,8 @@
#include "base/basictypes.h"
#if defined(OS_WIN)
+#include <ws2tcpip.h>
+#include "base/win/windows_version.h"
#include "net/base/winsock_init.h"
#endif
@@ -32,7 +34,18 @@ void PlatformSocketFactory::SetInstance(PlatformSocketFactory* factory) {
SocketDescriptor CreateSocketDefault(int family, int type, int protocol) {
#if defined(OS_WIN)
EnsureWinsockInit();
- return ::WSASocket(family, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
+ SocketDescriptor result = ::WSASocket(family, type, protocol, NULL, 0,
+ WSA_FLAG_OVERLAPPED);
+ if (result != kInvalidSocket && family == AF_INET6 &&
+ base::win::OSInfo::GetInstance()->version() >= base::win::VERSION_VISTA) {
+ DWORD value = 0;
+ if (setsockopt(result, IPPROTO_IPV6, IPV6_V6ONLY,
+ reinterpret_cast<const char*>(&value), sizeof(value))) {
+ closesocket(result);
+ return kInvalidSocket;
+ }
+ }
+ return result;
#else // OS_WIN
return ::socket(family, type, protocol);
#endif // OS_WIN
diff --git a/chromium/net/socket/socket_test_util.cc b/chromium/net/socket/socket_test_util.cc
index 78e9e7ce9c4..148b11c5698 100644
--- a/chromium/net/socket/socket_test_util.cc
+++ b/chromium/net/socket/socket_test_util.cc
@@ -698,9 +698,9 @@ void MockClientSocketFactory::ClearSSLSessionCache() {
const char MockClientSocket::kTlsUnique[] = "MOCK_TLSUNIQ";
MockClientSocket::MockClientSocket(const BoundNetLog& net_log)
- : weak_factory_(this),
- connected_(false),
- net_log_(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);
@@ -957,7 +957,7 @@ int MockTCPClientSocket::CompleteRead() {
was_used_to_convey_data_ = true;
// Save the pending async IO data and reset our |pending_| state.
- IOBuffer* buf = pending_buf_;
+ scoped_refptr<IOBuffer> buf = pending_buf_;
int buf_len = pending_buf_len_;
CompletionCallback callback = pending_callback_;
pending_buf_ = NULL;
@@ -1556,7 +1556,7 @@ int MockUDPClientSocket::CompleteRead() {
DCHECK(pending_buf_len_ > 0);
// Save the pending async IO data and reset our |pending_| state.
- IOBuffer* buf = pending_buf_;
+ scoped_refptr<IOBuffer> buf = pending_buf_;
int buf_len = pending_buf_len_;
CompletionCallback callback = pending_callback_;
pending_buf_ = NULL;
diff --git a/chromium/net/socket/socket_test_util.h b/chromium/net/socket/socket_test_util.h
index e4e56522c92..8df1d69538a 100644
--- a/chromium/net/socket/socket_test_util.h
+++ b/chromium/net/socket/socket_test_util.h
@@ -97,43 +97,76 @@ struct MockReadWrite {
};
// Default
- MockReadWrite() : mode(SYNCHRONOUS), result(0), data(NULL), data_len(0),
- sequence_number(0), time_stamp(base::Time::Now()) {}
+ MockReadWrite()
+ : mode(SYNCHRONOUS),
+ result(0),
+ data(NULL),
+ data_len(0),
+ sequence_number(0),
+ time_stamp(base::Time::Now()) {}
// Read/write failure (no data).
- MockReadWrite(IoMode io_mode, int result) : mode(io_mode), result(result),
- data(NULL), data_len(0), sequence_number(0),
- time_stamp(base::Time::Now()) { }
+ MockReadWrite(IoMode io_mode, int result)
+ : mode(io_mode),
+ result(result),
+ data(NULL),
+ data_len(0),
+ sequence_number(0),
+ time_stamp(base::Time::Now()) {}
// Read/write failure (no data), with sequence information.
- MockReadWrite(IoMode io_mode, int result, int seq) : mode(io_mode),
- result(result), data(NULL), data_len(0), sequence_number(seq),
- time_stamp(base::Time::Now()) { }
+ MockReadWrite(IoMode io_mode, int result, int seq)
+ : mode(io_mode),
+ result(result),
+ data(NULL),
+ data_len(0),
+ sequence_number(seq),
+ time_stamp(base::Time::Now()) {}
// Asynchronous read/write success (inferred data length).
- explicit MockReadWrite(const char* data) : mode(ASYNC), result(0),
- data(data), data_len(strlen(data)), sequence_number(0),
- time_stamp(base::Time::Now()) { }
+ explicit MockReadWrite(const char* data)
+ : mode(ASYNC),
+ result(0),
+ data(data),
+ data_len(strlen(data)),
+ sequence_number(0),
+ time_stamp(base::Time::Now()) {}
// Read/write success (inferred data length).
- MockReadWrite(IoMode io_mode, const char* data) : mode(io_mode), result(0),
- data(data), data_len(strlen(data)), sequence_number(0),
- time_stamp(base::Time::Now()) { }
+ MockReadWrite(IoMode io_mode, const char* data)
+ : mode(io_mode),
+ result(0),
+ data(data),
+ data_len(strlen(data)),
+ sequence_number(0),
+ time_stamp(base::Time::Now()) {}
// Read/write success.
- MockReadWrite(IoMode io_mode, const char* data, int data_len) : mode(io_mode),
- result(0), data(data), data_len(data_len), sequence_number(0),
- time_stamp(base::Time::Now()) { }
+ MockReadWrite(IoMode io_mode, const char* data, int data_len)
+ : mode(io_mode),
+ result(0),
+ data(data),
+ data_len(data_len),
+ sequence_number(0),
+ time_stamp(base::Time::Now()) {}
// Read/write success (inferred data length) with sequence information.
- MockReadWrite(IoMode io_mode, int seq, const char* data) : mode(io_mode),
- result(0), data(data), data_len(strlen(data)), sequence_number(seq),
- time_stamp(base::Time::Now()) { }
+ MockReadWrite(IoMode io_mode, int seq, const char* data)
+ : mode(io_mode),
+ result(0),
+ data(data),
+ data_len(strlen(data)),
+ sequence_number(seq),
+ time_stamp(base::Time::Now()) {}
// Read/write success with sequence information.
- MockReadWrite(IoMode io_mode, const char* data, int data_len, int seq) :
- mode(io_mode), result(0), data(data), data_len(data_len),
- sequence_number(seq), time_stamp(base::Time::Now()) { }
+ MockReadWrite(IoMode io_mode, const char* data, int data_len, int seq)
+ : mode(io_mode),
+ result(0),
+ data(data),
+ data_len(data_len),
+ sequence_number(seq),
+ time_stamp(base::Time::Now()) {}
IoMode mode;
int result;
@@ -143,18 +176,16 @@ struct MockReadWrite {
// For OrderedSocketData, which only allows reads to occur in a particular
// sequence. If a read occurs before the given |sequence_number| is reached,
// an ERR_IO_PENDING is returned.
- int sequence_number; // The sequence number at which a read is allowed
- // to occur.
- base::Time time_stamp; // The time stamp at which the operation occurred.
+ int sequence_number; // The sequence number at which a read is allowed
+ // to occur.
+ base::Time time_stamp; // The time stamp at which the operation occurred.
};
typedef MockReadWrite<MOCK_READ> MockRead;
typedef MockReadWrite<MOCK_WRITE> MockWrite;
struct MockWriteResult {
- MockWriteResult(IoMode io_mode, int result)
- : mode(io_mode),
- result(result) {}
+ MockWriteResult(IoMode io_mode, int result) : mode(io_mode), result(result) {}
IoMode mode;
int result;
@@ -208,8 +239,10 @@ class AsyncSocket {
class StaticSocketDataProvider : public SocketDataProvider {
public:
StaticSocketDataProvider();
- StaticSocketDataProvider(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ StaticSocketDataProvider(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
virtual ~StaticSocketDataProvider();
// These functions get access to the next available read and write data.
@@ -231,7 +264,7 @@ class StaticSocketDataProvider : public SocketDataProvider {
// SocketDataProvider implementation.
virtual MockRead GetNextRead() OVERRIDE;
virtual MockWriteResult OnWrite(const std::string& data) OVERRIDE;
- ; virtual void Reset() OVERRIDE;
+ virtual void Reset() OVERRIDE;
private:
MockRead* reads_;
@@ -267,9 +300,7 @@ class DynamicSocketDataProvider : public SocketDataProvider {
// The next time there is a read from this socket, it will return |data|.
// Before calling SimulateRead next time, the previous data must be consumed.
void SimulateRead(const char* data, size_t length);
- void SimulateRead(const char* data) {
- SimulateRead(data, std::strlen(data));
- }
+ void SimulateRead(const char* data) { SimulateRead(data, std::strlen(data)); }
private:
std::deque<MockRead> reads_;
@@ -316,8 +347,10 @@ class DelayedSocketData : public StaticSocketDataProvider {
// Note: For stream sockets, the MockRead list must end with a EOF, e.g., a
// MockRead(true, 0, 0);
DelayedSocketData(int write_delay,
- MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
// |connect| the result for the connect phase.
// |reads| the list of MockRead completions.
@@ -326,9 +359,12 @@ class DelayedSocketData : public StaticSocketDataProvider {
// |writes| the list of MockWrite completions.
// Note: For stream sockets, the MockRead list must end with a EOF, e.g., a
// MockRead(true, 0, 0);
- DelayedSocketData(const MockConnect& connect, int write_delay,
- MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ DelayedSocketData(const MockConnect& connect,
+ int write_delay,
+ MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
virtual ~DelayedSocketData();
void ForceNextRead();
@@ -342,7 +378,10 @@ class DelayedSocketData : public StaticSocketDataProvider {
private:
int write_delay_;
bool read_in_progress_;
+
base::WeakPtrFactory<DelayedSocketData> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelayedSocketData);
};
// A DataProvider where the reads are ordered.
@@ -363,8 +402,10 @@ class OrderedSocketData : public StaticSocketDataProvider {
// Note: All MockReads and MockWrites must be async.
// Note: For stream sockets, the MockRead list must end with a EOF, e.g., a
// MockRead(true, 0, 0);
- OrderedSocketData(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ OrderedSocketData(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
virtual ~OrderedSocketData();
// |connect| the result for the connect phase.
@@ -374,8 +415,10 @@ class OrderedSocketData : public StaticSocketDataProvider {
// Note: For stream sockets, the MockRead list must end with a EOF, e.g., a
// MockRead(true, 0, 0);
OrderedSocketData(const MockConnect& connect,
- MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
// Posts a quit message to the current message loop, if one is running.
void EndLoop();
@@ -390,7 +433,10 @@ class OrderedSocketData : public StaticSocketDataProvider {
int sequence_number_;
int loop_stop_stage_;
bool blocked_;
+
base::WeakPtrFactory<OrderedSocketData> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OrderedSocketData);
};
class DeterministicMockTCPClientSocket;
@@ -452,8 +498,7 @@ class DeterministicMockTCPClientSocket;
//
// For examples of how to use this class, see:
// deterministic_socket_data_unittests.cc
-class DeterministicSocketData
- : public StaticSocketDataProvider {
+class DeterministicSocketData : public StaticSocketDataProvider {
public:
// The Delegate is an abstract interface which handles the communication from
// the DeterministicSocketData to the Deterministic MockSocket. The
@@ -481,8 +526,10 @@ class DeterministicSocketData
// |reads| the list of MockRead completions.
// |writes| the list of MockWrite completions.
- DeterministicSocketData(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ DeterministicSocketData(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
virtual ~DeterministicSocketData();
// Consume all the data up to the give stop point (via SetStop()).
@@ -501,9 +548,7 @@ class DeterministicSocketData
MockRead& current_read() { return current_read_; }
MockWrite& current_write() { return current_write_; }
int sequence_number() const { return sequence_number_; }
- void set_delegate(base::WeakPtr<Delegate> delegate) {
- delegate_ = delegate;
- }
+ void set_delegate(base::WeakPtr<Delegate> delegate) { delegate_ = delegate; }
// StaticSocketDataProvider:
@@ -524,8 +569,10 @@ class DeterministicSocketData
void NextStep();
- void VerifyCorrectSequenceNumbers(MockRead* reads, size_t reads_count,
- MockWrite* writes, size_t writes_count);
+ void VerifyCorrectSequenceNumbers(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count);
int sequence_number_;
MockRead current_read_;
@@ -540,7 +587,7 @@ class DeterministicSocketData
// Holds an array of SocketDataProvider elements. As Mock{TCP,SSL}StreamSocket
// objects get instantiated, they take their data from the i'th element of this
// array.
-template<typename T>
+template <typename T>
class SocketDataProviderArray {
public:
SocketDataProviderArray() : next_index_(0) {}
@@ -557,9 +604,7 @@ class SocketDataProviderArray {
size_t next_index() { return next_index_; }
- void ResetNextIndex() {
- next_index_ = 0;
- }
+ void ResetNextIndex() { next_index_ = 0; }
private:
// Index of the next |data_providers_| element to use. Not an iterator
@@ -624,9 +669,11 @@ class MockClientSocket : public SSLClientSocket {
explicit MockClientSocket(const BoundNetLog& net_log);
// Socket implementation.
- virtual int Read(IOBuffer* buf, int buf_len,
+ virtual int Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) = 0;
- virtual int Write(IOBuffer* buf, int buf_len,
+ virtual int Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) = 0;
virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
virtual bool SetSendBufferSize(int32 size) OVERRIDE;
@@ -643,8 +690,8 @@ class MockClientSocket : public SSLClientSocket {
virtual void SetOmniboxSpeculation() OVERRIDE {}
// SSLClientSocket implementation.
- virtual void GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) OVERRIDE;
+ virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info)
+ OVERRIDE;
virtual int ExportKeyingMaterial(const base::StringPiece& label,
bool has_context,
const base::StringPiece& context,
@@ -660,8 +707,6 @@ class MockClientSocket : public SSLClientSocket {
void RunCallbackAsync(const CompletionCallback& callback, int result);
void RunCallback(const CompletionCallback& callback, int result);
- base::WeakPtrFactory<MockClientSocket> weak_factory_;
-
// True if Connect completed successfully and Disconnect hasn't been called.
bool connected_;
@@ -669,20 +714,27 @@ class MockClientSocket : public SSLClientSocket {
IPEndPoint peer_addr_;
BoundNetLog net_log_;
+
+ base::WeakPtrFactory<MockClientSocket> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
};
class MockTCPClientSocket : public MockClientSocket, public AsyncSocket {
public:
- MockTCPClientSocket(const AddressList& addresses, net::NetLog* net_log,
+ MockTCPClientSocket(const AddressList& addresses,
+ net::NetLog* net_log,
SocketDataProvider* socket);
virtual ~MockTCPClientSocket();
const AddressList& addresses() const { return addresses_; }
// Socket implementation.
- virtual int Read(IOBuffer* buf, int buf_len,
+ virtual int Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual int Write(IOBuffer* buf, int buf_len,
+ virtual int Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
// StreamSocket implementation.
@@ -716,10 +768,12 @@ class MockTCPClientSocket : public MockClientSocket, public AsyncSocket {
bool peer_closed_connection_;
// While an asynchronous IO is pending, we save our user-buffer state.
- IOBuffer* pending_buf_;
+ scoped_refptr<IOBuffer> pending_buf_;
int pending_buf_len_;
CompletionCallback pending_callback_;
bool was_used_to_convey_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockTCPClientSocket);
};
// DeterministicSocketHelper is a helper class that can be used
@@ -740,10 +794,8 @@ class DeterministicSocketHelper {
void CompleteWrite();
int CompleteRead();
- int Write(IOBuffer* buf, int buf_len,
- const CompletionCallback& callback);
- int Read(IOBuffer* buf, int buf_len,
- const CompletionCallback& callback);
+ int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
+ int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
const BoundNetLog& net_log() const { return net_log_; }
@@ -788,9 +840,11 @@ class DeterministicMockUDPClientSocket
virtual int CompleteRead() OVERRIDE;
// Socket implementation.
- virtual int Read(IOBuffer* buf, int buf_len,
+ virtual int Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual int Write(IOBuffer* buf, int buf_len,
+ virtual int Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
virtual bool SetSendBufferSize(int32 size) OVERRIDE;
@@ -812,6 +866,8 @@ class DeterministicMockUDPClientSocket
bool connected_;
IPEndPoint peer_address_;
DeterministicSocketHelper helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeterministicMockUDPClientSocket);
};
// Mock TCP socket to be used in conjunction with DeterministicSocketData.
@@ -832,9 +888,11 @@ class DeterministicMockTCPClientSocket
virtual int CompleteRead() OVERRIDE;
// Socket:
- virtual int Write(IOBuffer* buf, int buf_len,
+ virtual int Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual int Read(IOBuffer* buf, int buf_len,
+ virtual int Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
// StreamSocket:
@@ -853,21 +911,24 @@ class DeterministicMockTCPClientSocket
private:
DeterministicSocketHelper helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeterministicMockTCPClientSocket);
};
class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
public:
- MockSSLClientSocket(
- scoped_ptr<ClientSocketHandle> transport_socket,
- const HostPortPair& host_and_port,
- const SSLConfig& ssl_config,
- SSLSocketDataProvider* socket);
+ MockSSLClientSocket(scoped_ptr<ClientSocketHandle> transport_socket,
+ const HostPortPair& host_and_port,
+ const SSLConfig& ssl_config,
+ SSLSocketDataProvider* socket);
virtual ~MockSSLClientSocket();
// Socket implementation.
- virtual int Read(IOBuffer* buf, int buf_len,
+ virtual int Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual int Write(IOBuffer* buf, int buf_len,
+ virtual int Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
// StreamSocket implementation.
@@ -881,13 +942,12 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
// SSLClientSocket implementation.
- virtual void GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) OVERRIDE;
+ virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info)
+ OVERRIDE;
virtual NextProtoStatus GetNextProto(std::string* proto,
std::string* server_protos) OVERRIDE;
virtual bool set_was_npn_negotiated(bool negotiated) OVERRIDE;
- virtual void set_protocol_negotiated(
- NextProto protocol_negotiated) OVERRIDE;
+ virtual void set_protocol_negotiated(NextProto protocol_negotiated) OVERRIDE;
virtual NextProto GetNegotiatedProtocol() const OVERRIDE;
// This MockSocket does not implement the manual async IO feature.
@@ -899,7 +959,7 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
virtual ServerBoundCertService* GetServerBoundCertService() const OVERRIDE;
private:
- static void ConnectCallback(MockSSLClientSocket *ssl_client_socket,
+ static void ConnectCallback(MockSSLClientSocket* ssl_client_socket,
const CompletionCallback& callback,
int rv);
@@ -909,19 +969,21 @@ class MockSSLClientSocket : public MockClientSocket, public AsyncSocket {
bool new_npn_value_;
bool is_protocol_negotiated_set_;
NextProto protocol_negotiated_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket);
};
-class MockUDPClientSocket
- : public DatagramClientSocket,
- public AsyncSocket {
+class MockUDPClientSocket : public DatagramClientSocket, public AsyncSocket {
public:
MockUDPClientSocket(SocketDataProvider* data, net::NetLog* net_log);
virtual ~MockUDPClientSocket();
// Socket implementation.
- virtual int Read(IOBuffer* buf, int buf_len,
+ virtual int Read(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
- virtual int Write(IOBuffer* buf, int buf_len,
+ virtual int Write(IOBuffer* buf,
+ int buf_len,
const CompletionCallback& callback) OVERRIDE;
virtual bool SetReceiveBufferSize(int32 size) OVERRIDE;
virtual bool SetSendBufferSize(int32 size) OVERRIDE;
@@ -955,7 +1017,7 @@ class MockUDPClientSocket
IPEndPoint peer_addr_;
// While an asynchronous IO is pending, we save our user-buffer state.
- IOBuffer* pending_buf_;
+ scoped_refptr<IOBuffer> pending_buf_;
int pending_buf_len_;
CompletionCallback pending_callback_;
@@ -1009,12 +1071,15 @@ class ClientSocketPoolTest {
RequestPriority priority,
const scoped_refptr<typename PoolType::SocketParams>& socket_params) {
DCHECK(socket_pool);
- TestSocketRequest* request = new TestSocketRequest(&request_order_,
- &completion_count_);
+ TestSocketRequest* request =
+ new TestSocketRequest(&request_order_, &completion_count_);
requests_.push_back(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,
+ request->callback(),
+ socket_pool,
+ BoundNetLog());
if (rv != ERR_IO_PENDING)
request_order_.push_back(request);
return rv;
@@ -1045,6 +1110,8 @@ class ClientSocketPoolTest {
ScopedVector<TestSocketRequest> requests_;
std::vector<TestSocketRequest*> request_order_;
size_t completion_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClientSocketPoolTest);
};
class MockTransportSocketParams
@@ -1052,6 +1119,8 @@ class MockTransportSocketParams
private:
friend class base::RefCounted<MockTransportSocketParams>;
~MockTransportSocketParams() {}
+
+ DISALLOW_COPY_AND_ASSIGN(MockTransportSocketParams);
};
class MockTransportClientSocketPool : public TransportClientSocketPool {
@@ -1060,7 +1129,8 @@ class MockTransportClientSocketPool : public TransportClientSocketPool {
class MockConnectJob {
public:
- MockConnectJob(scoped_ptr<StreamSocket> socket, ClientSocketHandle* handle,
+ MockConnectJob(scoped_ptr<StreamSocket> socket,
+ ClientSocketHandle* handle,
const CompletionCallback& callback);
~MockConnectJob();
@@ -1077,11 +1147,10 @@ class MockTransportClientSocketPool : public TransportClientSocketPool {
DISALLOW_COPY_AND_ASSIGN(MockConnectJob);
};
- MockTransportClientSocketPool(
- int max_sockets,
- int max_sockets_per_group,
- ClientSocketPoolHistograms* histograms,
- ClientSocketFactory* socket_factory);
+ MockTransportClientSocketPool(int max_sockets,
+ int max_sockets_per_group,
+ ClientSocketPoolHistograms* histograms,
+ ClientSocketFactory* socket_factory);
virtual ~MockTransportClientSocketPool();
@@ -1163,15 +1232,16 @@ class DeterministicMockClientSocketFactory : public ClientSocketFactory {
std::vector<DeterministicMockTCPClientSocket*> tcp_client_sockets_;
std::vector<DeterministicMockUDPClientSocket*> udp_client_sockets_;
std::vector<MockSSLClientSocket*> ssl_client_sockets_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeterministicMockClientSocketFactory);
};
class MockSOCKSClientSocketPool : public SOCKSClientSocketPool {
public:
- MockSOCKSClientSocketPool(
- int max_sockets,
- int max_sockets_per_group,
- ClientSocketPoolHistograms* histograms,
- TransportClientSocketPool* transport_pool);
+ MockSOCKSClientSocketPool(int max_sockets,
+ int max_sockets_per_group,
+ ClientSocketPoolHistograms* histograms,
+ TransportClientSocketPool* transport_pool);
virtual ~MockSOCKSClientSocketPool();
diff --git a/chromium/net/socket/socks5_client_socket.cc b/chromium/net/socket/socks5_client_socket.cc
index 537b584a932..004b67c669f 100644
--- a/chromium/net/socket/socks5_client_socket.cc
+++ b/chromium/net/socket/socks5_client_socket.cc
@@ -254,7 +254,6 @@ int SOCKS5ClientSocket::DoLoop(int last_io_result) {
}
const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication
-const char kSOCKS5GreetReadData[] = { 0x05, 0x00 };
int SOCKS5ClientSocket::DoGreetWrite() {
// Since we only have 1 byte to send the hostname length in, if the
diff --git a/chromium/net/socket/socks_client_socket_pool_unittest.cc b/chromium/net/socket/socks_client_socket_pool_unittest.cc
index 4463e171f84..b2b8655ee22 100644
--- a/chromium/net/socket/socks_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/socks_client_socket_pool_unittest.cc
@@ -143,7 +143,7 @@ TEST_F(SOCKSClientSocketPoolTest, Simple) {
// Make sure that SOCKSConnectJob passes on its priority to its
// socket request on Init.
TEST_F(SOCKSClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
- for (int i = MINIMUM_PRIORITY; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
RequestPriority priority = static_cast<RequestPriority>(i);
SOCKS5MockData data(SYNCHRONOUS);
data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
@@ -162,7 +162,7 @@ TEST_F(SOCKSClientSocketPoolTest, SetSocketRequestPriorityOnInit) {
// Make sure that SOCKSConnectJob passes on its priority to its
// HostResolver request (for non-SOCKS5) on Init.
TEST_F(SOCKSClientSocketPoolTest, SetResolvePriorityOnInit) {
- for (int i = MINIMUM_PRIORITY; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
RequestPriority priority = static_cast<RequestPriority>(i);
SOCKS5MockData data(SYNCHRONOUS);
data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
diff --git a/chromium/net/socket/ssl_client_socket.cc b/chromium/net/socket/ssl_client_socket.cc
index 54f66a1f681..d96a720e428 100644
--- a/chromium/net/socket/ssl_client_socket.cc
+++ b/chromium/net/socket/ssl_client_socket.cc
@@ -4,7 +4,11 @@
#include "net/socket/ssl_client_socket.h"
+#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
+#include "crypto/ec_private_key.h"
+#include "net/ssl/server_bound_cert_service.h"
+#include "net/ssl/ssl_config_service.h"
namespace net {
@@ -12,7 +16,9 @@ SSLClientSocket::SSLClientSocket()
: was_npn_negotiated_(false),
was_spdy_negotiated_(false),
protocol_negotiated_(kProtoUnknown),
- channel_id_sent_(false) {
+ channel_id_sent_(false),
+ signed_cert_timestamps_received_(false),
+ stapled_ocsp_response_received_(false) {
}
// static
@@ -20,10 +26,8 @@ NextProto SSLClientSocket::NextProtoFromString(
const std::string& proto_string) {
if (proto_string == "http1.1" || proto_string == "http/1.1") {
return kProtoHTTP11;
- } else if (proto_string == "spdy/1") {
- return kProtoSPDY1;
} else if (proto_string == "spdy/2") {
- return kProtoSPDY2;
+ return kProtoDeprecatedSPDY2;
} else if (proto_string == "spdy/3") {
return kProtoSPDY3;
} else if (proto_string == "spdy/3.1") {
@@ -44,9 +48,7 @@ const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
switch (next_proto) {
case kProtoHTTP11:
return "http/1.1";
- case kProtoSPDY1:
- return "spdy/1";
- case kProtoSPDY2:
+ case kProtoDeprecatedSPDY2:
return "spdy/2";
case kProtoSPDY3:
return "spdy/3";
@@ -58,7 +60,6 @@ const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
return "HTTP-draft-04/2.0";
case kProtoQUIC1SPDY3:
return "quic/1+spdy/3";
- case kProtoSPDY21:
case kProtoUnknown:
break;
}
@@ -145,4 +146,68 @@ void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
channel_id_sent_ = channel_id_sent;
}
+void SSLClientSocket::set_signed_cert_timestamps_received(
+ bool signed_cert_timestamps_received) {
+ signed_cert_timestamps_received_ = signed_cert_timestamps_received;
+}
+
+void SSLClientSocket::set_stapled_ocsp_response_received(
+ bool stapled_ocsp_response_received) {
+ stapled_ocsp_response_received_ = stapled_ocsp_response_received;
+}
+
+// static
+void SSLClientSocket::RecordChannelIDSupport(
+ ServerBoundCertService* server_bound_cert_service,
+ bool negotiated_channel_id,
+ bool channel_id_enabled,
+ bool supports_ecc) {
+ // Since this enum is used for a histogram, do not change or re-use values.
+ enum {
+ DISABLED = 0,
+ CLIENT_ONLY = 1,
+ CLIENT_AND_SERVER = 2,
+ CLIENT_NO_ECC = 3,
+ CLIENT_BAD_SYSTEM_TIME = 4,
+ CLIENT_NO_SERVER_BOUND_CERT_SERVICE = 5,
+ DOMAIN_BOUND_CERT_USAGE_MAX
+ } supported = DISABLED;
+ if (negotiated_channel_id) {
+ supported = CLIENT_AND_SERVER;
+ } else if (channel_id_enabled) {
+ if (!server_bound_cert_service)
+ supported = CLIENT_NO_SERVER_BOUND_CERT_SERVICE;
+ else if (!supports_ecc)
+ supported = CLIENT_NO_ECC;
+ else if (!server_bound_cert_service->IsSystemTimeValid())
+ supported = CLIENT_BAD_SYSTEM_TIME;
+ else
+ supported = CLIENT_ONLY;
+ }
+ UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
+ DOMAIN_BOUND_CERT_USAGE_MAX);
+}
+
+// static
+bool SSLClientSocket::IsChannelIDEnabled(
+ const SSLConfig& ssl_config,
+ ServerBoundCertService* server_bound_cert_service) {
+ if (!ssl_config.channel_id_enabled)
+ return false;
+ if (!server_bound_cert_service) {
+ DVLOG(1) << "NULL server_bound_cert_service_, not enabling channel ID.";
+ return false;
+ }
+ if (!crypto::ECPrivateKey::IsSupported()) {
+ DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
+ return false;
+ }
+ if (!server_bound_cert_service->IsSystemTimeValid()) {
+ DVLOG(1) << "System time is not within the supported range for certificate "
+ "generation, not enabling channel ID.";
+ return false;
+ }
+ return true;
+}
+
} // namespace net
diff --git a/chromium/net/socket/ssl_client_socket.h b/chromium/net/socket/ssl_client_socket.h
index 41ee0873347..410062dc5a9 100644
--- a/chromium/net/socket/ssl_client_socket.h
+++ b/chromium/net/socket/ssl_client_socket.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/gtest_prod_util.h"
#include "net/base/completion_callback.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -16,8 +17,10 @@
namespace net {
class CertVerifier;
+class CTVerifier;
class ServerBoundCertService;
class SSLCertRequestInfo;
+struct SSLConfig;
class SSLInfo;
class TransportSecurityState;
@@ -27,20 +30,24 @@ struct SSLClientSocketContext {
SSLClientSocketContext()
: cert_verifier(NULL),
server_bound_cert_service(NULL),
- transport_security_state(NULL) {}
+ transport_security_state(NULL),
+ cert_transparency_verifier(NULL) {}
SSLClientSocketContext(CertVerifier* cert_verifier_arg,
ServerBoundCertService* server_bound_cert_service_arg,
TransportSecurityState* transport_security_state_arg,
+ CTVerifier* cert_transparency_verifier_arg,
const std::string& ssl_session_cache_shard_arg)
: cert_verifier(cert_verifier_arg),
server_bound_cert_service(server_bound_cert_service_arg),
transport_security_state(transport_security_state_arg),
+ cert_transparency_verifier(cert_transparency_verifier_arg),
ssl_session_cache_shard(ssl_session_cache_shard_arg) {}
CertVerifier* cert_verifier;
ServerBoundCertService* server_bound_cert_service;
TransportSecurityState* transport_security_state;
+ CTVerifier* cert_transparency_verifier;
// ssl_session_cache_shard is an opaque string that identifies a shard of the
// SSL session cache. SSL sockets with the same ssl_session_cache_shard may
// resume each other's SSL sessions but we'll never sessions between shards.
@@ -121,11 +128,41 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
// This may be useful for protocols, like SPDY, which allow the same
// connection to be shared between multiple domains, each of which need
// a channel ID.
+ //
+ // Public for ssl_client_socket_openssl_unittest.cc.
virtual bool WasChannelIDSent() const;
+ protected:
virtual void set_channel_id_sent(bool channel_id_sent);
+ virtual void set_signed_cert_timestamps_received(
+ bool signed_cert_timestamps_received);
+
+ virtual void set_stapled_ocsp_response_received(
+ bool stapled_ocsp_response_received);
+
+ // Records histograms for channel id support during full handshakes - resumed
+ // handshakes are ignored.
+ static void RecordChannelIDSupport(
+ ServerBoundCertService* server_bound_cert_service,
+ bool negotiated_channel_id,
+ bool channel_id_enabled,
+ bool supports_ecc);
+
+ // Returns whether TLS channel ID is enabled.
+ static bool IsChannelIDEnabled(
+ const SSLConfig& ssl_config,
+ ServerBoundCertService* server_bound_cert_service);
+
private:
+ // For signed_cert_timestamps_received_ and stapled_ocsp_response_received_.
+ FRIEND_TEST_ALL_PREFIXES(SSLClientSocketTest,
+ ConnectSignedCertTimestampsEnabledTLSExtension);
+ FRIEND_TEST_ALL_PREFIXES(SSLClientSocketTest,
+ ConnectSignedCertTimestampsEnabledOCSP);
+ FRIEND_TEST_ALL_PREFIXES(SSLClientSocketTest,
+ ConnectSignedCertTimestampsDisabled);
+
// True if NPN was responded to, independent of selecting SPDY or HTTP.
bool was_npn_negotiated_;
// True if NPN successfully negotiated SPDY.
@@ -134,6 +171,10 @@ class NET_EXPORT SSLClientSocket : public SSLSocket {
NextProto protocol_negotiated_;
// True if a channel ID was sent.
bool channel_id_sent_;
+ // True if SCTs were received via a TLS extension.
+ bool signed_cert_timestamps_received_;
+ // True if a stapled OCSP response was received.
+ bool stapled_ocsp_response_received_;
};
} // namespace net
diff --git a/chromium/net/socket/ssl_client_socket_nss.cc b/chromium/net/socket/ssl_client_socket_nss.cc
index 0de7cfb9060..0c73ec6c582 100644
--- a/chromium/net/socket/ssl_client_socket_nss.cc
+++ b/chromium/net/socket/ssl_client_socket_nss.cc
@@ -93,6 +93,11 @@
#include "net/cert/asn1_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_objects_extractor.h"
+#include "net/cert/ct_verifier.h"
+#include "net/cert/ct_verify_result.h"
+#include "net/cert/scoped_nss_types.h"
+#include "net/cert/sct_status_flags.h"
#include "net/cert/single_request_cert_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/cert/x509_util.h"
@@ -221,15 +226,6 @@ bool IsOCSPStaplingSupported() {
}
#endif
-class FreeCERTCertificate {
- public:
- inline void operator()(CERTCertificate* x) const {
- CERT_DestroyCertificate(x);
- }
-};
-typedef scoped_ptr_malloc<CERTCertificate, FreeCERTCertificate>
- ScopedCERTCertificate;
-
#if defined(OS_WIN)
// This callback is intended to be used with CertFindChainInStore. In addition
@@ -422,6 +418,8 @@ struct HandshakeState {
channel_id_sent = false;
server_cert_chain.Reset(NULL);
server_cert = NULL;
+ sct_list_from_tls_extension.clear();
+ stapled_ocsp_response.clear();
resumed_handshake = false;
ssl_connection_status = 0;
}
@@ -451,6 +449,10 @@ struct HandshakeState {
// always be non-NULL.
PeerCertificateChain server_cert_chain;
scoped_refptr<X509Certificate> server_cert;
+ // SignedCertificateTimestampList received via TLS extension (RFC 6962).
+ std::string sct_list_from_tls_extension;
+ // Stapled OCSP response received.
+ std::string stapled_ocsp_response;
// True if the current handshake was the result of TLS session resumption.
bool resumed_handshake;
@@ -650,6 +652,14 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
bool HasPendingAsyncOperation();
bool HasUnhandledReceivedData();
+ // Called on the network task runner.
+ // Causes the associated SSL/TLS session ID to be added to NSS's session
+ // cache, but only if the connection has not been False Started.
+ //
+ // This should only be called after the server's certificate has been
+ // verified, and may not be called within an NSS callback.
+ void CacheSessionIfNecessary();
+
private:
friend class base::RefCountedThreadSafe<Core>;
~Core();
@@ -707,10 +717,19 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
SECKEYPrivateKey** result_private_key);
#endif
+ // Called by NSS to determine if we can False Start.
+ // |arg| contains a pointer to the current SSLClientSocketNSS::Core.
+ static SECStatus CanFalseStartCallback(PRFileDesc* socket,
+ void* arg,
+ PRBool* can_false_start);
+
// Called by NSS once the handshake has completed.
// |arg| contains a pointer to the current SSLClientSocketNSS::Core.
static void HandshakeCallback(PRFileDesc* socket, void* arg);
+ // Called once the handshake has succeeded.
+ void HandshakeSucceeded();
+
// Handles an NSS error generated while handshaking or performing IO.
// Returns a network error code mapped from the original NSS error.
int HandleNSSError(PRErrorCode error, bool handshake_error);
@@ -753,11 +772,18 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
// Updates the NSS and platform specific certificates.
void UpdateServerCert();
+ // Update the nss_handshake_state_ with the SignedCertificateTimestampList
+ // received in the handshake via a TLS extension.
+ void UpdateSignedCertTimestamps();
+ // Update the OCSP response cache with the stapled response received in the
+ // handshake, and update nss_handshake_state_ with
+ // the SignedCertificateTimestampList received in the stapled OCSP response.
+ void UpdateStapledOCSPResponse();
// Updates the nss_handshake_state_ with the negotiated security parameters.
void UpdateConnectionStatus();
// Record histograms for channel id support during full handshakes - resumed
// handshakes are ignored.
- void RecordChannelIDSupport();
+ void RecordChannelIDSupportOnNSSTaskRunner();
// UpdateNextProto gets any application-layer protocol that may have been
// negotiated by the TLS connection.
void UpdateNextProto();
@@ -862,6 +888,8 @@ class SSLClientSocketNSS::Core : public base::RefCountedThreadSafe<Core> {
bool channel_id_needed_;
// True if the handshake state machine was interrupted for client auth.
bool client_auth_cert_needed_;
+ // True if NSS has False Started.
+ bool false_started_;
// True if NSS has called HandshakeCallback.
bool handshake_callback_called_;
@@ -930,6 +958,7 @@ SSLClientSocketNSS::Core::Core(
channel_id_xtn_negotiated_(false),
channel_id_needed_(false),
client_auth_cert_needed_(false),
+ false_started_(false),
handshake_callback_called_(false),
transport_recv_busy_(false),
transport_recv_eof_(false),
@@ -1009,22 +1038,22 @@ bool SSLClientSocketNSS::Core::Init(PRFileDesc* socket,
return false;
}
- if (ssl_config_.channel_id_enabled) {
- if (!server_bound_cert_service_) {
- DVLOG(1) << "NULL server_bound_cert_service_, not enabling channel ID.";
- } else if (!crypto::ECPrivateKey::IsSupported()) {
- DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
- } else if (!server_bound_cert_service_->IsSystemTimeValid()) {
- DVLOG(1) << "System time is weird, not enabling channel ID.";
- } else {
- rv = SSL_SetClientChannelIDCallback(
- nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
- if (rv != SECSuccess)
- LogFailedNSSFunction(*weak_net_log_, "SSL_SetClientChannelIDCallback",
- "");
+ if (IsChannelIDEnabled(ssl_config_, server_bound_cert_service_)) {
+ rv = SSL_SetClientChannelIDCallback(
+ nss_fd_, SSLClientSocketNSS::Core::ClientChannelIDHandler, this);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(
+ *weak_net_log_, "SSL_SetClientChannelIDCallback", "");
}
}
+ rv = SSL_SetCanFalseStartCallback(
+ nss_fd_, SSLClientSocketNSS::Core::CanFalseStartCallback, this);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(*weak_net_log_, "SSL_SetCanFalseStartCallback", "");
+ return false;
+ }
+
rv = SSL_HandshakeCallback(
nss_fd_, SSLClientSocketNSS::Core::HandshakeCallback, this);
if (rv != SECSuccess) {
@@ -1151,7 +1180,7 @@ int SSLClientSocketNSS::Core::Read(IOBuffer* buf, int buf_len,
}
DCHECK(OnNSSTaskRunner());
- DCHECK(handshake_callback_called_);
+ DCHECK(false_started_ || handshake_callback_called_);
DCHECK_EQ(STATE_NONE, next_handshake_state_);
DCHECK(user_read_callback_.is_null());
DCHECK(user_connect_callback_.is_null());
@@ -1205,7 +1234,7 @@ int SSLClientSocketNSS::Core::Write(IOBuffer* buf, int buf_len,
}
DCHECK(OnNSSTaskRunner());
- DCHECK(handshake_callback_called_);
+ DCHECK(false_started_ || handshake_callback_called_);
DCHECK_EQ(STATE_NONE, next_handshake_state_);
DCHECK(user_write_callback_.is_null());
DCHECK(user_connect_callback_.is_null());
@@ -1253,6 +1282,30 @@ bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() {
return unhandled_buffer_size_ != 0;
}
+void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
+ // TODO(rsleevi): This should occur on the NSS task runner, due to the use of
+ // nss_fd_. However, it happens on the network task runner in order to match
+ // the buggy behavior of ExportKeyingMaterial.
+ //
+ // Once http://crbug.com/330360 is fixed, this should be moved to an
+ // implementation that exclusively does this work on the NSS TaskRunner. This
+ // is "safe" because it is only called during the certificate verification
+ // state machine of the main socket, which is safe because no underlying
+ // transport IO will be occuring in that state, and NSS will not be blocking
+ // on any PKCS#11 related locks that might block the Network TaskRunner.
+ DCHECK(OnNetworkTaskRunner());
+
+ // Only cache the session if the connection was not False Started, because
+ // sessions should only be cached *after* the peer's Finished message is
+ // processed.
+ // In the case of False Start, the session will be cached once the
+ // HandshakeCallback is called, which signals the receipt and processing of
+ // the Finished message, and which will happen during a call to
+ // PR_Read/PR_Write.
+ if (!false_started_)
+ SSL_CacheSession(nss_fd_);
+}
+
bool SSLClientSocketNSS::Core::OnNSSTaskRunner() const {
return nss_task_runner_->RunsTasksOnCurrentThread();
}
@@ -1268,26 +1321,7 @@ SECStatus SSLClientSocketNSS::Core::OwnAuthCertHandler(
PRBool checksig,
PRBool is_server) {
Core* core = reinterpret_cast<Core*>(arg);
- if (!core->handshake_callback_called_) {
- // Only need to turn off False Start in the initial handshake. Also, it is
- // unsafe to call SSL_OptionSet in a renegotiation because the "first
- // handshake" lock isn't already held, which will result in an assertion
- // failure in the ssl_Get1stHandshakeLock call in SSL_OptionSet.
- PRBool negotiated_extension;
- SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
- ssl_app_layer_protocol_xtn,
- &negotiated_extension);
- if (rv != SECSuccess || !negotiated_extension) {
- rv = SSL_HandshakeNegotiatedExtension(socket,
- ssl_next_proto_nego_xtn,
- &negotiated_extension);
- }
- if (rv != SECSuccess || !negotiated_extension) {
- // If the server doesn't support NPN or ALPN, then we don't do False
- // Start with it.
- SSL_OptionSet(socket, SSL_ENABLE_FALSE_START, PR_FALSE);
- }
- } else {
+ if (core->handshake_callback_called_) {
// Disallow the server certificate to change in a renegotiation.
CERTCertificate* old_cert = core->nss_handshake_state_.server_cert_chain[0];
ScopedCERTCertificate new_cert(SSL_PeerCertificate(socket));
@@ -1615,6 +1649,30 @@ SECStatus SSLClientSocketNSS::Core::ClientAuthHandler(
#endif // NSS_PLATFORM_CLIENT_AUTH
// static
+SECStatus SSLClientSocketNSS::Core::CanFalseStartCallback(
+ PRFileDesc* socket,
+ void* arg,
+ PRBool* can_false_start) {
+ // If the server doesn't support NPN or ALPN, then we don't do False
+ // Start with it.
+ PRBool negotiated_extension;
+ SECStatus rv = SSL_HandshakeNegotiatedExtension(socket,
+ ssl_app_layer_protocol_xtn,
+ &negotiated_extension);
+ if (rv != SECSuccess || !negotiated_extension) {
+ rv = SSL_HandshakeNegotiatedExtension(socket,
+ ssl_next_proto_nego_xtn,
+ &negotiated_extension);
+ }
+ if (rv != SECSuccess || !negotiated_extension) {
+ *can_false_start = PR_FALSE;
+ return SECSuccess;
+ }
+
+ return SSL_RecommendedCanFalseStart(socket, can_false_start);
+}
+
+// static
void SSLClientSocketNSS::Core::HandshakeCallback(
PRFileDesc* socket,
void* arg) {
@@ -1622,27 +1680,47 @@ void SSLClientSocketNSS::Core::HandshakeCallback(
DCHECK(core->OnNSSTaskRunner());
core->handshake_callback_called_ = true;
+ if (core->false_started_) {
+ core->false_started_ = false;
+ // If the connection was False Started, then at the time of this callback,
+ // the peer's certificate will have been verified or the caller will have
+ // accepted the error.
+ // This is guaranteed when using False Start because this callback will
+ // not be invoked until processing the peer's Finished message, which
+ // will only happen in a PR_Read/PR_Write call, which can only happen
+ // after the peer's certificate is verified.
+ SSL_CacheSessionUnlocked(socket);
+
+ // Additionally, when False Starting, DoHandshake() will have already
+ // called HandshakeSucceeded(), so return now.
+ return;
+ }
+ core->HandshakeSucceeded();
+}
- HandshakeState* nss_state = &core->nss_handshake_state_;
+void SSLClientSocketNSS::Core::HandshakeSucceeded() {
+ DCHECK(OnNSSTaskRunner());
PRBool last_handshake_resumed;
- SECStatus rv = SSL_HandshakeResumedSession(socket, &last_handshake_resumed);
+ SECStatus rv = SSL_HandshakeResumedSession(nss_fd_, &last_handshake_resumed);
if (rv == SECSuccess && last_handshake_resumed) {
- nss_state->resumed_handshake = true;
+ nss_handshake_state_.resumed_handshake = true;
} else {
- nss_state->resumed_handshake = false;
+ nss_handshake_state_.resumed_handshake = false;
}
- core->RecordChannelIDSupport();
- core->UpdateServerCert();
- core->UpdateConnectionStatus();
- core->UpdateNextProto();
+ RecordChannelIDSupportOnNSSTaskRunner();
+ UpdateServerCert();
+ UpdateSignedCertTimestamps();
+ UpdateStapledOCSPResponse();
+ UpdateConnectionStatus();
+ UpdateNextProto();
// Update the network task runners view of the handshake state whenever
// a handshake has completed.
- core->PostOrRunCallback(
- FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, core,
- *nss_state));
+ PostOrRunCallback(
+ FROM_HERE, base::Bind(&Core::OnHandshakeStateUpdated, this,
+ nss_handshake_state_));
}
int SSLClientSocketNSS::Core::HandleNSSError(PRErrorCode nss_error,
@@ -1717,7 +1795,7 @@ int SSLClientSocketNSS::Core::DoHandshakeLoop(int last_io_result) {
int SSLClientSocketNSS::Core::DoReadLoop(int result) {
DCHECK(OnNSSTaskRunner());
- DCHECK(handshake_callback_called_);
+ DCHECK(false_started_ || handshake_callback_called_);
DCHECK_EQ(STATE_NONE, next_handshake_state_);
if (result < 0)
@@ -1746,7 +1824,7 @@ int SSLClientSocketNSS::Core::DoReadLoop(int result) {
int SSLClientSocketNSS::Core::DoWriteLoop(int result) {
DCHECK(OnNSSTaskRunner());
- DCHECK(handshake_callback_called_);
+ DCHECK(false_started_ || handshake_callback_called_);
DCHECK_EQ(STATE_NONE, next_handshake_state_);
if (result < 0)
@@ -1803,52 +1881,9 @@ int SSLClientSocketNSS::Core::DoHandshake() {
LOG(WARNING) << "Couldn't invalidate SSL session: " << PR_GetError();
} else if (rv == SECSuccess) {
if (!handshake_callback_called_) {
- // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=562434 -
- // SSL_ForceHandshake returned SECSuccess prematurely.
- rv = SECFailure;
- net_error = ERR_SSL_PROTOCOL_ERROR;
- PostOrRunCallback(
- FROM_HERE,
- base::Bind(&AddLogEventWithCallback, weak_net_log_,
- NetLog::TYPE_SSL_HANDSHAKE_ERROR,
- CreateNetLogSSLErrorCallback(net_error, 0)));
- } else {
- #if defined(SSL_ENABLE_OCSP_STAPLING)
- // TODO(agl): figure out how to plumb an OCSP response into the Mac
- // system library and update IsOCSPStaplingSupported for Mac.
- if (IsOCSPStaplingSupported()) {
- const SECItemArray* ocsp_responses =
- SSL_PeerStapledOCSPResponses(nss_fd_);
- if (ocsp_responses->len) {
- #if defined(OS_WIN)
- if (nss_handshake_state_.server_cert) {
- CRYPT_DATA_BLOB ocsp_response_blob;
- ocsp_response_blob.cbData = ocsp_responses->items[0].len;
- ocsp_response_blob.pbData = ocsp_responses->items[0].data;
- BOOL ok = CertSetCertificateContextProperty(
- nss_handshake_state_.server_cert->os_cert_handle(),
- CERT_OCSP_RESPONSE_PROP_ID,
- CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
- &ocsp_response_blob);
- if (!ok) {
- VLOG(1) << "Failed to set OCSP response property: "
- << GetLastError();
- }
- }
- #elif defined(USE_NSS)
- CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
- GetCacheOCSPResponseFromSideChannelFunction();
-
- cache_ocsp_response(
- CERT_GetDefaultCertDB(),
- nss_handshake_state_.server_cert_chain[0], PR_Now(),
- &ocsp_responses->items[0], NULL);
- #endif
- }
- }
- #endif
+ false_started_ = true;
+ HandshakeSucceeded();
}
- // Done!
} else {
PRErrorCode prerr = PR_GetError();
net_error = HandleNSSError(prerr, true);
@@ -2364,8 +2399,10 @@ int SSLClientSocketNSS::Core::ImportChannelIDKeys(SECKEYPublicKey** public_key,
if (cert == NULL)
return MapNSSError(PORT_GetError());
+ crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
// Set the private key.
if (!crypto::ECPrivateKey::ImportFromEncryptedPrivateKeyInfo(
+ slot.get(),
ServerBoundCertService::kEPKIPassword,
reinterpret_cast<const unsigned char*>(
domain_bound_private_key_.data()),
@@ -2400,6 +2437,58 @@ void SSLClientSocketNSS::Core::UpdateServerCert() {
}
}
+void SSLClientSocketNSS::Core::UpdateSignedCertTimestamps() {
+ const SECItem* signed_cert_timestamps =
+ SSL_PeerSignedCertTimestamps(nss_fd_);
+
+ if (!signed_cert_timestamps || !signed_cert_timestamps->len)
+ return;
+
+ nss_handshake_state_.sct_list_from_tls_extension = std::string(
+ reinterpret_cast<char*>(signed_cert_timestamps->data),
+ signed_cert_timestamps->len);
+}
+
+void SSLClientSocketNSS::Core::UpdateStapledOCSPResponse() {
+ const SECItemArray* ocsp_responses =
+ SSL_PeerStapledOCSPResponses(nss_fd_);
+ if (!ocsp_responses || !ocsp_responses->len)
+ return;
+
+ nss_handshake_state_.stapled_ocsp_response = std::string(
+ reinterpret_cast<char*>(ocsp_responses->items[0].data),
+ ocsp_responses->items[0].len);
+
+ // TODO(agl): figure out how to plumb an OCSP response into the Mac
+ // system library and update IsOCSPStaplingSupported for Mac.
+ if (IsOCSPStaplingSupported()) {
+ #if defined(OS_WIN)
+ if (nss_handshake_state_.server_cert) {
+ CRYPT_DATA_BLOB ocsp_response_blob;
+ ocsp_response_blob.cbData = ocsp_responses->items[0].len;
+ ocsp_response_blob.pbData = ocsp_responses->items[0].data;
+ BOOL ok = CertSetCertificateContextProperty(
+ nss_handshake_state_.server_cert->os_cert_handle(),
+ CERT_OCSP_RESPONSE_PROP_ID,
+ CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG,
+ &ocsp_response_blob);
+ if (!ok) {
+ VLOG(1) << "Failed to set OCSP response property: "
+ << GetLastError();
+ }
+ }
+ #elif defined(USE_NSS)
+ CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
+ GetCacheOCSPResponseFromSideChannelFunction();
+
+ cache_ocsp_response(
+ CERT_GetDefaultCertDB(),
+ nss_handshake_state_.server_cert_chain[0], PR_Now(),
+ &ocsp_responses->items[0], NULL);
+ #endif
+ } // IsOCSPStaplingSupported()
+}
+
void SSLClientSocketNSS::Core::UpdateConnectionStatus() {
SSLChannelInfo channel_info;
SECStatus ok = SSL_GetChannelInfo(nss_fd_,
@@ -2506,7 +2595,7 @@ void SSLClientSocketNSS::Core::UpdateNextProto() {
}
}
-void SSLClientSocketNSS::Core::RecordChannelIDSupport() {
+void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNSSTaskRunner() {
DCHECK(OnNSSTaskRunner());
if (nss_handshake_state_.resumed_handshake)
return;
@@ -2529,30 +2618,10 @@ void SSLClientSocketNSS::Core::RecordChannelIDSupportOnNetworkTaskRunner(
bool supports_ecc) const {
DCHECK(OnNetworkTaskRunner());
- // Since this enum is used for a histogram, do not change or re-use values.
- enum {
- DISABLED = 0,
- CLIENT_ONLY = 1,
- CLIENT_AND_SERVER = 2,
- CLIENT_NO_ECC = 3,
- CLIENT_BAD_SYSTEM_TIME = 4,
- CLIENT_NO_SERVER_BOUND_CERT_SERVICE = 5,
- DOMAIN_BOUND_CERT_USAGE_MAX
- } supported = DISABLED;
- if (negotiated_channel_id) {
- supported = CLIENT_AND_SERVER;
- } else if (channel_id_enabled) {
- if (!server_bound_cert_service_)
- supported = CLIENT_NO_SERVER_BOUND_CERT_SERVICE;
- else if (!supports_ecc)
- supported = CLIENT_NO_ECC;
- else if (!server_bound_cert_service_->IsSystemTimeValid())
- supported = CLIENT_BAD_SYSTEM_TIME;
- else
- supported = CLIENT_ONLY;
- }
- UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
- DOMAIN_BOUND_CERT_USAGE_MAX);
+ RecordChannelIDSupport(server_bound_cert_service_,
+ negotiated_channel_id,
+ channel_id_enabled,
+ supports_ecc);
}
int SSLClientSocketNSS::Core::DoBufferRecv(IOBuffer* read_buffer, int len) {
@@ -2769,6 +2838,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(
host_and_port_(host_and_port),
ssl_config_(ssl_config),
cert_verifier_(context.cert_verifier),
+ cert_transparency_verifier_(context.cert_transparency_verifier),
server_bound_cert_service_(context.server_bound_cert_service),
ssl_session_cache_shard_(context.ssl_session_cache_shard),
completed_handshake_(false),
@@ -2808,6 +2878,9 @@ bool SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->cert_status = server_cert_verify_result_.cert_status;
ssl_info->cert = server_cert_verify_result_.verified_cert;
+
+ AddSCTInfoToSSLInfo(ssl_info);
+
ssl_info->connection_status =
core_->state().ssl_connection_status;
ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
@@ -3098,9 +3171,10 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
/* Create SSL state machine */
/* Push SSL onto our fake I/O socket */
- nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
- if (nss_fd_ == NULL) {
+ if (SSL_ImportFD(GetNSSModelSocket(), nss_fd_) == NULL) {
LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
+ PR_Close(nss_fd_);
+ nss_fd_ = NULL;
return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
}
// TODO(port): set more ssl options! Check errors!
@@ -3135,6 +3209,14 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_NO_SSL_VERSIONS_ENABLED;
}
+ if (ssl_config_.version_fallback) {
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(
+ net_log_, "SSL_OptionSet", "SSL_ENABLE_FALLBACK_SCSV");
+ }
+ }
+
for (std::vector<uint16>::const_iterator it =
ssl_config_.disabled_cipher_suites.begin();
it != ssl_config_.disabled_cipher_suites.end(); ++it) {
@@ -3173,15 +3255,24 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
// Added in NSS 3.15
#ifdef SSL_ENABLE_OCSP_STAPLING
- if (IsOCSPStaplingSupported()) {
- rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
- if (rv != SECSuccess) {
- LogFailedNSSFunction(net_log_, "SSL_OptionSet",
- "SSL_ENABLE_OCSP_STAPLING");
- }
+ // Request OCSP stapling even on platforms that don't support it, in
+ // order to extract Certificate Transparency information.
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING,
+ (IsOCSPStaplingSupported() ||
+ ssl_config_.signed_cert_timestamps_enabled));
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet",
+ "SSL_ENABLE_OCSP_STAPLING");
}
#endif
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
+ ssl_config_.signed_cert_timestamps_enabled);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_OptionSet",
+ "SSL_ENABLE_SIGNED_CERT_TIMESTAMPS");
+ }
+
// Chromium patch to libssl
#ifdef SSL_ENABLE_CACHED_INFO
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_CACHED_INFO,
@@ -3327,12 +3418,15 @@ int SSLClientSocketNSS::DoHandshakeComplete(int result) {
// Done!
}
set_channel_id_sent(core_->state().channel_id_sent);
+ set_signed_cert_timestamps_received(
+ !core_->state().sct_list_from_tls_extension.empty());
+ set_stapled_ocsp_response_received(
+ !core_->state().stapled_ocsp_response.empty());
LeaveFunction(result);
return result;
}
-
int SSLClientSocketNSS::DoVerifyCert(int result) {
DCHECK(!core_->state().server_cert_chain.empty());
DCHECK(core_->state().server_cert_chain[0]);
@@ -3416,8 +3510,6 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
if (result == OK)
LogConnectionTypeMetrics();
- completed_handshake_ = true;
-
#if defined(OFFICIAL_BUILD) && !defined(OS_ANDROID) && !defined(OS_IOS)
// Take care of any mandates for public key pinning.
//
@@ -3465,11 +3557,45 @@ int SSLClientSocketNSS::DoVerifyCertComplete(int result) {
}
#endif
+ if (result == OK) {
+ // Only check Certificate Transparency if there were no other errors with
+ // the connection.
+ VerifyCT();
+
+ // Only cache the session if the certificate verified successfully.
+ core_->CacheSessionIfNecessary();
+ }
+
+ completed_handshake_ = true;
+
// Exit DoHandshakeLoop and return the result to the caller to Connect.
DCHECK_EQ(STATE_NONE, next_handshake_state_);
return result;
}
+void SSLClientSocketNSS::VerifyCT() {
+ if (!cert_transparency_verifier_)
+ return;
+
+ // Note that this is a completely synchronous operation: The CT Log Verifier
+ // gets all the data it needs for SCT verification and does not do any
+ // external communication.
+ int result = cert_transparency_verifier_->Verify(
+ server_cert_verify_result_.verified_cert,
+ core_->state().stapled_ocsp_response,
+ core_->state().sct_list_from_tls_extension,
+ &ct_verify_result_,
+ net_log_);
+ // TODO(ekasper): wipe stapled_ocsp_response and sct_list_from_tls_extension
+ // from the state after verification is complete, to conserve memory.
+
+ VLOG(1) << "CT Verification complete: result " << result
+ << " Invalid scts: " << ct_verify_result_.invalid_scts.size()
+ << " Verified scts: " << ct_verify_result_.verified_scts.size()
+ << " scts from unknown logs: "
+ << ct_verify_result_.unknown_logs_scts.size();
+}
+
void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
UpdateConnectionTypeHistograms(CONNECTION_SSL);
int ssl_version = SSLConnectionStatusToVersion(
@@ -3506,6 +3632,28 @@ bool SSLClientSocketNSS::CalledOnValidThread() const {
return valid_thread_id_ == base::PlatformThread::CurrentId();
}
+void SSLClientSocketNSS::AddSCTInfoToSSLInfo(SSLInfo* ssl_info) const {
+ for (ct::SCTList::const_iterator iter =
+ ct_verify_result_.verified_scts.begin();
+ iter != ct_verify_result_.verified_scts.end(); ++iter) {
+ ssl_info->signed_certificate_timestamps.push_back(
+ SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_OK));
+ }
+ for (ct::SCTList::const_iterator iter =
+ ct_verify_result_.invalid_scts.begin();
+ iter != ct_verify_result_.invalid_scts.end(); ++iter) {
+ ssl_info->signed_certificate_timestamps.push_back(
+ SignedCertificateTimestampAndStatus(*iter, ct::SCT_STATUS_INVALID));
+ }
+ for (ct::SCTList::const_iterator iter =
+ ct_verify_result_.unknown_logs_scts.begin();
+ iter != ct_verify_result_.unknown_logs_scts.end(); ++iter) {
+ ssl_info->signed_certificate_timestamps.push_back(
+ SignedCertificateTimestampAndStatus(*iter,
+ ct::SCT_STATUS_LOG_UNKNOWN));
+ }
+}
+
ServerBoundCertService* SSLClientSocketNSS::GetServerBoundCertService() const {
return server_bound_cert_service_;
}
diff --git a/chromium/net/socket/ssl_client_socket_nss.h b/chromium/net/socket/ssl_client_socket_nss.h
index b41d28d74a8..cc1412fa80b 100644
--- a/chromium/net/socket/ssl_client_socket_nss.h
+++ b/chromium/net/socket/ssl_client_socket_nss.h
@@ -24,6 +24,7 @@
#include "net/base/net_log.h"
#include "net/base/nss_memio.h"
#include "net/cert/cert_verify_result.h"
+#include "net/cert/ct_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/server_bound_cert_service.h"
@@ -37,6 +38,7 @@ namespace net {
class BoundNetLog;
class CertVerifier;
+class CTVerifier;
class ClientSocketHandle;
class ServerBoundCertService;
class SingleRequestCertVerifier;
@@ -135,6 +137,8 @@ class SSLClientSocketNSS : public SSLClientSocket {
int DoVerifyCert(int result);
int DoVerifyCertComplete(int result);
+ void VerifyCT();
+
void LogConnectionTypeMetrics() const;
// The following methods are for debugging bug 65948. Will remove this code
@@ -142,6 +146,13 @@ class SSLClientSocketNSS : public SSLClientSocket {
void EnsureThreadIdAssigned() const;
bool CalledOnValidThread() const;
+ // Adds the SignedCertificateTimestamps 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;
+
// The task runner used to perform NSS operations.
scoped_refptr<base::SequencedTaskRunner> nss_task_runner_;
scoped_ptr<ClientSocketHandle> transport_;
@@ -158,6 +169,10 @@ class SSLClientSocketNSS : public SSLClientSocket {
CertVerifier* const cert_verifier_;
scoped_ptr<SingleRequestCertVerifier> verifier_;
+ // Certificate Transparency: Verifier and result holder.
+ ct::CTVerifyResult ct_verify_result_;
+ CTVerifier* cert_transparency_verifier_;
+
// The service for retrieving Channel ID keys. May be NULL.
ServerBoundCertService* server_bound_cert_service_;
diff --git a/chromium/net/socket/ssl_client_socket_openssl.cc b/chromium/net/socket/ssl_client_socket_openssl.cc
index 416ab87bc4b..49bdc8eb68a 100644
--- a/chromium/net/socket/ssl_client_socket_openssl.cc
+++ b/chromium/net/socket/ssl_client_socket_openssl.cc
@@ -13,15 +13,18 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/debug/alias.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
+#include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/single_request_cert_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
#include "net/socket/ssl_error_params.h"
+#include "net/socket/ssl_session_cache_openssl.h"
#include "net/ssl/openssl_client_key_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
@@ -40,9 +43,6 @@ namespace {
#define GotoState(s) next_handshake_state_ = s
#endif
-const int kSessionCacheTimeoutSeconds = 60 * 60;
-const size_t kSessionCacheMaxEntires = 1024;
-
// This constant can be any non-negative/non-zero value (eg: it does not
// overlap with any value of the net::Error range, including net::OK).
const int kNoPendingReadResult = 1;
@@ -162,6 +162,9 @@ int MapOpenSSLErrorSSL() {
case SSL_R_INVALID_TICKET_KEYS_LENGTH:
case SSL_R_KEY_ARG_TOO_LONG:
case SSL_R_READ_WRONG_PACKET_TYPE:
+ // SSL_do_handshake reports this error when the server responds to a
+ // ClientHello with a fatal close_notify alert.
+ case SSL_AD_REASON_OFFSET + SSL_AD_CLOSE_NOTIFY:
case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
// TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
// server after receiving ClientHello if there's no common supported cipher.
@@ -214,114 +217,37 @@ int NoOpVerifyCallback(X509_STORE_CTX*, void *) {
return 1;
}
-// OpenSSL manages a cache of SSL_SESSION, this class provides the application
-// side policy for that cache about session re-use: we retain one session per
-// unique HostPortPair, per shard.
-class SSLSessionCache {
- public:
- SSLSessionCache() {}
-
- void OnSessionAdded(const HostPortPair& host_and_port,
- const std::string& shard,
- SSL_SESSION* session) {
- // Declare the session cleaner-upper before the lock, so any call into
- // OpenSSL to free the session will happen after the lock is released.
- crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
- base::AutoLock lock(lock_);
-
- DCHECK_EQ(0U, session_map_.count(session));
- const std::string cache_key = GetCacheKey(host_and_port, shard);
-
- std::pair<HostPortMap::iterator, bool> res =
- host_port_map_.insert(std::make_pair(cache_key, session));
- if (!res.second) { // Already exists: replace old entry.
- session_to_free.reset(res.first->second);
- session_map_.erase(session_to_free.get());
- res.first->second = session;
- }
- DVLOG(2) << "Adding session " << session << " => "
- << cache_key << ", new entry = " << res.second;
- DCHECK(host_port_map_[cache_key] == session);
- session_map_[session] = res.first;
- DCHECK_EQ(host_port_map_.size(), session_map_.size());
- DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires);
- }
-
- void OnSessionRemoved(SSL_SESSION* session) {
- // Declare the session cleaner-upper before the lock, so any call into
- // OpenSSL to free the session will happen after the lock is released.
- crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
- base::AutoLock lock(lock_);
-
- SessionMap::iterator it = session_map_.find(session);
- if (it == session_map_.end())
- return;
- DVLOG(2) << "Remove session " << session << " => " << it->second->first;
- DCHECK(it->second->second == session);
- host_port_map_.erase(it->second);
- session_map_.erase(it);
- session_to_free.reset(session);
- DCHECK_EQ(host_port_map_.size(), session_map_.size());
- }
-
- // Looks up the host:port in the cache, and if a session is found it is added
- // to |ssl|, returning true on success.
- bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port,
- const std::string& shard) {
- base::AutoLock lock(lock_);
- const std::string cache_key = GetCacheKey(host_and_port, shard);
- HostPortMap::iterator it = host_port_map_.find(cache_key);
- if (it == host_port_map_.end())
- return false;
- DVLOG(2) << "Lookup session: " << it->second << " => " << cache_key;
- SSL_SESSION* session = it->second;
- DCHECK(session);
- DCHECK(session_map_[session] == it);
- // Ideally we'd release |lock_| before calling into OpenSSL here, however
- // that opens a small risk |session| will go out of scope before it is used.
- // Alternatively we would take a temporary local refcount on |session|,
- // except OpenSSL does not provide a public API for adding a ref (c.f.
- // SSL_SESSION_free which decrements the ref).
- return SSL_set_session(ssl, session) == 1;
- }
-
- // Flush removes all entries from the cache. This is called when a client
- // certificate is added.
- void Flush() {
- for (HostPortMap::iterator i = host_port_map_.begin();
- i != host_port_map_.end(); i++) {
- SSL_SESSION_free(i->second);
- }
- host_port_map_.clear();
- session_map_.clear();
- }
-
- private:
- static std::string GetCacheKey(const HostPortPair& host_and_port,
- const std::string& shard) {
- return host_and_port.ToString() + "/" + shard;
+// Utility to construct the appropriate set & clear masks for use the OpenSSL
+// options and mode configuration functions. (SSL_set_options etc)
+struct SslSetClearMask {
+ SslSetClearMask() : set_mask(0), clear_mask(0) {}
+ void ConfigureFlag(long flag, bool state) {
+ (state ? set_mask : clear_mask) |= flag;
+ // Make sure we haven't got any intersection in the set & clear options.
+ DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
}
+ long set_mask;
+ long clear_mask;
+};
- // A pair of maps to allow bi-directional lookups between host:port and an
- // associated session.
- typedef std::map<std::string, SSL_SESSION*> HostPortMap;
- typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap;
- HostPortMap host_port_map_;
- SessionMap session_map_;
-
- // Protects access to both the above maps.
- base::Lock lock_;
+// Compute a unique key string for the SSL session cache. |socket| is an
+// input socket object. Return a string.
+std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) {
+ std::string result = socket.host_and_port().ToString();
+ result.append("/");
+ result.append(socket.ssl_session_cache_shard());
+ return result;
+}
- DISALLOW_COPY_AND_ASSIGN(SSLSessionCache);
-};
+} // namespace
-class SSLContext {
+class SSLClientSocketOpenSSL::SSLContext {
public:
static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); }
SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
- SSLSessionCache* session_cache() { return &session_cache_; }
+ SSLSessionCacheOpenSSL* session_cache() { return &session_cache_; }
- SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) {
+ SSLClientSocketOpenSSL* GetClientSocketFromSSL(const SSL* ssl) {
DCHECK(ssl);
SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>(
SSL_get_ex_data(ssl, ssl_socket_data_index_));
@@ -341,13 +267,10 @@ class SSLContext {
ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
DCHECK_NE(ssl_socket_data_index_, -1);
ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
+ session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig);
SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL);
- SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
- SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic);
- SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
- SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
- SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
+ SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback);
#if defined(OPENSSL_NPN_NEGOTIATED)
// TODO(kristianm): Only select this if ssl_config_.next_proto is not empty.
// It would be better if the callback were not a global setting,
@@ -357,26 +280,13 @@ class SSLContext {
#endif
}
- static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
- return GetInstance()->NewSessionCallback(ssl, session);
- }
-
- int NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
- SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl);
- session_cache_.OnSessionAdded(socket->host_and_port(),
- socket->ssl_session_cache_shard(),
- session);
- return 1; // 1 => We took ownership of |session|.
- }
-
- static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
- return GetInstance()->RemoveSessionCallback(ctx, session);
+ static std::string GetSessionCacheKey(const SSL* ssl) {
+ SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
+ DCHECK(socket);
+ return GetSocketSessionCacheKey(*socket);
}
- void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) {
- DCHECK(ctx == ssl_ctx());
- session_cache_.OnSessionRemoved(session);
- }
+ static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig;
static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) {
SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
@@ -384,6 +294,12 @@ class SSLContext {
return socket->ClientCertRequestCallback(ssl, x509, pkey);
}
+ static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) {
+ SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
+ CHECK(socket);
+ socket->ChannelIDRequestCallback(ssl, pkey);
+ }
+
static int SelectNextProtoCallback(SSL* ssl,
unsigned char** out, unsigned char* outlen,
const unsigned char* in,
@@ -396,31 +312,24 @@ class SSLContext {
// SSLClientSocketOpenSSL object from an SSL instance.
int ssl_socket_data_index_;
- // session_cache_ must appear before |ssl_ctx_| because the destruction of
- // |ssl_ctx_| may trigger callbacks into |session_cache_|. Therefore,
- // |session_cache_| must be destructed after |ssl_ctx_|.
- SSLSessionCache session_cache_;
crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
+ // |session_cache_| must be destroyed before |ssl_ctx_|.
+ SSLSessionCacheOpenSSL session_cache_;
};
-// Utility to construct the appropriate set & clear masks for use the OpenSSL
-// options and mode configuration functions. (SSL_set_options etc)
-struct SslSetClearMask {
- SslSetClearMask() : set_mask(0), clear_mask(0) {}
- void ConfigureFlag(long flag, bool state) {
- (state ? set_mask : clear_mask) |= flag;
- // Make sure we haven't got any intersection in the set & clear options.
- DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
- }
- long set_mask;
- long clear_mask;
+// static
+SSLSessionCacheOpenSSL::Config
+ SSLClientSocketOpenSSL::SSLContext::kDefaultSessionCacheConfig = {
+ &GetSessionCacheKey, // key_func
+ 1024, // max_entries
+ 256, // expiration_check_count
+ 60 * 60, // timeout_seconds
};
-} // namespace
-
// static
void SSLClientSocket::ClearSessionCache() {
- SSLContext* context = SSLContext::GetInstance();
+ SSLClientSocketOpenSSL::SSLContext* context =
+ SSLClientSocketOpenSSL::SSLContext::GetInstance();
context->session_cache()->Flush();
}
@@ -434,9 +343,11 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
transport_recv_eof_(false),
weak_factory_(this),
pending_read_error_(kNoPendingReadResult),
+ transport_write_error_(OK),
completed_handshake_(false),
client_auth_cert_needed_(false),
cert_verifier_(context.cert_verifier),
+ server_bound_cert_service_(context.server_bound_cert_service),
ssl_(NULL),
transport_bio_(NULL),
transport_(transport_socket.Pass()),
@@ -446,6 +357,8 @@ SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
trying_cached_session_(false),
next_handshake_state_(STATE_NONE),
npn_status_(kNextProtoUnsupported),
+ channel_id_request_return_value_(ERR_UNEXPECTED),
+ channel_id_xtn_negotiated_(false),
net_log_(transport_->socket()->NetLog()) {
}
@@ -453,6 +366,282 @@ SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
Disconnect();
}
+void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
+ SSLCertRequestInfo* cert_request_info) {
+ cert_request_info->host_and_port = host_and_port_.ToString();
+ cert_request_info->cert_authorities = cert_authorities_;
+}
+
+SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
+ std::string* proto, std::string* server_protos) {
+ *proto = npn_proto_;
+ *server_protos = server_protos_;
+ return npn_status_;
+}
+
+ServerBoundCertService*
+SSLClientSocketOpenSSL::GetServerBoundCertService() const {
+ return server_bound_cert_service_;
+}
+
+int SSLClientSocketOpenSSL::ExportKeyingMaterial(
+ const base::StringPiece& label,
+ bool has_context, const base::StringPiece& context,
+ unsigned char* out, unsigned int outlen) {
+ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
+
+ int rv = SSL_export_keying_material(
+ ssl_, out, outlen, const_cast<char*>(label.data()),
+ label.size(),
+ reinterpret_cast<unsigned char*>(const_cast<char*>(context.data())),
+ context.length(),
+ context.length() > 0);
+
+ if (rv != 1) {
+ int ssl_error = SSL_get_error(ssl_, rv);
+ LOG(ERROR) << "Failed to export keying material;"
+ << " returned " << rv
+ << ", SSL error code " << ssl_error;
+ return MapOpenSSLError(ssl_error, err_tracer);
+ }
+ return OK;
+}
+
+int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
+ return ERR_NOT_IMPLEMENTED;
+}
+
+int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
+ net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
+
+ // Set up new ssl object.
+ if (!Init()) {
+ int result = ERR_UNEXPECTED;
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
+ return result;
+ }
+
+ // Set SSL to client mode. Handshake happens in the loop below.
+ SSL_set_connect_state(ssl_);
+
+ GotoState(STATE_HANDSHAKE);
+ int rv = DoHandshakeLoop(net::OK);
+ if (rv == ERR_IO_PENDING) {
+ user_connect_callback_ = callback;
+ } else {
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
+ }
+
+ return rv > OK ? OK : rv;
+}
+
+void SSLClientSocketOpenSSL::Disconnect() {
+ if (ssl_) {
+ // Calling SSL_shutdown prevents the session from being marked as
+ // unresumable.
+ SSL_shutdown(ssl_);
+ SSL_free(ssl_);
+ ssl_ = NULL;
+ }
+ if (transport_bio_) {
+ BIO_free_all(transport_bio_);
+ transport_bio_ = NULL;
+ }
+
+ // Shut down anything that may call us back.
+ verifier_.reset();
+ transport_->socket()->Disconnect();
+
+ // Null all callbacks, delete all buffers.
+ transport_send_busy_ = false;
+ send_buffer_ = NULL;
+ transport_recv_busy_ = false;
+ transport_recv_eof_ = false;
+ recv_buffer_ = NULL;
+
+ user_connect_callback_.Reset();
+ user_read_callback_.Reset();
+ user_write_callback_.Reset();
+ user_read_buf_ = NULL;
+ user_read_buf_len_ = 0;
+ user_write_buf_ = NULL;
+ user_write_buf_len_ = 0;
+
+ pending_read_error_ = kNoPendingReadResult;
+ transport_write_error_ = OK;
+
+ server_cert_verify_result_.Reset();
+ completed_handshake_ = false;
+
+ cert_authorities_.clear();
+ client_auth_cert_needed_ = false;
+}
+
+bool SSLClientSocketOpenSSL::IsConnected() const {
+ // If the handshake has not yet completed.
+ if (!completed_handshake_)
+ return false;
+ // If an asynchronous operation is still pending.
+ if (user_read_buf_.get() || user_write_buf_.get())
+ return true;
+
+ return transport_->socket()->IsConnected();
+}
+
+bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
+ // If the handshake has not yet completed.
+ if (!completed_handshake_)
+ return false;
+ // If an asynchronous operation is still pending.
+ if (user_read_buf_.get() || user_write_buf_.get())
+ return false;
+ // If there is data waiting to be sent, or data read from the network that
+ // has not yet been consumed.
+ if (BIO_ctrl_pending(transport_bio_) > 0 ||
+ BIO_ctrl_wpending(transport_bio_) > 0) {
+ return false;
+ }
+
+ return transport_->socket()->IsConnectedAndIdle();
+}
+
+int SSLClientSocketOpenSSL::GetPeerAddress(IPEndPoint* addressList) const {
+ return transport_->socket()->GetPeerAddress(addressList);
+}
+
+int SSLClientSocketOpenSSL::GetLocalAddress(IPEndPoint* addressList) const {
+ return transport_->socket()->GetLocalAddress(addressList);
+}
+
+const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
+ return net_log_;
+}
+
+void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
+ if (transport_.get() && transport_->socket()) {
+ transport_->socket()->SetSubresourceSpeculation();
+ } else {
+ NOTREACHED();
+ }
+}
+
+void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
+ if (transport_.get() && transport_->socket()) {
+ transport_->socket()->SetOmniboxSpeculation();
+ } else {
+ NOTREACHED();
+ }
+}
+
+bool SSLClientSocketOpenSSL::WasEverUsed() const {
+ if (transport_.get() && transport_->socket())
+ return transport_->socket()->WasEverUsed();
+
+ NOTREACHED();
+ return false;
+}
+
+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_.get())
+ return false;
+
+ ssl_info->cert = server_cert_verify_result_.verified_cert;
+ ssl_info->cert_status = server_cert_verify_result_.cert_status;
+ ssl_info->is_issued_by_known_root =
+ server_cert_verify_result_.is_issued_by_known_root;
+ ssl_info->public_key_hashes =
+ server_cert_verify_result_.public_key_hashes;
+ ssl_info->client_cert_sent =
+ ssl_config_.send_client_cert && ssl_config_.client_cert.get();
+ ssl_info->channel_id_sent = WasChannelIDSent();
+
+ RecordChannelIDSupport(server_bound_cert_service_,
+ channel_id_xtn_negotiated_,
+ ssl_config_.channel_id_enabled,
+ crypto::ECPrivateKey::IsSupported());
+
+ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
+ CHECK(cipher);
+ ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
+ const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
+
+ ssl_info->connection_status = EncodeSSLConnectionStatus(
+ SSL_CIPHER_get_id(cipher),
+ compression ? compression->type : 0,
+ GetNetSSLVersion(ssl_));
+
+ bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
+ if (!peer_supports_renego_ext)
+ ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
+ UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
+ implicit_cast<int>(peer_supports_renego_ext), 2);
+
+ if (ssl_config_.version_fallback)
+ ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK;
+
+ ssl_info->handshake_type = SSL_session_reused(ssl_) ?
+ SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
+
+ DVLOG(3) << "Encoded connection status: cipher suite = "
+ << SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
+ << " version = "
+ << SSLConnectionStatusToVersion(ssl_info->connection_status);
+ return true;
+}
+
+int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ user_read_buf_ = buf;
+ user_read_buf_len_ = buf_len;
+
+ int rv = DoReadLoop(OK);
+
+ if (rv == ERR_IO_PENDING) {
+ user_read_callback_ = callback;
+ } else {
+ user_read_buf_ = NULL;
+ user_read_buf_len_ = 0;
+ }
+
+ return rv;
+}
+
+int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ user_write_buf_ = buf;
+ user_write_buf_len_ = buf_len;
+
+ int rv = DoWriteLoop(OK);
+
+ if (rv == ERR_IO_PENDING) {
+ user_write_callback_ = callback;
+ } else {
+ user_write_buf_ = NULL;
+ user_write_buf_len_ = 0;
+ }
+
+ return rv;
+}
+
+bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
+ return transport_->socket()->SetReceiveBufferSize(size);
+}
+
+bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
+ return transport_->socket()->SetSendBufferSize(size);
+}
+
bool SSLClientSocketOpenSSL::Init() {
DCHECK(!ssl_);
DCHECK(!transport_bio_);
@@ -467,9 +656,8 @@ bool SSLClientSocketOpenSSL::Init() {
if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
return false;
- trying_cached_session_ =
- context->session_cache()->SetSSLSession(ssl_, host_and_port_,
- ssl_session_cache_shard_);
+ trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey(
+ ssl_, GetSocketSessionCacheKey(*this));
BIO* ssl_bio = NULL;
// 0 => use default buffer sizes.
@@ -566,149 +754,15 @@ bool SSLClientSocketOpenSSL::Init() {
// 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 true;
-}
-
-int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
- X509** x509,
- EVP_PKEY** pkey) {
- DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
- DCHECK(ssl == ssl_);
- DCHECK(*x509 == NULL);
- DCHECK(*pkey == NULL);
-
- if (!ssl_config_.send_client_cert) {
- // First pass: we know that a client certificate is needed, but we do not
- // have one at hand.
- client_auth_cert_needed_ = true;
- STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl);
- for (int i = 0; i < sk_X509_NAME_num(authorities); i++) {
- X509_NAME *ca_name = (X509_NAME *)sk_X509_NAME_value(authorities, i);
- unsigned char* str = NULL;
- int length = i2d_X509_NAME(ca_name, &str);
- cert_authorities_.push_back(std::string(
- reinterpret_cast<const char*>(str),
- static_cast<size_t>(length)));
- OPENSSL_free(str);
- }
- return -1; // Suspends handshake.
+ // TLS channel ids.
+ if (IsChannelIDEnabled(ssl_config_, server_bound_cert_service_)) {
+ SSL_enable_tls_channel_id(ssl_);
}
- // Second pass: a client certificate should have been selected.
- if (ssl_config_.client_cert.get()) {
- // A note about ownership: FetchClientCertPrivateKey() increments
- // the reference count of the EVP_PKEY. Ownership of this reference
- // is passed directly to OpenSSL, which will release the reference
- // using EVP_PKEY_free() when the SSL object is destroyed.
- OpenSSLClientKeyStore::ScopedEVP_PKEY privkey;
- if (OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
- ssl_config_.client_cert.get(), &privkey)) {
- // TODO(joth): (copied from NSS) We should wait for server certificate
- // verification before sending our credentials. See http://crbug.com/13934
- *x509 = X509Certificate::DupOSCertHandle(
- ssl_config_.client_cert->os_cert_handle());
- *pkey = privkey.release();
- return 1;
- }
- LOG(WARNING) << "Client cert found without private key";
- }
-
- // Send no client certificate.
- return 0;
-}
-
-// SSLClientSocket methods
-
-bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
- ssl_info->Reset();
- if (!server_cert_.get())
- return false;
-
- ssl_info->cert = server_cert_verify_result_.verified_cert;
- ssl_info->cert_status = server_cert_verify_result_.cert_status;
- ssl_info->is_issued_by_known_root =
- server_cert_verify_result_.is_issued_by_known_root;
- ssl_info->public_key_hashes =
- server_cert_verify_result_.public_key_hashes;
- ssl_info->client_cert_sent =
- ssl_config_.send_client_cert && ssl_config_.client_cert.get();
- ssl_info->channel_id_sent = WasChannelIDSent();
-
- const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
- CHECK(cipher);
- ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
- const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
-
- ssl_info->connection_status = EncodeSSLConnectionStatus(
- SSL_CIPHER_get_id(cipher),
- compression ? compression->type : 0,
- GetNetSSLVersion(ssl_));
-
- bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
- if (!peer_supports_renego_ext)
- ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
- UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
- implicit_cast<int>(peer_supports_renego_ext), 2);
-
- if (ssl_config_.version_fallback)
- ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK;
-
- ssl_info->handshake_type = SSL_session_reused(ssl_) ?
- SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
-
- DVLOG(3) << "Encoded connection status: cipher suite = "
- << SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
- << " version = "
- << SSLConnectionStatusToVersion(ssl_info->connection_status);
return true;
}
-void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
- SSLCertRequestInfo* cert_request_info) {
- cert_request_info->host_and_port = host_and_port_.ToString();
- cert_request_info->cert_authorities = cert_authorities_;
-}
-
-int SSLClientSocketOpenSSL::ExportKeyingMaterial(
- const base::StringPiece& label,
- bool has_context, const base::StringPiece& context,
- unsigned char* out, unsigned int outlen) {
- crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
- int rv = SSL_export_keying_material(
- ssl_, out, outlen, const_cast<char*>(label.data()),
- label.size(),
- reinterpret_cast<unsigned char*>(const_cast<char*>(context.data())),
- context.length(),
- context.length() > 0);
-
- if (rv != 1) {
- int ssl_error = SSL_get_error(ssl_, rv);
- LOG(ERROR) << "Failed to export keying material;"
- << " returned " << rv
- << ", SSL error code " << ssl_error;
- return MapOpenSSLError(ssl_error, err_tracer);
- }
- return OK;
-}
-
-int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
- return ERR_NOT_IMPLEMENTED;
-}
-
-SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
- std::string* proto, std::string* server_protos) {
- *proto = npn_proto_;
- *server_protos = server_protos_;
- return npn_status_;
-}
-
-ServerBoundCertService*
-SSLClientSocketOpenSSL::GetServerBoundCertService() const {
- return NULL;
-}
-
void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
// Since Run may result in Read being called, clear |user_read_callback_|
// up front.
@@ -725,107 +779,19 @@ void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
base::ResetAndReturn(&user_write_callback_).Run(rv);
}
-// StreamSocket implementation.
-int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
- net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
-
- // Set up new ssl object.
- if (!Init()) {
- int result = ERR_UNEXPECTED;
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
- return result;
- }
-
- // Set SSL to client mode. Handshake happens in the loop below.
- SSL_set_connect_state(ssl_);
-
- GotoState(STATE_HANDSHAKE);
- int rv = DoHandshakeLoop(net::OK);
- if (rv == ERR_IO_PENDING) {
- user_connect_callback_ = callback;
- } else {
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
- }
-
- return rv > OK ? OK : rv;
-}
-
-void SSLClientSocketOpenSSL::Disconnect() {
- if (ssl_) {
- // Calling SSL_shutdown prevents the session from being marked as
- // unresumable.
- SSL_shutdown(ssl_);
- SSL_free(ssl_);
- ssl_ = NULL;
- }
- if (transport_bio_) {
- BIO_free_all(transport_bio_);
- transport_bio_ = NULL;
- }
-
- // Shut down anything that may call us back.
- verifier_.reset();
- transport_->socket()->Disconnect();
-
- // Null all callbacks, delete all buffers.
- transport_send_busy_ = false;
- send_buffer_ = NULL;
- transport_recv_busy_ = false;
- transport_recv_eof_ = false;
- recv_buffer_ = NULL;
-
- user_connect_callback_.Reset();
- user_read_callback_.Reset();
- user_write_callback_.Reset();
- user_read_buf_ = NULL;
- user_read_buf_len_ = 0;
- user_write_buf_ = NULL;
- user_write_buf_len_ = 0;
-
- server_cert_verify_result_.Reset();
- completed_handshake_ = false;
-
- cert_authorities_.clear();
- client_auth_cert_needed_ = false;
-}
-
-int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
- int rv = last_io_result;
+bool SSLClientSocketOpenSSL::DoTransportIO() {
+ bool network_moved = false;
+ int rv;
+ // Read and write as much data as possible. The loop is necessary because
+ // Write() may return synchronously.
do {
- // Default to STATE_NONE for next state.
- // (This is a quirk carried over from the windows
- // implementation. It makes reading the logs a bit harder.)
- // State handlers can and often do call GotoState just
- // to stay in the current state.
- State state = next_handshake_state_;
- GotoState(STATE_NONE);
- switch (state) {
- case STATE_HANDSHAKE:
- rv = DoHandshake();
- break;
- case STATE_VERIFY_CERT:
- DCHECK(rv == OK);
- rv = DoVerifyCert(rv);
- break;
- case STATE_VERIFY_CERT_COMPLETE:
- rv = DoVerifyCertComplete(rv);
- break;
- case STATE_NONE:
- default:
- rv = ERR_UNEXPECTED;
- NOTREACHED() << "unexpected state" << state;
- break;
- }
-
- bool network_moved = DoTransportIO();
- if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
- // In general we exit the loop if rv is ERR_IO_PENDING. In this
- // special case we keep looping even if rv is ERR_IO_PENDING because
- // the transport IO may allow DoHandshake to make progress.
- rv = OK; // This causes us to stay in the loop.
- }
- } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
- return rv;
+ rv = BufferSend();
+ if (rv != ERR_IO_PENDING && rv != 0)
+ network_moved = true;
+ } while (rv > 0);
+ if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
+ network_moved = true;
+ return network_moved;
}
int SSLClientSocketOpenSSL::DoHandshake() {
@@ -863,7 +829,14 @@ int SSLClientSocketOpenSSL::DoHandshake() {
GotoState(STATE_VERIFY_CERT);
} else {
int ssl_error = SSL_get_error(ssl_, rv);
- net_error = MapOpenSSLError(ssl_error, err_tracer);
+
+ if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) {
+ // The server supports TLS channel id and the lookup is asynchronous.
+ // Retrieve the error from the call to |server_bound_cert_service_|.
+ net_error = channel_id_request_return_value_;
+ } else {
+ net_error = MapOpenSSLError(ssl_error, err_tracer);
+ }
// If not done, stay in this state
if (net_error == ERR_IO_PENDING) {
@@ -880,58 +853,6 @@ int SSLClientSocketOpenSSL::DoHandshake() {
return net_error;
}
-// SelectNextProtoCallback is called by OpenSSL during the handshake. If the
-// server supports NPN, selects a protocol from the list that the server
-// provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the
-// callback can assume that |in| is syntactically valid.
-int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
- unsigned char* outlen,
- const unsigned char* in,
- unsigned int inlen) {
-#if defined(OPENSSL_NPN_NEGOTIATED)
- if (ssl_config_.next_protos.empty()) {
- *out = reinterpret_cast<uint8*>(
- const_cast<char*>(kDefaultSupportedNPNProtocol));
- *outlen = arraysize(kDefaultSupportedNPNProtocol) - 1;
- npn_status_ = kNextProtoUnsupported;
- return SSL_TLSEXT_ERR_OK;
- }
-
- // Assume there's no overlap between our protocols and the server's list.
- npn_status_ = kNextProtoNoOverlap;
-
- // For each protocol in server preference order, see if we support it.
- for (unsigned int i = 0; i < inlen; i += in[i] + 1) {
- for (std::vector<std::string>::const_iterator
- j = ssl_config_.next_protos.begin();
- j != ssl_config_.next_protos.end(); ++j) {
- if (in[i] == j->size() &&
- memcmp(&in[i + 1], j->data(), in[i]) == 0) {
- // We found a match.
- *out = const_cast<unsigned char*>(in) + i + 1;
- *outlen = in[i];
- npn_status_ = kNextProtoNegotiated;
- break;
- }
- }
- if (npn_status_ == kNextProtoNegotiated)
- break;
- }
-
- // If we didn't find a protocol, we select the first one from our list.
- if (npn_status_ == kNextProtoNoOverlap) {
- *out = reinterpret_cast<uint8*>(const_cast<char*>(
- ssl_config_.next_protos[0].data()));
- *outlen = ssl_config_.next_protos[0].size();
- }
-
- npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
- server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
- DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
-#endif
- return SSL_TLSEXT_ERR_OK;
-}
-
int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
DCHECK(server_cert_.get());
GotoState(STATE_VERIFY_CERT_COMPLETE);
@@ -972,6 +893,7 @@ int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
if (result == OK) {
// TODO(joth): Work out if we need to remember the intermediate CA certs
// when the server sends them to us, and do so here.
+ SSLContext::GetInstance()->session_cache()->MarkSSLSessionAsGood(ssl_);
} else {
DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result)
<< " (" << result << ")";
@@ -983,6 +905,14 @@ int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
return result;
}
+void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
+ if (!user_connect_callback_.is_null()) {
+ CompletionCallback c = user_connect_callback_;
+ user_connect_callback_.Reset();
+ c.Run(rv > OK ? OK : rv);
+ }
+}
+
X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
if (server_cert_.get())
return server_cert_.get();
@@ -1007,146 +937,6 @@ X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
return server_cert_.get();
}
-bool SSLClientSocketOpenSSL::DoTransportIO() {
- bool network_moved = false;
- int rv;
- // Read and write as much data as possible. The loop is necessary because
- // Write() may return synchronously.
- do {
- rv = BufferSend();
- if (rv != ERR_IO_PENDING && rv != 0)
- network_moved = true;
- } while (rv > 0);
- if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
- network_moved = true;
- return network_moved;
-}
-
-int SSLClientSocketOpenSSL::BufferSend(void) {
- if (transport_send_busy_)
- return ERR_IO_PENDING;
-
- if (!send_buffer_.get()) {
- // Get a fresh send buffer out of the send BIO.
- size_t max_read = BIO_ctrl_pending(transport_bio_);
- if (!max_read)
- return 0; // Nothing pending in the OpenSSL write BIO.
- send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
- int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
- DCHECK_GT(read_bytes, 0);
- CHECK_EQ(static_cast<int>(max_read), read_bytes);
- }
-
- int rv = transport_->socket()->Write(
- send_buffer_.get(),
- send_buffer_->BytesRemaining(),
- base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
- base::Unretained(this)));
- if (rv == ERR_IO_PENDING) {
- transport_send_busy_ = true;
- } else {
- TransportWriteComplete(rv);
- }
- return rv;
-}
-
-void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
- transport_send_busy_ = false;
- TransportWriteComplete(result);
- OnSendComplete(result);
-}
-
-void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
- DCHECK(ERR_IO_PENDING != result);
- if (result < 0) {
- // Got a socket write error; close the BIO to indicate this upward.
- DVLOG(1) << "TransportWriteComplete error " << result;
- (void)BIO_shutdown_wr(transport_bio_);
- BIO_set_mem_eof_return(transport_bio_, 0);
- send_buffer_ = NULL;
- } else {
- DCHECK(send_buffer_.get());
- send_buffer_->DidConsume(result);
- DCHECK_GE(send_buffer_->BytesRemaining(), 0);
- if (send_buffer_->BytesRemaining() <= 0)
- send_buffer_ = NULL;
- }
-}
-
-int SSLClientSocketOpenSSL::BufferRecv(void) {
- if (transport_recv_busy_)
- return ERR_IO_PENDING;
-
- // Determine how much was requested from |transport_bio_| that was not
- // actually available.
- size_t requested = BIO_ctrl_get_read_request(transport_bio_);
- if (requested == 0) {
- // This is not a perfect match of error codes, as no operation is
- // actually pending. However, returning 0 would be interpreted as
- // a possible sign of EOF, which is also an inappropriate match.
- return ERR_IO_PENDING;
- }
-
- // Known Issue: While only reading |requested| data is the more correct
- // implementation, it has the downside of resulting in frequent reads:
- // One read for the SSL record header (~5 bytes) and one read for the SSL
- // record body. Rather than issuing these reads to the underlying socket
- // (and constantly allocating new IOBuffers), a single Read() request to
- // fill |transport_bio_| is issued. As long as an SSL client socket cannot
- // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
- // traffic, this over-subscribed Read()ing will not cause issues.
- size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
- if (!max_write)
- return ERR_IO_PENDING;
-
- recv_buffer_ = new IOBuffer(max_write);
- int rv = transport_->socket()->Read(
- recv_buffer_.get(),
- max_write,
- base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
- base::Unretained(this)));
- if (rv == ERR_IO_PENDING) {
- transport_recv_busy_ = true;
- } else {
- TransportReadComplete(rv);
- }
- return rv;
-}
-
-void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
- TransportReadComplete(result);
- OnRecvComplete(result);
-}
-
-void SSLClientSocketOpenSSL::TransportReadComplete(int result) {
- DCHECK(ERR_IO_PENDING != result);
- if (result <= 0) {
- DVLOG(1) << "TransportReadComplete result " << result;
- // Received 0 (end of file) or an error. Either way, bubble it up to the
- // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
- // relay up to the SSL socket client (i.e. via DoReadCallback).
- if (result == 0)
- transport_recv_eof_ = true;
- BIO_set_mem_eof_return(transport_bio_, 0);
- (void)BIO_shutdown_wr(transport_bio_);
- } else {
- DCHECK(recv_buffer_.get());
- int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
- // A write into a memory BIO should always succeed.
- CHECK_EQ(result, ret);
- }
- recv_buffer_ = NULL;
- transport_recv_busy_ = false;
-}
-
-void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
- if (!user_connect_callback_.is_null()) {
- CompletionCallback c = user_connect_callback_;
- user_connect_callback_.Reset();
- c.Run(rv > OK ? OK : rv);
- }
-}
-
void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
int rv = DoHandshakeLoop(result);
if (rv != ERR_IO_PENDING) {
@@ -1207,95 +997,42 @@ void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
DoReadCallback(rv);
}
-bool SSLClientSocketOpenSSL::IsConnected() const {
- // If the handshake has not yet completed.
- if (!completed_handshake_)
- return false;
- // If an asynchronous operation is still pending.
- if (user_read_buf_.get() || user_write_buf_.get())
- return true;
-
- return transport_->socket()->IsConnected();
-}
-
-bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
- // If the handshake has not yet completed.
- if (!completed_handshake_)
- return false;
- // If an asynchronous operation is still pending.
- if (user_read_buf_.get() || user_write_buf_.get())
- return false;
- // If there is data waiting to be sent, or data read from the network that
- // has not yet been consumed.
- if (BIO_ctrl_pending(transport_bio_) > 0 ||
- BIO_ctrl_wpending(transport_bio_) > 0) {
- return false;
- }
-
- return transport_->socket()->IsConnectedAndIdle();
-}
-
-int SSLClientSocketOpenSSL::GetPeerAddress(IPEndPoint* addressList) const {
- return transport_->socket()->GetPeerAddress(addressList);
-}
-
-int SSLClientSocketOpenSSL::GetLocalAddress(IPEndPoint* addressList) const {
- return transport_->socket()->GetLocalAddress(addressList);
-}
-
-const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
- return net_log_;
-}
-
-void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
- if (transport_.get() && transport_->socket()) {
- transport_->socket()->SetSubresourceSpeculation();
- } else {
- NOTREACHED();
- }
-}
-
-void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
- if (transport_.get() && transport_->socket()) {
- transport_->socket()->SetOmniboxSpeculation();
- } else {
- NOTREACHED();
- }
-}
-
-bool SSLClientSocketOpenSSL::WasEverUsed() const {
- if (transport_.get() && transport_->socket())
- return transport_->socket()->WasEverUsed();
-
- NOTREACHED();
- return false;
-}
-
-bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
- if (transport_.get() && transport_->socket())
- return transport_->socket()->UsingTCPFastOpen();
-
- NOTREACHED();
- return false;
-}
-
-// Socket methods
-
-int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) {
- user_read_buf_ = buf;
- user_read_buf_len_ = buf_len;
-
- int rv = DoReadLoop(OK);
-
- if (rv == ERR_IO_PENDING) {
- user_read_callback_ = callback;
- } else {
- user_read_buf_ = NULL;
- user_read_buf_len_ = 0;
- }
+int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
+ int rv = last_io_result;
+ do {
+ // Default to STATE_NONE for next state.
+ // (This is a quirk carried over from the windows
+ // implementation. It makes reading the logs a bit harder.)
+ // State handlers can and often do call GotoState just
+ // to stay in the current state.
+ State state = next_handshake_state_;
+ GotoState(STATE_NONE);
+ switch (state) {
+ case STATE_HANDSHAKE:
+ rv = DoHandshake();
+ break;
+ case STATE_VERIFY_CERT:
+ DCHECK(rv == OK);
+ rv = DoVerifyCert(rv);
+ break;
+ case STATE_VERIFY_CERT_COMPLETE:
+ rv = DoVerifyCertComplete(rv);
+ break;
+ case STATE_NONE:
+ default:
+ rv = ERR_UNEXPECTED;
+ NOTREACHED() << "unexpected state" << state;
+ break;
+ }
+ bool network_moved = DoTransportIO();
+ if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
+ // In general we exit the loop if rv is ERR_IO_PENDING. In this
+ // special case we keep looping even if rv is ERR_IO_PENDING because
+ // the transport IO may allow DoHandshake to make progress.
+ rv = OK; // This causes us to stay in the loop.
+ }
+ } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
return rv;
}
@@ -1313,24 +1050,6 @@ int SSLClientSocketOpenSSL::DoReadLoop(int result) {
return rv;
}
-int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
- int buf_len,
- const CompletionCallback& callback) {
- user_write_buf_ = buf;
- user_write_buf_len_ = buf_len;
-
- int rv = DoWriteLoop(OK);
-
- if (rv == ERR_IO_PENDING) {
- user_write_callback_ = callback;
- } else {
- user_write_buf_ = NULL;
- user_write_buf_len_ = 0;
- }
-
- return rv;
-}
-
int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
if (result < 0)
return result;
@@ -1345,14 +1064,6 @@ int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
return rv;
}
-bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
- return transport_->socket()->SetReceiveBufferSize(size);
-}
-
-bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
- return transport_->socket()->SetSendBufferSize(size);
-}
-
int SSLClientSocketOpenSSL::DoPayloadRead() {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
@@ -1434,4 +1145,278 @@ int SSLClientSocketOpenSSL::DoPayloadWrite() {
return MapOpenSSLError(err, err_tracer);
}
+int SSLClientSocketOpenSSL::BufferSend(void) {
+ if (transport_send_busy_)
+ return ERR_IO_PENDING;
+
+ if (!send_buffer_.get()) {
+ // Get a fresh send buffer out of the send BIO.
+ size_t max_read = BIO_ctrl_pending(transport_bio_);
+ if (!max_read)
+ return 0; // Nothing pending in the OpenSSL write BIO.
+ send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
+ int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
+ DCHECK_GT(read_bytes, 0);
+ CHECK_EQ(static_cast<int>(max_read), read_bytes);
+ }
+
+ int rv = transport_->socket()->Write(
+ send_buffer_.get(),
+ send_buffer_->BytesRemaining(),
+ base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
+ base::Unretained(this)));
+ if (rv == ERR_IO_PENDING) {
+ transport_send_busy_ = true;
+ } else {
+ TransportWriteComplete(rv);
+ }
+ return rv;
+}
+
+int SSLClientSocketOpenSSL::BufferRecv(void) {
+ if (transport_recv_busy_)
+ return ERR_IO_PENDING;
+
+ // Determine how much was requested from |transport_bio_| that was not
+ // actually available.
+ size_t requested = BIO_ctrl_get_read_request(transport_bio_);
+ if (requested == 0) {
+ // This is not a perfect match of error codes, as no operation is
+ // actually pending. However, returning 0 would be interpreted as
+ // a possible sign of EOF, which is also an inappropriate match.
+ return ERR_IO_PENDING;
+ }
+
+ // Known Issue: While only reading |requested| data is the more correct
+ // implementation, it has the downside of resulting in frequent reads:
+ // One read for the SSL record header (~5 bytes) and one read for the SSL
+ // record body. Rather than issuing these reads to the underlying socket
+ // (and constantly allocating new IOBuffers), a single Read() request to
+ // fill |transport_bio_| is issued. As long as an SSL client socket cannot
+ // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
+ // traffic, this over-subscribed Read()ing will not cause issues.
+ size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
+ if (!max_write)
+ return ERR_IO_PENDING;
+
+ recv_buffer_ = new IOBuffer(max_write);
+ int rv = transport_->socket()->Read(
+ recv_buffer_.get(),
+ max_write,
+ base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
+ base::Unretained(this)));
+ if (rv == ERR_IO_PENDING) {
+ transport_recv_busy_ = true;
+ } else {
+ rv = TransportReadComplete(rv);
+ }
+ return rv;
+}
+
+void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
+ transport_send_busy_ = false;
+ TransportWriteComplete(result);
+ OnSendComplete(result);
+}
+
+void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
+ result = TransportReadComplete(result);
+ OnRecvComplete(result);
+}
+
+void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
+ DCHECK(ERR_IO_PENDING != result);
+ if (result < 0) {
+ // Got a socket write error; close the BIO to indicate this upward.
+ //
+ // TODO(davidben): The value of |result| gets lost. Feed the error back into
+ // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with
+ // BIO_set_callback.
+ DVLOG(1) << "TransportWriteComplete error " << result;
+ (void)BIO_shutdown_wr(SSL_get_wbio(ssl_));
+
+ // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
+ // from the socket after a write error.
+ //
+ // TODO(davidben): Avoid having read and write ends interact this way.
+ transport_write_error_ = result;
+ (void)BIO_shutdown_wr(transport_bio_);
+ send_buffer_ = NULL;
+ } else {
+ DCHECK(send_buffer_.get());
+ send_buffer_->DidConsume(result);
+ DCHECK_GE(send_buffer_->BytesRemaining(), 0);
+ if (send_buffer_->BytesRemaining() <= 0)
+ send_buffer_ = NULL;
+ }
+}
+
+int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
+ DCHECK(ERR_IO_PENDING != result);
+ if (result <= 0) {
+ DVLOG(1) << "TransportReadComplete result " << result;
+ // Received 0 (end of file) or an error. Either way, bubble it up to the
+ // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
+ // relay up to the SSL socket client (i.e. via DoReadCallback).
+ if (result == 0)
+ transport_recv_eof_ = true;
+ (void)BIO_shutdown_wr(transport_bio_);
+ } else if (transport_write_error_ < 0) {
+ // Mirror transport write errors as read failures; transport_bio_ has been
+ // shut down by TransportWriteComplete, so the BIO_write will fail, failing
+ // the CHECK. http://crbug.com/335557.
+ result = transport_write_error_;
+ } else {
+ DCHECK(recv_buffer_.get());
+ int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
+ // A write into a memory BIO should always succeed.
+ // Force values on the stack for http://crbug.com/335557
+ base::debug::Alias(&result);
+ base::debug::Alias(&ret);
+ CHECK_EQ(result, ret);
+ }
+ recv_buffer_ = NULL;
+ transport_recv_busy_ = false;
+ return result;
+}
+
+int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
+ X509** x509,
+ EVP_PKEY** pkey) {
+ DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
+ DCHECK(ssl == ssl_);
+ DCHECK(*x509 == NULL);
+ DCHECK(*pkey == NULL);
+
+ if (!ssl_config_.send_client_cert) {
+ // First pass: we know that a client certificate is needed, but we do not
+ // have one at hand.
+ client_auth_cert_needed_ = true;
+ STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl);
+ for (int i = 0; i < sk_X509_NAME_num(authorities); i++) {
+ X509_NAME *ca_name = (X509_NAME *)sk_X509_NAME_value(authorities, i);
+ unsigned char* str = NULL;
+ int length = i2d_X509_NAME(ca_name, &str);
+ cert_authorities_.push_back(std::string(
+ reinterpret_cast<const char*>(str),
+ static_cast<size_t>(length)));
+ OPENSSL_free(str);
+ }
+
+ return -1; // Suspends handshake.
+ }
+
+ // Second pass: a client certificate should have been selected.
+ if (ssl_config_.client_cert.get()) {
+ // A note about ownership: FetchClientCertPrivateKey() increments
+ // the reference count of the EVP_PKEY. Ownership of this reference
+ // is passed directly to OpenSSL, which will release the reference
+ // using EVP_PKEY_free() when the SSL object is destroyed.
+ OpenSSLClientKeyStore::ScopedEVP_PKEY privkey;
+ if (OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
+ ssl_config_.client_cert.get(), &privkey)) {
+ // TODO(joth): (copied from NSS) We should wait for server certificate
+ // verification before sending our credentials. See http://crbug.com/13934
+ *x509 = X509Certificate::DupOSCertHandle(
+ ssl_config_.client_cert->os_cert_handle());
+ *pkey = privkey.release();
+ return 1;
+ }
+ LOG(WARNING) << "Client cert found without private key";
+ }
+
+ // Send no client certificate.
+ return 0;
+}
+
+void SSLClientSocketOpenSSL::ChannelIDRequestCallback(SSL* ssl,
+ EVP_PKEY** pkey) {
+ DVLOG(3) << "OpenSSL ChannelIDRequestCallback called";
+ DCHECK_EQ(ssl, ssl_);
+ DCHECK(!*pkey);
+
+ channel_id_xtn_negotiated_ = true;
+ if (!channel_id_private_key_.size()) {
+ channel_id_request_return_value_ =
+ server_bound_cert_service_->GetOrCreateDomainBoundCert(
+ host_and_port_.host(),
+ &channel_id_private_key_,
+ &channel_id_cert_,
+ base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete,
+ base::Unretained(this)),
+ &channel_id_request_handle_);
+ if (channel_id_request_return_value_ != OK)
+ return;
+ }
+
+ // Decode key.
+ std::vector<uint8> encrypted_private_key_info;
+ std::vector<uint8> subject_public_key_info;
+ encrypted_private_key_info.assign(
+ channel_id_private_key_.data(),
+ channel_id_private_key_.data() + channel_id_private_key_.size());
+ subject_public_key_info.assign(
+ channel_id_cert_.data(),
+ channel_id_cert_.data() + channel_id_cert_.size());
+ scoped_ptr<crypto::ECPrivateKey> ec_private_key(
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+ ServerBoundCertService::kEPKIPassword,
+ encrypted_private_key_info,
+ subject_public_key_info));
+ set_channel_id_sent(true);
+ *pkey = EVP_PKEY_dup(ec_private_key->key());
+}
+
+// SelectNextProtoCallback is called by OpenSSL during the handshake. If the
+// server supports NPN, selects a protocol from the list that the server
+// provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the
+// callback can assume that |in| is syntactically valid.
+int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
+ unsigned char* outlen,
+ const unsigned char* in,
+ unsigned int inlen) {
+#if defined(OPENSSL_NPN_NEGOTIATED)
+ if (ssl_config_.next_protos.empty()) {
+ *out = reinterpret_cast<uint8*>(
+ const_cast<char*>(kDefaultSupportedNPNProtocol));
+ *outlen = arraysize(kDefaultSupportedNPNProtocol) - 1;
+ npn_status_ = kNextProtoUnsupported;
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+ // Assume there's no overlap between our protocols and the server's list.
+ npn_status_ = kNextProtoNoOverlap;
+
+ // For each protocol in server preference order, see if we support it.
+ for (unsigned int i = 0; i < inlen; i += in[i] + 1) {
+ for (std::vector<std::string>::const_iterator
+ j = ssl_config_.next_protos.begin();
+ j != ssl_config_.next_protos.end(); ++j) {
+ if (in[i] == j->size() &&
+ memcmp(&in[i + 1], j->data(), in[i]) == 0) {
+ // We found a match.
+ *out = const_cast<unsigned char*>(in) + i + 1;
+ *outlen = in[i];
+ npn_status_ = kNextProtoNegotiated;
+ break;
+ }
+ }
+ if (npn_status_ == kNextProtoNegotiated)
+ break;
+ }
+
+ // If we didn't find a protocol, we select the first one from our list.
+ if (npn_status_ == kNextProtoNoOverlap) {
+ *out = reinterpret_cast<uint8*>(const_cast<char*>(
+ ssl_config_.next_protos[0].data()));
+ *outlen = ssl_config_.next_protos[0].size();
+ }
+
+ npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
+ server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
+ DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
+#endif
+ return SSL_TLSEXT_ERR_OK;
+}
+
} // namespace net
diff --git a/chromium/net/socket/ssl_client_socket_openssl.h b/chromium/net/socket/ssl_client_socket_openssl.h
index f66d95cc69d..5f4800a08de 100644
--- a/chromium/net/socket/ssl_client_socket_openssl.h
+++ b/chromium/net/socket/ssl_client_socket_openssl.h
@@ -15,6 +15,7 @@
#include "net/cert/cert_verify_result.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
+#include "net/ssl/server_bound_cert_service.h"
#include "net/ssl/ssl_config_service.h"
// Avoid including misc OpenSSL headers, i.e.:
@@ -52,14 +53,6 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
return ssl_session_cache_shard_;
}
- // Callback from the SSL layer that indicates the remote server is requesting
- // a certificate for this client.
- int ClientCertRequestCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey);
-
- // Callback from the SSL layer to check which NPN protocol we are supporting
- int SelectNextProtoCallback(unsigned char** out, unsigned char* outlen,
- const unsigned char* in, unsigned int inlen);
-
// SSLClientSocket implementation.
virtual void GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) OVERRIDE;
@@ -98,6 +91,10 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
virtual bool SetSendBufferSize(int32 size) OVERRIDE;
private:
+ class SSLContext;
+ friend class SSLClientSocket;
+ friend class SSLContext;
+
bool Init();
void DoReadCallback(int result);
void DoWriteCallback(int result);
@@ -124,7 +121,19 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
void BufferSendComplete(int result);
void BufferRecvComplete(int result);
void TransportWriteComplete(int result);
- void TransportReadComplete(int result);
+ int TransportReadComplete(int result);
+
+ // Callback from the SSL layer that indicates the remote server is requesting
+ // a certificate for this client.
+ int ClientCertRequestCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey);
+
+ // Callback from the SSL layer that indicates the remote server supports TLS
+ // Channel IDs.
+ void ChannelIDRequestCallback(SSL* ssl, EVP_PKEY** pkey);
+
+ // Callback from the SSL layer to check which NPN protocol we are supporting
+ int SelectNextProtoCallback(unsigned char** out, unsigned char* outlen,
+ const unsigned char* in, unsigned int inlen);
bool transport_send_busy_;
bool transport_recv_busy_;
@@ -155,6 +164,10 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
// indicates an error.
int pending_read_error_;
+ // 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_;
+
// Set when handshake finishes.
scoped_refptr<X509Certificate> server_cert_;
CertVerifyResult server_cert_verify_result_;
@@ -170,6 +183,9 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
CertVerifier* const cert_verifier_;
scoped_ptr<SingleRequestCertVerifier> verifier_;
+ // The service for retrieving Channel ID keys. May be NULL.
+ ServerBoundCertService* server_bound_cert_service_;
+
// OpenSSL stuff
SSL* ssl_;
BIO* transport_bio_;
@@ -195,6 +211,15 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
NextProtoStatus npn_status_;
std::string npn_proto_;
std::string server_protos_;
+ // Written by the |server_bound_cert_service_|.
+ std::string channel_id_private_key_;
+ std::string channel_id_cert_;
+ // The return value of the last call to |server_bound_cert_service_|.
+ int channel_id_request_return_value_;
+ // True if channel ID extension was negotiated.
+ bool channel_id_xtn_negotiated_;
+ // The request handle for |server_bound_cert_service_|.
+ ServerBoundCertService::RequestHandle channel_id_request_handle_;
BoundNetLog net_log_;
};
diff --git a/chromium/net/socket/ssl_client_socket_openssl_unittest.cc b/chromium/net/socket/ssl_client_socket_openssl_unittest.cc
index 24c06059be5..48a4813f159 100644
--- a/chromium/net/socket/ssl_client_socket_openssl_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_openssl_unittest.cc
@@ -17,6 +17,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_handle.h"
+#include "base/message_loop/message_loop_proxy.h"
#include "base/values.h"
#include "crypto/openssl_util.h"
#include "net/base/address_list.h"
@@ -34,7 +35,9 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/tcp_client_socket.h"
+#include "net/ssl/default_server_bound_cert_store.h"
#include "net/ssl/openssl_client_key_store.h"
+#include "net/ssl/server_bound_cert_service.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_config_service.h"
#include "net/test/cert_test_util.h"
@@ -59,6 +62,35 @@ typedef crypto::ScopedOpenSSL<BIGNUM, BN_free> ScopedBIGNUM;
const SSLConfig kDefaultSSLConfig;
+// A ServerBoundCertStore that always returns an error when asked for a
+// certificate.
+class FailingServerBoundCertStore : public ServerBoundCertStore {
+ virtual int GetServerBoundCert(const std::string& server_identifier,
+ base::Time* expiration_time,
+ std::string* private_key_result,
+ std::string* cert_result,
+ const GetCertCallback& callback) OVERRIDE {
+ return ERR_UNEXPECTED;
+ }
+ virtual void SetServerBoundCert(const std::string& server_identifier,
+ base::Time creation_time,
+ base::Time expiration_time,
+ const std::string& private_key,
+ const std::string& cert) OVERRIDE {}
+ virtual void DeleteServerBoundCert(const std::string& server_identifier,
+ const base::Closure& completion_callback)
+ OVERRIDE {}
+ virtual void DeleteAllCreatedBetween(base::Time delete_begin,
+ base::Time delete_end,
+ const base::Closure& completion_callback)
+ OVERRIDE {}
+ virtual void DeleteAll(const base::Closure& completion_callback) OVERRIDE {}
+ virtual void GetAllServerBoundCerts(const GetCertListCallback& callback)
+ OVERRIDE {}
+ virtual int GetCertCount() OVERRIDE { return 0; }
+ virtual void SetForceKeepSessionState() OVERRIDE {}
+};
+
// 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.
@@ -107,6 +139,20 @@ class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
}
protected:
+ void EnabledChannelID() {
+ cert_service_.reset(
+ new ServerBoundCertService(new DefaultServerBoundCertStore(NULL),
+ base::MessageLoopProxy::current()));
+ context_.server_bound_cert_service = cert_service_.get();
+ }
+
+ void EnabledFailingChannelID() {
+ cert_service_.reset(
+ new ServerBoundCertService(new FailingServerBoundCertStore(),
+ base::MessageLoopProxy::current()));
+ context_.server_bound_cert_service = cert_service_.get();
+ }
+
scoped_ptr<SSLClientSocket> CreateSSLClientSocket(
scoped_ptr<StreamSocket> transport_socket,
const HostPortPair& host_and_port,
@@ -188,6 +234,7 @@ class SSLClientSocketOpenSSLClientAuthTest : public PlatformTest {
return ssl_info.client_cert_sent;
}
+ scoped_ptr<ServerBoundCertService> cert_service_;
ClientSocketFactory* socket_factory_;
scoped_ptr<MockCertVerifier> cert_verifier_;
scoped_ptr<TransportSecurityState> transport_security_state_;
@@ -275,5 +322,44 @@ TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendGoodCert) {
EXPECT_FALSE(sock_->IsConnected());
}
+// Connect to a server using channel id. It should allow the connection.
+TEST_F(SSLClientSocketOpenSSLClientAuthTest, SendChannelID) {
+ SpawnedTestServer::SSLOptions ssl_options;
+
+ ASSERT_TRUE(ConnectToTestServer(ssl_options));
+
+ EnabledChannelID();
+ SSLConfig ssl_config = kDefaultSSLConfig;
+ ssl_config.channel_id_enabled = true;
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock_->IsConnected());
+ EXPECT_TRUE(sock_->WasChannelIDSent());
+
+ sock_->Disconnect();
+ EXPECT_FALSE(sock_->IsConnected());
+}
+
+// Connect to a server using channel id but without sending a key. It should
+// fail.
+TEST_F(SSLClientSocketOpenSSLClientAuthTest, FailingChannelID) {
+ SpawnedTestServer::SSLOptions ssl_options;
+
+ ASSERT_TRUE(ConnectToTestServer(ssl_options));
+
+ EnabledFailingChannelID();
+ SSLConfig ssl_config = kDefaultSSLConfig;
+ ssl_config.channel_id_enabled = true;
+
+ int rv;
+ ASSERT_TRUE(CreateAndConnectSSLClientSocket(ssl_config, &rv));
+
+ EXPECT_EQ(ERR_UNEXPECTED, rv);
+ EXPECT_FALSE(sock_->IsConnected());
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/socket/ssl_client_socket_pool.cc b/chromium/net/socket/ssl_client_socket_pool.cc
index 5d574b7edda..de315fdc01a 100644
--- a/chromium/net/socket/ssl_client_socket_pool.cc
+++ b/chromium/net/socket/ssl_client_socket_pool.cc
@@ -123,6 +123,7 @@ SSLConnectJob::SSLConnectJob(const std::string& group_name,
context_(context.cert_verifier,
context.server_bound_cert_service,
context.transport_security_state,
+ context.cert_transparency_verifier,
(params->privacy_mode() == kPrivacyModeEnabled
? "pm/" + context.ssl_session_cache_shard
: context.ssl_session_cache_shard)),
@@ -508,6 +509,7 @@ SSLClientSocketPool::SSLClientSocketPool(
CertVerifier* cert_verifier,
ServerBoundCertService* server_bound_cert_service,
TransportSecurityState* transport_security_state,
+ CTVerifier* cert_transparency_verifier,
const std::string& ssl_session_cache_shard,
ClientSocketFactory* client_socket_factory,
TransportClientSocketPool* transport_pool,
@@ -530,6 +532,7 @@ SSLClientSocketPool::SSLClientSocketPool(
cert_verifier,
server_bound_cert_service,
transport_security_state,
+ cert_transparency_verifier,
ssl_session_cache_shard),
net_log)),
ssl_config_service_(ssl_config_service) {
diff --git a/chromium/net/socket/ssl_client_socket_pool.h b/chromium/net/socket/ssl_client_socket_pool.h
index ec62eb01f46..e03b76ade6a 100644
--- a/chromium/net/socket/ssl_client_socket_pool.h
+++ b/chromium/net/socket/ssl_client_socket_pool.h
@@ -24,6 +24,7 @@ namespace net {
class CertVerifier;
class ClientSocketFactory;
class ConnectJobFactory;
+class CTVerifier;
class HostPortPair;
class HttpProxyClientSocketPool;
class HttpProxySocketParams;
@@ -189,6 +190,7 @@ class NET_EXPORT_PRIVATE SSLClientSocketPool
CertVerifier* cert_verifier,
ServerBoundCertService* server_bound_cert_service,
TransportSecurityState* transport_security_state,
+ CTVerifier* cert_transparency_verifier,
const std::string& ssl_session_cache_shard,
ClientSocketFactory* client_socket_factory,
TransportClientSocketPool* transport_pool,
diff --git a/chromium/net/socket/ssl_client_socket_pool_unittest.cc b/chromium/net/socket/ssl_client_socket_pool_unittest.cc
index 8aecb98dd85..92ad51a4351 100644
--- a/chromium/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_pool_unittest.cc
@@ -140,6 +140,7 @@ class SSLClientSocketPoolTest
NULL /* cert_verifier */,
NULL /* server_bound_cert_service */,
NULL /* transport_security_state */,
+ NULL /* cert_transparency_verifier */,
std::string() /* ssl_session_cache_shard */,
&socket_factory_,
transport_pool ? &transport_socket_pool_ : NULL,
@@ -225,7 +226,8 @@ class SSLClientSocketPoolTest
INSTANTIATE_TEST_CASE_P(
NextProto,
SSLClientSocketPoolTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
TEST_P(SSLClientSocketPoolTest, TCPFail) {
@@ -297,7 +299,7 @@ TEST_P(SSLClientSocketPoolTest, SetSocketRequestPriorityOnInitDirect) {
scoped_refptr<SSLSocketParams> params =
SSLParams(ProxyServer::SCHEME_DIRECT, false);
- for (int i = MINIMUM_PRIORITY; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
RequestPriority priority = static_cast<RequestPriority>(i);
StaticSocketDataProvider data;
data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
diff --git a/chromium/net/socket/ssl_client_socket_unittest.cc b/chromium/net/socket/ssl_client_socket_unittest.cc
index f791928580f..14633a958ba 100644
--- a/chromium/net/socket/ssl_client_socket_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_unittest.cc
@@ -1171,6 +1171,112 @@ TEST_F(SSLClientSocketTest, Read_DeleteWhilePendingFullDuplex) {
EXPECT_FALSE(callback.have_result());
}
+// Tests that the SSLClientSocket does not crash if data is received on the
+// transport socket after a failing write. This can occur if we have a Write
+// error in a SPDY socket.
+// Regression test for http://crbug.com/335557
+TEST_F(SSLClientSocketTest, Read_WithWriteError) {
+ SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+ SpawnedTestServer::kLocalhost,
+ base::FilePath());
+ ASSERT_TRUE(test_server.Start());
+
+ AddressList addr;
+ ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+ TestCompletionCallback callback;
+ scoped_ptr<StreamSocket> real_transport(
+ new TCPClientSocket(addr, NULL, NetLog::Source()));
+ // Note: |error_socket|'s ownership is handed to |transport|, but a pointer
+ // is retained in order to configure additional errors.
+ scoped_ptr<SynchronousErrorStreamSocket> error_socket(
+ new SynchronousErrorStreamSocket(real_transport.Pass()));
+ SynchronousErrorStreamSocket* raw_error_socket = error_socket.get();
+ scoped_ptr<FakeBlockingStreamSocket> transport(
+ new FakeBlockingStreamSocket(error_socket.PassAs<StreamSocket>()));
+ FakeBlockingStreamSocket* raw_transport = transport.get();
+
+ int rv = callback.GetResult(transport->Connect(callback.callback()));
+ EXPECT_EQ(OK, rv);
+
+ // Disable TLS False Start to avoid handshake non-determinism.
+ SSLConfig ssl_config;
+ ssl_config.false_start_enabled = false;
+
+ scoped_ptr<SSLClientSocket> sock(
+ CreateSSLClientSocket(transport.PassAs<StreamSocket>(),
+ test_server.host_port_pair(),
+ ssl_config));
+
+ rv = callback.GetResult(sock->Connect(callback.callback()));
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock->IsConnected());
+
+ // Send a request so there is something to read from the socket.
+ const char request_text[] = "GET / HTTP/1.0\r\n\r\n";
+ static const int kRequestTextSize =
+ static_cast<int>(arraysize(request_text) - 1);
+ scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestTextSize));
+ memcpy(request_buffer->data(), request_text, kRequestTextSize);
+
+ rv = callback.GetResult(
+ sock->Write(request_buffer.get(), kRequestTextSize, callback.callback()));
+ EXPECT_EQ(kRequestTextSize, rv);
+
+ // Start a hanging read.
+ TestCompletionCallback read_callback;
+ raw_transport->SetNextReadShouldBlock();
+ scoped_refptr<IOBuffer> buf(new IOBuffer(4096));
+ rv = sock->Read(buf.get(), 4096, read_callback.callback());
+ EXPECT_EQ(ERR_IO_PENDING, rv);
+
+ // Perform another write, but have it fail. Write a request larger than the
+ // internal socket buffers so that the request hits the underlying transport
+ // socket and detects the error.
+ std::string long_request_text =
+ "GET / HTTP/1.1\r\nUser-Agent: long browser name ";
+ long_request_text.append(20 * 1024, '*');
+ long_request_text.append("\r\n\r\n");
+ scoped_refptr<DrainableIOBuffer> long_request_buffer(new DrainableIOBuffer(
+ new StringIOBuffer(long_request_text), long_request_text.size()));
+
+ raw_error_socket->SetNextWriteError(ERR_CONNECTION_RESET);
+
+ // Write as much data as possible until hitting an error. This is necessary
+ // for NSS. PR_Write will only consume as much data as it can encode into
+ // application data records before the internal memio buffer is full, which
+ // should only fill if writing a large amount of data and the underlying
+ // transport is blocked. Once this happens, NSS will return (total size of all
+ // application data records it wrote) - 1, with the caller expected to resume
+ // with the remaining unsent data.
+ do {
+ rv = callback.GetResult(sock->Write(long_request_buffer.get(),
+ long_request_buffer->BytesRemaining(),
+ callback.callback()));
+ if (rv > 0) {
+ long_request_buffer->DidConsume(rv);
+ // Abort if the entire buffer is ever consumed.
+ ASSERT_LT(0, long_request_buffer->BytesRemaining());
+ }
+ } while (rv > 0);
+
+#if !defined(USE_OPENSSL)
+ // NSS records the error exactly.
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+#else
+ // OpenSSL treats the reset as a generic protocol error.
+ EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
+#endif
+
+ // Release the read. Some bytes should go through.
+ raw_transport->UnblockRead();
+ rv = read_callback.WaitForResult();
+
+ // Per the fix for http://crbug.com/249848, write failures currently break
+ // reads. Change this assertion if they're changed to not collide.
+ EXPECT_EQ(ERR_CONNECTION_RESET, rv);
+}
+
TEST_F(SSLClientSocketTest, Read_SmallChunks) {
SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
SpawnedTestServer::kLocalhost,
@@ -1795,4 +1901,162 @@ TEST_F(SSLClientSocketCertRequestInfoTest, TwoAuthorities) {
} // namespace
+TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.signed_cert_timestamps_tls_ext = "test";
+
+ SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath());
+ ASSERT_TRUE(test_server.Start());
+
+ AddressList addr;
+ ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+ TestCompletionCallback callback;
+ CapturingNetLog log;
+ scoped_ptr<StreamSocket> transport(
+ new TCPClientSocket(addr, &log, NetLog::Source()));
+ int rv = transport->Connect(callback.callback());
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ SSLConfig ssl_config;
+ ssl_config.signed_cert_timestamps_enabled = true;
+
+ scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket(
+ transport.Pass(), test_server.host_port_pair(), ssl_config));
+
+ EXPECT_FALSE(sock->IsConnected());
+
+ rv = sock->Connect(callback.callback());
+
+ CapturingNetLog::CapturedEntryList entries;
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT));
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock->IsConnected());
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
+
+#if !defined(USE_OPENSSL)
+ EXPECT_TRUE(sock->signed_cert_timestamps_received_);
+#else
+ // Enabling CT for OpenSSL is currently a noop.
+ EXPECT_FALSE(sock->signed_cert_timestamps_received_);
+#endif
+
+ sock->Disconnect();
+ EXPECT_FALSE(sock->IsConnected());
+}
+
+// Test that enabling Signed Certificate Timestamps enables OCSP stapling.
+TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledOCSP) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.staple_ocsp_response = true;
+ // The test server currently only knows how to generate OCSP responses
+ // for a freshly minted certificate.
+ ssl_options.server_certificate = SpawnedTestServer::SSLOptions::CERT_AUTO;
+
+ SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath());
+ ASSERT_TRUE(test_server.Start());
+
+ AddressList addr;
+ ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+ TestCompletionCallback callback;
+ CapturingNetLog log;
+ scoped_ptr<StreamSocket> transport(
+ new TCPClientSocket(addr, &log, NetLog::Source()));
+ int rv = transport->Connect(callback.callback());
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ SSLConfig ssl_config;
+ // Enabling Signed Cert Timestamps ensures we request OCSP stapling for
+ // Certificate Transparency verification regardless of whether the platform
+ // is able to process the OCSP status itself.
+ ssl_config.signed_cert_timestamps_enabled = true;
+
+ scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket(
+ transport.Pass(), test_server.host_port_pair(), ssl_config));
+
+ EXPECT_FALSE(sock->IsConnected());
+
+ rv = sock->Connect(callback.callback());
+
+ CapturingNetLog::CapturedEntryList entries;
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT));
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock->IsConnected());
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
+
+#if !defined(USE_OPENSSL)
+ EXPECT_TRUE(sock->stapled_ocsp_response_received_);
+#else
+ // OCSP stapling isn't currently supported in the OpenSSL socket.
+ EXPECT_FALSE(sock->stapled_ocsp_response_received_);
+#endif
+
+ sock->Disconnect();
+ EXPECT_FALSE(sock->IsConnected());
+}
+
+TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsDisabled) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.signed_cert_timestamps_tls_ext = "test";
+
+ SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath());
+ ASSERT_TRUE(test_server.Start());
+
+ AddressList addr;
+ ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+ TestCompletionCallback callback;
+ CapturingNetLog log;
+ scoped_ptr<StreamSocket> transport(
+ new TCPClientSocket(addr, &log, NetLog::Source()));
+ int rv = transport->Connect(callback.callback());
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+
+ SSLConfig ssl_config;
+ ssl_config.signed_cert_timestamps_enabled = false;
+
+ scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket(
+ transport.Pass(), test_server.host_port_pair(), ssl_config));
+
+ EXPECT_FALSE(sock->IsConnected());
+
+ rv = sock->Connect(callback.callback());
+
+ CapturingNetLog::CapturedEntryList entries;
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT));
+ if (rv == ERR_IO_PENDING)
+ rv = callback.WaitForResult();
+ EXPECT_EQ(OK, rv);
+ EXPECT_TRUE(sock->IsConnected());
+ log.GetEntries(&entries);
+ EXPECT_TRUE(LogContainsSSLConnectEndEvent(entries, -1));
+
+ EXPECT_FALSE(sock->signed_cert_timestamps_received_);
+
+ sock->Disconnect();
+ EXPECT_FALSE(sock->IsConnected());
+}
+
} // namespace net
diff --git a/chromium/net/socket/ssl_server_socket_nss.cc b/chromium/net/socket/ssl_server_socket_nss.cc
index 7e5d70118ac..b95983a5159 100644
--- a/chromium/net/socket/ssl_server_socket_nss.cc
+++ b/chromium/net/socket/ssl_server_socket_nss.cc
@@ -106,10 +106,6 @@ SSLServerSocketNSS::SSLServerSocketNSS(
cert_(cert),
next_handshake_state_(STATE_NONE),
completed_handshake_(false) {
- ssl_config_.false_start_enabled = false;
- ssl_config_.version_min = SSL_PROTOCOL_VERSION_SSL3;
- ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
-
// TODO(hclam): Need a better way to clone a key.
std::vector<uint8> key_bytes;
CHECK(key->ExportPrivateKey(&key_bytes));
@@ -350,6 +346,23 @@ int SSLServerSocketNSS::InitializeSSLOptions() {
return ERR_NO_SSL_VERSIONS_ENABLED;
}
+ if (ssl_config_.require_forward_secrecy) {
+ const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
+ const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
+
+ // Require forward security by iterating over the cipher suites and
+ // disabling all those that don't use ECDHE.
+ for (unsigned i = 0; i < num_ciphers; i++) {
+ SSLCipherSuiteInfo info;
+ if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
+ SECSuccess) {
+ if (strcmp(info.keaTypeName, "ECDHE") != 0) {
+ SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
+ }
+ }
+ }
+ }
+
for (std::vector<uint16>::const_iterator it =
ssl_config_.disabled_cipher_suites.begin();
it != ssl_config_.disabled_cipher_suites.end(); ++it) {
diff --git a/chromium/net/socket/ssl_server_socket_unittest.cc b/chromium/net/socket/ssl_server_socket_unittest.cc
index e1f7f496131..d5d04b20a90 100644
--- a/chromium/net/socket/ssl_server_socket_unittest.cc
+++ b/chromium/net/socket/ssl_server_socket_unittest.cc
@@ -56,9 +56,9 @@ class FakeDataChannel {
public:
FakeDataChannel()
: read_buf_len_(0),
- weak_factory_(this),
closed_(false),
- write_called_after_close_(false) {
+ write_called_after_close_(false),
+ weak_factory_(this) {
}
int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
@@ -140,8 +140,6 @@ class FakeDataChannel {
std::queue<scoped_refptr<net::DrainableIOBuffer> > data_;
- base::WeakPtrFactory<FakeDataChannel> weak_factory_;
-
// True if Close() has been called.
bool closed_;
@@ -150,6 +148,8 @@ class FakeDataChannel {
// asynchronously.
bool write_called_after_close_;
+ base::WeakPtrFactory<FakeDataChannel> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(FakeDataChannel);
};
@@ -334,8 +334,6 @@ class SSLServerSocketTest : public PlatformTest {
ssl_config.cached_info_enabled = false;
ssl_config.false_start_enabled = false;
ssl_config.channel_id_enabled = false;
- ssl_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
- ssl_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
// Certificate provided by the host doesn't need authority.
net::SSLConfig::CertAndStatus cert_and_status;
diff --git a/chromium/net/socket/ssl_session_cache_openssl.cc b/chromium/net/socket/ssl_session_cache_openssl.cc
new file mode 100644
index 00000000000..d16bb8d6325
--- /dev/null
+++ b/chromium/net/socket/ssl_session_cache_openssl.cc
@@ -0,0 +1,508 @@
+// 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/socket/ssl_session_cache_openssl.h"
+
+#include <list>
+#include <map>
+
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
+
+#include "base/containers/hash_tables.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/synchronization/lock.h"
+
+namespace net {
+
+namespace {
+
+// A helper class to lazily create a new EX_DATA index to map SSL_CTX handles
+// to their corresponding SSLSessionCacheOpenSSLImpl object.
+class SSLContextExIndex {
+public:
+ SSLContextExIndex() {
+ context_index_ = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ DCHECK_NE(-1, context_index_);
+ session_index_ = SSL_SESSION_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ DCHECK_NE(-1, session_index_);
+ }
+
+ int context_index() const { return context_index_; }
+ int session_index() const { return session_index_; }
+
+ private:
+ int context_index_;
+ int session_index_;
+};
+
+// static
+base::LazyInstance<SSLContextExIndex>::Leaky s_ssl_context_ex_instance =
+ LAZY_INSTANCE_INITIALIZER;
+
+// Retrieve the global EX_DATA index, created lazily on first call, to
+// be used with SSL_CTX_set_ex_data() and SSL_CTX_get_ex_data().
+static int GetSSLContextExIndex() {
+ return s_ssl_context_ex_instance.Get().context_index();
+}
+
+// Retrieve the global EX_DATA index, created lazily on first call, to
+// be used with SSL_SESSION_set_ex_data() and SSL_SESSION_get_ex_data().
+static int GetSSLSessionExIndex() {
+ return s_ssl_context_ex_instance.Get().session_index();
+}
+
+// Helper struct used to store session IDs in a SessionIdIndex container
+// (see definition below). To save memory each entry only holds a pointer
+// to the session ID buffer, which must outlive the entry itself. On the
+// other hand, a hash is included to minimize the number of hashing
+// computations during cache operations.
+struct SessionId {
+ SessionId(const unsigned char* a_id, unsigned a_id_len)
+ : id(a_id), id_len(a_id_len), hash(ComputeHash(a_id, a_id_len)) {}
+
+ explicit SessionId(const SessionId& other)
+ : id(other.id), id_len(other.id_len), hash(other.hash) {}
+
+ explicit SessionId(SSL_SESSION* session)
+ : id(session->session_id),
+ id_len(session->session_id_length),
+ hash(ComputeHash(session->session_id, session->session_id_length)) {}
+
+ bool operator==(const SessionId& other) const {
+ return hash == other.hash && id_len == other.id_len &&
+ !memcmp(id, other.id, id_len);
+ }
+
+ const unsigned char* id;
+ unsigned id_len;
+ size_t hash;
+
+ private:
+ // Session ID are random strings of bytes. This happens to compute the same
+ // value as std::hash<std::string> without the extra string copy. See
+ // base/containers/hash_tables.h. Other hashing computations are possible,
+ // this one is just simple enough to do the job.
+ size_t ComputeHash(const unsigned char* id, unsigned id_len) {
+ size_t result = 0;
+ for (unsigned n = 0; n < id_len; ++n)
+ result += 131 * id[n];
+ return result;
+ }
+};
+
+} // namespace
+
+} // namespace net
+
+namespace BASE_HASH_NAMESPACE {
+
+template <>
+struct hash<net::SessionId> {
+ std::size_t operator()(const net::SessionId& entry) const {
+ return entry.hash;
+ }
+};
+
+} // namespace BASE_HASH_NAMESPACE
+
+namespace net {
+
+// Implementation of the real SSLSessionCache.
+//
+// The implementation is inspired by base::MRUCache, except that the deletor
+// also needs to remove the entry from other containers. In a nutshell, this
+// uses several basic containers:
+//
+// |ordering_| is a doubly-linked list of SSL_SESSION handles, ordered in
+// MRU order.
+//
+// |key_index_| is a hash table mapping unique cache keys (e.g. host/port
+// values) to a single iterator of |ordering_|. It is used to efficiently
+// find the cached session associated with a given key.
+//
+// |id_index_| is a hash table mapping SessionId values to iterators
+// of |key_index_|. If is used to efficiently remove sessions from the cache,
+// as well as check for the existence of a session ID value in the cache.
+//
+// SSL_SESSION objects are reference-counted, and owned by the cache. This
+// means that their reference count is incremented when they are added, and
+// decremented when they are removed.
+//
+// Assuming an average key size of 100 characters, each node requires the
+// following memory usage on 32-bit Android, when linked against STLport:
+//
+// 12 (ordering_ node, including SSL_SESSION handle)
+// 100 (key characters)
+// + 24 (std::string header/minimum size)
+// + 8 (key_index_ node, excluding the 2 lines above for the key).
+// + 20 (id_index_ node)
+// --------
+// 164 bytes/node
+//
+// Hence, 41 KiB for a full cache with a maximum of 1024 entries, excluding
+// the size of SSL_SESSION objects and heap fragmentation.
+//
+
+class SSLSessionCacheOpenSSLImpl {
+ public:
+ // Construct new instance. This registers various hooks into the SSL_CTX
+ // context |ctx|. OpenSSL will call back during SSL connection
+ // operations. |key_func| is used to map a SSL handle to a unique cache
+ // string, according to the client's preferences.
+ SSLSessionCacheOpenSSLImpl(SSL_CTX* ctx,
+ const SSLSessionCacheOpenSSL::Config& config)
+ : ctx_(ctx), config_(config), expiration_check_(0) {
+ DCHECK(ctx);
+
+ // NO_INTERNAL_STORE disables OpenSSL's builtin cache, and
+ // NO_AUTO_CLEAR disables the call to SSL_CTX_flush_sessions
+ // every 256 connections (this number is hard-coded in the library
+ // and can't be changed).
+ SSL_CTX_set_session_cache_mode(ctx_,
+ SSL_SESS_CACHE_CLIENT |
+ SSL_SESS_CACHE_NO_INTERNAL_STORE |
+ SSL_SESS_CACHE_NO_AUTO_CLEAR);
+
+ SSL_CTX_sess_set_new_cb(ctx_, NewSessionCallbackStatic);
+ SSL_CTX_sess_set_remove_cb(ctx_, RemoveSessionCallbackStatic);
+ SSL_CTX_set_generate_session_id(ctx_, GenerateSessionIdStatic);
+ SSL_CTX_set_timeout(ctx_, config_.timeout_seconds);
+
+ SSL_CTX_set_ex_data(ctx_, GetSSLContextExIndex(), this);
+ }
+
+ // Destroy this instance. Must happen before |ctx_| is destroyed.
+ ~SSLSessionCacheOpenSSLImpl() {
+ Flush();
+ SSL_CTX_set_ex_data(ctx_, GetSSLContextExIndex(), NULL);
+ SSL_CTX_sess_set_new_cb(ctx_, NULL);
+ SSL_CTX_sess_set_remove_cb(ctx_, NULL);
+ SSL_CTX_set_generate_session_id(ctx_, NULL);
+ }
+
+ // Return the number of items in this cache.
+ size_t size() const { return key_index_.size(); }
+
+ // Retrieve the cache key from |ssl| and look for a corresponding
+ // cached session ID. If one is found, call SSL_set_session() to associate
+ // it with the |ssl| connection.
+ //
+ // Will also check for expired sessions every |expiration_check_count|
+ // calls.
+ //
+ // Return true if a cached session ID was found, false otherwise.
+ bool SetSSLSession(SSL* ssl) {
+ std::string cache_key = config_.key_func(ssl);
+ if (cache_key.empty())
+ return false;
+
+ return SetSSLSessionWithKey(ssl, cache_key);
+ }
+
+ // Variant of SetSSLSession to be used when the client already has computed
+ // the cache key. Avoid a call to the configuration's |key_func| function.
+ bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key) {
+ base::AutoLock locked(lock_);
+
+ DCHECK_EQ(config_.key_func(ssl), cache_key);
+
+ if (++expiration_check_ >= config_.expiration_check_count) {
+ expiration_check_ = 0;
+ FlushExpiredSessionsLocked();
+ }
+
+ KeyIndex::iterator it = key_index_.find(cache_key);
+ if (it == key_index_.end())
+ return false;
+
+ SSL_SESSION* session = *it->second;
+ DCHECK(session);
+
+ DVLOG(2) << "Lookup session: " << session << " for " << cache_key;
+
+ void* session_is_good =
+ SSL_SESSION_get_ex_data(session, GetSSLSessionExIndex());
+ if (!session_is_good)
+ return false; // Session has not yet been marked good. Treat as a miss.
+
+ // Move to front of MRU list.
+ ordering_.push_front(session);
+ ordering_.erase(it->second);
+ it->second = ordering_.begin();
+
+ return SSL_set_session(ssl, session) == 1;
+ }
+
+ void MarkSSLSessionAsGood(SSL* ssl) {
+ SSL_SESSION* session = SSL_get_session(ssl);
+ if (!session)
+ return;
+
+ // Mark the session as good, allowing it to be used for future connections.
+ SSL_SESSION_set_ex_data(
+ session, GetSSLSessionExIndex(), reinterpret_cast<void*>(1));
+ }
+
+ // Flush all entries from the cache.
+ void Flush() {
+ base::AutoLock lock(lock_);
+ id_index_.clear();
+ key_index_.clear();
+ while (!ordering_.empty()) {
+ SSL_SESSION* session = ordering_.front();
+ ordering_.pop_front();
+ SSL_SESSION_free(session);
+ }
+ }
+
+ private:
+ // Type for list of SSL_SESSION handles, ordered in MRU order.
+ typedef std::list<SSL_SESSION*> MRUSessionList;
+ // Type for a dictionary from unique cache keys to session list nodes.
+ typedef base::hash_map<std::string, MRUSessionList::iterator> KeyIndex;
+ // Type for a dictionary from SessionId values to key index nodes.
+ typedef base::hash_map<SessionId, KeyIndex::iterator> SessionIdIndex;
+
+ // Return the key associated with a given session, or the empty string if
+ // none exist. This shall only be used for debugging.
+ std::string SessionKey(SSL_SESSION* session) {
+ if (!session)
+ return std::string("<null-session>");
+
+ if (session->session_id_length == 0)
+ return std::string("<empty-session-id>");
+
+ SessionIdIndex::iterator it = id_index_.find(SessionId(session));
+ if (it == id_index_.end())
+ return std::string("<unknown-session>");
+
+ return it->second->first;
+ }
+
+ // Remove a given |session| from the cache. Lock must be held.
+ void RemoveSessionLocked(SSL_SESSION* session) {
+ lock_.AssertAcquired();
+ DCHECK(session);
+ DCHECK_GT(session->session_id_length, 0U);
+ SessionId session_id(session);
+ SessionIdIndex::iterator id_it = id_index_.find(session_id);
+ if (id_it == id_index_.end()) {
+ LOG(ERROR) << "Trying to remove unknown session from cache: " << session;
+ return;
+ }
+ KeyIndex::iterator key_it = id_it->second;
+ DCHECK(key_it != key_index_.end());
+ DCHECK_EQ(session, *key_it->second);
+
+ id_index_.erase(session_id);
+ ordering_.erase(key_it->second);
+ key_index_.erase(key_it);
+
+ SSL_SESSION_free(session);
+
+ DCHECK_EQ(key_index_.size(), id_index_.size());
+ }
+
+ // Used internally to flush expired sessions. Lock must be held.
+ void FlushExpiredSessionsLocked() {
+ lock_.AssertAcquired();
+
+ // Unfortunately, OpenSSL initializes |session->time| with a time()
+ // timestamps, which makes mocking / unit testing difficult.
+ long timeout_secs = static_cast<long>(::time(NULL));
+ MRUSessionList::iterator it = ordering_.begin();
+ while (it != ordering_.end()) {
+ SSL_SESSION* session = *it++;
+
+ // Important, use <= instead of < here to allow unit testing to
+ // work properly. That's because unit tests that check the expiration
+ // behaviour will use a session timeout of 0 seconds.
+ if (session->time + session->timeout <= timeout_secs) {
+ DVLOG(2) << "Expiring session " << session << " for "
+ << SessionKey(session);
+ RemoveSessionLocked(session);
+ }
+ }
+ }
+
+ // Retrieve the cache associated with a given SSL context |ctx|.
+ static SSLSessionCacheOpenSSLImpl* GetCache(SSL_CTX* ctx) {
+ DCHECK(ctx);
+ void* result = SSL_CTX_get_ex_data(ctx, GetSSLContextExIndex());
+ DCHECK(result);
+ return reinterpret_cast<SSLSessionCacheOpenSSLImpl*>(result);
+ }
+
+ // Called by OpenSSL when a new |session| was created and added to a given
+ // |ssl| connection. Note that the session's reference count was already
+ // incremented before the function is entered. The function must return 1
+ // to indicate that it took ownership of the session, i.e. that the caller
+ // should not decrement its reference count after completion.
+ static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
+ GetCache(ssl->ctx)->OnSessionAdded(ssl, session);
+ return 1;
+ }
+
+ // Called by OpenSSL to indicate that a session must be removed from the
+ // cache. This happens when SSL_CTX is destroyed.
+ static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
+ GetCache(ctx)->OnSessionRemoved(session);
+ }
+
+ // Called by OpenSSL to generate a new session ID. This happens during a
+ // SSL connection operation, when the SSL object doesn't have a session yet.
+ //
+ // A session ID is a random string of bytes used to uniquely identify the
+ // session between a client and a server.
+ //
+ // |ssl| is a SSL connection handle. Ignored here.
+ // |id| is the target buffer where the ID must be generated.
+ // |*id_len| is, on input, the size of the desired ID. It will be 16 for
+ // SSLv2, and 32 for anything else. OpenSSL allows an implementation
+ // to change it on output, but this will not happen here.
+ //
+ // The function must ensure the generated ID is really unique, i.e. that
+ // another session in the cache doesn't already use the same value. It must
+ // return 1 to indicate success, or 0 for failure.
+ static int GenerateSessionIdStatic(const SSL* ssl,
+ unsigned char* id,
+ unsigned* id_len) {
+ if (!GetCache(ssl->ctx)->OnGenerateSessionId(id, *id_len))
+ return 0;
+
+ return 1;
+ }
+
+ // Add |session| to the cache in association with |cache_key|. If a session
+ // already exists, it is replaced with the new one. This assumes that the
+ // caller already incremented the session's reference count.
+ void OnSessionAdded(SSL* ssl, SSL_SESSION* session) {
+ base::AutoLock locked(lock_);
+ DCHECK(ssl);
+ DCHECK_GT(session->session_id_length, 0U);
+ std::string cache_key = config_.key_func(ssl);
+ KeyIndex::iterator it = key_index_.find(cache_key);
+ if (it == key_index_.end()) {
+ DVLOG(2) << "Add session " << session << " for " << cache_key;
+ // This is a new session. Add it to the cache.
+ ordering_.push_front(session);
+ std::pair<KeyIndex::iterator, bool> ret =
+ key_index_.insert(std::make_pair(cache_key, ordering_.begin()));
+ DCHECK(ret.second);
+ it = ret.first;
+ DCHECK(it != key_index_.end());
+ } else {
+ // An existing session exists for this key, so replace it if needed.
+ DVLOG(2) << "Replace session " << *it->second << " with " << session
+ << " for " << cache_key;
+ SSL_SESSION* old_session = *it->second;
+ if (old_session != session) {
+ id_index_.erase(SessionId(old_session));
+ SSL_SESSION_free(old_session);
+ }
+ ordering_.erase(it->second);
+ ordering_.push_front(session);
+ it->second = ordering_.begin();
+ }
+
+ id_index_[SessionId(session)] = it;
+
+ if (key_index_.size() > config_.max_entries)
+ ShrinkCacheLocked();
+
+ DCHECK_EQ(key_index_.size(), id_index_.size());
+ DCHECK_LE(key_index_.size(), config_.max_entries);
+ }
+
+ // Shrink the cache to ensure no more than config_.max_entries entries,
+ // starting with older entries first. Lock must be acquired.
+ void ShrinkCacheLocked() {
+ lock_.AssertAcquired();
+ DCHECK_EQ(key_index_.size(), ordering_.size());
+ DCHECK_EQ(key_index_.size(), id_index_.size());
+
+ while (key_index_.size() > config_.max_entries) {
+ MRUSessionList::reverse_iterator it = ordering_.rbegin();
+ DCHECK(it != ordering_.rend());
+
+ SSL_SESSION* session = *it;
+ DCHECK(session);
+ DVLOG(2) << "Evicting session " << session << " for "
+ << SessionKey(session);
+ RemoveSessionLocked(session);
+ }
+ }
+
+ // Remove |session| from the cache.
+ void OnSessionRemoved(SSL_SESSION* session) {
+ base::AutoLock locked(lock_);
+ DVLOG(2) << "Remove session " << session << " for " << SessionKey(session);
+ RemoveSessionLocked(session);
+ }
+
+ // See GenerateSessionIdStatic for a description of what this function does.
+ bool OnGenerateSessionId(unsigned char* id, unsigned id_len) {
+ base::AutoLock locked(lock_);
+ // This mimics def_generate_session_id() in openssl/ssl/ssl_sess.cc,
+ // I.e. try to generate a pseudo-random bit string, and check that no
+ // other entry in the cache has the same value.
+ const size_t kMaxTries = 10;
+ for (size_t tries = 0; tries < kMaxTries; ++tries) {
+ if (RAND_pseudo_bytes(id, id_len) <= 0) {
+ DLOG(ERROR) << "Couldn't generate " << id_len
+ << " pseudo random bytes?";
+ return false;
+ }
+ if (id_index_.find(SessionId(id, id_len)) == id_index_.end())
+ return true;
+ }
+ DLOG(ERROR) << "Couldn't generate unique session ID of " << id_len
+ << "bytes after " << kMaxTries << " tries.";
+ return false;
+ }
+
+ SSL_CTX* ctx_;
+ SSLSessionCacheOpenSSL::Config config_;
+
+ // method to get the index which can later be used with SSL_CTX_get_ex_data()
+ // or SSL_CTX_set_ex_data().
+ base::Lock lock_; // Protects access to containers below.
+
+ MRUSessionList ordering_;
+ KeyIndex key_index_;
+ SessionIdIndex id_index_;
+
+ size_t expiration_check_;
+};
+
+SSLSessionCacheOpenSSL::~SSLSessionCacheOpenSSL() { delete impl_; }
+
+size_t SSLSessionCacheOpenSSL::size() const { return impl_->size(); }
+
+void SSLSessionCacheOpenSSL::Reset(SSL_CTX* ctx, const Config& config) {
+ if (impl_)
+ delete impl_;
+
+ impl_ = new SSLSessionCacheOpenSSLImpl(ctx, config);
+}
+
+bool SSLSessionCacheOpenSSL::SetSSLSession(SSL* ssl) {
+ return impl_->SetSSLSession(ssl);
+}
+
+bool SSLSessionCacheOpenSSL::SetSSLSessionWithKey(
+ SSL* ssl,
+ const std::string& cache_key) {
+ return impl_->SetSSLSessionWithKey(ssl, cache_key);
+}
+
+void SSLSessionCacheOpenSSL::MarkSSLSessionAsGood(SSL* ssl) {
+ return impl_->MarkSSLSessionAsGood(ssl);
+}
+
+void SSLSessionCacheOpenSSL::Flush() { impl_->Flush(); }
+
+} // namespace net
diff --git a/chromium/net/socket/ssl_session_cache_openssl.h b/chromium/net/socket/ssl_session_cache_openssl.h
new file mode 100644
index 00000000000..bbd9659641d
--- /dev/null
+++ b/chromium/net/socket/ssl_session_cache_openssl.h
@@ -0,0 +1,141 @@
+// 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_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
+#define NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "net/base/net_export.h"
+
+// Avoid including OpenSSL headers here.
+typedef struct ssl_ctx_st SSL_CTX;
+typedef struct ssl_st SSL;
+
+namespace net {
+
+class SSLSessionCacheOpenSSLImpl;
+
+// A class used to implement a custom cache of SSL_SESSION objects.
+// Usage is as follows:
+//
+// - Client creates a new cache instance with appropriate configuration,
+// associating it with a given SSL_CTX object.
+//
+// The configuration must include a pointer to a client-provided function
+// that can retrieve a unique cache key from an existing SSL handle.
+//
+// - When creating a new SSL connection, call SetSSLSession() with the newly
+// created SSL handle, and a cache key for the current host/port. If a
+// session is already in the cache, it will be added to the connection
+// through SSL_set_session().
+//
+// - Otherwise, OpenSSL will create a new SSL_SESSION object during the
+// connection, and will pass it to the cache's internal functions,
+// transparently to the client.
+//
+// - Each session has a timeout in seconds, which are checked every N-th call
+// to SetSSLSession(), where N is the current configuration's
+// |check_expiration_count|. Expired sessions are removed automatically
+// from the cache.
+//
+// - Clients can call Flush() to remove all sessions from the cache, this is
+// useful when the system's certificate store has changed.
+//
+// This class is thread-safe. There shouldn't be any issue with multiple
+// SSL connections being performed in parallel in multiple threads.
+class NET_EXPORT SSLSessionCacheOpenSSL {
+ public:
+ // Type of a function that takes a SSL handle and returns a unique cache
+ // key string to identify it.
+ typedef std::string GetSessionKeyFunction(const SSL* ssl);
+
+ // A small structure used to configure a cache on creation.
+ // |key_func| is a function used at runtime to retrieve the unique cache key
+ // from a given SSL connection handle.
+ // |max_entries| is the maximum number of entries in the cache.
+ // |expiration_check_count| is the number of calls to SetSSLSession() that
+ // will trigger a check for expired sessions.
+ // |timeout_seconds| is the timeout of new cached sessions in seconds.
+ struct Config {
+ GetSessionKeyFunction* key_func;
+ size_t max_entries;
+ size_t expiration_check_count;
+ int timeout_seconds;
+ };
+
+ SSLSessionCacheOpenSSL() : impl_(NULL) {}
+
+ // Construct a new cache instance.
+ // |ctx| is a SSL_CTX context handle that will be associated with this cache.
+ // |key_func| is a function that will be used at runtime to retrieve the
+ // unique cache key from a SSL connection handle.
+ // |max_entries| is the maximum number of entries in the cache.
+ // |timeout_seconds| is the timeout of new cached sessions in seconds.
+ // |expiration_check_count| is the number of calls to SetSSLSession() that
+ // will trigger a check for expired sessions.
+ SSLSessionCacheOpenSSL(SSL_CTX* ctx, const Config& config) : impl_(NULL) {
+ Reset(ctx, config);
+ }
+
+ // Destroy this instance. This must be called before the SSL_CTX handle
+ // is destroyed.
+ ~SSLSessionCacheOpenSSL();
+
+ // Reset the cache configuration. This flushes any existing entries.
+ void Reset(SSL_CTX* ctx, const Config& config);
+
+ size_t size() const;
+
+ // Lookup the unique cache key associated with |ssl| connection handle,
+ // and find a cached session for it in the cache. If one is found, associate
+ // it with the |ssl| connection through SSL_set_session(). Consider using
+ // SetSSLSessionWithKey() if you already have the key.
+ //
+ // Every |check_expiration_count| call to either SetSSLSession() or
+ // SetSSLSessionWithKey() triggers a check for, and removal of, expired
+ // sessions.
+ //
+ // Return true iff a cached session was associated with the |ssl| connection.
+ bool SetSSLSession(SSL* ssl);
+
+ // A more efficient variant of SetSSLSession() that can be used if the caller
+ // already has the cache key for the session of interest. The caller must
+ // ensure that the value of |cache_key| matches the result of calling the
+ // configuration's |key_func| function with the |ssl| as parameter.
+ //
+ // Every |check_expiration_count| call to either SetSSLSession() or
+ // SetSSLSessionWithKey() triggers a check for, and removal of, expired
+ // sessions.
+ //
+ // Return true iff a cached session was associated with the |ssl| connection.
+ bool SetSSLSessionWithKey(SSL* ssl, const std::string& cache_key);
+
+ // Indicates that the SSL session associated with |ssl| is "good" - that is,
+ // that all associated cryptographic parameters that were negotiated,
+ // including the peer's certificate, were successfully validated. Because
+ // OpenSSL does not provide an asynchronous certificate verification
+ // callback, it's necessary to manually manage the sessions to ensure that
+ // only validated sessions are resumed.
+ void MarkSSLSessionAsGood(SSL* ssl);
+
+ // Flush removes all entries from the cache. This is typically called when
+ // the system's certificate store has changed.
+ void Flush();
+
+ // TODO(digit): Move to client code.
+ static const int kDefaultTimeoutSeconds = 60 * 60;
+ static const size_t kMaxEntries = 1024;
+ static const size_t kMaxExpirationChecks = 256;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SSLSessionCacheOpenSSL);
+
+ SSLSessionCacheOpenSSLImpl* impl_;
+};
+
+} // namespace net
+
+#endif // NET_SOCKET_SSL_SESSION_CACHE_OPENSSL_H
diff --git a/chromium/net/socket/ssl_session_cache_openssl_unittest.cc b/chromium/net/socket/ssl_session_cache_openssl_unittest.cc
new file mode 100644
index 00000000000..22c4fbaeb9c
--- /dev/null
+++ b/chromium/net/socket/ssl_session_cache_openssl_unittest.cc
@@ -0,0 +1,378 @@
+// 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/socket/ssl_session_cache_openssl.h"
+
+#include <openssl/ssl.h>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "crypto/openssl_util.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// This is an internal OpenSSL function that can be used to create a new
+// session for an existing SSL object. This shall force a call to the
+// 'generate_session_id' callback from the SSL's session context.
+// |s| is the target SSL connection handle.
+// |session| is non-0 to ask for the creation of a new session. If 0,
+// this will set an empty session with no ID instead.
+extern "C" int ssl_get_new_session(SSL* s, int session);
+
+// This is an internal OpenSSL function which is used internally to add
+// a new session to the cache. It is normally triggered by a succesful
+// connection. However, this unit test does not use the network at all.
+extern "C" void ssl_update_cache(SSL* s, int mode);
+
+namespace net {
+
+namespace {
+
+typedef crypto::ScopedOpenSSL<SSL, SSL_free> ScopedSSL;
+
+// Helper class used to associate arbitrary std::string keys with SSL objects.
+class SSLKeyHelper {
+ public:
+ // Return the string associated with a given SSL handle |ssl|, or the
+ // empty string if none exists.
+ static std::string Get(const SSL* ssl) {
+ return GetInstance()->GetValue(ssl);
+ }
+
+ // Associate a string with a given SSL handle |ssl|.
+ static void Set(SSL* ssl, const std::string& value) {
+ GetInstance()->SetValue(ssl, value);
+ }
+
+ static SSLKeyHelper* GetInstance() {
+ static base::LazyInstance<SSLKeyHelper>::Leaky s_instance =
+ LAZY_INSTANCE_INITIALIZER;
+ return s_instance.Pointer();
+ }
+
+ SSLKeyHelper() {
+ ex_index_ = SSL_get_ex_new_index(0, NULL, NULL, KeyDup, KeyFree);
+ CHECK_NE(-1, ex_index_);
+ }
+
+ std::string GetValue(const SSL* ssl) {
+ std::string* value =
+ reinterpret_cast<std::string*>(SSL_get_ex_data(ssl, ex_index_));
+ if (!value)
+ return std::string();
+ return *value;
+ }
+
+ void SetValue(SSL* ssl, const std::string& value) {
+ int ret = SSL_set_ex_data(ssl, ex_index_, new std::string(value));
+ CHECK_EQ(1, ret);
+ }
+
+ // Called when an SSL object is copied through SSL_dup(). This needs to copy
+ // the value as well.
+ static int KeyDup(CRYPTO_EX_DATA* to,
+ CRYPTO_EX_DATA* from,
+ void* from_fd,
+ int idx,
+ long argl,
+ void* argp) {
+ // |from_fd| is really the address of a temporary pointer. On input, it
+ // points to the value from the original SSL object. The function must
+ // update it to the address of a copy.
+ std::string** ptr = reinterpret_cast<std::string**>(from_fd);
+ std::string* old_string = *ptr;
+ std::string* new_string = new std::string(*old_string);
+ *ptr = new_string;
+ return 0; // Ignored by the implementation.
+ }
+
+ // Called to destroy the value associated with an SSL object.
+ static void KeyFree(void* parent,
+ void* ptr,
+ CRYPTO_EX_DATA* ad,
+ int index,
+ long argl,
+ void* argp) {
+ std::string* value = reinterpret_cast<std::string*>(ptr);
+ delete value;
+ }
+
+ int ex_index_;
+};
+
+} // namespace
+
+class SSLSessionCacheOpenSSLTest : public testing::Test {
+ public:
+ SSLSessionCacheOpenSSLTest() {
+ crypto::EnsureOpenSSLInit();
+ ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
+ cache_.Reset(ctx_.get(), kDefaultConfig);
+ }
+
+ // Reset cache configuration.
+ void ResetConfig(const SSLSessionCacheOpenSSL::Config& config) {
+ cache_.Reset(ctx_.get(), config);
+ }
+
+ // Helper function to create a new SSL connection object associated with
+ // a given unique |cache_key|. This does _not_ add the session to the cache.
+ // Caller must free the object with SSL_free().
+ SSL* NewSSL(const std::string& cache_key) {
+ SSL* ssl = SSL_new(ctx_.get());
+ if (!ssl)
+ return NULL;
+
+ SSLKeyHelper::Set(ssl, cache_key); // associate cache key.
+ ResetSessionID(ssl); // create new unique session ID.
+ return ssl;
+ }
+
+ // Reset the session ID of a given SSL object. This creates a new session
+ // with a new unique random ID. Does not add it to the cache.
+ static void ResetSessionID(SSL* ssl) { ssl_get_new_session(ssl, 1); }
+
+ // Add a given SSL object and its session to the cache.
+ void AddToCache(SSL* ssl) {
+ ssl_update_cache(ssl, ctx_.get()->session_cache_mode);
+ }
+
+ static const SSLSessionCacheOpenSSL::Config kDefaultConfig;
+
+ protected:
+ crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ctx_;
+ // |cache_| must be destroyed before |ctx_| and thus appears after it.
+ SSLSessionCacheOpenSSL cache_;
+};
+
+// static
+const SSLSessionCacheOpenSSL::Config
+ SSLSessionCacheOpenSSLTest::kDefaultConfig = {
+ &SSLKeyHelper::Get, // key_func
+ 1024, // max_entries
+ 256, // expiration_check_count
+ 60 * 60, // timeout_seconds
+};
+
+TEST_F(SSLSessionCacheOpenSSLTest, EmptyCacheCreation) {
+ EXPECT_EQ(0U, cache_.size());
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, CacheOneSession) {
+ ScopedSSL ssl(NewSSL("hello"));
+
+ EXPECT_EQ(0U, cache_.size());
+ AddToCache(ssl.get());
+ EXPECT_EQ(1U, cache_.size());
+ ssl.reset(NULL);
+ EXPECT_EQ(1U, cache_.size());
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, CacheMultipleSessions) {
+ const size_t kNumItems = 100;
+ int local_id = 1;
+
+ // Add kNumItems to the cache.
+ for (size_t n = 0; n < kNumItems; ++n) {
+ std::string local_id_string = base::StringPrintf("%d", local_id++);
+ ScopedSSL ssl(NewSSL(local_id_string));
+ AddToCache(ssl.get());
+ EXPECT_EQ(n + 1, cache_.size());
+ }
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, Flush) {
+ const size_t kNumItems = 100;
+ int local_id = 1;
+
+ // Add kNumItems to the cache.
+ for (size_t n = 0; n < kNumItems; ++n) {
+ std::string local_id_string = base::StringPrintf("%d", local_id++);
+ ScopedSSL ssl(NewSSL(local_id_string));
+ AddToCache(ssl.get());
+ }
+ EXPECT_EQ(kNumItems, cache_.size());
+
+ cache_.Flush();
+ EXPECT_EQ(0U, cache_.size());
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, SetSSLSession) {
+ const std::string key("hello");
+ ScopedSSL ssl(NewSSL(key));
+
+ // First call should fail because the session is not in the cache.
+ EXPECT_FALSE(cache_.SetSSLSession(ssl.get()));
+ SSL_SESSION* session = ssl.get()->session;
+ EXPECT_TRUE(session);
+ EXPECT_EQ(1, session->references);
+
+ AddToCache(ssl.get());
+ EXPECT_EQ(2, session->references);
+
+ // Mark the session as good, so that it is re-used for the second connection.
+ cache_.MarkSSLSessionAsGood(ssl.get());
+
+ ssl.reset(NULL);
+ EXPECT_EQ(1, session->references);
+
+ // Second call should find the session ID and associate it with |ssl2|.
+ ScopedSSL ssl2(NewSSL(key));
+ EXPECT_TRUE(cache_.SetSSLSession(ssl2.get()));
+
+ EXPECT_EQ(session, ssl2.get()->session);
+ EXPECT_EQ(2, session->references);
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, SetSSLSessionWithKey) {
+ const std::string key("hello");
+ ScopedSSL ssl(NewSSL(key));
+ AddToCache(ssl.get());
+ cache_.MarkSSLSessionAsGood(ssl.get());
+ ssl.reset(NULL);
+
+ ScopedSSL ssl2(NewSSL(key));
+ EXPECT_TRUE(cache_.SetSSLSessionWithKey(ssl2.get(), key));
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, CheckSessionReplacement) {
+ // Check that if two SSL connections have the same key, only one
+ // corresponding session can be stored in the cache.
+ const std::string common_key("common-key");
+ ScopedSSL ssl1(NewSSL(common_key));
+ ScopedSSL ssl2(NewSSL(common_key));
+
+ AddToCache(ssl1.get());
+ EXPECT_EQ(1U, cache_.size());
+ EXPECT_EQ(2, ssl1.get()->session->references);
+
+ // This ends up calling OnSessionAdded which will discover that there is
+ // already one session ID associated with the key, and will replace it.
+ AddToCache(ssl2.get());
+ EXPECT_EQ(1U, cache_.size());
+ EXPECT_EQ(1, ssl1.get()->session->references);
+ EXPECT_EQ(2, ssl2.get()->session->references);
+}
+
+// Check that when two connections have the same key, a new session is created
+// if the existing session has not yet been marked "good". Further, after the
+// first session completes, if the second session has replaced it in the cache,
+// new sessions should continue to fail until the currently cached session
+// succeeds.
+TEST_F(SSLSessionCacheOpenSSLTest, CheckSessionReplacementWhenNotGood) {
+ const std::string key("hello");
+ ScopedSSL ssl(NewSSL(key));
+
+ // First call should fail because the session is not in the cache.
+ EXPECT_FALSE(cache_.SetSSLSession(ssl.get()));
+ SSL_SESSION* session = ssl.get()->session;
+ ASSERT_TRUE(session);
+ EXPECT_EQ(1, session->references);
+
+ AddToCache(ssl.get());
+ EXPECT_EQ(2, session->references);
+
+ // Second call should find the session ID, but because it is not yet good,
+ // fail to associate it with |ssl2|.
+ ScopedSSL ssl2(NewSSL(key));
+ EXPECT_FALSE(cache_.SetSSLSession(ssl2.get()));
+ SSL_SESSION* session2 = ssl2.get()->session;
+ ASSERT_TRUE(session2);
+ EXPECT_EQ(1, session2->references);
+
+ EXPECT_NE(session, session2);
+
+ // Add the second connection to the cache. It should replace the first
+ // session, and the cache should hold on to the second session.
+ AddToCache(ssl2.get());
+ EXPECT_EQ(1, session->references);
+ EXPECT_EQ(2, session2->references);
+
+ // Mark the first session as good, simulating it completing.
+ cache_.MarkSSLSessionAsGood(ssl.get());
+
+ // Third call should find the session ID, but because the second session (the
+ // current cache entry) is not yet good, fail to associate it with |ssl3|.
+ ScopedSSL ssl3(NewSSL(key));
+ EXPECT_FALSE(cache_.SetSSLSession(ssl3.get()));
+ EXPECT_NE(session, ssl3.get()->session);
+ EXPECT_NE(session2, ssl3.get()->session);
+ EXPECT_EQ(1, ssl3.get()->session->references);
+}
+
+TEST_F(SSLSessionCacheOpenSSLTest, CheckEviction) {
+ const size_t kMaxItems = 20;
+ int local_id = 1;
+
+ SSLSessionCacheOpenSSL::Config config = kDefaultConfig;
+ config.max_entries = kMaxItems;
+ ResetConfig(config);
+
+ // Add kMaxItems to the cache.
+ for (size_t n = 0; n < kMaxItems; ++n) {
+ std::string local_id_string = base::StringPrintf("%d", local_id++);
+ ScopedSSL ssl(NewSSL(local_id_string));
+
+ AddToCache(ssl.get());
+ EXPECT_EQ(n + 1, cache_.size());
+ }
+
+ // Continue adding new items to the cache, check that old ones are
+ // evicted.
+ for (size_t n = 0; n < kMaxItems; ++n) {
+ std::string local_id_string = base::StringPrintf("%d", local_id++);
+ ScopedSSL ssl(NewSSL(local_id_string));
+
+ AddToCache(ssl.get());
+ EXPECT_EQ(kMaxItems, cache_.size());
+ }
+}
+
+// Check that session expiration works properly.
+TEST_F(SSLSessionCacheOpenSSLTest, CheckExpiration) {
+ const size_t kMaxCheckCount = 10;
+ const size_t kNumEntries = 20;
+
+ SSLSessionCacheOpenSSL::Config config = kDefaultConfig;
+ config.expiration_check_count = kMaxCheckCount;
+ config.timeout_seconds = 1000;
+ ResetConfig(config);
+
+ // Add |kNumItems - 1| session entries with crafted time values.
+ for (size_t n = 0; n < kNumEntries - 1U; ++n) {
+ std::string key = base::StringPrintf("%d", static_cast<int>(n));
+ ScopedSSL ssl(NewSSL(key));
+ // Cheat a little: Force the session |time| value, this guarantees that they
+ // are expired, given that ::time() will always return a value that is
+ // past the first 100 seconds after the Unix epoch.
+ ssl.get()->session->time = static_cast<long>(n);
+ AddToCache(ssl.get());
+ }
+ EXPECT_EQ(kNumEntries - 1U, cache_.size());
+
+ // Add nother session which will get the current time, and thus not be
+ // expirable until 1000 seconds have passed.
+ ScopedSSL good_ssl(NewSSL("good-key"));
+ AddToCache(good_ssl.get());
+ good_ssl.reset(NULL);
+ EXPECT_EQ(kNumEntries, cache_.size());
+
+ // Call SetSSLSession() |kMaxCheckCount - 1| times, this shall not expire
+ // any session
+ for (size_t n = 0; n < kMaxCheckCount - 1U; ++n) {
+ ScopedSSL ssl(NewSSL("unknown-key"));
+ cache_.SetSSLSession(ssl.get());
+ EXPECT_EQ(kNumEntries, cache_.size());
+ }
+
+ // Call SetSSLSession another time, this shall expire all sessions except
+ // the last one.
+ ScopedSSL bad_ssl(NewSSL("unknown-key"));
+ cache_.SetSSLSession(bad_ssl.get());
+ bad_ssl.reset(NULL);
+ EXPECT_EQ(1U, cache_.size());
+}
+
+} // namespace net
diff --git a/chromium/net/socket/stream_listen_socket.cc b/chromium/net/socket/stream_listen_socket.cc
index 1109e7527c3..960991b7c6d 100644
--- a/chromium/net/socket/stream_listen_socket.cc
+++ b/chromium/net/socket/stream_listen_socket.cc
@@ -65,13 +65,13 @@ StreamListenSocket::StreamListenSocket(SocketDescriptor s,
}
StreamListenSocket::~StreamListenSocket() {
+ CloseSocket();
#if defined(OS_WIN)
if (socket_event_) {
WSACloseEvent(socket_event_);
socket_event_ = WSA_INVALID_EVENT;
}
#endif
- CloseSocket(socket_);
}
void StreamListenSocket::Send(const char* bytes, int len,
@@ -194,13 +194,13 @@ void StreamListenSocket::Close() {
socket_delegate_->DidClose(this);
}
-void StreamListenSocket::CloseSocket(SocketDescriptor s) {
- if (s && s != kInvalidSocket) {
+void StreamListenSocket::CloseSocket() {
+ if (socket_ != kInvalidSocket) {
UnwatchSocket();
#if defined(OS_WIN)
- closesocket(s);
+ closesocket(socket_);
#elif defined(OS_POSIX)
- close(s);
+ close(socket_);
#endif
}
}
diff --git a/chromium/net/socket/stream_listen_socket.h b/chromium/net/socket/stream_listen_socket.h
index 9825a4ef126..3c9b984ed76 100644
--- a/chromium/net/socket/stream_listen_socket.h
+++ b/chromium/net/socket/stream_listen_socket.h
@@ -91,7 +91,7 @@ class NET_EXPORT StreamListenSocket
void Listen();
void Read();
void Close();
- void CloseSocket(SocketDescriptor s);
+ void CloseSocket();
// Pass any value in case of Windows, because in Windows
// we are not using state.
diff --git a/chromium/net/socket/tcp_listen_socket_unittest.cc b/chromium/net/socket/tcp_listen_socket_unittest.cc
index b122c6143d8..41c41f81fe7 100644
--- a/chromium/net/socket/tcp_listen_socket_unittest.cc
+++ b/chromium/net/socket/tcp_listen_socket_unittest.cc
@@ -18,11 +18,9 @@
namespace net {
-static const int kReadBufSize = 1024;
-static const char kHelloWorld[] = "HELLO, WORLD";
-static const int kMaxQueueSize = 20;
-static const char kLoopback[] = "127.0.0.1";
-static const int kDefaultTimeoutMs = 5000;
+const int kReadBufSize = 1024;
+const char kHelloWorld[] = "HELLO, WORLD";
+const char kLoopback[] = "127.0.0.1";
TCPListenSocketTester::TCPListenSocketTester()
: loop_(NULL),
@@ -75,7 +73,7 @@ void TCPListenSocketTester::TearDown() {
#if defined(OS_WIN)
ASSERT_EQ(0, closesocket(test_socket_));
#elif defined(OS_POSIX)
- ASSERT_EQ(0, HANDLE_EINTR(close(test_socket_)));
+ ASSERT_EQ(0, IGNORE_EINTR(close(test_socket_)));
#endif
NextAction();
ASSERT_EQ(ACTION_CLOSE, last_action_.type());
diff --git a/chromium/net/socket/tcp_socket_libevent.cc b/chromium/net/socket/tcp_socket_libevent.cc
index 66416f70207..f4e4fe861af 100644
--- a/chromium/net/socket/tcp_socket_libevent.cc
+++ b/chromium/net/socket/tcp_socket_libevent.cc
@@ -69,6 +69,20 @@ bool SetTCPKeepAlive(int fd, bool enable, int delay) {
return true;
}
+int MapAcceptError(int os_error) {
+ switch (os_error) {
+ // If the client aborts the connection before the server calls accept,
+ // POSIX specifies accept should fail with ECONNABORTED. The server can
+ // ignore the error and just call accept again, so we map the error to
+ // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
+ // 5.11, "Connection Abort before accept Returns".
+ case ECONNABORTED:
+ return ERR_IO_PENDING;
+ default:
+ return MapSystemError(os_error);
+ }
+}
+
int MapConnectError(int os_error) {
switch (os_error) {
case EACCES:
@@ -507,7 +521,7 @@ void TCPSocketLibevent::Close() {
DCHECK(ok);
if (socket_ != kInvalidSocket) {
- if (HANDLE_EINTR(close(socket_)) < 0)
+ if (IGNORE_EINTR(close(socket_)) < 0)
PLOG(ERROR) << "close";
socket_ = kInvalidSocket;
}
@@ -567,7 +581,7 @@ int TCPSocketLibevent::AcceptInternal(scoped_ptr<TCPSocketLibevent>* socket,
storage.addr,
&storage.addr_len));
if (new_socket < 0) {
- int net_error = MapSystemError(errno);
+ int net_error = MapAcceptError(errno);
if (net_error != ERR_IO_PENDING)
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
return net_error;
@@ -576,7 +590,7 @@ int TCPSocketLibevent::AcceptInternal(scoped_ptr<TCPSocketLibevent>* socket,
IPEndPoint ip_end_point;
if (!ip_end_point.FromSockAddr(storage.addr, storage.addr_len)) {
NOTREACHED();
- if (HANDLE_EINTR(close(new_socket)) < 0)
+ if (IGNORE_EINTR(close(new_socket)) < 0)
PLOG(ERROR) << "close";
net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT,
ERR_ADDRESS_INVALID);
diff --git a/chromium/net/socket/tcp_socket_win.cc b/chromium/net/socket/tcp_socket_win.cc
index 7d76232f962..5f8cd5c3e86 100644
--- a/chromium/net/socket/tcp_socket_win.cc
+++ b/chromium/net/socket/tcp_socket_win.cc
@@ -636,11 +636,6 @@ void TCPSocketWin::Close() {
socket_ = INVALID_SOCKET;
}
- if (accept_event_) {
- WSACloseEvent(accept_event_);
- accept_event_ = WSA_INVALID_EVENT;
- }
-
if (!accept_callback_.is_null()) {
accept_watcher_.StopWatching();
accept_socket_ = NULL;
@@ -648,6 +643,11 @@ void TCPSocketWin::Close() {
accept_callback_.Reset();
}
+ if (accept_event_) {
+ WSACloseEvent(accept_event_);
+ accept_event_ = WSA_INVALID_EVENT;
+ }
+
if (core_) {
if (waiting_connect_) {
// We closed the socket, so this notification will never come.
@@ -742,6 +742,14 @@ void TCPSocketWin::OnObjectSignaled(HANDLE object) {
accept_address_ = NULL;
base::ResetAndReturn(&accept_callback_).Run(result);
}
+ } else {
+ // This happens when a client opens a connection and closes it before we
+ // have a chance to accept it.
+ DCHECK(ev.lNetworkEvents == 0);
+
+ // Start watching the next FD_ACCEPT event.
+ WSAEventSelect(socket_, accept_event_, FD_ACCEPT);
+ accept_watcher_.StartWatching(accept_event_, this);
}
}
diff --git a/chromium/net/socket/transport_client_socket_pool.cc b/chromium/net/socket/transport_client_socket_pool.cc
index d03e3e651ac..ec56dcba65c 100644
--- a/chromium/net/socket/transport_client_socket_pool.cc
+++ b/chromium/net/socket/transport_client_socket_pool.cc
@@ -7,10 +7,12 @@
#include <algorithm>
#include "base/compiler_specific.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
+#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/ip_endpoint.h"
@@ -46,6 +48,14 @@ bool AddressListOnlyContainsIPv6(const AddressList& list) {
} // namespace
+// This lock protects |g_last_connect_time|.
+static base::LazyInstance<base::Lock>::Leaky
+ g_last_connect_time_lock = LAZY_INSTANCE_INITIALIZER;
+
+// |g_last_connect_time| has the last time a connect() call is made.
+static base::LazyInstance<base::TimeTicks>::Leaky
+ g_last_connect_time = LAZY_INSTANCE_INITIALIZER;
+
TransportSocketParams::TransportSocketParams(
const HostPortPair& host_port_pair,
bool disable_resolver_cache,
@@ -85,7 +95,8 @@ TransportConnectJob::TransportConnectJob(
params_(params),
client_socket_factory_(client_socket_factory),
resolver_(host_resolver),
- next_state_(STATE_NONE) {
+ next_state_(STATE_NONE),
+ interval_between_connects_(CONNECT_INTERVAL_GT_20MS) {
}
TransportConnectJob::~TransportConnectJob() {
@@ -186,6 +197,25 @@ int TransportConnectJob::DoResolveHostComplete(int result) {
}
int TransportConnectJob::DoTransportConnect() {
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks last_connect_time;
+ {
+ base::AutoLock lock(g_last_connect_time_lock.Get());
+ last_connect_time = g_last_connect_time.Get();
+ *g_last_connect_time.Pointer() = now;
+ }
+ if (last_connect_time.is_null()) {
+ interval_between_connects_ = CONNECT_INTERVAL_GT_20MS;
+ } else {
+ int64 interval = (now - last_connect_time).InMilliseconds();
+ if (interval <= 10)
+ interval_between_connects_ = CONNECT_INTERVAL_LE_10MS;
+ else if (interval <= 20)
+ interval_between_connects_ = CONNECT_INTERVAL_LE_20MS;
+ else
+ interval_between_connects_ = CONNECT_INTERVAL_GT_20MS;
+ }
+
next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
transport_socket_ = client_socket_factory_->CreateTransportClientSocket(
addresses_, net_log().net_log(), net_log().source());
@@ -222,6 +252,36 @@ int TransportConnectJob::DoTransportConnectComplete(int result) {
base::TimeDelta::FromMinutes(10),
100);
+ switch (interval_between_connects_) {
+ case CONNECT_INTERVAL_LE_10MS:
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_10ms",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ break;
+ case CONNECT_INTERVAL_LE_20MS:
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "Net.TCP_Connection_Latency_Interval_LessThanOrEqual_20ms",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ break;
+ case CONNECT_INTERVAL_GT_20MS:
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "Net.TCP_Connection_Latency_Interval_GreaterThan_20ms",
+ connect_duration,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromMinutes(10),
+ 100);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
if (is_ipv4) {
UMA_HISTOGRAM_CUSTOM_TIMES("Net.TCP_Connection_Latency_IPv4_No_Race",
connect_duration,
diff --git a/chromium/net/socket/transport_client_socket_pool.h b/chromium/net/socket/transport_client_socket_pool.h
index 16e421a4550..1c22bf29ec3 100644
--- a/chromium/net/socket/transport_client_socket_pool.h
+++ b/chromium/net/socket/transport_client_socket_pool.h
@@ -93,6 +93,12 @@ class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
STATE_NONE,
};
+ enum ConnectInterval {
+ CONNECT_INTERVAL_LE_10MS,
+ CONNECT_INTERVAL_LE_20MS,
+ CONNECT_INTERVAL_GT_20MS,
+ };
+
void OnIOComplete(int result);
// Runs the state transition loop.
@@ -125,6 +131,9 @@ class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
base::TimeTicks fallback_connect_start_time_;
base::OneShotTimer<TransportConnectJob> fallback_timer_;
+ // Track the interval between this connect and previous connect.
+ ConnectInterval interval_between_connects_;
+
DISALLOW_COPY_AND_ASSIGN(TransportConnectJob);
};
diff --git a/chromium/net/socket/transport_client_socket_pool_unittest.cc b/chromium/net/socket/transport_client_socket_pool_unittest.cc
index a984ea3b740..ff85847979b 100644
--- a/chromium/net/socket/transport_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/transport_client_socket_pool_unittest.cc
@@ -152,6 +152,8 @@ class MockClientSocket : public StreamSocket {
bool connected_;
const AddressList addrlist_;
BoundNetLog net_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClientSocket);
};
class MockFailingClientSocket : public StreamSocket {
@@ -214,6 +216,8 @@ class MockFailingClientSocket : public StreamSocket {
private:
const AddressList addrlist_;
BoundNetLog net_log_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockFailingClientSocket);
};
class MockPendingClientSocket : public StreamSocket {
@@ -228,13 +232,13 @@ class MockPendingClientSocket : public StreamSocket {
bool should_stall,
base::TimeDelta delay,
net::NetLog* net_log)
- : weak_factory_(this),
- should_connect_(should_connect),
+ : should_connect_(should_connect),
should_stall_(should_stall),
delay_(delay),
is_connected_(false),
addrlist_(addrlist),
- net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
+ net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
+ weak_factory_(this) {
}
// StreamSocket implementation.
@@ -312,13 +316,16 @@ class MockPendingClientSocket : public StreamSocket {
}
}
- base::WeakPtrFactory<MockPendingClientSocket> weak_factory_;
bool should_connect_;
bool should_stall_;
base::TimeDelta delay_;
bool is_connected_;
const AddressList addrlist_;
BoundNetLog net_log_;
+
+ base::WeakPtrFactory<MockPendingClientSocket> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockPendingClientSocket);
};
class MockClientSocketFactory : public ClientSocketFactory {
@@ -430,6 +437,8 @@ class MockClientSocketFactory : public ClientSocketFactory {
int client_socket_index_;
int client_socket_index_max_;
base::TimeDelta delay_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClientSocketFactory);
};
class TransportClientSocketPoolTest : public testing::Test {
@@ -488,6 +497,8 @@ class TransportClientSocketPoolTest : public testing::Test {
MockClientSocketFactory client_socket_factory_;
TransportClientSocketPool pool_;
ClientSocketPoolTest test_base_;
+
+ DISALLOW_COPY_AND_ASSIGN(TransportClientSocketPoolTest);
};
TEST(TransportConnectJobTest, MakeAddrListStartWithIPv4) {
@@ -579,7 +590,7 @@ TEST_F(TransportClientSocketPoolTest, Basic) {
// Make sure that TransportConnectJob passes on its priority to its
// HostResolver request on Init.
TEST_F(TransportClientSocketPoolTest, SetResolvePriorityOnInit) {
- for (int i = MINIMUM_PRIORITY; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
RequestPriority priority = static_cast<RequestPriority>(i);
TestCompletionCallback callback;
ClientSocketHandle handle;
diff --git a/chromium/net/socket/unix_domain_socket_posix.cc b/chromium/net/socket/unix_domain_socket_posix.cc
index 2b781d58b35..3141f7166b2 100644
--- a/chromium/net/socket/unix_domain_socket_posix.cc
+++ b/chromium/net/socket/unix_domain_socket_posix.cc
@@ -130,7 +130,7 @@ SocketDescriptor UnixDomainSocket::CreateAndBind(const std::string& path,
LOG(ERROR) << "Could not bind unix domain socket to " << path;
if (use_abstract_namespace)
LOG(ERROR) << " (with abstract namespace enabled)";
- if (HANDLE_EINTR(close(s)) < 0)
+ if (IGNORE_EINTR(close(s)) < 0)
LOG(ERROR) << "close() error";
return kInvalidSocket;
}
@@ -145,7 +145,7 @@ void UnixDomainSocket::Accept() {
gid_t group_id;
if (!GetPeerIds(conn, &user_id, &group_id) ||
!auth_callback_.Run(user_id, group_id)) {
- if (HANDLE_EINTR(close(conn)) < 0)
+ if (IGNORE_EINTR(close(conn)) < 0)
LOG(ERROR) << "close() error";
return;
}
diff --git a/chromium/net/socket/unix_domain_socket_posix_unittest.cc b/chromium/net/socket/unix_domain_socket_posix_unittest.cc
index f062d274205..b1857e62e0e 100644
--- a/chromium/net/socket/unix_domain_socket_posix_unittest.cc
+++ b/chromium/net/socket/unix_domain_socket_posix_unittest.cc
@@ -40,7 +40,6 @@ namespace net {
namespace {
const char kSocketFilename[] = "unix_domain_socket_for_testing";
-const char kFallbackSocketName[] = "unix_domain_socket_for_testing_2";
const char kInvalidSocketPath[] = "/invalid/path";
const char kMsg[] = "hello";
@@ -55,7 +54,7 @@ enum EventType {
string MakeSocketPath(const string& socket_file_name) {
base::FilePath temp_dir;
- file_util::GetTempDir(&temp_dir);
+ base::GetTempDir(&temp_dir);
return temp_dir.Append(socket_file_name).value();
}
@@ -275,6 +274,7 @@ TEST_F(UnixDomainSocketTest, TestFallbackName) {
file_path_.value(), "", socket_delegate_.get(), MakeAuthCallback());
EXPECT_TRUE(socket_.get() == NULL);
// Now with a fallback name.
+ const char kFallbackSocketName[] = "unix_domain_socket_for_testing_2";
socket_ = UnixDomainSocket::CreateAndListenWithAbstractNamespace(
file_path_.value(),
MakeSocketPath(kFallbackSocketName),
@@ -306,7 +306,7 @@ TEST_F(UnixDomainSocketTest, TestWithClient) {
ASSERT_EQ(kMsg, socket_delegate_->ReceivedData());
// Close the client socket.
- ret = HANDLE_EINTR(close(sock));
+ ret = IGNORE_EINTR(close(sock));
event = event_manager_->WaitForEvent();
ASSERT_EQ(EVENT_CLOSE, event);
}
diff --git a/chromium/net/socket_stream/socket_stream.cc b/chromium/net/socket_stream/socket_stream.cc
index 699c8204aea..64190f09715 100644
--- a/chromium/net/socket_stream/socket_stream.cc
+++ b/chromium/net/socket_stream/socket_stream.cc
@@ -331,11 +331,16 @@ void SocketStream::set_addresses(const AddressList& addresses) {
void SocketStream::DoClose() {
closing_ = true;
- // If next_state_ is STATE_TCP_CONNECT, it's waiting other socket
- // establishing connection. If next_state_ is STATE_AUTH_REQUIRED, it's
- // waiting for restarting. In these states, we'll close the SocketStream
- // now.
- if (next_state_ == STATE_TCP_CONNECT || next_state_ == STATE_AUTH_REQUIRED) {
+ // If next_state_ is:
+ // - STATE_TCP_CONNECT_COMPLETE, it's waiting other socket establishing
+ // connection.
+ // - STATE_AUTH_REQUIRED, it's waiting for restarting.
+ // - STATE_RESOLVE_PROTOCOL_COMPLETE, it's waiting for delegate_ to finish
+ // OnStartOpenConnection method call
+ // In these states, we'll close the SocketStream now.
+ if (next_state_ == STATE_TCP_CONNECT_COMPLETE ||
+ next_state_ == STATE_AUTH_REQUIRED ||
+ next_state_ == STATE_RESOLVE_PROTOCOL_COMPLETE) {
DoLoop(ERR_ABORTED);
return;
}
@@ -451,13 +456,13 @@ void SocketStream::OnWriteCompleted(int result) {
}
void SocketStream::DoLoop(int result) {
+ if (next_state_ == STATE_NONE)
+ return;
+
// If context was not set, close immediately.
if (!context_)
next_state_ = STATE_CLOSE;
- if (next_state_ == STATE_NONE)
- return;
-
do {
State state = next_state_;
next_state_ = STATE_NONE;
diff --git a/chromium/net/socket_stream/socket_stream.h b/chromium/net/socket_stream/socket_stream.h
index 90aeb8c54b9..a91d5cac501 100644
--- a/chromium/net/socket_stream/socket_stream.h
+++ b/chromium/net/socket_stream/socket_stream.h
@@ -189,6 +189,8 @@ class NET_EXPORT SocketStream
private:
FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, IOPending);
FRIEND_TEST_ALL_PREFIXES(SocketStreamTest, SwitchAfterPending);
+ FRIEND_TEST_ALL_PREFIXES(SocketStreamTest,
+ NullContextSocketStreamShouldNotCrash);
friend class WebSocketThrottleTest;
diff --git a/chromium/net/socket_stream/socket_stream_unittest.cc b/chromium/net/socket_stream/socket_stream_unittest.cc
index bd0a348b0ef..cbf559495c0 100644
--- a/chromium/net/socket_stream/socket_stream_unittest.cc
+++ b/chromium/net/socket_stream/socket_stream_unittest.cc
@@ -160,6 +160,8 @@ class SocketStreamEventRecorder : public SocketStream::Delegate {
void SetAuthInfo(const AuthCredentials& credentials) {
credentials_ = credentials;
}
+ // Wakes up the SocketStream waiting for completion of OnStartOpenConnection()
+ // of its delegate.
void CompleteConnection(int result) {
connection_callback_.Run(result);
}
@@ -290,6 +292,9 @@ class SocketStreamTest : public PlatformTest {
return mock_socket_factory_.get();
}
+ // Functions for SocketStreamEventRecorder to handle calls to the
+ // SocketStream::Delegate methods from the SocketStream.
+
virtual void DoSendWebSocketHandshake(SocketStreamEvent* event) {
event->socket->SendData(
handshake_request_.data(), handshake_request_.size());
@@ -309,6 +314,22 @@ class SocketStreamTest : public PlatformTest {
event->socket->Close();
}
+ virtual void DoCloseFlushPendingWriteTestWithSetContextNull(
+ SocketStreamEvent* event) {
+ event->socket->set_context(NULL);
+ // handshake response received.
+ for (size_t i = 0; i < messages_.size(); i++) {
+ std::vector<char> frame;
+ frame.push_back('\0');
+ frame.insert(frame.end(), messages_[i].begin(), messages_[i].end());
+ frame.push_back('\xff');
+ EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size()));
+ }
+ // Actual StreamSocket close must happen after all frames queued by
+ // SendData above are sent out.
+ event->socket->Close();
+ }
+
virtual void DoFailByTooBigDataAndClose(SocketStreamEvent* event) {
std::string frame(event->number + 1, 0x00);
VLOG(1) << event->number;
@@ -320,6 +341,8 @@ class SocketStreamTest : public PlatformTest {
return ERR_PROTOCOL_SWITCHED;
}
+ // Notifies |io_test_callback_| of that this method is called, and keeps the
+ // SocketStream waiting.
virtual int DoIOPending(SocketStreamEvent* event) {
io_test_callback_.callback().Run(OK);
return ERR_IO_PENDING;
@@ -406,6 +429,9 @@ TEST_F(SocketStreamTest, CloseFlushPendingWrite) {
test_callback.WaitForResult();
+ EXPECT_TRUE(data_provider.at_read_eof());
+ EXPECT_TRUE(data_provider.at_write_eof());
+
const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
ASSERT_EQ(7U, events.size());
@@ -682,13 +708,13 @@ TEST_F(SocketStreamTest, IOPending) {
scoped_ptr<SocketStreamEventRecorder> delegate(
new SocketStreamEventRecorder(test_callback.callback()));
+ delegate->SetOnStartOpenConnection(base::Bind(
+ &SocketStreamTest::DoIOPending, base::Unretained(this)));
delegate->SetOnConnected(base::Bind(
&SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
delegate->SetOnReceivedData(base::Bind(
&SocketStreamTest::DoCloseFlushPendingWriteTest,
base::Unretained(this)));
- delegate->SetOnStartOpenConnection(base::Bind(
- &SocketStreamTest::DoIOPending, base::Unretained(this)));
TestURLRequestContext context;
@@ -728,6 +754,9 @@ TEST_F(SocketStreamTest, IOPending) {
EXPECT_EQ(OK, test_callback.WaitForResult());
+ EXPECT_TRUE(data_provider.at_read_eof());
+ EXPECT_TRUE(data_provider.at_write_eof());
+
const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
ASSERT_EQ(7U, events.size());
@@ -786,6 +815,7 @@ TEST_F(SocketStreamTest, SwitchAfterPending) {
socket_stream->Connect();
io_test_callback_.WaitForResult();
+
EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE,
socket_stream->next_state_);
delegate->CompleteConnection(ERR_PROTOCOL_SWITCHED);
@@ -962,4 +992,58 @@ TEST_F(SocketStreamTest, OnErrorDetachDelegate) {
EXPECT_EQ(OK, test_callback.WaitForResult());
}
+TEST_F(SocketStreamTest, NullContextSocketStreamShouldNotCrash) {
+ TestCompletionCallback test_callback;
+
+ scoped_ptr<SocketStreamEventRecorder> delegate(
+ new SocketStreamEventRecorder(test_callback.callback()));
+ TestURLRequestContext context;
+ scoped_refptr<SocketStream> socket_stream(
+ new SocketStream(GURL("ws://example.com/demo"), delegate.get()));
+ delegate->SetOnStartOpenConnection(base::Bind(
+ &SocketStreamTest::DoIOPending, base::Unretained(this)));
+ delegate->SetOnConnected(base::Bind(
+ &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this)));
+ delegate->SetOnReceivedData(base::Bind(
+ &SocketStreamTest::DoCloseFlushPendingWriteTestWithSetContextNull,
+ base::Unretained(this)));
+
+ socket_stream->set_context(&context);
+
+ MockWrite data_writes[] = {
+ MockWrite(SocketStreamTest::kWebSocketHandshakeRequest),
+ };
+ MockRead data_reads[] = {
+ MockRead(SocketStreamTest::kWebSocketHandshakeResponse),
+ };
+ AddWebSocketMessage("message1");
+ AddWebSocketMessage("message2");
+
+ DelayedSocketData data_provider(
+ 1, data_reads, arraysize(data_reads),
+ data_writes, arraysize(data_writes));
+
+ MockClientSocketFactory* mock_socket_factory = GetMockClientSocketFactory();
+ mock_socket_factory->AddSocketDataProvider(&data_provider);
+ socket_stream->SetClientSocketFactory(mock_socket_factory);
+
+ socket_stream->Connect();
+ io_test_callback_.WaitForResult();
+ delegate->CompleteConnection(OK);
+ EXPECT_EQ(OK, test_callback.WaitForResult());
+
+ EXPECT_TRUE(data_provider.at_read_eof());
+ EXPECT_TRUE(data_provider.at_write_eof());
+
+ const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents();
+ ASSERT_EQ(5U, events.size());
+
+ EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION,
+ events[0].event_type);
+ EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type);
+ EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type);
+ EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type);
+ EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type);
+}
+
} // namespace net
diff --git a/chromium/net/spdy/buffered_spdy_framer.cc b/chromium/net/spdy/buffered_spdy_framer.cc
index 46d028404fe..fee2192dc4d 100644
--- a/chromium/net/spdy/buffered_spdy_framer.cc
+++ b/chromium/net/spdy/buffered_spdy_framer.cc
@@ -10,8 +10,7 @@ namespace net {
SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
switch (next_proto) {
- case kProtoSPDY2:
- case kProtoSPDY21:
+ case kProtoDeprecatedSPDY2:
return SPDY2;
case kProtoSPDY3:
case kProtoSPDY31:
@@ -22,7 +21,6 @@ SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
return SPDY4;
case kProtoUnknown:
case kProtoHTTP11:
- case kProtoSPDY1:
case kProtoQUIC1SPDY3:
break;
}
@@ -177,6 +175,7 @@ void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
bool fin) {
frames_received_++;
header_stream_id_ = stream_id;
+ visitor_->OnDataFrameHeader(stream_id, length, fin);
}
void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
@@ -219,7 +218,7 @@ void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id,
visitor_->OnPushPromise(stream_id, promised_stream_id);
}
-int BufferedSpdyFramer::protocol_version() {
+SpdyMajorVersion BufferedSpdyFramer::protocol_version() {
return spdy_framer_.protocol_version();
}
@@ -253,19 +252,16 @@ SpdyFrame* BufferedSpdyFramer::CreateSynStream(
SpdyPriority priority,
uint8 credential_slot,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers) {
return spdy_framer_.CreateSynStream(stream_id, associated_stream_id, priority,
- credential_slot, flags, compressed,
- headers);
+ credential_slot, flags, headers);
}
SpdyFrame* BufferedSpdyFramer::CreateSynReply(
SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers) {
- return spdy_framer_.CreateSynReply(stream_id, flags, compressed, headers);
+ return spdy_framer_.CreateSynReply(stream_id, flags, headers);
}
SpdyFrame* BufferedSpdyFramer::CreateRstStream(
@@ -293,9 +289,8 @@ SpdyFrame* BufferedSpdyFramer::CreateGoAway(
SpdyFrame* BufferedSpdyFramer::CreateHeaders(
SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers) {
- return spdy_framer_.CreateHeaders(stream_id, flags, compressed, headers);
+ return spdy_framer_.CreateHeaders(stream_id, flags, headers);
}
SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
@@ -304,11 +299,6 @@ SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
return spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size);
}
-SpdyFrame* BufferedSpdyFramer::CreateCredentialFrame(
- const SpdyCredential& credential) const {
- return spdy_framer_.CreateCredentialFrame(credential);
-}
-
SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
const char* data,
uint32 len,
diff --git a/chromium/net/spdy/buffered_spdy_framer.h b/chromium/net/spdy/buffered_spdy_framer.h
index 1786067d6a3..3e10561ba93 100644
--- a/chromium/net/spdy/buffered_spdy_framer.h
+++ b/chromium/net/spdy/buffered_spdy_framer.h
@@ -53,6 +53,11 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramerVisitorInterface {
bool fin,
const SpdyHeaderBlock& headers) = 0;
+ // Called when a data frame header is received.
+ virtual void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) = 0;
+
// Called when data is received.
// |stream_id| The stream receiving data.
// |data| A buffer containing the data received.
@@ -154,7 +159,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
// SpdyFramer methods.
size_t ProcessInput(const char* data, size_t len);
- int protocol_version();
+ SpdyMajorVersion protocol_version();
void Reset();
SpdyFramer::SpdyError error_code() const;
SpdyFramer::SpdyState state() const;
@@ -165,11 +170,9 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
SpdyPriority priority,
uint8 credential_slot,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers);
SpdyFrame* CreateSynReply(SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers);
SpdyFrame* CreateRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) const;
@@ -180,13 +183,10 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer
SpdyGoAwayStatus status) const;
SpdyFrame* CreateHeaders(SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers);
SpdyFrame* CreateWindowUpdate(
SpdyStreamId stream_id,
uint32 delta_window_size) const;
- SpdyFrame* CreateCredentialFrame(
- const SpdyCredential& credential) const;
SpdyFrame* CreateDataFrame(SpdyStreamId stream_id,
const char* data,
uint32 len,
diff --git a/chromium/net/spdy/buffered_spdy_framer_unittest.cc b/chromium/net/spdy/buffered_spdy_framer_unittest.cc
index 849138f98eb..9a11fd3d52c 100644
--- a/chromium/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/chromium/net/spdy/buffered_spdy_framer_unittest.cc
@@ -67,6 +67,12 @@ class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
headers_ = headers;
}
+ virtual void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) OVERRIDE {
+ ADD_FAILURE() << "Unexpected OnDataFrameHeader call.";
+ }
+
virtual void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
@@ -187,7 +193,8 @@ class BufferedSpdyFramerTest
INSTANTIATE_TEST_CASE_P(
NextProto,
BufferedSpdyFramerTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
TEST_P(BufferedSpdyFramerTest, OnSetting) {
@@ -219,7 +226,6 @@ TEST_P(BufferedSpdyFramerTest, ReadSynStreamHeaderBlock) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
@@ -242,7 +248,6 @@ TEST_P(BufferedSpdyFramerTest, ReadSynReplyHeaderBlock) {
scoped_ptr<SpdyFrame> control_frame(
framer.CreateSynReply(1, // stream_id
CONTROL_FLAG_NONE,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
@@ -265,7 +270,6 @@ TEST_P(BufferedSpdyFramerTest, ReadHeadersHeaderBlock) {
scoped_ptr<SpdyFrame> control_frame(
framer.CreateHeaders(1, // stream_id
CONTROL_FLAG_NONE,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
diff --git a/chromium/net/spdy/spdy_bitmasks.h b/chromium/net/spdy/spdy_bitmasks.h
index 72fb9484103..71ad1e6a93f 100644
--- a/chromium/net/spdy/spdy_bitmasks.h
+++ b/chromium/net/spdy/spdy_bitmasks.h
@@ -13,10 +13,6 @@ const unsigned int kStreamIdMask = 0x7fffffff;
// Control flag mask from the SpdyHeader
const unsigned int kControlFlagMask = 0x8000;
-// Priority mask from the SYN_FRAME
-const unsigned int kSpdy3PriorityMask = 0xe0;
-const unsigned int kSpdy2PriorityMask = 0xc0;
-
// Mask the lower 24 bits.
const unsigned int kLengthMask = 0xffffff;
diff --git a/chromium/net/spdy/spdy_credential_builder.cc b/chromium/net/spdy/spdy_credential_builder.cc
deleted file mode 100644
index 79567b668af..00000000000
--- a/chromium/net/spdy/spdy_credential_builder.cc
+++ /dev/null
@@ -1,86 +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/spdy/spdy_credential_builder.h"
-
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/ec_signature_creator.h"
-#include "net/base/net_errors.h"
-#include "net/cert/asn1_util.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/spdy/spdy_framer.h"
-#include "net/ssl/server_bound_cert_service.h"
-
-namespace net {
-
-namespace {
-
-std::vector<uint8> ToVector(base::StringPiece piece) {
- return std::vector<uint8>(piece.data(), piece.data() + piece.length());
-}
-
-} // namespace
-
-// static
-int SpdyCredentialBuilder::Build(const std::string& tls_unique,
- const std::string& key,
- const std::string& cert,
- size_t slot,
- SpdyCredential* credential) {
- std::string secret = SpdyCredentialBuilder::GetCredentialSecret(tls_unique);
-
- // Extract the SubjectPublicKeyInfo from the certificate.
- base::StringPiece public_key_info;
- if(!asn1::ExtractSPKIFromDERCert(cert, &public_key_info))
- return ERR_BAD_SSL_CLIENT_AUTH_CERT;
-
- // Next, extract the SubjectPublicKey data, which will actually
- // be stored in the cert field of the credential frame.
- base::StringPiece public_key;
- if (!asn1::ExtractSubjectPublicKeyFromSPKI(public_key_info, &public_key))
- return ERR_BAD_SSL_CLIENT_AUTH_CERT;
- // Drop one byte of padding bits count from the BIT STRING
- // (this will always be zero). Drop one byte of X9.62 format specification
- // (this will always be 4 to indicated an uncompressed point).
- DCHECK_GT(public_key.length(), 2u);
- DCHECK_EQ(0, static_cast<int>(public_key[0]));
- DCHECK_EQ(4, static_cast<int>(public_key[1]));
- public_key = public_key.substr(2, public_key.length());
-
- // Convert the strings into a vector<unit8>
- std::vector<uint8> der_signature;
- scoped_ptr<crypto::ECPrivateKey> private_key(
- crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
- ServerBoundCertService::kEPKIPassword,
- ToVector(key), ToVector(public_key_info)));
- scoped_ptr<crypto::ECSignatureCreator> creator(
- crypto::ECSignatureCreator::Create(private_key.get()));
- creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()),
- secret.length(), &der_signature);
-
- std::vector<uint8> proof_vector;
- if (!creator->DecodeSignature(der_signature, &proof_vector)) {
- NOTREACHED();
- return ERR_UNEXPECTED;
- }
-
- credential->slot = slot;
- credential->certs.push_back(public_key.as_string());
- credential->proof.assign(proof_vector.begin(), proof_vector.end());
- return OK;
-}
-
-// static
-std::string SpdyCredentialBuilder::GetCredentialSecret(
- const std::string& tls_unique) {
- const char prefix[] = "SPDY CREDENTIAL ChannelID\0client -> server";
- std::string secret(prefix, arraysize(prefix));
- secret.append(tls_unique);
-
- return secret;
-}
-
-} // namespace net
diff --git a/chromium/net/spdy/spdy_credential_builder.h b/chromium/net/spdy/spdy_credential_builder.h
deleted file mode 100644
index 3bdc0a1171e..00000000000
--- a/chromium/net/spdy/spdy_credential_builder.h
+++ /dev/null
@@ -1,36 +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_SPDY_SPDY_CREDENTIAL_BUILDER_H_
-#define NET_SPDY_SPDY_CREDENTIAL_BUILDER_H_
-
-#include <string>
-
-#include "net/base/net_export.h"
-
-namespace net {
-
-class SSLClientSocket;
-struct SpdyCredential;
-
-// This class provides facilities for building the various fields of
-// SPDY CREDENTIAL frames.
-class NET_EXPORT_PRIVATE SpdyCredentialBuilder {
- public:
- static int Build(const std::string& tls_unique,
- const std::string& key,
- const std::string& cert,
- size_t slot,
- SpdyCredential* credential);
-
- private:
- friend class SpdyCredentialBuilderTest;
-
- // Returns the secret data to be signed as part of a credential frame.
- static std::string GetCredentialSecret(const std::string& tls_unique);
-};
-
-} // namespace net
-
-#endif // NET_SPDY_SPDY_CREDENTIAL_BUILDER_H_
diff --git a/chromium/net/spdy/spdy_credential_builder_unittest.cc b/chromium/net/spdy/spdy_credential_builder_unittest.cc
deleted file mode 100644
index 84aff7a60c4..00000000000
--- a/chromium/net/spdy/spdy_credential_builder_unittest.cc
+++ /dev/null
@@ -1,145 +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/spdy/spdy_credential_builder.h"
-
-#include "base/message_loop/message_loop_proxy.h"
-#include "crypto/ec_private_key.h"
-#include "crypto/ec_signature_creator.h"
-#include "net/cert/asn1_util.h"
-#include "net/spdy/spdy_test_util_common.h"
-#include "net/ssl/default_server_bound_cert_store.h"
-#include "net/ssl/server_bound_cert_service.h"
-#include "testing/platform_test.h"
-
-namespace net {
-
-namespace {
-
-const static size_t kSlot = 2;
-const static char kSecretPrefix[] =
- "SPDY CREDENTIAL ChannelID\0client -> server";
-
-void CreateCertAndKey(std::string* cert, std::string* key) {
- // TODO(rch): Share this code with ServerBoundCertServiceTest.
- scoped_ptr<ServerBoundCertService> server_bound_cert_service(
- new ServerBoundCertService(new DefaultServerBoundCertStore(NULL),
- base::MessageLoopProxy::current()));
-
- TestCompletionCallback callback;
- ServerBoundCertService::RequestHandle request_handle;
- int rv = server_bound_cert_service->GetOrCreateDomainBoundCert(
- "www.google.com", key, cert, callback.callback(), &request_handle);
- EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_EQ(OK, callback.WaitForResult());
-}
-
-} // namespace
-
-class SpdyCredentialBuilderTest : public testing::Test {
- public:
- SpdyCredentialBuilderTest() {
- CreateCertAndKey(&cert_, &key_);
- }
-
- protected:
- int Build() {
- return SpdyCredentialBuilder::Build(
- MockClientSocket::kTlsUnique, key_, cert_, kSlot, &credential_);
- }
-
- std::string GetCredentialSecret() {
- return SpdyCredentialBuilder::GetCredentialSecret(
- MockClientSocket::kTlsUnique);
- }
-
- std::string cert_;
- std::string key_;
- SpdyCredential credential_;
- MockECSignatureCreatorFactory ec_signature_creator_factory_;
-};
-
-// http://crbug.com/142833, http://crbug.com/140991. The following tests fail
-// with OpenSSL due to the unimplemented ec_private_key_openssl.cc.
-#if defined(USE_OPENSSL)
-#define MAYBE_GetCredentialSecret DISABLED_GetCredentialSecret
-#else
-#define MAYBE_GetCredentialSecret GetCredentialSecret
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_GetCredentialSecret) {
- std::string secret_str(kSecretPrefix, arraysize(kSecretPrefix));
- secret_str.append(MockClientSocket::kTlsUnique);
-
- EXPECT_EQ(secret_str, GetCredentialSecret());
-}
-
-#if defined(USE_OPENSSL)
-#define MAYBE_Succeeds DISABLED_Succeeds
-#else
-#define MAYBE_Succeeds Succeeds
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_Succeeds) {
- EXPECT_EQ(OK, Build());
-}
-
-#if defined(USE_OPENSSL)
-#define MAYBE_SetsSlotCorrectly DISABLED_SetsSlotCorrectly
-#else
-#define MAYBE_SetsSlotCorrectly SetsSlotCorrectly
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_SetsSlotCorrectly) {
- ASSERT_EQ(OK, Build());
- EXPECT_EQ(kSlot, credential_.slot);
-}
-
-#if defined(USE_OPENSSL)
-#define MAYBE_SetsCertCorrectly DISABLED_SetsCertCorrectly
-#else
-#define MAYBE_SetsCertCorrectly SetsCertCorrectly
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_SetsCertCorrectly) {
- ASSERT_EQ(OK, Build());
- base::StringPiece spki;
- ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_, &spki));
- base::StringPiece spk;
- ASSERT_TRUE(asn1::ExtractSubjectPublicKeyFromSPKI(spki, &spk));
- EXPECT_EQ(1u, credential_.certs.size());
- EXPECT_EQ(0, (int)spk[0]);
- EXPECT_EQ(4, (int)spk[1]);
- EXPECT_EQ(spk.substr(2, spk.length()).as_string(), credential_.certs[0]);
-}
-
-#if defined(USE_OPENSSL)
-#define MAYBE_SetsProofCorrectly DISABLED_SetsProofCorrectly
-#else
-#define MAYBE_SetsProofCorrectly SetsProofCorrectly
-#endif
-
-TEST_F(SpdyCredentialBuilderTest, MAYBE_SetsProofCorrectly) {
- ASSERT_EQ(OK, Build());
- base::StringPiece spki;
- ASSERT_TRUE(asn1::ExtractSPKIFromDERCert(cert_, &spki));
- std::vector<uint8> spki_data(spki.data(),
- spki.data() + spki.size());
- std::vector<uint8> key_data(key_.data(),
- key_.data() + key_.length());
- std::vector<uint8> proof_data;
- scoped_ptr<crypto::ECPrivateKey> private_key(
- crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
- ServerBoundCertService::kEPKIPassword, key_data, spki_data));
- scoped_ptr<crypto::ECSignatureCreator> creator(
- crypto::ECSignatureCreator::Create(private_key.get()));
- std::string secret = GetCredentialSecret();
- creator->Sign(reinterpret_cast<const unsigned char *>(secret.data()),
- secret.length(), &proof_data);
-
- std::string proof(proof_data.begin(), proof_data.end());
- EXPECT_EQ(proof, credential_.proof);
-}
-
-} // namespace net
diff --git a/chromium/net/spdy/spdy_credential_state.cc b/chromium/net/spdy/spdy_credential_state.cc
deleted file mode 100644
index 4549b3727f3..00000000000
--- a/chromium/net/spdy/spdy_credential_state.cc
+++ /dev/null
@@ -1,69 +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/spdy/spdy_credential_state.h"
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "net/ssl/server_bound_cert_service.h"
-
-namespace net {
-
-namespace {
-
-GURL GetCanonicalOrigin(const GURL& url) {
- std::string domain =
- ServerBoundCertService::GetDomainForHost(url.host());
- DCHECK(!domain.empty());
- if (domain == url.host())
- return url.GetOrigin();
- return GURL(url.scheme() + "://" + domain + ":" + url.port());
-}
-
-} // namespace
-
-const size_t SpdyCredentialState::kDefaultNumSlots = 8;
-const size_t SpdyCredentialState::kNoEntry = 0;
-
-SpdyCredentialState::SpdyCredentialState(size_t num_slots)
- : slots_(num_slots),
- last_added_(-1) {}
-
-SpdyCredentialState::~SpdyCredentialState() {}
-
-bool SpdyCredentialState::HasCredential(const GURL& origin) const {
- return FindCredentialSlot(origin) != kNoEntry;
-}
-
-size_t SpdyCredentialState::SetHasCredential(const GURL& origin) {
- size_t i = FindCredentialSlot(origin);
- if (i != kNoEntry)
- return i;
- // Add the new entry at the next index following the index of the last
- // entry added, or at index 0 if the last added index is the last index.
- if (last_added_ + 1 == slots_.size()) {
- last_added_ = 0;
- } else {
- last_added_++;
- }
- slots_[last_added_] = GetCanonicalOrigin(origin);
- return last_added_ + 1;
-}
-
-size_t SpdyCredentialState::FindCredentialSlot(const GURL& origin) const {
- GURL url = GetCanonicalOrigin(origin);
- for (size_t i = 0; i < slots_.size(); i++) {
- if (url == slots_[i])
- return i + 1;
- }
- return kNoEntry;
-}
-
-void SpdyCredentialState::Resize(size_t size) {
- slots_.resize(size);
- if (last_added_ >= slots_.size())
- last_added_ = slots_.size() - 1;
-}
-
-} // namespace net
diff --git a/chromium/net/spdy/spdy_credential_state.h b/chromium/net/spdy/spdy_credential_state.h
deleted file mode 100644
index 505b012c07e..00000000000
--- a/chromium/net/spdy/spdy_credential_state.h
+++ /dev/null
@@ -1,56 +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_SPDY_SPDY_CREDENTIAL_STATE_H_
-#define NET_SPDY_SPDY_CREDENTIAL_STATE_H_
-
-#include <vector>
-
-#include "net/base/net_export.h"
-#include "url/gurl.h"
-
-namespace net {
-
-// A class for tracking the credentials associated with a SPDY session.
-class NET_EXPORT_PRIVATE SpdyCredentialState {
- public:
- explicit SpdyCredentialState(size_t num_slots);
- ~SpdyCredentialState();
-
- // Changes the number of credentials being tracked. If the new size is
- // larger, then empty slots will be added to the end. If the new size is
- // smaller than the current size, then the extra slots will be truncated
- // from the end.
- void Resize(size_t size);
-
- // Returns the one-based index in |slots_| for |url| or kNoEntry, if no entry
- // for |url| exists.
- size_t FindCredentialSlot(const GURL& url) const;
-
- // Returns true if there is a credential associated with |url|.
- bool HasCredential(const GURL& url) const;
-
- // Adds the new credentials to be associated with all origins matching
- // |url|. If there is space, then it will add in the first available
- // position. Otherwise, an existing credential will be evicted. Returns
- // the slot in which this domain was added.
- size_t SetHasCredential(const GURL& url);
-
- // This value is defined as the default initial value in the SPDY spec unless
- // otherwise negotiated via SETTINGS.
- static const size_t kDefaultNumSlots;
-
- // Sentinel value to be returned by FindCredentialSlot when no entry exists.
- static const size_t kNoEntry;
-
- private:
- // Vector of origins that have credentials.
- std::vector<GURL> slots_;
- // Index of the last origin added to |slots_|.
- size_t last_added_;
-};
-
-} // namespace net
-
-#endif // NET_SPDY_SPDY_CREDENTIAL_STATE_H_
diff --git a/chromium/net/spdy/spdy_credential_state_unittest.cc b/chromium/net/spdy/spdy_credential_state_unittest.cc
deleted file mode 100644
index b5129217560..00000000000
--- a/chromium/net/spdy/spdy_credential_state_unittest.cc
+++ /dev/null
@@ -1,108 +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/spdy/spdy_credential_state.h"
-
-#include "net/base/host_port_pair.h"
-#include "testing/platform_test.h"
-
-namespace net {
-
-class SpdyCredentialStateTest : public PlatformTest {
- public:
- SpdyCredentialStateTest()
- : state_(4),
- origin1_("https://1.com"),
- origin2_("https://2.com"),
- origin3_("https://3.com"),
- origin4_("https://4.com"),
- origin5_("https://5.com"),
- origin6_("https://6.com"),
- origin11_("https://11.com"),
- host1_("https://www.1.com:443") {
- }
-
- protected:
- SpdyCredentialState state_;
- const GURL origin1_;
- const GURL origin2_;
- const GURL origin3_;
- const GURL origin4_;
- const GURL origin5_;
- const GURL origin6_;
- const GURL origin11_;
- const GURL host1_;
-
- DISALLOW_COPY_AND_ASSIGN(SpdyCredentialStateTest);
-};
-
-TEST_F(SpdyCredentialStateTest, HasCredentialReturnsFalseWhenEmpty) {
- EXPECT_FALSE(state_.HasCredential(origin1_));
- EXPECT_FALSE(state_.HasCredential(origin2_));
- EXPECT_FALSE(state_.HasCredential(origin3_));
-}
-
-TEST_F(SpdyCredentialStateTest, HasCredentialReturnsTrueWhenAdded) {
- state_.SetHasCredential(origin1_);
- EXPECT_TRUE(state_.HasCredential(origin1_));
- EXPECT_TRUE(state_.HasCredential(host1_));
- EXPECT_FALSE(state_.HasCredential(origin11_));
- EXPECT_FALSE(state_.HasCredential(origin2_));
- EXPECT_FALSE(state_.HasCredential(origin3_));
-}
-
-TEST_F(SpdyCredentialStateTest, SetCredentialAddsToEndOfList) {
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
- EXPECT_EQ(3u, (state_.SetHasCredential(origin3_)));
-}
-
-TEST_F(SpdyCredentialStateTest, SetReturnsPositionIfAlreadyInList) {
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
-}
-
-TEST_F(SpdyCredentialStateTest, SetReplacesOldestElementWhenFull) {
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
- EXPECT_EQ(3u, (state_.SetHasCredential(origin3_)));
- EXPECT_EQ(4u, (state_.SetHasCredential(origin4_)));
- EXPECT_EQ(1u, (state_.SetHasCredential(origin5_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin6_)));
- EXPECT_EQ(3u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(4u, (state_.SetHasCredential(origin2_)));
-}
-
-TEST_F(SpdyCredentialStateTest, ResizeAddsEmptySpaceAtEnd) {
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
- EXPECT_EQ(3u, (state_.SetHasCredential(origin3_)));
- EXPECT_EQ(4u, (state_.SetHasCredential(origin4_)));
- state_.Resize(6);
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
- EXPECT_EQ(3u, (state_.SetHasCredential(origin3_)));
- EXPECT_EQ(4u, (state_.SetHasCredential(origin4_)));
- EXPECT_EQ(5u, (state_.SetHasCredential(origin5_)));
- EXPECT_EQ(6u, (state_.SetHasCredential(origin6_)));
-}
-
-TEST_F(SpdyCredentialStateTest, ResizeTrunatesFromEnd) {
- EXPECT_EQ(1u, (state_.SetHasCredential(origin1_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin2_)));
- EXPECT_EQ(3u, (state_.SetHasCredential(origin3_)));
- EXPECT_EQ(4u, (state_.SetHasCredential(origin4_)));
- state_.Resize(2);
- EXPECT_TRUE(state_.HasCredential(origin1_));
- EXPECT_TRUE(state_.HasCredential(origin2_));
- EXPECT_FALSE(state_.HasCredential(origin3_));
- EXPECT_FALSE(state_.HasCredential(origin4_));
- EXPECT_EQ(1u, (state_.SetHasCredential(origin5_)));
- EXPECT_EQ(2u, (state_.SetHasCredential(origin6_)));
-}
-
-
-} // namespace net
diff --git a/chromium/net/spdy/spdy_frame_builder.h b/chromium/net/spdy/spdy_frame_builder.h
index 825254de416..348f105cd70 100644
--- a/chromium/net/spdy/spdy_frame_builder.h
+++ b/chromium/net/spdy/spdy_frame_builder.h
@@ -111,9 +111,6 @@ class NET_EXPORT_PRIVATE SpdyFrameBuilder {
// with the correct version for the frame being written.
bool OverwriteLength(const SpdyFramer& framer, size_t length);
- protected:
- const char* end_of_payload() const { return buffer_.get() + length_; }
-
private:
// Checks to make sure that there is an appropriate amount of space for a
// write of given size, in bytes.
diff --git a/chromium/net/spdy/spdy_framer.cc b/chromium/net/spdy/spdy_framer.cc
index 89a8309ea44..37e6a282dbf 100644
--- a/chromium/net/spdy/spdy_framer.cc
+++ b/chromium/net/spdy/spdy_framer.cc
@@ -61,9 +61,9 @@ const size_t SpdyFramer::kControlFrameBufferSize = 18;
#ifdef DEBUG_SPDY_STATE_CHANGES
#define CHANGE_STATE(newstate) \
do { \
- LOG(INFO) << "Changing state from: " \
- << StateToString(state_) \
- << " to " << StateToString(newstate) << "\n"; \
+ DVLOG(1) << "Changing state from: " \
+ << StateToString(state_) \
+ << " to " << StateToString(newstate) << "\n"; \
DCHECK(state_ != SPDY_ERROR); \
DCHECK_EQ(previous_state_, state_); \
previous_state_ = state_; \
@@ -652,8 +652,8 @@ size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
} else if (version != spdy_version_) {
// We check version before we check validity: version can never be
// 'invalid', it can only be unsupported.
- DLOG(INFO) << "Unsupported SPDY version " << version
- << " (expected " << spdy_version_ << ")";
+ DVLOG(1) << "Unsupported SPDY version " << version
+ << " (expected " << spdy_version_ << ")";
set_error(SPDY_UNSUPPORTED_VERSION);
} else {
ProcessControlFrameHeader(control_frame_type_field);
@@ -675,7 +675,7 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field);
if (current_frame_type_ == NOOP) {
- DLOG(INFO) << "NOOP control frame found. Ignoring.";
+ DVLOG(1) << "NOOP control frame found. Ignoring.";
CHANGE_STATE(SPDY_AUTO_RESET);
return;
}
@@ -1517,13 +1517,13 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
if (spdy_version_ < 3) {
uint16 temp;
if (!reader.ReadUInt16(&temp)) {
- DLOG(INFO) << "Unable to read number of headers.";
+ DVLOG(1) << "Unable to read number of headers.";
return 0;
}
num_headers = temp;
} else {
if (!reader.ReadUInt32(&num_headers)) {
- DLOG(INFO) << "Unable to read number of headers.";
+ DVLOG(1) << "Unable to read number of headers.";
return 0;
}
}
@@ -1535,8 +1535,8 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
// Read header name.
if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
: !reader.ReadStringPiece32(&temp)) {
- DLOG(INFO) << "Unable to read header name (" << index + 1 << " of "
- << num_headers << ").";
+ DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
+ << num_headers << ").";
return 0;
}
std::string name = temp.as_string();
@@ -1544,16 +1544,16 @@ size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
// Read header value.
if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
: !reader.ReadStringPiece32(&temp)) {
- DLOG(INFO) << "Unable to read header value (" << index + 1 << " of "
- << num_headers << ").";
+ DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
+ << num_headers << ").";
return 0;
}
std::string value = temp.as_string();
// Ensure no duplicates.
if (block->find(name) != block->end()) {
- DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of "
- << num_headers << ").";
+ DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
+ << num_headers << ").";
return 0;
}
@@ -1639,10 +1639,8 @@ SpdyFrame* SpdyFramer::CreateSynStream(
SpdyPriority priority,
uint8 credential_slot,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers) {
DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL);
- DCHECK_EQ(enable_compression_, compressed);
SpdySynStreamIR syn_stream(stream_id);
syn_stream.set_associated_to_stream_id(associated_stream_id);
@@ -1706,10 +1704,8 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
SpdyFrame* SpdyFramer::CreateSynReply(
SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers) {
DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN);
- DCHECK_EQ(enable_compression_, compressed);
SpdySynReplyIR syn_reply(stream_id);
syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
@@ -1884,11 +1880,9 @@ SpdySerializedFrame* SpdyFramer::SerializeGoAway(
SpdyFrame* SpdyFramer::CreateHeaders(
SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* header_block) {
// Basically the same as CreateSynReply().
DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN));
- DCHECK_EQ(enable_compression_, compressed);
SpdyHeadersIR headers(stream_id);
headers.set_fin(flags & CONTROL_FLAG_FIN);
diff --git a/chromium/net/spdy/spdy_framer.h b/chromium/net/spdy/spdy_framer.h
index fa004696a4c..0447af07515 100644
--- a/chromium/net/spdy/spdy_framer.h
+++ b/chromium/net/spdy/spdy_framer.h
@@ -19,6 +19,8 @@
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_protocol.h"
+// TODO(akalin): Remove support for CREDENTIAL frames.
+
typedef struct z_stream_s z_stream; // Forward declaration for zlib.
namespace net {
@@ -378,7 +380,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
SpdyPriority priority,
uint8 credential_slot,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers);
SpdySerializedFrame* SerializeSynStream(const SpdySynStreamIR& syn_stream);
@@ -390,7 +391,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// |headers| is the header block to include in the frame.
SpdyFrame* CreateSynReply(SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers);
SpdySerializedFrame* SerializeSynReply(const SpdySynReplyIR& syn_reply);
@@ -422,7 +422,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// arguments are the same as for CreateSynReply.
SpdyFrame* CreateHeaders(SpdyStreamId stream_id,
SpdyControlFlags flags,
- bool compressed,
const SpdyHeaderBlock* headers);
SpdySerializedFrame* SerializeHeaders(const SpdyHeadersIR& headers);
@@ -624,8 +623,6 @@ class NET_EXPORT_PRIVATE SpdyFramer {
// Set the error code and moves the framer into the error state.
void set_error(SpdyError error);
- size_t GoAwaySize() const;
-
// The maximum size of the control frames that we support.
// This limit is arbitrary. We can enforce it here or at the application
// layer. We chose the framing layer, but this can be changed (or removed)
diff --git a/chromium/net/spdy/spdy_framer_test.cc b/chromium/net/spdy/spdy_framer_test.cc
index d731b3adae9..f9c25036097 100644
--- a/chromium/net/spdy/spdy_framer_test.cc
+++ b/chromium/net/spdy/spdy_framer_test.cc
@@ -173,7 +173,6 @@ class SpdyFramerTestUtil {
priority,
slot,
static_cast<SpdyControlFlags>(flags),
- false,
&null_headers));
ResetBuffer();
memcpy(buffer_.get(), frame->data(), framer.GetSynStreamMinimumSize());
@@ -191,7 +190,6 @@ class SpdyFramerTestUtil {
scoped_ptr<SpdyFrame> frame(
framer.CreateHeaders(stream_id,
static_cast<SpdyControlFlags>(flags),
- false,
&null_headers));
ResetBuffer();
memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
@@ -226,7 +224,6 @@ class SpdyFramerTestUtil {
scoped_ptr<SpdyFrame> frame(
framer.CreateHeaders(stream_id,
static_cast<SpdyControlFlags>(flags),
- false,
&null_headers));
ResetBuffer();
memcpy(buffer_.get(), frame->data(), framer.GetHeadersMinimumSize());
@@ -674,7 +671,6 @@ TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
EXPECT_TRUE(frame.get() != NULL);
base::StringPiece serialized_headers =
@@ -704,7 +700,6 @@ TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
EXPECT_TRUE(frame.get() != NULL);
@@ -772,7 +767,6 @@ TEST_P(SpdyFramerTest, SynStreamWithStreamIdZero) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
ASSERT_TRUE(frame.get() != NULL);
@@ -796,7 +790,6 @@ TEST_P(SpdyFramerTest, SynReplyWithStreamIdZero) {
scoped_ptr<SpdySerializedFrame> frame(
framer.CreateSynReply(0, // stream id
CONTROL_FLAG_NONE,
- true, // compress
&headers));
ASSERT_TRUE(frame.get() != NULL);
@@ -820,7 +813,6 @@ TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
scoped_ptr<SpdySerializedFrame> frame(
framer.CreateHeaders(0, // stream id
CONTROL_FLAG_NONE,
- true, // compress
&headers));
ASSERT_TRUE(frame.get() != NULL);
@@ -1103,7 +1095,6 @@ TEST_P(SpdyFramerTest, BasicCompression) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
size_t uncompressed_size1 = visitor->last_payload_len_;
size_t compressed_size1 =
@@ -1129,7 +1120,6 @@ TEST_P(SpdyFramerTest, BasicCompression) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
size_t uncompressed_size2 = visitor->last_payload_len_;
size_t compressed_size2 =
@@ -1183,7 +1173,6 @@ TEST_P(SpdyFramerTest, BasicCompression) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
CompareFrames("Uncompressed SYN_STREAM", *frame3, *uncompressed_frame);
}
@@ -1207,7 +1196,6 @@ TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1, // priority
0, // credential slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
}
@@ -1610,7 +1598,6 @@ TEST_P(SpdyFramerTest, HeaderCompression) {
0, // priority
0, // credential slot
flags,
- true, // compress
&block));
EXPECT_TRUE(syn_frame_2.get() != NULL);
@@ -1668,7 +1655,6 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressors) {
0, // priority
0, // credential slot
flags,
- true, // compress
&block));
EXPECT_TRUE(syn_frame.get() != NULL);
@@ -1721,7 +1707,6 @@ TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
0, // priority
0, // credential slot
flags,
- true, // compress
&block));
EXPECT_TRUE(syn_frame.get() != NULL);
@@ -1999,7 +1984,6 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
framer.GetLowestPriority(),
kCre, // credential slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
@@ -2064,7 +2048,6 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
framer.GetHighestPriority(),
0, // credential slot
CONTROL_FLAG_FIN,
- false, // compress
&headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
@@ -2130,7 +2113,6 @@ TEST_P(SpdyFramerTest, CreateSynStreamUncompressed) {
1, // priority
0, // credential slot
CONTROL_FLAG_FIN,
- false, // compress
&headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
@@ -2217,7 +2199,6 @@ TEST_P(SpdyFramerTest, CreateSynStreamCompressed) {
priority,
0, // credential slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
@@ -2278,7 +2259,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
0x03, 'b', 'a', 'r'
};
scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 1, CONTROL_FLAG_NONE, false, &headers));
+ 1, CONTROL_FLAG_NONE, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2333,7 +2314,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
'r'
};
scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
+ 0x7fffffff, CONTROL_FLAG_FIN, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2388,7 +2369,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyUncompressed) {
0x00
};
scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
+ 0x7fffffff, CONTROL_FLAG_FIN, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2464,7 +2445,7 @@ TEST_P(SpdyFramerTest, CreateSynReplyCompressed) {
0xff,
};
scoped_ptr<SpdyFrame> frame(framer.CreateSynReply(
- 1, CONTROL_FLAG_NONE, true, &headers));
+ 1, CONTROL_FLAG_NONE, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2800,7 +2781,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
0x03, 'b', 'a', 'r'
};
scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 1, CONTROL_FLAG_NONE, false, &headers));
+ 1, CONTROL_FLAG_NONE, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2855,7 +2836,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
'r'
};
scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
+ 0x7fffffff, CONTROL_FLAG_FIN, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2910,7 +2891,7 @@ TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
0x00
};
scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 0x7fffffff, CONTROL_FLAG_FIN, false, &headers));
+ 0x7fffffff, CONTROL_FLAG_FIN, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -2986,7 +2967,7 @@ TEST_P(SpdyFramerTest, CreateHeadersCompressed) {
0xff
};
scoped_ptr<SpdyFrame> frame(framer.CreateHeaders(
- 1, CONTROL_FLAG_NONE, true, &headers));
+ 1, CONTROL_FLAG_NONE, &headers));
if (IsSpdy2()) {
CompareFrame(kDescription, *frame, kV2FrameData, arraysize(kV2FrameData));
} else if (IsSpdy3()) {
@@ -3163,7 +3144,6 @@ TEST_P(SpdyFramerTest, ReadCompressedSynStreamHeaderBlock) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestSpdyVisitor visitor(spdy_version_);
@@ -3183,7 +3163,6 @@ TEST_P(SpdyFramerTest, ReadCompressedSynReplyHeaderBlock) {
scoped_ptr<SpdyFrame> control_frame(
framer.CreateSynReply(1, // stream_id
CONTROL_FLAG_NONE,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestSpdyVisitor visitor(spdy_version_);
@@ -3203,7 +3182,6 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
scoped_ptr<SpdyFrame> control_frame(
framer.CreateHeaders(1, // stream_id
CONTROL_FLAG_NONE,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestSpdyVisitor visitor(spdy_version_);
@@ -3230,7 +3208,6 @@ TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
scoped_ptr<SpdyFrame> control_frame(
framer.CreateHeaders(1, // stream_id
CONTROL_FLAG_FIN,
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestSpdyVisitor visitor(spdy_version_);
@@ -3262,7 +3239,6 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
const size_t kBigValueSize =
framer.GetControlFrameBufferMaxSize() - control_frame->size();
@@ -3276,7 +3252,6 @@ TEST_P(SpdyFramerTest, ControlFrameAtMaxSizeLimit) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
EXPECT_EQ(framer.GetControlFrameBufferMaxSize(), control_frame->size());
@@ -3306,7 +3281,6 @@ TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
const size_t kBigValueSize =
framer.GetControlFrameBufferMaxSize() - control_frame->size() + 1;
@@ -3320,7 +3294,6 @@ TEST_P(SpdyFramerTest, ControlFrameTooLarge) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
EXPECT_EQ(framer.GetControlFrameBufferMaxSize() + 1,
@@ -3357,7 +3330,6 @@ TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
1, // priority
0, // credential_slot
CONTROL_FLAG_FIN, // half close
- true, // compress
&headers));
EXPECT_TRUE(control_frame.get() != NULL);
TestSpdyVisitor visitor(spdy_version_);
@@ -3401,7 +3373,6 @@ TEST_P(SpdyFramerTest, DecompressCorruptHeaderBlock) {
1, // priority
0, // credential_slot
CONTROL_FLAG_NONE,
- false, // compress
&headers));
TestSpdyVisitor visitor(spdy_version_);
visitor.use_compression_ = true;
@@ -4073,7 +4044,7 @@ TEST_P(SpdyFramerTest, SynStreamFrameFlags) {
SpdyHeaderBlock headers;
headers["foo"] = "bar";
scoped_ptr<SpdyFrame> frame(
- framer.CreateSynStream(8, 3, 1, 0, CONTROL_FLAG_NONE, true, &headers));
+ framer.CreateSynStream(8, 3, 1, 0, CONTROL_FLAG_NONE, &headers));
SetFrameFlags(frame.get(), flags, spdy_version_);
if (flags & ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
@@ -4114,7 +4085,7 @@ TEST_P(SpdyFramerTest, SynReplyFrameFlags) {
SpdyHeaderBlock headers;
headers["foo"] = "bar";
scoped_ptr<SpdyFrame> frame(
- framer.CreateSynReply(37, CONTROL_FLAG_NONE, true, &headers));
+ framer.CreateSynReply(37, CONTROL_FLAG_NONE, &headers));
SetFrameFlags(frame.get(), flags, spdy_version_);
if (flags & ~CONTROL_FLAG_FIN) {
@@ -4252,7 +4223,7 @@ TEST_P(SpdyFramerTest, HeadersFrameFlags) {
SpdyHeaderBlock headers;
headers["foo"] = "bar";
scoped_ptr<SpdyFrame> frame(
- framer.CreateHeaders(57, CONTROL_FLAG_NONE, true, &headers));
+ framer.CreateHeaders(57, CONTROL_FLAG_NONE, &headers));
SetFrameFlags(frame.get(), flags, spdy_version_);
if (flags & ~CONTROL_FLAG_FIN) {
@@ -4431,8 +4402,7 @@ TEST_P(SpdyFramerTest, EmptySynStream) {
EXPECT_CALL(debug_visitor, OnSendCompressedFrame(1, SYN_STREAM, _, _));
scoped_ptr<SpdyFrame>
- frame(framer.CreateSynStream(1, 0, 1, 0, CONTROL_FLAG_NONE, true,
- &headers));
+ frame(framer.CreateSynStream(1, 0, 1, 0, CONTROL_FLAG_NONE, &headers));
// Adjust size to remove the name/value block.
if (IsSpdy4()) {
SetFrameLength(
diff --git a/chromium/net/spdy/spdy_http_stream.cc b/chromium/net/spdy/spdy_http_stream.cc
index 4d9117514ab..878ccb00aa7 100644
--- a/chromium/net/spdy/spdy_http_stream.cc
+++ b/chromium/net/spdy/spdy_http_stream.cc
@@ -33,6 +33,7 @@ SpdyHttpStream::SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session,
stream_closed_(false),
closed_stream_status_(ERR_FAILED),
closed_stream_id_(0),
+ closed_stream_received_bytes_(0),
request_info_(NULL),
response_info_(NULL),
response_headers_status_(RESPONSE_HEADERS_ARE_INCOMPLETE),
@@ -177,6 +178,16 @@ bool SpdyHttpStream::IsConnectionReusable() const {
return false;
}
+int64 SpdyHttpStream::GetTotalReceivedBytes() const {
+ if (stream_closed_)
+ return closed_stream_received_bytes_;
+
+ if (!stream_)
+ return 0;
+
+ return stream_->raw_received_bytes();
+}
+
bool SpdyHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
if (stream_closed_) {
if (!closed_stream_has_load_timing_info_)
@@ -365,6 +376,7 @@ void SpdyHttpStream::OnClose(int status) {
closed_stream_id_ = stream_->stream_id();
closed_stream_has_load_timing_info_ =
stream_->GetLoadTimingInfo(&closed_stream_load_timing_info_);
+ closed_stream_received_bytes_ = stream_->raw_received_bytes();
}
stream_.reset();
bool invoked_callback = false;
diff --git a/chromium/net/spdy/spdy_http_stream.h b/chromium/net/spdy/spdy_http_stream.h
index f6e39cd102e..5a9377c4f1d 100644
--- a/chromium/net/spdy/spdy_http_stream.h
+++ b/chromium/net/spdy/spdy_http_stream.h
@@ -66,6 +66,7 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
virtual void SetConnectionReused() OVERRIDE;
virtual bool IsConnectionReusable() const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
virtual bool GetLoadTimingInfo(
LoadTimingInfo* load_timing_info) const OVERRIDE;
virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
@@ -122,6 +123,7 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
SpdyStreamId closed_stream_id_;
bool closed_stream_has_load_timing_info_;
LoadTimingInfo closed_stream_load_timing_info_;
+ int64 closed_stream_received_bytes_;
// The request to send.
const HttpRequestInfo* request_info_;
diff --git a/chromium/net/spdy/spdy_http_stream_unittest.cc b/chromium/net/spdy/spdy_http_stream_unittest.cc
index 7388dc01ddf..5a5870365b5 100644
--- a/chromium/net/spdy/spdy_http_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_http_stream_unittest.cc
@@ -23,7 +23,6 @@
#include "net/http/http_response_info.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
-#include "net/spdy/spdy_credential_builder.h"
#include "net/spdy/spdy_http_utils.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_test_util_common.h"
@@ -130,7 +129,8 @@ class SpdyHttpStreamTest : public testing::Test,
INSTANTIATE_TEST_CASE_P(
NextProto,
SpdyHttpStreamTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
// SpdyHttpStream::GetUploadProgress() should still work even before the
@@ -532,159 +532,6 @@ TEST_P(SpdyHttpStreamTest, SpdyURLTest) {
EXPECT_TRUE(data()->at_write_eof());
}
-namespace {
-
-void GetECServerBoundCertAndProof(
- const std::string& host,
- ServerBoundCertService* server_bound_cert_service,
- std::string* cert,
- std::string* proof) {
- TestCompletionCallback callback;
- std::string key;
- ServerBoundCertService::RequestHandle request_handle;
- int rv = server_bound_cert_service->GetOrCreateDomainBoundCert(
- host, &key, cert, callback.callback(),
- &request_handle);
- EXPECT_EQ(ERR_IO_PENDING, rv);
- EXPECT_EQ(OK, callback.WaitForResult());
-
- SpdyCredential credential;
- EXPECT_EQ(OK,
- SpdyCredentialBuilder::Build(
- MockClientSocket::kTlsUnique, key, *cert, 2, &credential));
-
- ASSERT_FALSE(credential.certs.empty());
- cert->assign(credential.certs[0]);
- proof->assign(credential.proof);
-}
-
-// Constructs a standard SPDY SYN_STREAM frame for a GET request with
-// a credential set.
-SpdyFrame* ConstructCredentialRequestFrame(NextProto next_proto,
- size_t slot, const GURL& url,
- SpdyStreamId stream_id) {
- SpdyTestUtil util(next_proto);
-
- const SpdyHeaderInfo syn_headers = {
- SYN_STREAM,
- stream_id,
- 0,
- ConvertRequestPriorityToSpdyPriority(LOWEST, 3),
- slot,
- CONTROL_FLAG_FIN,
- false,
- RST_STREAM_INVALID,
- NULL,
- 0,
- DATA_FLAG_NONE
- };
-
- scoped_ptr<SpdyHeaderBlock> headers(util.ConstructGetHeaderBlock(url.spec()));
- return util.ConstructSpdyFrame(syn_headers, headers.Pass());
-}
-
-} // namespace
-
-// TODO(rch): When openssl supports server bound certifictes, this
-// guard can be removed
-#if !defined(USE_OPENSSL)
-// Test that if we request a resource for a new origin on a session that
-// used domain bound certificates, that we send a CREDENTIAL frame for
-// the new domain before we send the new request.
-void SpdyHttpStreamTest::TestSendCredentials(
- ServerBoundCertService* server_bound_cert_service,
- const std::string& cert,
- const std::string& proof) {
- const char* kUrl1 = "https://www.google.com/";
- const char* kUrl2 = "https://www.gmail.com/";
-
- SpdyCredential cred;
- cred.slot = 2;
- cred.proof = proof;
- cred.certs.push_back(cert);
-
- scoped_ptr<SpdyFrame> req(ConstructCredentialRequestFrame(
- GetParam(), 1, GURL(kUrl1), 1));
- scoped_ptr<SpdyFrame> credential(
- spdy_util_.ConstructSpdyCredential(cred));
- scoped_ptr<SpdyFrame> req2(ConstructCredentialRequestFrame(
- GetParam(), 2, GURL(kUrl2), 3));
- MockWrite writes[] = {
- CreateMockWrite(*req.get(), 0),
- CreateMockWrite(*credential.get(), 2),
- CreateMockWrite(*req2.get(), 3),
- };
-
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- MockRead reads[] = {
- CreateMockRead(*resp, 1),
- CreateMockRead(*resp2, 4),
- MockRead(SYNCHRONOUS, 0, 5) // EOF
- };
-
- HostPortPair host_port_pair(HostPortPair::FromURL(GURL(kUrl1)));
- SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
-
- DeterministicMockClientSocketFactory* socket_factory =
- session_deps_.deterministic_socket_factory.get();
- DeterministicSocketData data(reads, arraysize(reads),
- writes, arraysize(writes));
- socket_factory->AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.channel_id_sent = true;
- ssl.server_bound_cert_service = server_bound_cert_service;
- ssl.protocol_negotiated = GetParam();
- socket_factory->AddSSLSocketDataProvider(&ssl);
- http_session_ = SpdySessionDependencies::SpdyCreateSessionDeterministic(
- &session_deps_);
- session_ = CreateSecureSpdySession(http_session_, key, BoundNetLog());
-
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL(kUrl1);
- HttpResponseInfo response;
- HttpRequestHeaders headers;
- BoundNetLog net_log;
- scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true));
- ASSERT_EQ(
- OK,
- http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
-
- // EXPECT_FALSE(session_->NeedsCredentials(request.url));
- // GURL new_origin(kUrl2);
- // EXPECT_TRUE(session_->NeedsCredentials(new_origin));
-
- TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
- EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key));
-
- data.RunFor(2);
- callback.WaitForResult();
-
- // Start up second request for resource on a new origin.
- scoped_ptr<SpdyHttpStream> http_stream2(new SpdyHttpStream(session_, true));
- request.url = GURL(kUrl2);
- ASSERT_EQ(
- OK,
- http_stream2->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers, &response,
- callback.callback()));
- data.RunFor(2);
- callback.WaitForResult();
-
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->ReadResponseHeaders(
- callback.callback()));
- data.RunFor(1);
- EXPECT_EQ(OK, callback.WaitForResult());
- ASSERT_TRUE(response.headers.get() != NULL);
- ASSERT_EQ(200, response.headers->response_code());
-}
-
// The tests below are only for SPDY/3 and above.
// Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be
@@ -779,112 +626,6 @@ TEST_P(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) {
EXPECT_TRUE(deterministic_data_->at_write_eof());
}
-TEST_P(SpdyHttpStreamTest, SendCredentialsEC) {
- if (GetParam() < kProtoSPDY3)
- return;
-
- scoped_ptr<ServerBoundCertService> server_bound_cert_service(
- new ServerBoundCertService(new DefaultServerBoundCertStore(NULL),
- base::MessageLoopProxy::current()));
- std::string cert;
- std::string proof;
- GetECServerBoundCertAndProof("www.gmail.com",
- server_bound_cert_service.get(),
- &cert, &proof);
-
- TestSendCredentials(server_bound_cert_service.get(), cert, proof);
-}
-
-TEST_P(SpdyHttpStreamTest, DontSendCredentialsForHttpUrlsEC) {
- if (GetParam() < kProtoSPDY3)
- return;
-
- scoped_ptr<ServerBoundCertService> server_bound_cert_service(
- new ServerBoundCertService(new DefaultServerBoundCertStore(NULL),
- base::MessageLoopProxy::current()));
- std::string cert;
- std::string proof;
- GetECServerBoundCertAndProof("proxy.google.com",
- server_bound_cert_service.get(),
- &cert, &proof);
-
- const char* kUrl1 = "http://www.google.com/";
- const char* kUrl2 = "http://www.gmail.com/";
-
- SpdyCredential cred;
- cred.slot = 2;
- cred.proof = proof;
- cred.certs.push_back(cert);
-
- scoped_ptr<SpdyFrame> req(ConstructCredentialRequestFrame(
- GetParam(), 0, GURL(kUrl1), 1));
- scoped_ptr<SpdyFrame> req2(ConstructCredentialRequestFrame(
- GetParam(), 0, GURL(kUrl2), 3));
- MockWrite writes[] = {
- CreateMockWrite(*req.get(), 0),
- CreateMockWrite(*req2.get(), 2),
- };
-
- scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
- scoped_ptr<SpdyFrame> resp2(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 3));
- MockRead reads[] = {
- CreateMockRead(*resp, 1),
- CreateMockRead(*resp2, 3),
- MockRead(ASYNC, 0, 4) // EOF
- };
-
- HostPortPair host_port_pair(HostPortPair::FromURL(GURL(kUrl1)));
- SpdySessionKey key(host_port_pair,
- ProxyServer::FromURI("proxy.google.com",
- ProxyServer::SCHEME_HTTPS),
- kPrivacyModeDisabled);
- InitSessionDeterministic(reads, arraysize(reads),
- writes, arraysize(writes),
- key);
-
- HttpRequestInfo request;
- request.method = "GET";
- request.url = GURL(kUrl1);
- HttpResponseInfo response;
- HttpRequestHeaders headers;
- BoundNetLog net_log;
- scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true));
- ASSERT_EQ(
- OK,
- http_stream->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
-
- TestCompletionCallback callback;
- EXPECT_EQ(ERR_IO_PENDING, http_stream->SendRequest(headers, &response,
- callback.callback()));
- EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key));
-
- deterministic_data_->RunFor(2);
- EXPECT_EQ(OK, callback.WaitForResult());
-
- // Start up second request for resource on a new origin.
- scoped_ptr<SpdyHttpStream> http_stream2(new SpdyHttpStream(session_, true));
- request.url = GURL(kUrl2);
- ASSERT_EQ(
- OK,
- http_stream2->InitializeStream(&request, DEFAULT_PRIORITY,
- net_log, CompletionCallback()));
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->SendRequest(headers, &response,
- callback.callback()));
- deterministic_data_->RunFor(1);
- EXPECT_EQ(OK, callback.WaitForResult());
-
- EXPECT_EQ(ERR_IO_PENDING, http_stream2->ReadResponseHeaders(
- callback.callback()));
- deterministic_data_->RunFor(1);
- EXPECT_EQ(OK, callback.WaitForResult());
- ASSERT_TRUE(response.headers.get() != NULL);
- ASSERT_EQ(200, response.headers->response_code());
- deterministic_data_->RunFor(1);
-}
-
-#endif // !defined(USE_OPENSSL)
-
// TODO(willchan): Write a longer test for SpdyStream that exercises all
// methods.
diff --git a/chromium/net/spdy/spdy_http_utils.cc b/chromium/net/spdy/spdy_http_utils.cc
index 21012f23fc1..da95b51fad0 100644
--- a/chromium/net/spdy/spdy_http_utils.cc
+++ b/chromium/net/spdy/spdy_http_utils.cc
@@ -21,10 +21,11 @@
namespace net {
bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers,
- int protocol_version,
+ SpdyMajorVersion protocol_version,
HttpResponseInfo* response) {
- std::string status_key = (protocol_version >= 3) ? ":status" : "status";
- std::string version_key = (protocol_version >= 3) ? ":version" : "version";
+ std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status";
+ std::string version_key =
+ (protocol_version >= SPDY3) ? ":version" : "version";
std::string version;
std::string status;
@@ -82,7 +83,7 @@ bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers,
void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info,
const HttpRequestHeaders& request_headers,
SpdyHeaderBlock* headers,
- int protocol_version,
+ SpdyMajorVersion protocol_version,
bool direct) {
HttpRequestHeaders::Iterator it(request_headers);
@@ -103,7 +104,7 @@ void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info,
}
static const char kHttpProtocolVersion[] = "HTTP/1.1";
- if (protocol_version < 3) {
+ if (protocol_version < SPDY3) {
(*headers)["version"] = kHttpProtocolVersion;
(*headers)["method"] = info.method;
(*headers)["host"] = GetHostAndOptionalPort(info.url);
@@ -129,10 +130,10 @@ COMPILE_ASSERT(HIGHEST - LOWEST < 4 &&
SpdyPriority ConvertRequestPriorityToSpdyPriority(
const RequestPriority priority,
- int protocol_version) {
+ SpdyMajorVersion protocol_version) {
DCHECK_GE(priority, MINIMUM_PRIORITY);
- DCHECK_LT(priority, NUM_PRIORITIES);
- if (protocol_version == 2) {
+ DCHECK_LE(priority, MAXIMUM_PRIORITY);
+ if (protocol_version == SPDY2) {
// SPDY 2 only has 2 bits of priority, but we have 5 RequestPriorities.
// Map IDLE => 3, LOWEST => 2, LOW => 2, MEDIUM => 1, HIGHEST => 0.
if (priority > LOWEST) {
@@ -147,19 +148,19 @@ SpdyPriority ConvertRequestPriorityToSpdyPriority(
NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
SpdyPriority priority,
- int protocol_version) {
+ SpdyMajorVersion protocol_version) {
// Handle invalid values gracefully, and pick LOW to map 2 back
// to for SPDY/2.
- SpdyPriority idle_cutoff = (protocol_version == 2) ? 3 : 5;
+ SpdyPriority idle_cutoff = (protocol_version == SPDY2) ? 3 : 5;
return (priority >= idle_cutoff) ?
IDLE : static_cast<RequestPriority>(HIGHEST - priority);
}
GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
- int protocol_version,
+ SpdyMajorVersion protocol_version,
bool pushed) {
// SPDY 2 server push urls are specified in a single "url" header.
- if (pushed && protocol_version == 2) {
+ if (pushed && protocol_version == SPDY2) {
std::string url;
SpdyHeaderBlock::const_iterator it;
it = headers.find("url");
@@ -168,9 +169,9 @@ GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
return GURL(url);
}
- const char* scheme_header = protocol_version >= 3 ? ":scheme" : "scheme";
- const char* host_header = protocol_version >= 3 ? ":host" : "host";
- const char* path_header = protocol_version >= 3 ? ":path" : "url";
+ const char* scheme_header = protocol_version >= SPDY3 ? ":scheme" : "scheme";
+ const char* host_header = protocol_version >= SPDY3 ? ":host" : "host";
+ const char* path_header = protocol_version >= SPDY3 ? ":path" : "url";
std::string scheme;
std::string host_port;
diff --git a/chromium/net/spdy/spdy_http_utils.h b/chromium/net/spdy/spdy_http_utils.h
index 26511a77834..6a91c888c9a 100644
--- a/chromium/net/spdy/spdy_http_utils.h
+++ b/chromium/net/spdy/spdy_http_utils.h
@@ -24,7 +24,7 @@ class HttpRequestHeaders;
// Returns true if successfully converted. False if the SpdyHeaderBlock is
// incomplete (e.g. missing 'status' or 'version').
bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers,
- int protocol_version,
+ SpdyMajorVersion protocol_version,
HttpResponseInfo* response);
// Create a SpdyHeaderBlock for a Spdy SYN_STREAM Frame from
@@ -33,13 +33,13 @@ void NET_EXPORT_PRIVATE CreateSpdyHeadersFromHttpRequest(
const HttpRequestInfo& info,
const HttpRequestHeaders& request_headers,
SpdyHeaderBlock* headers,
- int protocol_version,
+ SpdyMajorVersion protocol_version,
bool direct);
// Returns the URL associated with the |headers| by assembling the
// scheme, host and path from the protocol specific keys.
GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
- int protocol_version,
+ SpdyMajorVersion protocol_version,
bool pushed);
// Returns true if the value of this header should be displayed.
@@ -48,11 +48,11 @@ NET_EXPORT_PRIVATE bool ShouldShowHttpHeaderValue(
NET_EXPORT_PRIVATE SpdyPriority ConvertRequestPriorityToSpdyPriority(
RequestPriority priority,
- int protocol_version);
+ SpdyMajorVersion protocol_version);
NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
SpdyPriority priority,
- int protocol_version);
+ SpdyMajorVersion protocol_version);
} // namespace net
diff --git a/chromium/net/spdy/spdy_http_utils_unittest.cc b/chromium/net/spdy/spdy_http_utils_unittest.cc
index b198808c9b1..daac323bcfe 100644
--- a/chromium/net/spdy/spdy_http_utils_unittest.cc
+++ b/chromium/net/spdy/spdy_http_utils_unittest.cc
@@ -12,43 +12,43 @@ namespace net {
namespace {
TEST(SpdyHttpUtilsTest, ConvertRequestPriorityToSpdy2Priority) {
- EXPECT_EQ(0, ConvertRequestPriorityToSpdyPriority(HIGHEST, 2));
- EXPECT_EQ(1, ConvertRequestPriorityToSpdyPriority(MEDIUM, 2));
- EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOW, 2));
- EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOWEST, 2));
- EXPECT_EQ(3, ConvertRequestPriorityToSpdyPriority(IDLE, 2));
+ EXPECT_EQ(0, ConvertRequestPriorityToSpdyPriority(HIGHEST, SPDY2));
+ EXPECT_EQ(1, ConvertRequestPriorityToSpdyPriority(MEDIUM, SPDY2));
+ EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOW, SPDY2));
+ EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOWEST, SPDY2));
+ EXPECT_EQ(3, ConvertRequestPriorityToSpdyPriority(IDLE, SPDY2));
}
TEST(SpdyHttpUtilsTest, ConvertRequestPriorityToSpdy3Priority) {
- EXPECT_EQ(0, ConvertRequestPriorityToSpdyPriority(HIGHEST, 3));
- EXPECT_EQ(1, ConvertRequestPriorityToSpdyPriority(MEDIUM, 3));
- EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOW, 3));
- EXPECT_EQ(3, ConvertRequestPriorityToSpdyPriority(LOWEST, 3));
- EXPECT_EQ(4, ConvertRequestPriorityToSpdyPriority(IDLE, 3));
+ EXPECT_EQ(0, ConvertRequestPriorityToSpdyPriority(HIGHEST, SPDY3));
+ EXPECT_EQ(1, ConvertRequestPriorityToSpdyPriority(MEDIUM, SPDY3));
+ EXPECT_EQ(2, ConvertRequestPriorityToSpdyPriority(LOW, SPDY3));
+ EXPECT_EQ(3, ConvertRequestPriorityToSpdyPriority(LOWEST, SPDY3));
+ EXPECT_EQ(4, ConvertRequestPriorityToSpdyPriority(IDLE, SPDY3));
}
TEST(SpdyHttpUtilsTest, ConvertSpdy2PriorityToRequestPriority) {
- EXPECT_EQ(HIGHEST, ConvertSpdyPriorityToRequestPriority(0, 2));
- EXPECT_EQ(MEDIUM, ConvertSpdyPriorityToRequestPriority(1, 2));
- EXPECT_EQ(LOW, ConvertSpdyPriorityToRequestPriority(2, 2));
- EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(3, 2));
+ EXPECT_EQ(HIGHEST, ConvertSpdyPriorityToRequestPriority(0, SPDY2));
+ EXPECT_EQ(MEDIUM, ConvertSpdyPriorityToRequestPriority(1, SPDY2));
+ EXPECT_EQ(LOW, ConvertSpdyPriorityToRequestPriority(2, SPDY2));
+ EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(3, SPDY2));
// These are invalid values, but we should still handle them
// gracefully.
for (int i = 4; i < kuint8max; ++i) {
- EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(i, 2));
+ EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(i, SPDY2));
}
}
TEST(SpdyHttpUtilsTest, ConvertSpdy3PriorityToRequestPriority) {
- EXPECT_EQ(HIGHEST, ConvertSpdyPriorityToRequestPriority(0, 3));
- EXPECT_EQ(MEDIUM, ConvertSpdyPriorityToRequestPriority(1, 3));
- EXPECT_EQ(LOW, ConvertSpdyPriorityToRequestPriority(2, 3));
- EXPECT_EQ(LOWEST, ConvertSpdyPriorityToRequestPriority(3, 3));
- EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(4, 3));
+ EXPECT_EQ(HIGHEST, ConvertSpdyPriorityToRequestPriority(0, SPDY3));
+ EXPECT_EQ(MEDIUM, ConvertSpdyPriorityToRequestPriority(1, SPDY3));
+ EXPECT_EQ(LOW, ConvertSpdyPriorityToRequestPriority(2, SPDY3));
+ EXPECT_EQ(LOWEST, ConvertSpdyPriorityToRequestPriority(3, SPDY3));
+ EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(4, SPDY3));
// These are invalid values, but we should still handle them
// gracefully.
for (int i = 5; i < kuint8max; ++i) {
- EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(i, 3));
+ EXPECT_EQ(IDLE, ConvertSpdyPriorityToRequestPriority(i, SPDY3));
}
}
diff --git a/chromium/net/spdy/spdy_network_transaction_unittest.cc b/chromium/net/spdy/spdy_network_transaction_unittest.cc
index f3f9f344995..bf9fbce45b6 100644
--- a/chromium/net/spdy/spdy_network_transaction_unittest.cc
+++ b/chromium/net/spdy/spdy_network_transaction_unittest.cc
@@ -12,6 +12,7 @@
#include "base/memory/scoped_vector.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/test/test_file_util.h"
#include "net/base/auth.h"
#include "net/base/net_log_unittest.h"
#include "net/base/request_priority.h"
@@ -49,7 +50,7 @@ enum SpdyNetworkTransactionTestSSLType {
struct SpdyNetworkTransactionTestParams {
SpdyNetworkTransactionTestParams()
- : protocol(kProtoSPDY2),
+ : protocol(kProtoSPDY3),
ssl_type(SPDYNPN) {}
SpdyNetworkTransactionTestParams(
@@ -423,7 +424,8 @@ class SpdyNetworkTransactionTest
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(
new UploadBytesElementReader(kUploadData, kUploadDataSize));
- upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
+ upload_data_stream_.reset(
+ new UploadDataStream(element_readers.Pass(), 0));
google_post_request_.method = "POST";
google_post_request_.url = GURL(kDefaultURL);
@@ -436,7 +438,7 @@ class SpdyNetworkTransactionTest
const HttpRequestInfo& CreateFilePostRequest() {
if (!google_post_request_initialized_) {
base::FilePath file_path;
- CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
+ CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
CHECK_EQ(static_cast<int>(kUploadDataSize),
file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
@@ -447,7 +449,8 @@ class SpdyNetworkTransactionTest
0,
kUploadDataSize,
base::Time()));
- upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
+ upload_data_stream_.reset(
+ new UploadDataStream(element_readers.Pass(), 0));
google_post_request_.method = "POST";
google_post_request_.url = GURL(kDefaultURL);
@@ -457,6 +460,33 @@ class SpdyNetworkTransactionTest
return google_post_request_;
}
+ const HttpRequestInfo& CreateUnreadableFilePostRequest() {
+ if (google_post_request_initialized_)
+ return google_post_request_;
+
+ base::FilePath file_path;
+ CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
+ CHECK_EQ(static_cast<int>(kUploadDataSize),
+ file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
+ CHECK(file_util::MakeFileUnreadable(file_path));
+
+ ScopedVector<UploadElementReader> element_readers;
+ element_readers.push_back(
+ new UploadFileElementReader(base::MessageLoopProxy::current().get(),
+ file_path,
+ 0,
+ kUploadDataSize,
+ base::Time()));
+ upload_data_stream_.reset(
+ new UploadDataStream(element_readers.Pass(), 0));
+
+ google_post_request_.method = "POST";
+ google_post_request_.url = GURL(kDefaultURL);
+ google_post_request_.upload_data_stream = upload_data_stream_.get();
+ google_post_request_initialized_ = true;
+ return google_post_request_;
+ }
+
const HttpRequestInfo& CreateComplexPostRequest() {
if (!google_post_request_initialized_) {
const int kFileRangeOffset = 1;
@@ -464,7 +494,7 @@ class SpdyNetworkTransactionTest
CHECK_LT(kFileRangeOffset + kFileRangeLength, kUploadDataSize);
base::FilePath file_path;
- CHECK(file_util::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
+ CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &file_path));
CHECK_EQ(static_cast<int>(kUploadDataSize),
file_util::WriteFile(file_path, kUploadData, kUploadDataSize));
@@ -480,7 +510,8 @@ class SpdyNetworkTransactionTest
element_readers.push_back(new UploadBytesElementReader(
kUploadData + kFileRangeOffset + kFileRangeLength,
kUploadDataSize - (kFileRangeOffset + kFileRangeLength)));
- upload_data_stream_.reset(new UploadDataStream(&element_readers, 0));
+ upload_data_stream_.reset(
+ new UploadDataStream(element_readers.Pass(), 0));
google_post_request_.method = "POST";
google_post_request_.url = GURL(kDefaultURL);
@@ -650,9 +681,9 @@ INSTANTIATE_TEST_CASE_P(
Spdy,
SpdyNetworkTransactionTest,
::testing::Values(
- SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYNOSSL),
- SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYSSL),
- SpdyNetworkTransactionTestParams(kProtoSPDY2, SPDYNPN),
+ SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNOSSL),
+ SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYSSL),
+ SpdyNetworkTransactionTestParams(kProtoDeprecatedSPDY2, SPDYNPN),
SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNOSSL),
SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYSSL),
SpdyNetworkTransactionTestParams(kProtoSPDY3, SPDYNPN),
@@ -702,7 +733,7 @@ TEST_P(SpdyNetworkTransactionTest, Get) {
}
TEST_P(SpdyNetworkTransactionTest, GetAtEachPriority) {
- for (RequestPriority p = MINIMUM_PRIORITY; p < NUM_PRIORITIES;
+ for (RequestPriority p = MINIMUM_PRIORITY; p <= MAXIMUM_PRIORITY;
p = RequestPriority(p + 1)) {
// Construct the request.
scoped_ptr<SpdyFrame> req(
@@ -1782,6 +1813,28 @@ TEST_P(SpdyNetworkTransactionTest, FilePost) {
EXPECT_EQ("hello!", out.response_data);
}
+// Test that a POST with a unreadable file fails.
+TEST_P(SpdyNetworkTransactionTest, UnreadableFilePost) {
+ MockWrite writes[] = {
+ MockWrite(ASYNC, 0, 0) // EOF
+ };
+ MockRead reads[] = {
+ MockRead(ASYNC, 0, 0) // EOF
+ };
+
+ DelayedSocketData data(1, reads, arraysize(reads), writes, arraysize(writes));
+ NormalSpdyTransactionHelper helper(CreateUnreadableFilePostRequest(),
+ DEFAULT_PRIORITY,
+ BoundNetLog(), GetParam(), NULL);
+ helper.RunPreTestSetup();
+ helper.AddData(&data);
+ helper.RunDefaultTest();
+
+ base::RunLoop().RunUntilIdle();
+ helper.VerifyDataNotConsumed();
+ EXPECT_EQ(ERR_ACCESS_DENIED, helper.output().rv);
+}
+
// Test that a complex POST works.
TEST_P(SpdyNetworkTransactionTest, ComplexPost) {
scoped_ptr<SpdyFrame> req(
@@ -1947,7 +2000,7 @@ TEST_P(SpdyNetworkTransactionTest, NullPost) {
TEST_P(SpdyNetworkTransactionTest, EmptyPost) {
// Create an empty UploadDataStream.
ScopedVector<UploadElementReader> element_readers;
- UploadDataStream stream(&element_readers, 0);
+ UploadDataStream stream(element_readers.Pass(), 0);
// Setup the request
HttpRequestInfo request;
@@ -1990,7 +2043,7 @@ TEST_P(SpdyNetworkTransactionTest, PostWithEarlySynReply) {
ScopedVector<UploadElementReader> element_readers;
element_readers.push_back(
new UploadBytesElementReader(upload, sizeof(upload)));
- UploadDataStream stream(&element_readers, 0);
+ UploadDataStream stream(element_readers.Pass(), 0);
// Setup the request
HttpRequestInfo request;
@@ -2463,8 +2516,10 @@ TEST_P(SpdyNetworkTransactionTest, RedirectGetRequest) {
TestDelegate d;
{
SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
- net::URLRequest r(
- GURL("http://www.google.com/"), &d, &spdy_url_request_context);
+ net::URLRequest r(GURL("http://www.google.com/"),
+ DEFAULT_PRIORITY,
+ &d,
+ &spdy_url_request_context);
spdy_url_request_context.socket_factory().
AddSocketDataProvider(&data);
spdy_url_request_context.socket_factory().
@@ -2556,8 +2611,10 @@ TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
TestDelegate d2;
SpdyURLRequestContext spdy_url_request_context(GetParam().protocol);
{
- net::URLRequest r(
- GURL("http://www.google.com/"), &d, &spdy_url_request_context);
+ net::URLRequest r(GURL("http://www.google.com/"),
+ DEFAULT_PRIORITY,
+ &d,
+ &spdy_url_request_context);
spdy_url_request_context.socket_factory().
AddSocketDataProvider(&data);
@@ -2568,8 +2625,10 @@ TEST_P(SpdyNetworkTransactionTest, RedirectServerPush) {
std::string contents("hello!");
EXPECT_EQ(contents, d.data_received());
- net::URLRequest r2(
- GURL("http://www.google.com/foo.dat"), &d2, &spdy_url_request_context);
+ net::URLRequest r2(GURL("http://www.google.com/foo.dat"),
+ DEFAULT_PRIORITY,
+ &d2,
+ &spdy_url_request_context);
spdy_url_request_context.socket_factory().
AddSocketDataProvider(&data2);
@@ -3547,19 +3606,30 @@ TEST_P(SpdyNetworkTransactionTest, WriteError) {
spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
MockWrite writes[] = {
// We'll write 10 bytes successfully
- MockWrite(ASYNC, req->data(), 10),
+ MockWrite(ASYNC, req->data(), 10, 0),
// Followed by ERROR!
- MockWrite(ASYNC, ERR_FAILED),
+ MockWrite(ASYNC, ERR_FAILED, 1),
};
- DelayedSocketData data(2, NULL, 0,
- writes, arraysize(writes));
+ MockRead reads[] = {
+ MockRead(ASYNC, 0, 2) // EOF
+ };
+
+ DeterministicSocketData data(reads, arraysize(reads),
+ writes, arraysize(writes));
+
NormalSpdyTransactionHelper helper(CreateGetRequest(), DEFAULT_PRIORITY,
BoundNetLog(), GetParam(), NULL);
- helper.RunToCompletion(&data);
+ helper.SetDeterministic();
+ helper.RunPreTestSetup();
+ helper.AddDeterministicData(&data);
+ EXPECT_TRUE(helper.StartDefaultTest());
+ data.RunFor(2);
+ helper.FinishDefaultTest();
+ EXPECT_TRUE(data.at_write_eof());
+ EXPECT_TRUE(!data.at_read_eof());
TransactionHelperResult out = helper.output();
EXPECT_EQ(ERR_FAILED, out.rv);
- data.Reset();
}
// Test that partial writes work.
@@ -5836,7 +5906,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateReceived) {
element_readers.push_back(
new UploadBytesElementReader(content->c_str(), content->size()));
}
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
// Setup the request
HttpRequestInfo request;
@@ -6009,7 +6079,7 @@ TEST_P(SpdyNetworkTransactionTest, WindowUpdateOverflow) {
element_readers.push_back(
new UploadBytesElementReader(content->c_str(), content->size()));
}
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
// Setup the request
HttpRequestInfo request;
@@ -6125,7 +6195,7 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResume) {
upload_data_string.append(kUploadData, kUploadDataSize);
element_readers.push_back(new UploadBytesElementReader(
upload_data_string.c_str(), upload_data_string.size()));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
@@ -6239,7 +6309,7 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlStallResumeAfterSettings) {
upload_data_string.append(kUploadData, kUploadDataSize);
element_readers.push_back(new UploadBytesElementReader(
upload_data_string.c_str(), upload_data_string.size()));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
@@ -6363,7 +6433,7 @@ TEST_P(SpdyNetworkTransactionTest, FlowControlNegativeSendWindowSize) {
upload_data_string.append(kUploadData, kUploadDataSize);
element_readers.push_back(new UploadBytesElementReader(
upload_data_string.c_str(), upload_data_string.size()));
- UploadDataStream upload_data_stream(&element_readers, 0);
+ UploadDataStream upload_data_stream(element_readers.Pass(), 0);
HttpRequestInfo request;
request.method = "POST";
diff --git a/chromium/net/spdy/spdy_protocol.h b/chromium/net/spdy/spdy_protocol.h
index 438d9d7f517..3c891a5e88a 100644
--- a/chromium/net/spdy/spdy_protocol.h
+++ b/chromium/net/spdy/spdy_protocol.h
@@ -45,10 +45,10 @@ typedef uint32 SpdyStreamId;
// flow control).
const SpdyStreamId kSessionFlowControlStreamId = 0;
-// Initial window size for a Spdy stream.
+// Initial window size for a Spdy stream in bytes.
const int32 kSpdyStreamInitialWindowSize = 64 * 1024; // 64 KBytes
-// Initial window size for a Spdy session.
+// Initial window size for a Spdy session in bytes.
const int32 kSpdySessionInitialWindowSize = 64 * 1024; // 64 KBytes
// Maximum window size for a Spdy stream or session.
diff --git a/chromium/net/spdy/spdy_protocol_test.cc b/chromium/net/spdy/spdy_protocol_test.cc
index 006dfe15ca5..98661f01de5 100644
--- a/chromium/net/spdy/spdy_protocol_test.cc
+++ b/chromium/net/spdy/spdy_protocol_test.cc
@@ -30,8 +30,6 @@ class SpdyProtocolTest
spdy_version_ = GetParam();
}
- bool IsSpdy2() { return spdy_version_ == SPDY2; }
-
// Version of SPDY protocol to be used.
int spdy_version_;
};
diff --git a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
index c128d9cdace..c2b1ac010f1 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -140,7 +140,8 @@ class SpdyProxyClientSocketTest
INSTANTIATE_TEST_CASE_P(
NextProto,
SpdyProxyClientSocketTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
diff --git a/chromium/net/spdy/spdy_session.cc b/chromium/net/spdy/spdy_session.cc
index 7f31cd5cbc6..9508f0e6af4 100644
--- a/chromium/net/spdy/spdy_session.cc
+++ b/chromium/net/spdy/spdy_session.cc
@@ -32,7 +32,6 @@
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/spdy/spdy_buffer_producer.h"
-#include "net/spdy/spdy_credential_builder.h"
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_http_utils.h"
#include "net/spdy/spdy_protocol.h"
@@ -54,36 +53,60 @@ const SpdyStreamId kFirstStreamId = 1;
// Minimum seconds that unclaimed pushed streams will be kept in memory.
const int kMinPushedStreamLifetimeSeconds = 300;
-base::Value* NetLogSpdySynCallback(const SpdyHeaderBlock* headers,
- bool fin,
- bool unidirectional,
- SpdyStreamId stream_id,
- SpdyStreamId associated_stream,
- NetLog::LogLevel /* log_level */) {
+scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue(
+ const SpdyHeaderBlock& headers) {
+ scoped_ptr<base::ListValue> headers_list(new base::ListValue());
+ for (SpdyHeaderBlock::const_iterator it = headers.begin();
+ it != headers.end(); ++it) {
+ headers_list->AppendString(
+ it->first + ": " +
+ (ShouldShowHttpHeaderValue(it->first) ? it->second : "[elided]"));
+ }
+ return headers_list.Pass();
+}
+
+base::Value* NetLogSpdySynStreamSentCallback(const SpdyHeaderBlock* headers,
+ bool fin,
+ bool unidirectional,
+ SpdyPriority spdy_priority,
+ SpdyStreamId stream_id,
+ NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
- base::ListValue* headers_list = new base::ListValue();
- for (SpdyHeaderBlock::const_iterator it = headers->begin();
- it != headers->end(); ++it) {
- headers_list->Append(new base::StringValue(base::StringPrintf(
- "%s: %s", it->first.c_str(),
- (ShouldShowHttpHeaderValue(
- it->first) ? it->second : "[elided]").c_str())));
- }
+ dict->Set("headers", SpdyHeaderBlockToListValue(*headers).release());
+ dict->SetBoolean("fin", fin);
+ dict->SetBoolean("unidirectional", unidirectional);
+ dict->SetInteger("spdy_priority", static_cast<int>(spdy_priority));
+ dict->SetInteger("stream_id", stream_id);
+ return dict;
+}
+
+base::Value* NetLogSpdySynStreamReceivedCallback(
+ const SpdyHeaderBlock* headers,
+ bool fin,
+ bool unidirectional,
+ SpdyPriority spdy_priority,
+ SpdyStreamId stream_id,
+ SpdyStreamId associated_stream,
+ NetLog::LogLevel /* log_level */) {
+ base::DictionaryValue* dict = new base::DictionaryValue();
+ dict->Set("headers", SpdyHeaderBlockToListValue(*headers).release());
dict->SetBoolean("fin", fin);
dict->SetBoolean("unidirectional", unidirectional);
- dict->Set("headers", headers_list);
+ dict->SetInteger("spdy_priority", static_cast<int>(spdy_priority));
dict->SetInteger("stream_id", stream_id);
- if (associated_stream)
- dict->SetInteger("associated_stream", associated_stream);
+ dict->SetInteger("associated_stream", associated_stream);
return dict;
}
-base::Value* NetLogSpdyCredentialCallback(size_t slot,
- const std::string* origin,
- NetLog::LogLevel /* log_level */) {
+base::Value* NetLogSpdySynReplyOrHeadersReceivedCallback(
+ const SpdyHeaderBlock* headers,
+ bool fin,
+ SpdyStreamId stream_id,
+ NetLog::LogLevel /* log_level */) {
base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetInteger("slot", slot);
- dict->SetString("origin", *origin);
+ dict->Set("headers", SpdyHeaderBlockToListValue(*headers).release());
+ dict->SetBoolean("fin", fin);
+ dict->SetInteger("stream_id", stream_id);
return dict;
}
@@ -345,7 +368,6 @@ SpdySession::SpdySession(
const base::WeakPtr<HttpServerProperties>& http_server_properties,
bool verify_domain_authentication,
bool enable_sending_initial_data,
- bool enable_credential_frames,
bool enable_compression,
bool enable_ping_based_connection_checking,
NextProto default_protocol,
@@ -387,6 +409,7 @@ SpdySession::SpdySession(
pings_in_flight_(0),
next_ping_id_(1),
last_activity_time_(time_func()),
+ last_compressed_frame_len_(0),
check_ping_status_pending_(false),
send_connection_header_prefix_(false),
flow_control_state_(FLOW_CONTROL_NONE),
@@ -400,21 +423,17 @@ SpdySession::SpdySession(
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SPDY_SESSION)),
verify_domain_authentication_(verify_domain_authentication),
enable_sending_initial_data_(enable_sending_initial_data),
- enable_credential_frames_(enable_credential_frames),
enable_compression_(enable_compression),
enable_ping_based_connection_checking_(
enable_ping_based_connection_checking),
protocol_(default_protocol),
- credential_state_(SpdyCredentialState::kDefaultNumSlots),
connection_at_risk_of_loss_time_(
base::TimeDelta::FromSeconds(kDefaultConnectionAtRiskOfLossSeconds)),
hung_interval_(
base::TimeDelta::FromSeconds(kHungIntervalSeconds)),
trusted_spdy_proxy_(trusted_spdy_proxy),
time_func_(time_func) {
- // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we
- // stop supporting SPDY/1.
- DCHECK_GE(protocol_, kProtoSPDY2);
+ DCHECK_GE(protocol_, kProtoSPDYMinimumVersion);
DCHECK_LE(protocol_, kProtoSPDYMaximumVersion);
DCHECK(HttpStreamFactory::spdy_enabled());
net_log_.BeginEvent(
@@ -470,19 +489,9 @@ Error SpdySession::InitializeWithSocket(
if (protocol_negotiated != kProtoUnknown) {
protocol_ = protocol_negotiated;
}
- // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we
- // stop supporting SPDY/1.
- DCHECK_GE(protocol_, kProtoSPDY2);
+ DCHECK_GE(protocol_, kProtoSPDYMinimumVersion);
DCHECK_LE(protocol_, kProtoSPDYMaximumVersion);
- SSLClientSocket* ssl_socket = GetSSLClientSocket();
- if (ssl_socket && ssl_socket->WasChannelIDSent()) {
- // According to the SPDY spec, the credential associated with the TLS
- // connection is stored in slot[1].
- credential_state_.SetHasCredential(GURL("https://" +
- host_port_pair().ToString()));
- }
-
if (protocol_ == kProtoHTTP2Draft04)
send_connection_header_prefix_ = true;
@@ -540,11 +549,13 @@ bool SpdySession::VerifyDomainAuthentication(const std::string& domain) {
if (!GetSSLInfo(&ssl_info, &was_npn_negotiated, &protocol_negotiated))
return true; // This is not a secure session, so all domains are okay.
- return !ssl_info.client_cert_sent &&
- (enable_credential_frames_ || !ssl_info.channel_id_sent ||
- ServerBoundCertService::GetDomainForHost(domain) ==
- ServerBoundCertService::GetDomainForHost(host_port_pair().host())) &&
- ssl_info.cert->VerifyNameMatch(domain);
+ bool unused = false;
+ return
+ !ssl_info.client_cert_sent &&
+ (!ssl_info.channel_id_sent ||
+ (ServerBoundCertService::GetDomainForHost(domain) ==
+ ServerBoundCertService::GetDomainForHost(host_port_pair().host()))) &&
+ ssl_info.cert->VerifyNameMatch(domain, &unused);
}
int SpdySession::GetPushStream(
@@ -616,14 +627,17 @@ int SpdySession::TryCreateStream(
stalled_streams_++;
net_log().AddEvent(NetLog::TYPE_SPDY_SESSION_STALLED_MAX_STREAMS);
- pending_create_stream_queues_[request->priority()].push_back(request);
+ RequestPriority priority = request->priority();
+ CHECK_GE(priority, MINIMUM_PRIORITY);
+ CHECK_LE(priority, MAXIMUM_PRIORITY);
+ pending_create_stream_queues_[priority].push_back(request);
return ERR_IO_PENDING;
}
int SpdySession::CreateStream(const SpdyStreamRequest& request,
base::WeakPtr<SpdyStream>* stream) {
DCHECK_GE(request.priority(), MINIMUM_PRIORITY);
- DCHECK_LT(request.priority(), NUM_PRIORITIES);
+ DCHECK_LE(request.priority(), MAXIMUM_PRIORITY);
if (availability_state_ == STATE_GOING_AWAY)
return ERR_FAILED;
@@ -672,11 +686,14 @@ int SpdySession::CreateStream(const SpdyStreamRequest& request,
void SpdySession::CancelStreamRequest(
const base::WeakPtr<SpdyStreamRequest>& request) {
DCHECK(request);
+ RequestPriority priority = request->priority();
+ CHECK_GE(priority, MINIMUM_PRIORITY);
+ CHECK_LE(priority, MAXIMUM_PRIORITY);
if (DCHECK_IS_ON()) {
// |request| should not be in a queue not matching its priority.
- for (int i = 0; i < NUM_PRIORITIES; ++i) {
- if (request->priority() == i)
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
+ if (priority == i)
continue;
PendingStreamRequestQueue* queue = &pending_create_stream_queues_[i];
DCHECK(std::find_if(queue->begin(),
@@ -686,7 +703,7 @@ void SpdySession::CancelStreamRequest(
}
PendingStreamRequestQueue* queue =
- &pending_create_stream_queues_[request->priority()];
+ &pending_create_stream_queues_[priority];
// Remove |request| from |queue| while preserving the order of the
// other elements.
PendingStreamRequestQueue::iterator it =
@@ -703,7 +720,7 @@ void SpdySession::CancelStreamRequest(
}
base::WeakPtr<SpdyStreamRequest> SpdySession::GetNextPendingStreamRequest() {
- for (int j = NUM_PRIORITIES - 1; j >= MINIMUM_PRIORITY; --j) {
+ for (int j = MAXIMUM_PRIORITY; j >= MINIMUM_PRIORITY; --j) {
if (pending_create_stream_queues_[j].empty())
continue;
@@ -740,20 +757,11 @@ void SpdySession::ProcessPendingStreamRequests() {
}
}
-bool SpdySession::NeedsCredentials() const {
- if (!is_secure_)
- return false;
- SSLClientSocket* ssl_socket = GetSSLClientSocket();
- if (ssl_socket->GetNegotiatedProtocol() < kProtoSPDY3)
- return false;
- return ssl_socket->WasChannelIDSent();
-}
-
void SpdySession::AddPooledAlias(const SpdySessionKey& alias_key) {
pooled_aliases_.insert(alias_key);
}
-int SpdySession::GetProtocolVersion() const {
+SpdyMajorVersion SpdySession::GetProtocolVersion() const {
DCHECK(buffered_spdy_framer_.get());
return buffered_spdy_framer_->protocol_version();
}
@@ -801,11 +809,12 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
SendPrefacePingIfNoneInFlight();
DCHECK(buffered_spdy_framer_.get());
+ SpdyPriority spdy_priority =
+ ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion());
scoped_ptr<SpdyFrame> syn_frame(
buffered_spdy_framer_->CreateSynStream(
- stream_id, 0,
- ConvertRequestPriorityToSpdyPriority(priority, GetProtocolVersion()),
- credential_slot, flags, enable_compression_, &headers));
+ stream_id, 0, spdy_priority,
+ credential_slot, flags, &headers));
base::StatsCounter spdy_requests("spdy.requests");
spdy_requests.Increment();
@@ -814,48 +823,16 @@ scoped_ptr<SpdyFrame> SpdySession::CreateSynStream(
if (net_log().IsLoggingAllEvents()) {
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_SYN_STREAM,
- base::Bind(&NetLogSpdySynCallback, &headers,
+ base::Bind(&NetLogSpdySynStreamSentCallback, &headers,
(flags & CONTROL_FLAG_FIN) != 0,
(flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0,
- stream_id, 0));
+ spdy_priority,
+ stream_id));
}
return syn_frame.Pass();
}
-int SpdySession::CreateCredentialFrame(
- const std::string& origin,
- const std::string& key,
- const std::string& cert,
- RequestPriority priority,
- scoped_ptr<SpdyFrame>* credential_frame) {
- DCHECK(is_secure_);
- SSLClientSocket* ssl_socket = GetSSLClientSocket();
- DCHECK(ssl_socket);
- DCHECK(ssl_socket->WasChannelIDSent());
-
- SpdyCredential credential;
- std::string tls_unique;
- ssl_socket->GetTLSUniqueChannelBinding(&tls_unique);
- size_t slot = credential_state_.SetHasCredential(GURL(origin));
- int rv = SpdyCredentialBuilder::Build(tls_unique, key, cert, slot,
- &credential);
- DCHECK_NE(rv, ERR_IO_PENDING);
- if (rv != OK)
- return rv;
-
- DCHECK(buffered_spdy_framer_.get());
- credential_frame->reset(
- buffered_spdy_framer_->CreateCredentialFrame(credential));
-
- if (net_log().IsLoggingAllEvents()) {
- net_log().AddEvent(
- NetLog::TYPE_SPDY_SESSION_SEND_CREDENTIAL,
- base::Bind(&NetLogSpdyCredentialCallback, credential.slot, &origin));
- }
- return OK;
-}
-
scoped_ptr<SpdyBuffer> SpdySession::CreateDataBuffer(SpdyStreamId stream_id,
IOBuffer* data,
int len,
@@ -1421,7 +1398,7 @@ int SpdySession::DoWriteComplete(int result) {
void SpdySession::DcheckGoingAway() const {
DCHECK_GE(availability_state_, STATE_GOING_AWAY);
if (DCHECK_IS_ON()) {
- for (int i = 0; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
DCHECK(pending_create_stream_queues_[i].empty());
}
}
@@ -1796,12 +1773,6 @@ bool SpdySession::GetSSLCertRequestInfo(
return true;
}
-ServerBoundCertService* SpdySession::GetServerBoundCertService() const {
- if (!is_secure_)
- return NULL;
- return GetSSLClientSocket()->GetServerBoundCertService();
-}
-
void SpdySession::OnError(SpdyFramer::SpdyError error_code) {
CHECK(in_io_loop_);
@@ -1836,6 +1807,28 @@ void SpdySession::OnStreamError(SpdyStreamId stream_id,
ResetStreamIterator(it, RST_STREAM_PROTOCOL_ERROR, description);
}
+void SpdySession::OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) {
+ CHECK(in_io_loop_);
+
+ if (availability_state_ == STATE_CLOSED)
+ return;
+
+ ActiveStreamMap::iterator it = active_streams_.find(stream_id);
+
+ // By the time data comes in, the stream may already be inactive.
+ if (it == active_streams_.end())
+ return;
+
+ SpdyStream* stream = it->second.stream;
+ CHECK_EQ(stream->stream_id(), stream_id);
+
+ DCHECK(buffered_spdy_framer_);
+ size_t header_len = buffered_spdy_framer_->GetDataFrameMinimumSize();
+ stream->IncrementRawReceivedBytes(header_len);
+}
+
void SpdySession::OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
@@ -1881,6 +1874,8 @@ void SpdySession::OnStreamFrameData(SpdyStreamId stream_id,
SpdyStream* stream = it->second.stream;
CHECK_EQ(stream->stream_id(), stream_id);
+ stream->IncrementRawReceivedBytes(len);
+
if (it->second.waiting_for_syn_reply) {
const std::string& error = "Data received before SYN_REPLY.";
stream->LogStreamError(ERR_SPDY_PROTOCOL_ERROR, error);
@@ -1951,6 +1946,13 @@ void SpdySession::OnSendCompressedFrame(
}
}
+void SpdySession::OnReceiveCompressedFrame(
+ SpdyStreamId stream_id,
+ SpdyFrameType type,
+ size_t frame_len) {
+ last_compressed_frame_len_ = frame_len;
+}
+
int SpdySession::OnInitialResponseHeadersReceived(
const SpdyHeaderBlock& response_headers,
base::Time response_time,
@@ -1986,8 +1988,8 @@ void SpdySession::OnSynStream(SpdyStreamId stream_id,
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_SPDY_SESSION_PUSHED_SYN_STREAM,
- base::Bind(&NetLogSpdySynCallback,
- &headers, fin, unidirectional,
+ base::Bind(&NetLogSpdySynStreamReceivedCallback,
+ &headers, fin, unidirectional, priority,
stream_id, associated_stream_id));
}
@@ -2091,6 +2093,8 @@ void SpdySession::OnSynStream(SpdyStreamId stream_id,
stream_initial_recv_window_size_,
net_log_));
stream->set_stream_id(stream_id);
+ stream->IncrementRawReceivedBytes(last_compressed_frame_len_);
+ last_compressed_frame_len_ = 0;
DeleteExpiredPushedStreams();
PushedStreamMap::iterator inserted_pushed_it =
@@ -2166,9 +2170,8 @@ void SpdySession::OnSynReply(SpdyStreamId stream_id,
if (net_log().IsLoggingAllEvents()) {
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_SYN_REPLY,
- base::Bind(&NetLogSpdySynCallback,
- &headers, fin, false, // not unidirectional
- stream_id, 0));
+ base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback,
+ &headers, fin, stream_id));
}
ActiveStreamMap::iterator it = active_streams_.find(stream_id);
@@ -2180,6 +2183,9 @@ void SpdySession::OnSynReply(SpdyStreamId stream_id,
SpdyStream* stream = it->second.stream;
CHECK_EQ(stream->stream_id(), stream_id);
+ stream->IncrementRawReceivedBytes(last_compressed_frame_len_);
+ last_compressed_frame_len_ = 0;
+
if (!it->second.waiting_for_syn_reply) {
const std::string& error =
"Received duplicate SYN_REPLY for stream.";
@@ -2204,9 +2210,8 @@ void SpdySession::OnHeaders(SpdyStreamId stream_id,
if (net_log().IsLoggingAllEvents()) {
net_log().AddEvent(
NetLog::TYPE_SPDY_SESSION_RECV_HEADERS,
- base::Bind(&NetLogSpdySynCallback,
- &headers, fin, /*unidirectional=*/false,
- stream_id, 0));
+ base::Bind(&NetLogSpdySynReplyOrHeadersReceivedCallback,
+ &headers, fin, stream_id));
}
ActiveStreamMap::iterator it = active_streams_.find(stream_id);
@@ -2219,6 +2224,9 @@ void SpdySession::OnHeaders(SpdyStreamId stream_id,
SpdyStream* stream = it->second.stream;
CHECK_EQ(stream->stream_id(), stream_id);
+ stream->IncrementRawReceivedBytes(last_compressed_frame_len_);
+ last_compressed_frame_len_ = 0;
+
int rv = stream->OnAdditionalResponseHeadersReceived(headers);
if (rv < 0) {
DCHECK_NE(rv, ERR_IO_PENDING);
@@ -2897,7 +2905,10 @@ void SpdySession::DecreaseRecvWindowSize(int32 delta_window_size) {
void SpdySession::QueueSendStalledStream(const SpdyStream& stream) {
DCHECK(stream.send_stalled_by_flow_control());
- stream_send_unstall_queue_[stream.priority()].push_back(stream.stream_id());
+ RequestPriority priority = stream.priority();
+ CHECK_GE(priority, MINIMUM_PRIORITY);
+ CHECK_LE(priority, MAXIMUM_PRIORITY);
+ stream_send_unstall_queue_[priority].push_back(stream.stream_id());
}
void SpdySession::ResumeSendStalledStreams() {
@@ -2930,7 +2941,7 @@ void SpdySession::ResumeSendStalledStreams() {
}
SpdyStreamId SpdySession::PopStreamToPossiblyResume() {
- for (int i = NUM_PRIORITIES - 1; i >= 0; --i) {
+ for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) {
std::deque<SpdyStreamId>* queue = &stream_send_unstall_queue_[i];
if (!queue->empty()) {
SpdyStreamId stream_id = queue->front();
diff --git a/chromium/net/spdy/spdy_session.h b/chromium/net/spdy/spdy_session.h
index f9c0623d5d4..fde42024be8 100644
--- a/chromium/net/spdy/spdy_session.h
+++ b/chromium/net/spdy/spdy_session.h
@@ -28,7 +28,6 @@
#include "net/socket/stream_socket.h"
#include "net/spdy/buffered_spdy_framer.h"
#include "net/spdy/spdy_buffer.h"
-#include "net/spdy/spdy_credential_state.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_protocol.h"
@@ -207,7 +206,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
const base::WeakPtr<HttpServerProperties>& http_server_properties,
bool verify_domain_authentication,
bool enable_sending_initial_data,
- bool enable_credential_frames,
bool enable_compression,
bool enable_ping_based_connection_checking,
NextProto default_protocol,
@@ -262,10 +260,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
int certificate_error_code);
// Returns the protocol used by this session. Always between
- // kProtoSPDY2 and kProtoSPDYMaximumVersion.
- //
- // TODO(akalin): Change the lower bound to kProtoSPDYMinimumVersion
- // once we stop supporting SPDY/1.
+ // kProtoSPDYMinimumVersion and kProtoSPDYMaximumVersion.
NextProto protocol() const { return protocol_; }
// Check to see if this SPDY session can support an additional domain.
@@ -295,15 +290,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
SpdyControlFlags flags,
const SpdyHeaderBlock& headers);
- // Tries to create a CREDENTIAL frame. If successful, fills in
- // |credential_frame| and returns OK. Returns the error (guaranteed
- // to not be ERR_IO_PENDING) otherwise.
- int CreateCredentialFrame(const std::string& origin,
- const std::string& key,
- const std::string& cert,
- RequestPriority priority,
- scoped_ptr<SpdyFrame>* credential_frame);
-
// Creates and returns a SpdyBuffer holding a data frame with the
// given data. May return NULL if stalled by flow control.
scoped_ptr<SpdyBuffer> CreateDataBuffer(SpdyStreamId stream_id,
@@ -344,10 +330,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// true when SSL is in use.
bool GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
- // Returns the ServerBoundCertService used by this Socket, or NULL
- // if server bound certs are not supported in this session.
- ServerBoundCertService* GetServerBoundCertService() const;
-
// Send a WINDOW_UPDATE frame for a stream. Called by a stream
// whenever receive window size is increased.
void SendStreamWindowUpdate(SpdyStreamId stream_id,
@@ -410,7 +392,8 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
size_t num_created_streams() const { return created_streams_.size(); }
size_t pending_create_stream_queue_size(RequestPriority priority) const {
- DCHECK_LT(priority, NUM_PRIORITIES);
+ DCHECK_GE(priority, MINIMUM_PRIORITY);
+ DCHECK_LE(priority, MAXIMUM_PRIORITY);
return pending_create_stream_queues_[priority].size();
}
@@ -442,11 +425,6 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
int GetPeerAddress(IPEndPoint* address) const;
int GetLocalAddress(IPEndPoint* address) const;
- // Returns true if requests on this session require credentials.
- bool NeedsCredentials() const;
-
- SpdyCredentialState* credential_state() { return &credential_state_; }
-
// Adds |alias| to set of aliases associated with this session.
void AddPooledAlias(const SpdySessionKey& alias_key);
@@ -455,7 +433,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
return pooled_aliases_;
}
- int GetProtocolVersion() const;
+ SpdyMajorVersion GetProtocolVersion() const;
size_t GetDataFrameMinimumSize() const {
return buffered_spdy_framer_->GetDataFrameMinimumSize();
@@ -803,6 +781,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
SpdyRstStreamStatus status) OVERRIDE;
virtual void OnGoAway(SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status) OVERRIDE;
+ virtual void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) OVERRIDE;
virtual void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
@@ -839,7 +820,7 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
virtual void OnReceiveCompressedFrame(
SpdyStreamId stream_id,
SpdyFrameType type,
- size_t frame_len) OVERRIDE {}
+ size_t frame_len) OVERRIDE;
// Called when bytes are consumed from a SpdyBuffer for a DATA frame
// that is to be written or is being written. Increases the send
@@ -1055,6 +1036,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// This is the last time we had activity in the session.
base::TimeTicks last_activity_time_;
+ // This is the length of the last compressed frame.
+ size_t last_compressed_frame_len_;
+
// This is the next time that unclaimed push streams should be checked for
// expirations.
base::TimeTicks next_unclaimed_push_stream_sweep_time_;
@@ -1096,19 +1080,13 @@ 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_credential_frames_;
bool enable_compression_;
bool enable_ping_based_connection_checking_;
- // The SPDY protocol used. Always between kProtoSPDY2 and
+ // The SPDY protocol used. Always between kProtoSPDYMinimumVersion and
// kProtoSPDYMaximumVersion.
- //
- // TODO(akalin): Change the lower bound to kProtoSPDYMinimumVersion
- // once we stop supporting SPDY/1.
NextProto protocol_;
- SpdyCredentialState credential_state_;
-
// |connection_at_risk_of_loss_time_| is an optimization to avoid sending
// wasteful preface pings (when we just got some data).
//
diff --git a/chromium/net/spdy/spdy_session_pool.cc b/chromium/net/spdy/spdy_session_pool.cc
index 9e47f3f4e89..72beec465db 100644
--- a/chromium/net/spdy/spdy_session_pool.cc
+++ b/chromium/net/spdy/spdy_session_pool.cc
@@ -33,7 +33,6 @@ SpdySessionPool::SpdySessionPool(
const base::WeakPtr<HttpServerProperties>& http_server_properties,
bool force_single_domain,
bool enable_ip_pooling,
- bool enable_credential_frames,
bool enable_compression,
bool enable_ping_based_connection_checking,
NextProto default_protocol,
@@ -49,25 +48,21 @@ SpdySessionPool::SpdySessionPool(
enable_sending_initial_data_(true),
force_single_domain_(force_single_domain),
enable_ip_pooling_(enable_ip_pooling),
- enable_credential_frames_(enable_credential_frames),
enable_compression_(enable_compression),
enable_ping_based_connection_checking_(
enable_ping_based_connection_checking),
// TODO(akalin): Force callers to have a valid value of
- // |default_protocol_|. Or at least make the default be
- // kProtoSPDY3.
+ // |default_protocol_|.
default_protocol_(
(default_protocol == kProtoUnknown) ?
- kProtoSPDY2 : default_protocol),
+ kProtoSPDY3 : default_protocol),
stream_initial_recv_window_size_(stream_initial_recv_window_size),
initial_max_concurrent_streams_(initial_max_concurrent_streams),
max_concurrent_streams_limit_(max_concurrent_streams_limit),
time_func_(time_func),
trusted_spdy_proxy_(
HostPortPair::FromString(trusted_spdy_proxy)) {
- // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we
- // stop supporting SPDY/1.
- DCHECK(default_protocol_ >= kProtoSPDY2 &&
+ DCHECK(default_protocol_ >= kProtoSPDYMinimumVersion &&
default_protocol_ <= kProtoSPDYMaximumVersion);
NetworkChangeNotifier::AddIPAddressObserver(this);
if (ssl_config_service_.get())
@@ -91,9 +86,7 @@ net::Error SpdySessionPool::CreateAvailableSessionFromSocket(
int certificate_error_code,
base::WeakPtr<SpdySession>* available_session,
bool is_secure) {
- // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we
- // stop supporting SPDY/1.
- DCHECK_GE(default_protocol_, kProtoSPDY2);
+ DCHECK_GE(default_protocol_, kProtoSPDYMinimumVersion);
DCHECK_LE(default_protocol_, kProtoSPDYMaximumVersion);
UMA_HISTOGRAM_ENUMERATION(
@@ -104,7 +97,6 @@ net::Error SpdySessionPool::CreateAvailableSessionFromSocket(
http_server_properties_,
verify_domain_authentication_,
enable_sending_initial_data_,
- enable_credential_frames_,
enable_compression_,
enable_ping_based_connection_checking_,
default_protocol_,
@@ -295,15 +287,15 @@ void SpdySessionPool::OnSSLConfigChanged() {
}
void SpdySessionPool::OnCertAdded(const X509Certificate* cert) {
- CloseCurrentSessions(ERR_NETWORK_CHANGED);
+ CloseCurrentSessions(ERR_CERT_DATABASE_CHANGED);
}
-void SpdySessionPool::OnCertTrustChanged(const X509Certificate* cert) {
+void SpdySessionPool::OnCACertChanged(const X509Certificate* cert) {
// Per wtc, we actually only need to CloseCurrentSessions when trust is
- // reduced. CloseCurrentSessions now because OnCertTrustChanged does not
+ // reduced. CloseCurrentSessions now because OnCACertChanged does not
// tell us this.
- // See comments in ClientSocketPoolManager::OnCertTrustChanged.
- CloseCurrentSessions(ERR_NETWORK_CHANGED);
+ // See comments in ClientSocketPoolManager::OnCACertChanged.
+ CloseCurrentSessions(ERR_CERT_DATABASE_CHANGED);
}
bool SpdySessionPool::IsSessionAvailable(
diff --git a/chromium/net/spdy/spdy_session_pool.h b/chromium/net/spdy/spdy_session_pool.h
index 812b7bd8890..e68d0c4f6d5 100644
--- a/chromium/net/spdy/spdy_session_pool.h
+++ b/chromium/net/spdy/spdy_session_pool.h
@@ -52,7 +52,6 @@ class NET_EXPORT SpdySessionPool
const base::WeakPtr<HttpServerProperties>& http_server_properties,
bool force_single_domain,
bool enable_ip_pooling,
- bool enable_credential_frames,
bool enable_compression,
bool enable_ping_based_connection_checking,
NextProto default_protocol,
@@ -142,8 +141,11 @@ class NET_EXPORT SpdySessionPool
virtual void OnSSLConfigChanged() OVERRIDE;
// CertDatabase::Observer methods:
+
+ // We perform the same flushing as described above when certificate database
+ // is changed.
virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE;
- virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;
+ virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE;
private:
friend class SpdySessionPoolPeer; // For testing.
@@ -214,7 +216,6 @@ class NET_EXPORT SpdySessionPool
bool enable_sending_initial_data_;
bool force_single_domain_;
bool enable_ip_pooling_;
- bool enable_credential_frames_;
bool enable_compression_;
bool enable_ping_based_connection_checking_;
const NextProto default_protocol_;
diff --git a/chromium/net/spdy/spdy_session_pool_unittest.cc b/chromium/net/spdy/spdy_session_pool_unittest.cc
index 33688759096..c9873fc8141 100644
--- a/chromium/net/spdy/spdy_session_pool_unittest.cc
+++ b/chromium/net/spdy/spdy_session_pool_unittest.cc
@@ -50,7 +50,8 @@ class SpdySessionPoolTest : public ::testing::Test,
INSTANTIATE_TEST_CASE_P(
NextProto,
SpdySessionPoolTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
// A delegate that opens a new session when it is closed.
diff --git a/chromium/net/spdy/spdy_session_unittest.cc b/chromium/net/spdy/spdy_session_unittest.cc
index 72dc5747998..2f185c7c01a 100644
--- a/chromium/net/spdy/spdy_session_unittest.cc
+++ b/chromium/net/spdy/spdy_session_unittest.cc
@@ -181,7 +181,8 @@ class SpdySessionTest : public PlatformTest,
INSTANTIATE_TEST_CASE_P(
NextProto,
SpdySessionTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
// Try to create a SPDY session that will fail during
@@ -2284,38 +2285,6 @@ TEST_P(SpdySessionTest, CancelTwoStalledCreateStream) {
EXPECT_EQ(0u, session->pending_create_stream_queue_size(LOWEST));
}
-TEST_P(SpdySessionTest, NeedsCredentials) {
- MockConnect connect_data(SYNCHRONOUS, OK);
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
- };
- StaticSocketDataProvider data(reads, arraysize(reads), NULL, 0);
- data.set_connect_data(connect_data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
-
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.channel_id_sent = true;
- ssl.protocol_negotiated = GetParam();
- session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
-
- CreateNetworkSession();
-
- const GURL url("https://www.foo.com");
- HostPortPair test_host_port_pair(url.host(), 443);
- SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
-
- base::WeakPtr<SpdySession> session =
- CreateSecureSpdySession(http_session_, key, BoundNetLog());
-
- EXPECT_EQ(spdy_util_.spdy_version() >= SPDY3, session->NeedsCredentials());
-
- // Flush the read completion task.
- base::MessageLoop::current()->RunUntilIdle();
-
- session->CloseSessionOnError(ERR_ABORTED, std::string());
-}
-
// Test that SpdySession::DoReadLoop reads data from the socket
// without yielding. This test makes 32k - 1 bytes of data available
// on the socket for reading. It then verifies that it has read all
@@ -2705,7 +2674,7 @@ TEST_P(SpdySessionTest, ProtocolNegotiation) {
EXPECT_EQ(spdy_util_.spdy_version(),
session->buffered_spdy_framer_->protocol_version());
- if (GetParam() == kProtoSPDY2) {
+ if (GetParam() == kProtoDeprecatedSPDY2) {
EXPECT_EQ(SpdySession::FLOW_CONTROL_NONE, session->flow_control_state());
EXPECT_EQ(0, session->session_send_window_size_);
EXPECT_EQ(0, session->session_recv_window_size_);
@@ -3075,49 +3044,6 @@ TEST_P(SpdySessionTest, CreateStreamOnStreamReset) {
// The tests below are only for SPDY/3 and above.
-TEST_P(SpdySessionTest, SendCredentials) {
- if (GetParam() < kProtoSPDY3)
- return;
-
- MockConnect connect_data(SYNCHRONOUS, OK);
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
- };
- SettingsMap settings;
- scoped_ptr<SpdyFrame> settings_frame(
- spdy_util_.ConstructSpdySettings(settings));
- MockWrite writes[] = {
- CreateMockWrite(*settings_frame),
- };
- StaticSocketDataProvider data(reads, arraysize(reads),
- writes, arraysize(writes));
- data.set_connect_data(connect_data);
- session_deps_.socket_factory->AddSocketDataProvider(&data);
-
- SSLSocketDataProvider ssl(SYNCHRONOUS, OK);
- ssl.channel_id_sent = true;
- ssl.protocol_negotiated = GetParam();
- session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
-
- CreateNetworkSession();
-
- const GURL kTestUrl("https://www.foo.com");
- HostPortPair test_host_port_pair(kTestUrl.host(), 443);
- SpdySessionKey key(test_host_port_pair, ProxyServer::Direct(),
- kPrivacyModeDisabled);
-
- base::WeakPtr<SpdySession> session =
- CreateSecureSpdySession(http_session_, key, BoundNetLog());
-
- EXPECT_TRUE(session->NeedsCredentials());
-
- // Flush the read completion task.
- base::MessageLoop::current()->RunUntilIdle();
-
- session->CloseSessionOnError(ERR_ABORTED, std::string());
- EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key));
-}
-
TEST_P(SpdySessionTest, UpdateStreamsSendWindowSize) {
if (GetParam() < kProtoSPDY3)
return;
diff --git a/chromium/net/spdy/spdy_stream.cc b/chromium/net/spdy/spdy_stream.cc
index a603a6c93e0..ccf48ecd7d2 100644
--- a/chromium/net/spdy/spdy_stream.cc
+++ b/chromium/net/spdy/spdy_stream.cc
@@ -106,6 +106,7 @@ SpdyStream::SpdyStream(SpdyStreamType type,
io_state_((type_ == SPDY_PUSH_STREAM) ? STATE_IDLE : STATE_NONE),
response_status_(OK),
net_log_(net_log),
+ raw_received_bytes_(0),
send_bytes_(0),
recv_bytes_(0),
just_completed_frame_type_(DATA),
@@ -113,6 +114,8 @@ SpdyStream::SpdyStream(SpdyStreamType type,
CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
type_ == SPDY_REQUEST_RESPONSE_STREAM ||
type_ == SPDY_PUSH_STREAM);
+ CHECK_GE(priority_, MINIMUM_PRIORITY);
+ CHECK_LE(priority_, MAXIMUM_PRIORITY);
}
SpdyStream::~SpdyStream() {
@@ -518,7 +521,7 @@ void SpdyStream::OnFrameWriteComplete(SpdyFrameType frame_type,
DoLoop(OK);
}
-int SpdyStream::GetProtocolVersion() const {
+SpdyMajorVersion SpdyStream::GetProtocolVersion() const {
return session_->GetProtocolVersion();
}
@@ -581,7 +584,7 @@ int SpdyStream::SendRequestHeaders(scoped_ptr<SpdyHeaderBlock> request_headers,
CHECK_EQ(io_state_, STATE_NONE);
request_headers_ = request_headers.Pass();
send_status_ = send_status;
- io_state_ = STATE_GET_DOMAIN_BOUND_CERT;
+ io_state_ = STATE_SEND_REQUEST_HEADERS;
return DoLoop(OK);
}
@@ -654,11 +657,6 @@ bool SpdyStream::HasUrlFromHeaders() const {
return !GetUrlFromHeaders().is_empty();
}
-void SpdyStream::OnGetDomainBoundCertComplete(int result) {
- DCHECK_EQ(io_state_, STATE_GET_DOMAIN_BOUND_CERT_COMPLETE);
- DoLoop(result);
-}
-
int SpdyStream::DoLoop(int result) {
CHECK(!in_do_loop_);
in_do_loop_ = true;
@@ -667,20 +665,6 @@ int SpdyStream::DoLoop(int result) {
State state = io_state_;
io_state_ = STATE_NONE;
switch (state) {
- case STATE_GET_DOMAIN_BOUND_CERT:
- CHECK_EQ(result, OK);
- result = DoGetDomainBoundCert();
- break;
- case STATE_GET_DOMAIN_BOUND_CERT_COMPLETE:
- result = DoGetDomainBoundCertComplete(result);
- break;
- case STATE_SEND_DOMAIN_BOUND_CERT:
- CHECK_EQ(result, OK);
- result = DoSendDomainBoundCert();
- break;
- case STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE:
- result = DoSendDomainBoundCertComplete(result);
- break;
case STATE_SEND_REQUEST_HEADERS:
CHECK_EQ(result, OK);
result = DoSendRequestHeaders();
@@ -720,91 +704,6 @@ int SpdyStream::DoLoop(int result) {
return result;
}
-int SpdyStream::DoGetDomainBoundCert() {
- CHECK(request_headers_);
- DCHECK_NE(type_, SPDY_PUSH_STREAM);
- GURL url = GetUrlFromHeaders();
- if (!session_->NeedsCredentials() || !url.SchemeIs("https")) {
- // Proceed directly to sending the request headers
- io_state_ = STATE_SEND_REQUEST_HEADERS;
- return OK;
- }
-
- slot_ = session_->credential_state()->FindCredentialSlot(GetUrlFromHeaders());
- if (slot_ != SpdyCredentialState::kNoEntry) {
- // Proceed directly to sending the request headers
- io_state_ = STATE_SEND_REQUEST_HEADERS;
- return OK;
- }
-
- io_state_ = STATE_GET_DOMAIN_BOUND_CERT_COMPLETE;
- ServerBoundCertService* sbc_service = session_->GetServerBoundCertService();
- DCHECK(sbc_service != NULL);
- int rv = sbc_service->GetOrCreateDomainBoundCert(
- url.GetOrigin().host(),
- &domain_bound_private_key_,
- &domain_bound_cert_,
- base::Bind(&SpdyStream::OnGetDomainBoundCertComplete, GetWeakPtr()),
- &domain_bound_cert_request_handle_);
- return rv;
-}
-
-int SpdyStream::DoGetDomainBoundCertComplete(int result) {
- DCHECK_NE(type_, SPDY_PUSH_STREAM);
- if (result != OK)
- return result;
-
- io_state_ = STATE_SEND_DOMAIN_BOUND_CERT;
- slot_ = session_->credential_state()->SetHasCredential(GetUrlFromHeaders());
- return OK;
-}
-
-int SpdyStream::DoSendDomainBoundCert() {
- CHECK(request_headers_);
- DCHECK_NE(type_, SPDY_PUSH_STREAM);
- io_state_ = STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE;
-
- std::string origin = GetUrlFromHeaders().GetOrigin().spec();
- DCHECK(origin[origin.length() - 1] == '/');
- origin.erase(origin.length() - 1); // Trim trailing slash.
- scoped_ptr<SpdyFrame> frame;
- int rv = session_->CreateCredentialFrame(
- origin,
- domain_bound_private_key_,
- domain_bound_cert_,
- priority_,
- &frame);
- if (rv != OK) {
- DCHECK_NE(rv, ERR_IO_PENDING);
- return rv;
- }
-
- DCHECK(frame);
- // TODO(akalin): Fix the following race condition:
- //
- // Since this is decoupled from sending the SYN_STREAM frame, it is
- // possible that other domain-bound cert frames will clobber ours
- // before our SYN_STREAM frame gets sent. This can be solved by
- // immediately enqueueing the SYN_STREAM frame here and adjusting
- // the state machine appropriately.
- session_->EnqueueStreamWrite(
- GetWeakPtr(), CREDENTIAL,
- scoped_ptr<SpdyBufferProducer>(
- new SimpleBufferProducer(
- scoped_ptr<SpdyBuffer>(new SpdyBuffer(frame.Pass())))));
- return ERR_IO_PENDING;
-}
-
-int SpdyStream::DoSendDomainBoundCertComplete(int result) {
- DCHECK_NE(type_, SPDY_PUSH_STREAM);
- if (result != OK)
- return result;
-
- DCHECK_EQ(just_completed_frame_type_, CREDENTIAL);
- io_state_ = STATE_SEND_REQUEST_HEADERS;
- return OK;
-}
-
int SpdyStream::DoSendRequestHeaders() {
DCHECK_NE(type_, SPDY_PUSH_STREAM);
io_state_ = STATE_SEND_REQUEST_HEADERS_COMPLETE;
diff --git a/chromium/net/spdy/spdy_stream.h b/chromium/net/spdy/spdy_stream.h
index 4d18e3eff38..6f5c62e4139 100644
--- a/chromium/net/spdy/spdy_stream.h
+++ b/chromium/net/spdy/spdy_stream.h
@@ -383,14 +383,17 @@ class NET_EXPORT_PRIVATE SpdyStream {
bool IsIdle() const;
// Returns the protocol used by this stream. Always between
- // kProtoSPDY2 and kProtoSPDYMaximumVersion.
- //
- // TODO(akalin): Change the lower bound to kProtoSPDYMinimumVersion
- // once we stop supporting SPDY/1.
+ // kProtoSPDYMinimumVersion and kProtoSPDYMaximumVersion.
NextProto GetProtocol() const;
int response_status() const { return response_status_; }
+ void IncrementRawReceivedBytes(size_t received_bytes) {
+ raw_received_bytes_ += received_bytes;
+ }
+
+ int64 raw_received_bytes() const { return raw_received_bytes_; }
+
bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const;
// Get the URL from the appropriate stream headers, or the empty
@@ -407,7 +410,7 @@ class NET_EXPORT_PRIVATE SpdyStream {
// TODO(akalin): Remove this, as it's only used in tests.
bool HasUrlFromHeaders() const;
- int GetProtocolVersion() const;
+ SpdyMajorVersion GetProtocolVersion() const;
private:
class SynStreamBufferProducer;
@@ -415,26 +418,16 @@ class NET_EXPORT_PRIVATE SpdyStream {
enum State {
STATE_NONE,
- STATE_GET_DOMAIN_BOUND_CERT,
- STATE_GET_DOMAIN_BOUND_CERT_COMPLETE,
- STATE_SEND_DOMAIN_BOUND_CERT,
- STATE_SEND_DOMAIN_BOUND_CERT_COMPLETE,
STATE_SEND_REQUEST_HEADERS,
STATE_SEND_REQUEST_HEADERS_COMPLETE,
STATE_IDLE,
STATE_CLOSED
};
- void OnGetDomainBoundCertComplete(int result);
-
// Try to make progress sending/receiving the request/response.
int DoLoop(int result);
// The implementations of each state of the state machine.
- int DoGetDomainBoundCert();
- int DoGetDomainBoundCertComplete(int result);
- int DoSendDomainBoundCert();
- int DoSendDomainBoundCertComplete(int result);
int DoSendRequestHeaders();
int DoSendRequestHeadersComplete();
int DoReadHeaders();
@@ -533,6 +526,10 @@ class NET_EXPORT_PRIVATE SpdyStream {
base::TimeTicks recv_first_byte_time_;
base::TimeTicks recv_last_byte_time_;
+ // Number of bytes that have been received on this stream, including frame
+ // overhead and headers.
+ int64 raw_received_bytes_;
+
// Number of data bytes that have been sent/received on this stream, not
// including frame overhead. Note that this does not count headers.
int send_bytes_;
diff --git a/chromium/net/spdy/spdy_stream_unittest.cc b/chromium/net/spdy/spdy_stream_unittest.cc
index c98ba937be0..cc1386dab43 100644
--- a/chromium/net/spdy/spdy_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_stream_unittest.cc
@@ -112,7 +112,8 @@ class SpdyStreamTest : public ::testing::Test,
INSTANTIATE_TEST_CASE_P(
NextProto,
SpdyStreamTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
TEST_P(SpdyStreamTest, SendDataAfterOpen) {
@@ -992,6 +993,70 @@ TEST_P(SpdyStreamTest, ResumeAfterSendWindowSizeAdjustBidirectional) {
base::Bind(&AdjustStreamSendWindowSize));
}
+// Test calculation of amount of bytes received from network.
+TEST_P(SpdyStreamTest, ReceivedBytes) {
+ GURL url(kStreamUrl);
+
+ session_ =
+ SpdySessionDependencies::SpdyCreateSessionDeterministic(&session_deps_);
+
+ scoped_ptr<SpdyFrame> syn(
+ spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true));
+ AddWrite(*syn);
+
+ scoped_ptr<SpdyFrame>
+ reply(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+ AddRead(*reply);
+
+ scoped_ptr<SpdyFrame> msg(
+ spdy_util_.ConstructSpdyBodyFrame(1, kPostBody, kPostBodyLength, false));
+ AddRead(*msg);
+
+ AddReadEOF();
+
+ DeterministicSocketData data(GetReads(), GetNumReads(),
+ GetWrites(), GetNumWrites());
+ MockConnect connect_data(SYNCHRONOUS, OK);
+ data.set_connect_data(connect_data);
+
+ session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data);
+
+ base::WeakPtr<SpdySession> session(CreateDefaultSpdySession());
+
+ base::WeakPtr<SpdyStream> stream =
+ CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog());
+ ASSERT_TRUE(stream.get() != NULL);
+
+ StreamDelegateDoNothing delegate(stream);
+ stream->SetDelegate(&delegate);
+
+ EXPECT_FALSE(stream->HasUrlFromHeaders());
+
+ scoped_ptr<SpdyHeaderBlock> headers(
+ spdy_util_.ConstructGetHeaderBlock(kStreamUrl));
+ EXPECT_EQ(ERR_IO_PENDING,
+ stream->SendRequestHeaders(headers.Pass(), NO_MORE_DATA_TO_SEND));
+ EXPECT_TRUE(stream->HasUrlFromHeaders());
+ EXPECT_EQ(kStreamUrl, stream->GetUrlFromHeaders().spec());
+
+ int64 reply_frame_len = reply->size();
+ int64 data_header_len = spdy_util_.CreateFramer()->GetDataFrameMinimumSize();
+ int64 data_frame_len = data_header_len + kPostBodyLength;
+ int64 response_len = reply_frame_len + data_frame_len;
+
+ EXPECT_EQ(0, stream->raw_received_bytes());
+ data.RunFor(1); // SYN
+ EXPECT_EQ(0, stream->raw_received_bytes());
+ data.RunFor(1); // REPLY
+ EXPECT_EQ(reply_frame_len, stream->raw_received_bytes());
+ data.RunFor(1); // DATA
+ EXPECT_EQ(response_len, stream->raw_received_bytes());
+ data.RunFor(1); // FIN
+
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, delegate.WaitForClose());
+}
+
} // namespace
} // namespace test
diff --git a/chromium/net/spdy/spdy_test_util_common.cc b/chromium/net/spdy/spdy_test_util_common.cc
index 8fb085a3d8c..89d18821b28 100644
--- a/chromium/net/spdy/spdy_test_util_common.cc
+++ b/chromium/net/spdy/spdy_test_util_common.cc
@@ -30,9 +30,8 @@ namespace net {
namespace {
bool next_proto_is_spdy(NextProto next_proto) {
- // TODO(akalin): Change this to kProtoSPDYMinimumVersion once we
- // stop supporting SPDY/1.
- return next_proto >= kProtoSPDY2 && next_proto <= kProtoSPDYMaximumVersion;
+ return next_proto >= kProtoSPDYMinimumVersion &&
+ next_proto <= kProtoSPDYMaximumVersion;
}
// Parses a URL into the scheme, host, and path components required for a
@@ -54,9 +53,7 @@ void ParseUrl(base::StringPiece url, std::string* scheme, std::string* host,
std::vector<NextProto> SpdyNextProtos() {
std::vector<NextProto> next_protos;
for (int i = kProtoMinimumVersion; i <= kProtoMaximumVersion; ++i) {
- NextProto proto = static_cast<NextProto>(i);
- if (proto != kProtoSPDY1 && proto != kProtoSPDY21)
- next_protos.push_back(proto);
+ next_protos.push_back(static_cast<NextProto>(i));
}
return next_protos;
}
@@ -231,6 +228,9 @@ class PriorityGetter : public BufferedSpdyFramerVisitorInterface {
virtual void OnHeaders(SpdyStreamId stream_id,
bool fin,
const SpdyHeaderBlock& headers) OVERRIDE {}
+ virtual void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) OVERRIDE {}
virtual void OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
@@ -755,19 +755,19 @@ SpdyFrame* SpdyTestUtil::ConstructSpdyFrame(
header_info.priority,
credential_slot,
header_info.control_flags,
- header_info.compressed, headers.get());
+ headers.get());
}
break;
case SYN_REPLY:
frame = framer.CreateSynReply(header_info.id, header_info.control_flags,
- header_info.compressed, headers.get());
+ headers.get());
break;
case RST_STREAM:
frame = framer.CreateRstStream(header_info.id, header_info.status);
break;
case HEADERS:
frame = framer.CreateHeaders(header_info.id, header_info.control_flags,
- header_info.compressed, headers.get());
+ headers.get());
break;
default:
ADD_FAILURE();
diff --git a/chromium/net/spdy/spdy_websocket_stream_unittest.cc b/chromium/net/spdy/spdy_websocket_stream_unittest.cc
index e0661a05407..3c1b3cb7626 100644
--- a/chromium/net/spdy/spdy_websocket_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_websocket_stream_unittest.cc
@@ -287,7 +287,8 @@ class SpdyWebSocketStreamTest
INSTANTIATE_TEST_CASE_P(
NextProto,
SpdyWebSocketStreamTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
// TODO(toyoshim): Replace old framing data to new one, then use HEADERS and
diff --git a/chromium/net/spdy/spdy_websocket_test_util.cc b/chromium/net/spdy/spdy_websocket_test_util.cc
index 0872e3f116e..0e09453b347 100644
--- a/chromium/net/spdy/spdy_websocket_test_util.cc
+++ b/chromium/net/spdy/spdy_websocket_test_util.cc
@@ -9,12 +9,10 @@
namespace net {
-static const int kDefaultAssociatedStreamId = 0;
-static const bool kDefaultCompressed = false;
-static const char* const kDefaultDataPointer = NULL;
-static const uint32 kDefaultDataLength = 0;
-static const char** const kDefaultExtraHeaders = NULL;
-static const int kDefaultExtraHeaderCount = 0;
+const int kDefaultAssociatedStreamId = 0;
+const bool kDefaultCompressed = false;
+const char* const kDefaultDataPointer = NULL;
+const uint32 kDefaultDataLength = 0;
SpdyWebSocketTestUtil::SpdyWebSocketTestUtil(
NextProto protocol) : spdy_util_(protocol) {}
@@ -74,7 +72,7 @@ SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHandshakeRequestFrame(
SYN_STREAM,
stream_id,
kDefaultAssociatedStreamId,
- ConvertRequestPriorityToSpdyPriority(request_priority, 2),
+ ConvertRequestPriorityToSpdyPriority(request_priority, SPDY2),
kSpdyCredentialSlotUnused,
CONTROL_FLAG_NONE,
kDefaultCompressed,
@@ -99,7 +97,7 @@ SpdyFrame* SpdyWebSocketTestUtil::ConstructSpdyWebSocketHandshakeResponseFrame(
SYN_REPLY,
stream_id,
kDefaultAssociatedStreamId,
- ConvertRequestPriorityToSpdyPriority(request_priority, 2),
+ ConvertRequestPriorityToSpdyPriority(request_priority, SPDY2),
kSpdyCredentialSlotUnused,
CONTROL_FLAG_NONE,
kDefaultCompressed,
diff --git a/chromium/net/spdy/spdy_write_queue.cc b/chromium/net/spdy/spdy_write_queue.cc
index 2ac42413232..ea6eb1f2922 100644
--- a/chromium/net/spdy/spdy_write_queue.cc
+++ b/chromium/net/spdy/spdy_write_queue.cc
@@ -33,7 +33,7 @@ SpdyWriteQueue::~SpdyWriteQueue() {
}
bool SpdyWriteQueue::IsEmpty() const {
- for (int i = 0; i < NUM_PRIORITIES; i++) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; i++) {
if (!queue_[i].empty())
return false;
}
@@ -44,6 +44,8 @@ void SpdyWriteQueue::Enqueue(RequestPriority priority,
SpdyFrameType frame_type,
scoped_ptr<SpdyBufferProducer> frame_producer,
const base::WeakPtr<SpdyStream>& stream) {
+ CHECK_GE(priority, MINIMUM_PRIORITY);
+ CHECK_LE(priority, MAXIMUM_PRIORITY);
if (stream.get())
DCHECK_EQ(stream->priority(), priority);
queue_[priority].push_back(
@@ -53,7 +55,7 @@ void SpdyWriteQueue::Enqueue(RequestPriority priority,
bool SpdyWriteQueue::Dequeue(SpdyFrameType* frame_type,
scoped_ptr<SpdyBufferProducer>* frame_producer,
base::WeakPtr<SpdyStream>* stream) {
- for (int i = NUM_PRIORITIES - 1; i >= 0; --i) {
+ for (int i = MAXIMUM_PRIORITY; i >= MINIMUM_PRIORITY; --i) {
if (!queue_[i].empty()) {
PendingWrite pending_write = queue_[i].front();
queue_[i].pop_front();
@@ -70,12 +72,16 @@ bool SpdyWriteQueue::Dequeue(SpdyFrameType* frame_type,
void SpdyWriteQueue::RemovePendingWritesForStream(
const base::WeakPtr<SpdyStream>& stream) {
+ RequestPriority priority = stream->priority();
+ CHECK_GE(priority, MINIMUM_PRIORITY);
+ CHECK_LE(priority, MAXIMUM_PRIORITY);
+
DCHECK(stream.get());
if (DCHECK_IS_ON()) {
// |stream| should not have pending writes in a queue not matching
// its priority.
- for (int i = 0; i < NUM_PRIORITIES; ++i) {
- if (stream->priority() == i)
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
+ if (priority == i)
continue;
for (std::deque<PendingWrite>::const_iterator it = queue_[i].begin();
it != queue_[i].end(); ++it) {
@@ -85,7 +91,7 @@ void SpdyWriteQueue::RemovePendingWritesForStream(
}
// Do the actual deletion and removal, preserving FIFO-ness.
- std::deque<PendingWrite>* queue = &queue_[stream->priority()];
+ std::deque<PendingWrite>* queue = &queue_[priority];
std::deque<PendingWrite>::iterator out_it = queue->begin();
for (std::deque<PendingWrite>::const_iterator it = queue->begin();
it != queue->end(); ++it) {
@@ -101,7 +107,7 @@ void SpdyWriteQueue::RemovePendingWritesForStream(
void SpdyWriteQueue::RemovePendingWritesForStreamsAfter(
SpdyStreamId last_good_stream_id) {
- for (int i = 0; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
// Do the actual deletion and removal, preserving FIFO-ness.
std::deque<PendingWrite>* queue = &queue_[i];
std::deque<PendingWrite>::iterator out_it = queue->begin();
@@ -120,7 +126,7 @@ void SpdyWriteQueue::RemovePendingWritesForStreamsAfter(
}
void SpdyWriteQueue::Clear() {
- for (int i = 0; i < NUM_PRIORITIES; ++i) {
+ for (int i = MINIMUM_PRIORITY; i <= MAXIMUM_PRIORITY; ++i) {
for (std::deque<PendingWrite>::iterator it = queue_[i].begin();
it != queue_[i].end(); ++it) {
delete it->frame_producer;
diff --git a/chromium/net/spdy/write_blocked_list.h b/chromium/net/spdy/write_blocked_list.h
index fe5668fae8a..be97f89c71f 100644
--- a/chromium/net/spdy/write_blocked_list.h
+++ b/chromium/net/spdy/write_blocked_list.h
@@ -9,6 +9,7 @@
#include <deque>
#include "base/logging.h"
+#include "net/spdy/spdy_protocol.h"
namespace net {
@@ -22,25 +23,39 @@ class WriteBlockedList {
typedef std::deque<IdType> BlockedList;
typedef typename BlockedList::iterator iterator;
- // Returns the priority of the highest priority list with sessions on it, or
- // -1 if none of the lists have pending sessions.
- int GetHighestPriorityWriteBlockedList() const {
- for (int i = 0; i <= kLowestPriority; ++i) {
+ static SpdyPriority ClampPriority(SpdyPriority priority) {
+ if (priority < kHighestPriority) {
+ LOG(DFATAL) << "Invalid priority: " << static_cast<int>(priority);
+ return kHighestPriority;
+ }
+ if (priority > kLowestPriority) {
+ LOG(DFATAL) << "Invalid priority: " << static_cast<int>(priority);
+ return kLowestPriority;
+ }
+ return priority;
+ }
+
+ // Returns the priority of the highest priority list with sessions on it.
+ SpdyPriority GetHighestPriorityWriteBlockedList() const {
+ for (SpdyPriority i = 0; i <= kLowestPriority; ++i) {
if (write_blocked_lists_[i].size() > 0)
return i;
}
- return -1;
+ LOG(DFATAL) << "No blocked streams";
+ return kHighestPriority;
}
- int PopFront(int priority) {
+ IdType PopFront(SpdyPriority priority) {
+ priority = ClampPriority(priority);
DCHECK(!write_blocked_lists_[priority].empty());
IdType stream_id = write_blocked_lists_[priority].front();
write_blocked_lists_[priority].pop_front();
return stream_id;
}
- bool HasWriteBlockedStreamsGreaterThanPriority(int priority) const {
- for (int i = kHighestPriority; i < priority; ++i) {
+ bool HasWriteBlockedStreamsGreaterThanPriority(SpdyPriority priority) const {
+ priority = ClampPriority(priority);
+ for (SpdyPriority i = kHighestPriority; i < priority; ++i) {
if (!write_blocked_lists_[i].empty()) {
return true;
}
@@ -49,14 +64,20 @@ class WriteBlockedList {
}
bool HasWriteBlockedStreams() const {
- return HasWriteBlockedStreamsGreaterThanPriority(kLowestPriority + 1);
+ for (SpdyPriority i = kHighestPriority; i <= kLowestPriority; ++i) {
+ if (!write_blocked_lists_[i].empty()) {
+ return true;
+ }
+ }
+ return false;
}
- void PushBack(IdType stream_id, int priority) {
- write_blocked_lists_[priority].push_back(stream_id);
+ void PushBack(IdType stream_id, SpdyPriority priority) {
+ write_blocked_lists_[ClampPriority(priority)].push_back(stream_id);
}
- void RemoveStreamFromWriteBlockedList(IdType stream_id, int priority) {
+ void RemoveStreamFromWriteBlockedList(IdType stream_id,
+ SpdyPriority priority) {
iterator it = std::find(write_blocked_lists_[priority].begin(),
write_blocked_lists_[priority].end(),
stream_id);
@@ -68,17 +89,16 @@ class WriteBlockedList {
}
}
- int NumBlockedStreams() {
- int num_blocked_streams = 0;
- for (int i = kHighestPriority; i <= kLowestPriority; ++i) {
+ size_t NumBlockedStreams() const {
+ size_t num_blocked_streams = 0;
+ for (SpdyPriority i = kHighestPriority; i <= kLowestPriority; ++i) {
num_blocked_streams += write_blocked_lists_[i].size();
}
return num_blocked_streams;
}
private:
- // Priority ranges from 0 to 7
- BlockedList write_blocked_lists_[8];
+ BlockedList write_blocked_lists_[kLowestPriority + 1];
};
} // namespace net
diff --git a/chromium/net/spdy/write_blocked_list_test.cc b/chromium/net/spdy/write_blocked_list_test.cc
index 3bb49df94f4..908f0a9e6ed 100644
--- a/chromium/net/spdy/write_blocked_list_test.cc
+++ b/chromium/net/spdy/write_blocked_list_test.cc
@@ -15,10 +15,12 @@ typedef WriteBlockedList<int> IntWriteBlockedList;
TEST(WriteBlockedListTest, GetHighestPriority) {
IntWriteBlockedList list;
- EXPECT_EQ(-1, list.GetHighestPriorityWriteBlockedList());
+ EXPECT_FALSE(list.HasWriteBlockedStreams());
list.PushBack(1, 1);
+ EXPECT_TRUE(list.HasWriteBlockedStreams());
EXPECT_EQ(1, list.GetHighestPriorityWriteBlockedList());
list.PushBack(1, 0);
+ EXPECT_TRUE(list.HasWriteBlockedStreams());
EXPECT_EQ(0, list.GetHighestPriorityWriteBlockedList());
}
@@ -55,22 +57,19 @@ TEST(WriteBlockedListTest, PopFront) {
IntWriteBlockedList list;
list.PushBack(1, 4);
- EXPECT_EQ(1, list.NumBlockedStreams());
+ EXPECT_EQ(1u, list.NumBlockedStreams());
list.PushBack(2, 4);
list.PushBack(1, 4);
list.PushBack(3, 4);
- EXPECT_EQ(4, list.NumBlockedStreams());
+ EXPECT_EQ(4u, list.NumBlockedStreams());
EXPECT_EQ(1, list.PopFront(4));
EXPECT_EQ(2, list.PopFront(4));
EXPECT_EQ(1, list.PopFront(4));
- EXPECT_EQ(1, list.NumBlockedStreams());
+ EXPECT_EQ(1u, list.NumBlockedStreams());
EXPECT_EQ(3, list.PopFront(4));
}
} // namespace
} // namespace test
} // namespace net
-
-
-
diff --git a/chromium/net/ssl/client_cert_store.h b/chromium/net/ssl/client_cert_store.h
index 46ef3362b3b..394d774f6c3 100644
--- a/chromium/net/ssl/client_cert_store.h
+++ b/chromium/net/ssl/client_cert_store.h
@@ -6,6 +6,7 @@
#define NET_SSL_CLIENT_CERT_STORE_H_
#include "base/basictypes.h"
+#include "base/callback_forward.h"
#include "net/base/net_export.h"
#include "net/cert/x509_certificate.h"
@@ -13,12 +14,19 @@ namespace net {
class SSLCertRequestInfo;
+// The caller is expected to keep the ClientCertStore alive until the callback
+// supplied to GetClientCerts has been run.
class NET_EXPORT ClientCertStore {
public:
virtual ~ClientCertStore() {}
- virtual bool GetClientCerts(const SSLCertRequestInfo& cert_request_info,
- CertificateList* selected_certs) = 0;
+ // Get client certs matching the |cert_request_info|. On completion, the
+ // results will be stored in |selected_certs| and the |callback| will be run.
+ // The |callback| may be called sychronously. The caller must ensure the
+ // |selected_certs| object remains alive until the callback has been run.
+ virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs,
+ const base::Closure& callback) = 0;
protected:
ClientCertStore() {}
diff --git a/chromium/net/ssl/client_cert_store_impl_unittest.cc b/chromium/net/ssl/client_cert_store_impl_unittest.cc
deleted file mode 100644
index 500e156169d..00000000000
--- a/chromium/net/ssl/client_cert_store_impl_unittest.cc
+++ /dev/null
@@ -1,169 +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/ssl/client_cert_store_impl.h"
-
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/base/test_data_directory.h"
-#include "net/test/cert_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-// "CN=B CA" - DER encoded DN of the issuer of client_1.pem
-const unsigned char kAuthority1DN[] = {
- 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
- 0x04, 0x42, 0x20, 0x43, 0x41
-};
-
-// "CN=E CA" - DER encoded DN of the issuer of client_2.pem
-unsigned char kAuthority2DN[] = {
- 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
- 0x04, 0x45, 0x20, 0x43, 0x41
-};
-
-} // namespace
-
-class ClientCertStoreImplTest : public ::testing::Test {
- protected:
- bool SelectClientCerts(const CertificateList& input_certs,
- const SSLCertRequestInfo& cert_request_info,
- CertificateList* selected_certs) {
- return store_.SelectClientCertsForTesting(
- input_certs, cert_request_info, selected_certs);
- }
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- bool SelectClientCertsGivenPreferred(
- const scoped_refptr<X509Certificate>& preferred_cert,
- const CertificateList& regular_certs,
- const SSLCertRequestInfo& request,
- CertificateList* selected_certs) {
- return store_.SelectClientCertsGivenPreferredForTesting(
- preferred_cert, regular_certs, request, selected_certs);
- }
-#endif
-
- private:
- ClientCertStoreImpl store_;
-};
-
-TEST_F(ClientCertStoreImplTest, EmptyQuery) {
- std::vector<scoped_refptr<X509Certificate> > certs;
- scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
-
- std::vector<scoped_refptr<X509Certificate> > selected_certs;
- bool rv = SelectClientCerts(certs, *request.get(), &selected_certs);
- EXPECT_TRUE(rv);
- EXPECT_EQ(0u, selected_certs.size());
-}
-
-// Verify that CertRequestInfo with empty |cert_authorities| matches all
-// issuers, rather than no issuers.
-TEST_F(ClientCertStoreImplTest, AllIssuersAllowed) {
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
- ASSERT_TRUE(cert.get());
-
- std::vector<scoped_refptr<X509Certificate> > certs;
- certs.push_back(cert);
- scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
-
- std::vector<scoped_refptr<X509Certificate> > selected_certs;
- bool rv = SelectClientCerts(certs, *request.get(), &selected_certs);
- EXPECT_TRUE(rv);
- ASSERT_EQ(1u, selected_certs.size());
- EXPECT_TRUE(selected_certs[0]->Equals(cert.get()));
-}
-
-// Verify that certificates are correctly filtered against CertRequestInfo with
-// |cert_authorities| containing only |authority_1_DN|.
-TEST_F(ClientCertStoreImplTest, CertAuthorityFiltering) {
- scoped_refptr<X509Certificate> cert_1(
- ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
- ASSERT_TRUE(cert_1.get());
- scoped_refptr<X509Certificate> cert_2(
- ImportCertFromFile(GetTestCertsDirectory(), "client_2.pem"));
- ASSERT_TRUE(cert_2.get());
-
- std::vector<std::string> authority_1(
- 1, std::string(reinterpret_cast<const char*>(kAuthority1DN),
- sizeof(kAuthority1DN)));
- std::vector<std::string> authority_2(
- 1, std::string(reinterpret_cast<const char*>(kAuthority2DN),
- sizeof(kAuthority2DN)));
- EXPECT_TRUE(cert_1->IsIssuedByEncoded(authority_1));
- EXPECT_FALSE(cert_1->IsIssuedByEncoded(authority_2));
- EXPECT_TRUE(cert_2->IsIssuedByEncoded(authority_2));
- EXPECT_FALSE(cert_2->IsIssuedByEncoded(authority_1));
-
- std::vector<scoped_refptr<X509Certificate> > certs;
- certs.push_back(cert_1);
- certs.push_back(cert_2);
- scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
- request->cert_authorities = authority_1;
-
- std::vector<scoped_refptr<X509Certificate> > selected_certs;
- bool rv = SelectClientCerts(certs, *request.get(), &selected_certs);
- EXPECT_TRUE(rv);
- ASSERT_EQ(1u, selected_certs.size());
- EXPECT_TRUE(selected_certs[0]->Equals(cert_1.get()));
-}
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-// Verify that the preferred cert gets filtered out when it doesn't match the
-// server criteria.
-TEST_F(ClientCertStoreImplTest, FilterOutThePreferredCert) {
- scoped_refptr<X509Certificate> cert_1(
- ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
- ASSERT_TRUE(cert_1.get());
-
- std::vector<std::string> authority_2(
- 1, std::string(reinterpret_cast<const char*>(kAuthority2DN),
- sizeof(kAuthority2DN)));
- EXPECT_FALSE(cert_1->IsIssuedByEncoded(authority_2));
-
- std::vector<scoped_refptr<X509Certificate> > certs;
- scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
- request->cert_authorities = authority_2;
-
- std::vector<scoped_refptr<X509Certificate> > selected_certs;
- bool rv = SelectClientCertsGivenPreferred(
- cert_1, certs, *request.get(), &selected_certs);
- EXPECT_TRUE(rv);
- EXPECT_EQ(0u, selected_certs.size());
-}
-
-// Verify that the preferred cert takes the first position in the output list,
-// when it does not get filtered out.
-TEST_F(ClientCertStoreImplTest, PreferredCertGoesFirst) {
- scoped_refptr<X509Certificate> cert_1(
- ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
- ASSERT_TRUE(cert_1.get());
- scoped_refptr<X509Certificate> cert_2(
- ImportCertFromFile(GetTestCertsDirectory(), "client_2.pem"));
- ASSERT_TRUE(cert_2.get());
-
- std::vector<scoped_refptr<X509Certificate> > certs;
- certs.push_back(cert_2);
- scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
-
- std::vector<scoped_refptr<X509Certificate> > selected_certs;
- bool rv = SelectClientCertsGivenPreferred(
- cert_1, certs, *request.get(), &selected_certs);
- EXPECT_TRUE(rv);
- ASSERT_EQ(2u, selected_certs.size());
- EXPECT_TRUE(selected_certs[0]->Equals(cert_1.get()));
- EXPECT_TRUE(selected_certs[1]->Equals(cert_2.get()));
-}
-#endif
-
-} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_impl_mac.cc b/chromium/net/ssl/client_cert_store_mac.cc
index 33457358f1e..746d1230632 100644
--- a/chromium/net/ssl/client_cert_store_impl_mac.cc
+++ b/chromium/net/ssl/client_cert_store_mac.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/ssl/client_cert_store_impl.h"
+#include "net/ssl/client_cert_store_mac.h"
#include <CommonCrypto/CommonDigest.h>
#include <CoreFoundation/CFArray.h>
@@ -13,6 +13,7 @@
#include <algorithm>
#include <string>
+#include "base/callback.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h"
@@ -122,7 +123,7 @@ bool IsIssuedByInKeychain(const std::vector<std::string>& valid_issuers,
// full certificate chains. If it is false, only the the certificates and their
// intermediates (available via X509Certificate::GetIntermediateCertificates())
// will be considered.
-bool GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
+void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
const CertificateList& regular_certs,
const SSLCertRequestInfo& request,
bool query_keychain,
@@ -167,13 +168,17 @@ bool GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
++sort_begin;
}
sort(sort_begin, sort_end, x509_util::ClientCertSorter());
- return true;
}
} // namespace
-bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request,
- CertificateList* selected_certs) {
+ClientCertStoreMac::ClientCertStoreMac() {}
+
+ClientCertStoreMac::~ClientCertStoreMac() {}
+
+void ClientCertStoreMac::GetClientCerts(const SSLCertRequestInfo& request,
+ CertificateList* selected_certs,
+ const base::Closure& callback) {
std::string server_domain =
HostPortPair::FromString(request.host_and_port).host();
@@ -205,8 +210,11 @@ bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request,
base::AutoLock lock(crypto::GetMacSecurityServicesLock());
err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
}
- if (err)
- return false;
+ if (err) {
+ selected_certs->clear();
+ callback.Run();
+ return;
+ }
ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
while (!err) {
SecIdentityRef identity = NULL;
@@ -239,30 +247,32 @@ bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request,
if (err != errSecItemNotFound) {
OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error";
- return false;
+ selected_certs->clear();
+ callback.Run();
+ return;
}
- return GetClientCertsImpl(preferred_cert, regular_certs, request, true,
- selected_certs);
+ GetClientCertsImpl(preferred_cert, regular_certs, request, true,
+ selected_certs);
+ callback.Run();
}
-bool ClientCertStoreImpl::SelectClientCertsForTesting(
+bool ClientCertStoreMac::SelectClientCertsForTesting(
const CertificateList& input_certs,
const SSLCertRequestInfo& request,
CertificateList* selected_certs) {
- return GetClientCertsImpl(NULL, input_certs, request, false,
- selected_certs);
+ GetClientCertsImpl(NULL, input_certs, request, false, selected_certs);
+ return true;
}
-#if !defined(OS_IOS)
-bool ClientCertStoreImpl::SelectClientCertsGivenPreferredForTesting(
+bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting(
const scoped_refptr<X509Certificate>& preferred_cert,
const CertificateList& regular_certs,
const SSLCertRequestInfo& request,
CertificateList* selected_certs) {
- return GetClientCertsImpl(preferred_cert, regular_certs, request, false,
- selected_certs);
+ GetClientCertsImpl(
+ preferred_cert, regular_certs, request, false, selected_certs);
+ return true;
}
-#endif
} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_impl.h b/chromium/net/ssl/client_cert_store_mac.h
index e02cd1c7935..b3f7ef34cc4 100644
--- a/chromium/net/ssl/client_cert_store_impl.h
+++ b/chromium/net/ssl/client_cert_store_mac.h
@@ -1,11 +1,12 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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_SSL_CLIENT_CERT_STORE_IMPL_H_
-#define NET_SSL_CLIENT_CERT_STORE_IMPL_H_
+#ifndef NET_SSL_CLIENT_CERT_STORE_MAC_H_
+#define NET_SSL_CLIENT_CERT_STORE_MAC_H_
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "net/base/net_export.h"
#include "net/ssl/client_cert_store.h"
@@ -13,31 +14,29 @@
namespace net {
-class NET_EXPORT ClientCertStoreImpl : public ClientCertStore {
+class NET_EXPORT ClientCertStoreMac : public ClientCertStore {
public:
- ClientCertStoreImpl() {}
- virtual ~ClientCertStoreImpl() {}
+ ClientCertStoreMac();
+ virtual ~ClientCertStoreMac();
// ClientCertStore:
- virtual bool GetClientCerts(const SSLCertRequestInfo& cert_request_info,
- CertificateList* selected_certs) OVERRIDE;
+ virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs,
+ const base::Closure& callback) OVERRIDE;
private:
- friend class ClientCertStoreImplTest;
+ friend class ClientCertStoreMacTest;
+ friend class ClientCertStoreMacTestDelegate;
// A hook for testing. Filters |input_certs| using the logic being used to
- // filter the system store when GetClientCerts() is called. Depending on the
- // implementation, this might be:
- // - Implemented by creating a temporary in-memory store and filtering it
- // using the common logic (preferable, currently on Windows).
- // - Implemented by creating a list of certificates that otherwise would be
+ // filter the system store when GetClientCerts() is called.
+ // Implemented by creating a list of certificates that otherwise would be
// extracted from the system store and filtering it using the common logic
- // (less adequate, currently on NSS and Mac).
+ // (less adequate than the approach used on Windows).
bool SelectClientCertsForTesting(const CertificateList& input_certs,
const SSLCertRequestInfo& cert_request_info,
CertificateList* selected_certs);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
// Testing hook specific to Mac, where the internal logic recognizes preferred
// certificates for particular domains. If the preferred certificate is
// present in the output list (i.e. it doesn't get filtered out), it should
@@ -47,11 +46,10 @@ class NET_EXPORT ClientCertStoreImpl : public ClientCertStore {
const CertificateList& regular_certs,
const SSLCertRequestInfo& request,
CertificateList* selected_certs);
-#endif
- DISALLOW_COPY_AND_ASSIGN(ClientCertStoreImpl);
+ DISALLOW_COPY_AND_ASSIGN(ClientCertStoreMac);
};
} // namespace net
-#endif // NET_SSL_CLIENT_CERT_STORE_IMPL_H_
+#endif // NET_SSL_CLIENT_CERT_STORE_MAC_H_
diff --git a/chromium/net/ssl/client_cert_store_mac_unittest.cc b/chromium/net/ssl/client_cert_store_mac_unittest.cc
new file mode 100644
index 00000000000..6dc9279950a
--- /dev/null
+++ b/chromium/net/ssl/client_cert_store_mac_unittest.cc
@@ -0,0 +1,89 @@
+// 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/ssl/client_cert_store_mac.h"
+
+#include "net/ssl/client_cert_store_unittest-inl.h"
+
+namespace net {
+
+class ClientCertStoreMacTestDelegate {
+ public:
+ bool SelectClientCerts(const CertificateList& input_certs,
+ const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs) {
+ return store_.SelectClientCertsForTesting(
+ input_certs, cert_request_info, selected_certs);
+ }
+
+ private:
+ ClientCertStoreMac store_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(Mac,
+ ClientCertStoreTest,
+ ClientCertStoreMacTestDelegate);
+
+class ClientCertStoreMacTest : public ::testing::Test {
+ protected:
+ bool SelectClientCertsGivenPreferred(
+ const scoped_refptr<X509Certificate>& preferred_cert,
+ const CertificateList& regular_certs,
+ const SSLCertRequestInfo& request,
+ CertificateList* selected_certs) {
+ return store_.SelectClientCertsGivenPreferredForTesting(
+ preferred_cert, regular_certs, request, selected_certs);
+ }
+
+ private:
+ ClientCertStoreMac store_;
+};
+
+// Verify that the preferred cert gets filtered out when it doesn't match the
+// server criteria.
+TEST_F(ClientCertStoreMacTest, FilterOutThePreferredCert) {
+ scoped_refptr<X509Certificate> cert_1(
+ ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
+ ASSERT_TRUE(cert_1.get());
+
+ std::vector<std::string> authority_2(
+ 1, std::string(reinterpret_cast<const char*>(kAuthority2DN),
+ sizeof(kAuthority2DN)));
+ EXPECT_FALSE(cert_1->IsIssuedByEncoded(authority_2));
+
+ std::vector<scoped_refptr<X509Certificate> > certs;
+ scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
+ request->cert_authorities = authority_2;
+
+ std::vector<scoped_refptr<X509Certificate> > selected_certs;
+ bool rv = SelectClientCertsGivenPreferred(
+ cert_1, certs, *request.get(), &selected_certs);
+ EXPECT_TRUE(rv);
+ EXPECT_EQ(0u, selected_certs.size());
+}
+
+// Verify that the preferred cert takes the first position in the output list,
+// when it does not get filtered out.
+TEST_F(ClientCertStoreMacTest, PreferredCertGoesFirst) {
+ scoped_refptr<X509Certificate> cert_1(
+ ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
+ ASSERT_TRUE(cert_1.get());
+ scoped_refptr<X509Certificate> cert_2(
+ ImportCertFromFile(GetTestCertsDirectory(), "client_2.pem"));
+ ASSERT_TRUE(cert_2.get());
+
+ std::vector<scoped_refptr<X509Certificate> > certs;
+ certs.push_back(cert_2);
+ scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
+
+ std::vector<scoped_refptr<X509Certificate> > selected_certs;
+ bool rv = SelectClientCertsGivenPreferred(
+ cert_1, certs, *request.get(), &selected_certs);
+ EXPECT_TRUE(rv);
+ ASSERT_EQ(2u, selected_certs.size());
+ EXPECT_TRUE(selected_certs[0]->Equals(cert_1.get()));
+ EXPECT_TRUE(selected_certs[1]->Equals(cert_2.get()));
+}
+
+} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_impl_nss.cc b/chromium/net/ssl/client_cert_store_nss.cc
index ffab2680c68..9df561271c7 100644
--- a/chromium/net/ssl/client_cert_store_impl_nss.cc
+++ b/chromium/net/ssl/client_cert_store_nss.cc
@@ -1,13 +1,18 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/ssl/client_cert_store_impl.h"
+#include "net/ssl/client_cert_store_nss.h"
#include <nss.h>
#include <ssl.h>
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/worker_pool.h"
+#include "crypto/nss_crypto_module_delegate.h"
#include "net/cert/x509_util.h"
namespace net {
@@ -19,7 +24,7 @@ namespace {
// certificates in |selected_certs|.
// If |query_nssdb| is true, NSS will be queried to construct full certificate
// chains. If it is false, only the certificate will be considered.
-bool GetClientCertsImpl(CERTCertList* cert_list,
+void GetClientCertsImpl(CERTCertList* cert_list,
const SSLCertRequestInfo& request,
bool query_nssdb,
CertificateList* selected_certs) {
@@ -72,26 +77,58 @@ bool GetClientCertsImpl(CERTCertList* cert_list,
std::sort(selected_certs->begin(), selected_certs->end(),
x509_util::ClientCertSorter());
- return true;
}
-} // namespace
-
-bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request,
- CertificateList* selected_certs) {
+void GetClientCertsOnWorkerThread(
+ scoped_ptr<crypto::CryptoModuleBlockingPasswordDelegate> password_delegate,
+ const SSLCertRequestInfo* request,
+ CertificateList* selected_certs) {
CERTCertList* client_certs = CERT_FindUserCertsByUsage(
- CERT_GetDefaultCertDB(), certUsageSSLClient,
- PR_FALSE, PR_FALSE, NULL);
+ CERT_GetDefaultCertDB(),
+ certUsageSSLClient,
+ PR_FALSE,
+ PR_FALSE,
+ password_delegate.get());
// It is ok for a user not to have any client certs.
- if (!client_certs)
- return true;
+ if (!client_certs) {
+ selected_certs->clear();
+ return;
+ }
- bool rv = GetClientCertsImpl(client_certs, request, true, selected_certs);
+ GetClientCertsImpl(client_certs, *request, true, selected_certs);
CERT_DestroyCertList(client_certs);
- return rv;
}
-bool ClientCertStoreImpl::SelectClientCertsForTesting(
+} // namespace
+
+ClientCertStoreNSS::ClientCertStoreNSS(
+ const PasswordDelegateFactory& password_delegate_factory)
+ : password_delegate_factory_(password_delegate_factory) {}
+
+ClientCertStoreNSS::~ClientCertStoreNSS() {}
+
+void ClientCertStoreNSS::GetClientCerts(const SSLCertRequestInfo& request,
+ CertificateList* selected_certs,
+ const base::Closure& callback) {
+ scoped_ptr<crypto::CryptoModuleBlockingPasswordDelegate> password_delegate;
+ if (!password_delegate_factory_.is_null()) {
+ password_delegate.reset(
+ password_delegate_factory_.Run(request.host_and_port));
+ }
+ if (!base::WorkerPool::PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&GetClientCertsOnWorkerThread,
+ base::Passed(&password_delegate),
+ &request,
+ selected_certs),
+ callback,
+ true)) {
+ selected_certs->clear();
+ callback.Run();
+ }
+}
+
+bool ClientCertStoreNSS::SelectClientCertsForTesting(
const CertificateList& input_certs,
const SSLCertRequestInfo& request,
CertificateList* selected_certs) {
@@ -103,9 +140,9 @@ bool ClientCertStoreImpl::SelectClientCertsForTesting(
cert_list, CERT_DupCertificate(input_certs[i]->os_cert_handle()));
}
- bool rv = GetClientCertsImpl(cert_list, request, false, selected_certs);
+ GetClientCertsImpl(cert_list, request, false, selected_certs);
CERT_DestroyCertList(cert_list);
- return rv;
+ return true;
}
} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_nss.h b/chromium/net/ssl/client_cert_store_nss.h
new file mode 100644
index 00000000000..53b7c608031
--- /dev/null
+++ b/chromium/net/ssl/client_cert_store_nss.h
@@ -0,0 +1,56 @@
+// 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_SSL_CLIENT_CERT_STORE_NSS_H_
+#define NET_SSL_CLIENT_CERT_STORE_NSS_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "net/base/net_export.h"
+#include "net/ssl/client_cert_store.h"
+#include "net/ssl/ssl_cert_request_info.h"
+
+namespace crypto {
+class CryptoModuleBlockingPasswordDelegate;
+}
+
+namespace net {
+
+class NET_EXPORT ClientCertStoreNSS : public ClientCertStore {
+ public:
+ typedef base::Callback<crypto::CryptoModuleBlockingPasswordDelegate*(
+ const std::string& /* server */)> PasswordDelegateFactory;
+
+ explicit ClientCertStoreNSS(
+ const PasswordDelegateFactory& password_delegate_factory);
+ virtual ~ClientCertStoreNSS();
+
+ // ClientCertStore:
+ virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs,
+ const base::Closure& callback) OVERRIDE;
+
+ private:
+ friend class ClientCertStoreNSSTestDelegate;
+
+ // A hook for testing. Filters |input_certs| using the logic being used to
+ // filter the system store when GetClientCerts() is called.
+ // Implemented by creating a list of certificates that otherwise would be
+ // extracted from the system store and filtering it using the common logic
+ // (less adequate than the approach used on Windows).
+ bool SelectClientCertsForTesting(const CertificateList& input_certs,
+ const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs);
+
+ // The factory for creating the delegate for requesting a password to a
+ // PKCS #11 token. May be null.
+ PasswordDelegateFactory password_delegate_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ClientCertStoreNSS);
+};
+
+} // namespace net
+
+#endif // NET_SSL_CLIENT_CERT_STORE_NSS_H_
diff --git a/chromium/net/ssl/client_cert_store_nss_unittest.cc b/chromium/net/ssl/client_cert_store_nss_unittest.cc
new file mode 100644
index 00000000000..6690e674966
--- /dev/null
+++ b/chromium/net/ssl/client_cert_store_nss_unittest.cc
@@ -0,0 +1,31 @@
+// 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/ssl/client_cert_store_nss.h"
+
+#include "net/ssl/client_cert_store_unittest-inl.h"
+
+namespace net {
+
+class ClientCertStoreNSSTestDelegate {
+ public:
+ ClientCertStoreNSSTestDelegate()
+ : store_(ClientCertStoreNSS::PasswordDelegateFactory()) {}
+
+ bool SelectClientCerts(const CertificateList& input_certs,
+ const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs) {
+ return store_.SelectClientCertsForTesting(
+ input_certs, cert_request_info, selected_certs);
+ }
+
+ private:
+ ClientCertStoreNSS store_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(NSS,
+ ClientCertStoreTest,
+ ClientCertStoreNSSTestDelegate);
+
+} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_unittest-inl.h b/chromium/net/ssl/client_cert_store_unittest-inl.h
new file mode 100644
index 00000000000..a0e29dc83b5
--- /dev/null
+++ b/chromium/net/ssl/client_cert_store_unittest-inl.h
@@ -0,0 +1,128 @@
+// 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_SSL_CLIENT_CERT_STORE_UNITTEST_INL_H_
+#define NET_SSL_CLIENT_CERT_STORE_UNITTEST_INL_H_
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/test_data_directory.h"
+#include "net/test/cert_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+// "CN=B CA" - DER encoded DN of the issuer of client_1.pem
+const unsigned char kAuthority1DN[] = {
+ 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x04, 0x42, 0x20, 0x43, 0x41
+};
+
+// "CN=E CA" - DER encoded DN of the issuer of client_2.pem
+unsigned char kAuthority2DN[] = {
+ 0x30, 0x0f, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x04, 0x45, 0x20, 0x43, 0x41
+};
+
+} // namespace
+
+// Use a templated test to provide common testcases for all the platform
+// implementations of ClientCertStore. These cases test the client cert
+// filtering behavior.
+//
+// NOTE: If any test cases are added, removed, or renamed, the
+// REGISTER_TYPED_TEST_CASE_P macro at the bottom of this file must be updated.
+//
+// The type T provided as the third argument to INSTANTIATE_TYPED_TEST_CASE_P by
+// the platform implementation should implement this method:
+// bool SelectClientCerts(const CertificateList& input_certs,
+// const SSLCertRequestInfo& cert_request_info,
+// CertificateList* selected_certs);
+template <typename T>
+class ClientCertStoreTest : public ::testing::Test {
+ public:
+ T delegate_;
+};
+
+TYPED_TEST_CASE_P(ClientCertStoreTest);
+
+TYPED_TEST_P(ClientCertStoreTest, EmptyQuery) {
+ std::vector<scoped_refptr<X509Certificate> > certs;
+ scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
+
+ std::vector<scoped_refptr<X509Certificate> > selected_certs;
+ bool rv = this->delegate_.SelectClientCerts(
+ certs, *request.get(), &selected_certs);
+ EXPECT_TRUE(rv);
+ EXPECT_EQ(0u, selected_certs.size());
+}
+
+// Verify that CertRequestInfo with empty |cert_authorities| matches all
+// issuers, rather than no issuers.
+TYPED_TEST_P(ClientCertStoreTest, AllIssuersAllowed) {
+ scoped_refptr<X509Certificate> cert(
+ ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
+ ASSERT_TRUE(cert.get());
+
+ std::vector<scoped_refptr<X509Certificate> > certs;
+ certs.push_back(cert);
+ scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
+
+ std::vector<scoped_refptr<X509Certificate> > selected_certs;
+ bool rv = this->delegate_.SelectClientCerts(
+ certs, *request.get(), &selected_certs);
+ EXPECT_TRUE(rv);
+ ASSERT_EQ(1u, selected_certs.size());
+ EXPECT_TRUE(selected_certs[0]->Equals(cert.get()));
+}
+
+// Verify that certificates are correctly filtered against CertRequestInfo with
+// |cert_authorities| containing only |authority_1_DN|.
+TYPED_TEST_P(ClientCertStoreTest, CertAuthorityFiltering) {
+ scoped_refptr<X509Certificate> cert_1(
+ ImportCertFromFile(GetTestCertsDirectory(), "client_1.pem"));
+ ASSERT_TRUE(cert_1.get());
+ scoped_refptr<X509Certificate> cert_2(
+ ImportCertFromFile(GetTestCertsDirectory(), "client_2.pem"));
+ ASSERT_TRUE(cert_2.get());
+
+ std::vector<std::string> authority_1(
+ 1, std::string(reinterpret_cast<const char*>(kAuthority1DN),
+ sizeof(kAuthority1DN)));
+ std::vector<std::string> authority_2(
+ 1, std::string(reinterpret_cast<const char*>(kAuthority2DN),
+ sizeof(kAuthority2DN)));
+ EXPECT_TRUE(cert_1->IsIssuedByEncoded(authority_1));
+ EXPECT_FALSE(cert_1->IsIssuedByEncoded(authority_2));
+ EXPECT_TRUE(cert_2->IsIssuedByEncoded(authority_2));
+ EXPECT_FALSE(cert_2->IsIssuedByEncoded(authority_1));
+
+ std::vector<scoped_refptr<X509Certificate> > certs;
+ certs.push_back(cert_1);
+ certs.push_back(cert_2);
+ scoped_refptr<SSLCertRequestInfo> request(new SSLCertRequestInfo());
+ request->cert_authorities = authority_1;
+
+ std::vector<scoped_refptr<X509Certificate> > selected_certs;
+ bool rv = this->delegate_.SelectClientCerts(
+ certs, *request.get(), &selected_certs);
+ EXPECT_TRUE(rv);
+ ASSERT_EQ(1u, selected_certs.size());
+ EXPECT_TRUE(selected_certs[0]->Equals(cert_1.get()));
+}
+
+REGISTER_TYPED_TEST_CASE_P(ClientCertStoreTest,
+ EmptyQuery,
+ AllIssuersAllowed,
+ CertAuthorityFiltering);
+
+} // namespace net
+
+#endif // NET_SSL_CLIENT_CERT_STORE_UNITTEST_INL_H_
diff --git a/chromium/net/ssl/client_cert_store_impl_win.cc b/chromium/net/ssl/client_cert_store_win.cc
index 63ea6e4a875..24ae1aa6d51 100644
--- a/chromium/net/ssl/client_cert_store_impl_win.cc
+++ b/chromium/net/ssl/client_cert_store_win.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// 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/ssl/client_cert_store_impl.h"
+#include "net/ssl/client_cert_store_win.h"
#include <algorithm>
#include <string>
@@ -12,6 +12,7 @@
#include <wincrypt.h>
#include <security.h>
+#include "base/callback.h"
#include "base/logging.h"
#include "crypto/scoped_capi_types.h"
#include "net/cert/x509_util.h"
@@ -63,7 +64,7 @@ static BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
return TRUE;
}
-bool GetClientCertsImpl(HCERTSTORE cert_store,
+void GetClientCertsImpl(HCERTSTORE cert_store,
const SSLCertRequestInfo& request,
CertificateList* selected_certs) {
selected_certs->clear();
@@ -138,29 +139,33 @@ bool GetClientCertsImpl(HCERTSTORE cert_store,
std::sort(selected_certs->begin(), selected_certs->end(),
x509_util::ClientCertSorter());
- return true;
}
} // namespace
-bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request,
- CertificateList* selected_certs) {
+ClientCertStoreWin::ClientCertStoreWin() {}
+
+ClientCertStoreWin::~ClientCertStoreWin() {}
+
+void ClientCertStoreWin::GetClientCerts(const SSLCertRequestInfo& request,
+ CertificateList* selected_certs,
+ const base::Closure& callback) {
// Client certificates of the user are in the "MY" system certificate store.
HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY");
if (!my_cert_store) {
PLOG(ERROR) << "Could not open the \"MY\" system certificate store: ";
- return false;
+ selected_certs->clear();
+ callback.Run();
+ return;
}
- bool rv = GetClientCertsImpl(my_cert_store, request, selected_certs);
- if (!CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG)) {
+ GetClientCertsImpl(my_cert_store, request, selected_certs);
+ if (!CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG))
PLOG(ERROR) << "Could not close the \"MY\" system certificate store: ";
- return false;
- }
- return rv;
+ callback.Run();
}
-bool ClientCertStoreImpl::SelectClientCertsForTesting(
+bool ClientCertStoreWin::SelectClientCertsForTesting(
const CertificateList& input_certs,
const SSLCertRequestInfo& request,
CertificateList* selected_certs) {
@@ -198,8 +203,8 @@ bool ClientCertStoreImpl::SelectClientCertsForTesting(
return false;
}
- bool rv = GetClientCertsImpl(test_store.get(), request, selected_certs);
- return rv;
+ GetClientCertsImpl(test_store.get(), request, selected_certs);
+ return true;
}
} // namespace net
diff --git a/chromium/net/ssl/client_cert_store_win.h b/chromium/net/ssl/client_cert_store_win.h
new file mode 100644
index 00000000000..785603dc1e2
--- /dev/null
+++ b/chromium/net/ssl/client_cert_store_win.h
@@ -0,0 +1,43 @@
+// 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_SSL_CLIENT_CERT_STORE_WIN_H_
+#define NET_SSL_CLIENT_CERT_STORE_WIN_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/gtest_prod_util.h"
+#include "net/base/net_export.h"
+#include "net/ssl/client_cert_store.h"
+#include "net/ssl/ssl_cert_request_info.h"
+
+namespace net {
+
+class NET_EXPORT ClientCertStoreWin : public ClientCertStore {
+ public:
+ ClientCertStoreWin();
+ virtual ~ClientCertStoreWin();
+
+ // ClientCertStore:
+ virtual void GetClientCerts(const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs,
+ const base::Closure& callback) OVERRIDE;
+
+ private:
+ friend class ClientCertStoreWinTestDelegate;
+
+ // A hook for testing. Filters |input_certs| using the logic being used to
+ // filter the system store when GetClientCerts() is called.
+ // Implemented by creating a temporary in-memory store and filtering it
+ // using the common logic.
+ bool SelectClientCertsForTesting(const CertificateList& input_certs,
+ const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs);
+
+ DISALLOW_COPY_AND_ASSIGN(ClientCertStoreWin);
+};
+
+} // namespace net
+
+#endif // NET_SSL_CLIENT_CERT_STORE_WIN_H_
diff --git a/chromium/net/ssl/client_cert_store_win_unittest.cc b/chromium/net/ssl/client_cert_store_win_unittest.cc
new file mode 100644
index 00000000000..eb8c0a66698
--- /dev/null
+++ b/chromium/net/ssl/client_cert_store_win_unittest.cc
@@ -0,0 +1,28 @@
+// 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/ssl/client_cert_store_win.h"
+
+#include "net/ssl/client_cert_store_unittest-inl.h"
+
+namespace net {
+
+class ClientCertStoreWinTestDelegate {
+ public:
+ bool SelectClientCerts(const CertificateList& input_certs,
+ const SSLCertRequestInfo& cert_request_info,
+ CertificateList* selected_certs) {
+ return store_.SelectClientCertsForTesting(
+ input_certs, cert_request_info, selected_certs);
+ }
+
+ private:
+ ClientCertStoreWin store_;
+};
+
+INSTANTIATE_TYPED_TEST_CASE_P(Win,
+ ClientCertStoreTest,
+ ClientCertStoreWinTestDelegate);
+
+} // namespace net
diff --git a/chromium/net/ssl/default_server_bound_cert_store_unittest.cc b/chromium/net/ssl/default_server_bound_cert_store_unittest.cc
index c3f8452fa9a..a742e0c3f1c 100644
--- a/chromium/net/ssl/default_server_bound_cert_store_unittest.cc
+++ b/chromium/net/ssl/default_server_bound_cert_store_unittest.cc
@@ -24,10 +24,6 @@ void CallCounter(int* counter) {
(*counter)++;
}
-void NotCalled() {
- ADD_FAILURE() << "Unexpected callback execution.";
-}
-
void GetCertCallbackNotCalled(int err,
const std::string& server_identifier,
base::Time expiration_time,
diff --git a/chromium/net/ssl/server_bound_cert_service.cc b/chromium/net/ssl/server_bound_cert_service.cc
index 2bbcbc79e6b..61d610b5bb6 100644
--- a/chromium/net/ssl/server_bound_cert_service.cc
+++ b/chromium/net/ssl/server_bound_cert_service.cc
@@ -35,7 +35,6 @@ namespace net {
namespace {
-const int kKeySizeInBits = 1024;
const int kValidityPeriodInDays = 365;
// When we check the system time, we add this many days to the end of the check
// so the result will still hold even after chrome has been running for a
@@ -99,15 +98,13 @@ scoped_ptr<ServerBoundCertStore::ServerBoundCert> GenerateCert(
not_valid_before + base::TimeDelta::FromDays(kValidityPeriodInDays);
std::string der_cert;
std::vector<uint8> private_key_info;
- scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create());
- if (!key.get()) {
- DLOG(ERROR) << "Unable to create key pair for client";
- *error = ERR_KEY_GENERATION_FAILED;
- return result.Pass();
- }
- if (!x509_util::CreateDomainBoundCertEC(key.get(), server_identifier,
- serial_number, not_valid_before,
- not_valid_after, &der_cert)) {
+ scoped_ptr<crypto::ECPrivateKey> key;
+ if (!x509_util::CreateKeyAndDomainBoundCertEC(server_identifier,
+ serial_number,
+ not_valid_before,
+ not_valid_after,
+ &key,
+ &der_cert)) {
DLOG(ERROR) << "Unable to create x509 cert for client";
*error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED;
return result.Pass();
@@ -372,11 +369,11 @@ ServerBoundCertService::ServerBoundCertService(
const scoped_refptr<base::TaskRunner>& task_runner)
: server_bound_cert_store_(server_bound_cert_store),
task_runner_(task_runner),
- weak_ptr_factory_(this),
requests_(0),
cert_store_hits_(0),
inflight_joins_(0),
- workers_created_(0) {
+ workers_created_(0),
+ weak_ptr_factory_(this) {
base::Time start = base::Time::Now();
base::Time end = start + base::TimeDelta::FromDays(
kValidityPeriodInDays + kSystemTimeValidityBufferInDays);
diff --git a/chromium/net/ssl/server_bound_cert_service.h b/chromium/net/ssl/server_bound_cert_service.h
index 0dc7f4ae390..45472102ff6 100644
--- a/chromium/net/ssl/server_bound_cert_service.h
+++ b/chromium/net/ssl/server_bound_cert_service.h
@@ -197,7 +197,6 @@ class NET_EXPORT ServerBoundCertService
// inflight_ maps from a server to an active generation which is taking
// place.
std::map<std::string, ServerBoundCertServiceJob*> inflight_;
- base::WeakPtrFactory<ServerBoundCertService> weak_ptr_factory_;
uint64 requests_;
uint64 cert_store_hits_;
@@ -206,6 +205,8 @@ class NET_EXPORT ServerBoundCertService
bool is_system_time_valid_;
+ base::WeakPtrFactory<ServerBoundCertService> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ServerBoundCertService);
};
diff --git a/chromium/net/ssl/server_bound_cert_service_unittest.cc b/chromium/net/ssl/server_bound_cert_service_unittest.cc
index fc25b0b9322..4df003913aa 100644
--- a/chromium/net/ssl/server_bound_cert_service_unittest.cc
+++ b/chromium/net/ssl/server_bound_cert_service_unittest.cc
@@ -24,6 +24,7 @@ namespace net {
namespace {
+#if !defined(USE_OPENSSL)
void FailTest(int /* result */) {
FAIL();
}
@@ -50,18 +51,6 @@ class FailingTaskRunner : public base::TaskRunner {
DISALLOW_COPY_AND_ASSIGN(FailingTaskRunner);
};
-class ServerBoundCertServiceTest : public testing::Test {
- public:
- ServerBoundCertServiceTest()
- : service_(new ServerBoundCertService(
- new DefaultServerBoundCertStore(NULL),
- base::MessageLoopProxy::current())) {
- }
-
- protected:
- scoped_ptr<ServerBoundCertService> service_;
-};
-
class MockServerBoundCertStoreWithAsyncGet
: public DefaultServerBoundCertStore {
public:
@@ -128,6 +117,20 @@ MockServerBoundCertStoreWithAsyncGet::CallGetServerBoundCertCallbackWithResult(
cert));
}
+#endif // !defined(USE_OPENSSL)
+
+class ServerBoundCertServiceTest : public testing::Test {
+ public:
+ ServerBoundCertServiceTest()
+ : service_(new ServerBoundCertService(
+ new DefaultServerBoundCertStore(NULL),
+ base::MessageLoopProxy::current())) {
+ }
+
+ protected:
+ scoped_ptr<ServerBoundCertService> service_;
+};
+
TEST_F(ServerBoundCertServiceTest, GetDomainForHost) {
EXPECT_EQ("google.com",
ServerBoundCertService::GetDomainForHost("google.com"));
diff --git a/chromium/net/ssl/signed_certificate_timestamp_and_status.cc b/chromium/net/ssl/signed_certificate_timestamp_and_status.cc
new file mode 100644
index 00000000000..2808fec3e4d
--- /dev/null
+++ b/chromium/net/ssl/signed_certificate_timestamp_and_status.cc
@@ -0,0 +1,18 @@
+// 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/ssl/signed_certificate_timestamp_and_status.h"
+
+#include "net/cert/signed_certificate_timestamp.h"
+
+namespace net {
+
+SignedCertificateTimestampAndStatus::SignedCertificateTimestampAndStatus(
+ const scoped_refptr<ct::SignedCertificateTimestamp>& sct,
+ const ct::SCTVerifyStatus status)
+ : sct_(sct), status_(status) {}
+
+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
new file mode 100644
index 00000000000..042c7ac41ab
--- /dev/null
+++ b/chromium/net/ssl/signed_certificate_timestamp_and_status.h
@@ -0,0 +1,35 @@
+// 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_SSL_SIGNED_CERTIFICATE_TIMESTAMP_AND_STATUS_H_
+#define NET_SSL_SIGNED_CERTIFICATE_TIMESTAMP_AND_STATUS_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "net/cert/sct_status_flags.h"
+
+namespace net {
+
+namespace ct {
+struct SignedCertificateTimestamp;
+}
+
+struct SignedCertificateTimestampAndStatus {
+ SignedCertificateTimestampAndStatus(
+ const scoped_refptr<ct::SignedCertificateTimestamp>& sct,
+ ct::SCTVerifyStatus status);
+
+ ~SignedCertificateTimestampAndStatus();
+
+ scoped_refptr<ct::SignedCertificateTimestamp> sct_;
+ ct::SCTVerifyStatus status_;
+};
+
+typedef std::vector<SignedCertificateTimestampAndStatus>
+ SignedCertificateTimestampAndStatusList;
+
+} // namespace net
+
+#endif // NET_SSL_SIGNED_CERTIFICATE_TIMESTAMP_AND_STATUS_H_
diff --git a/chromium/net/ssl/ssl_cipher_suite_names.cc b/chromium/net/ssl/ssl_cipher_suite_names.cc
index f9394dfd68c..8204fc154d5 100644
--- a/chromium/net/ssl/ssl_cipher_suite_names.cc
+++ b/chromium/net/ssl/ssl_cipher_suite_names.cc
@@ -195,7 +195,7 @@ static const struct CipherSuite kCipherSuites[] = {
{0xc08c, 0xf7f}, // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
{0xc08d, 0xf87}, // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
{0xcc13, 0x108f}, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- {0xcc14, 0x0d8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
+ {0xcc14, 0x0e8f}, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
};
static const struct {
diff --git a/chromium/net/ssl/ssl_config_service.cc b/chromium/net/ssl/ssl_config_service.cc
index a2c34a26852..a28c46d97d7 100644
--- a/chromium/net/ssl/ssl_config_service.cc
+++ b/chromium/net/ssl/ssl_config_service.cc
@@ -43,6 +43,8 @@ SSLConfig::SSLConfig()
cached_info_enabled(false),
channel_id_enabled(true),
false_start_enabled(true),
+ signed_cert_timestamps_enabled(true),
+ require_forward_secrecy(false),
unrestricted_ssl3_fallback_enabled(false),
send_client_cert(false),
verify_ev_cert(false),
@@ -163,6 +165,8 @@ void SSLConfigService::ProcessConfigUpdate(const SSLConfig& orig_config,
new_config.disabled_cipher_suites) ||
(orig_config.channel_id_enabled != new_config.channel_id_enabled) ||
(orig_config.false_start_enabled != new_config.false_start_enabled) ||
+ (orig_config.require_forward_secrecy !=
+ new_config.require_forward_secrecy) ||
(orig_config.unrestricted_ssl3_fallback_enabled !=
new_config.unrestricted_ssl3_fallback_enabled);
diff --git a/chromium/net/ssl/ssl_config_service.h b/chromium/net/ssl/ssl_config_service.h
index a6a2bc7cbfb..0b19e301303 100644
--- a/chromium/net/ssl/ssl_config_service.h
+++ b/chromium/net/ssl/ssl_config_service.h
@@ -99,6 +99,14 @@ struct NET_EXPORT SSLConfig {
bool cached_info_enabled; // True if TLS cached info extension is enabled.
bool channel_id_enabled; // True if TLS channel ID extension is enabled.
bool false_start_enabled; // True if we'll use TLS False Start.
+ // True if the Certificate Transparency signed_certificate_timestamp
+ // TLS extension is enabled.
+ bool signed_cert_timestamps_enabled;
+
+ // require_forward_secrecy, if true, causes only (EC)DHE cipher suites to be
+ // enabled. NOTE: this only applies to server sockets currently, although
+ // that could be extended if needed.
+ bool require_forward_secrecy;
// If |unrestricted_ssl3_fallback_enabled| is true, SSL 3.0 fallback will be
// enabled for all sites.
@@ -170,6 +178,7 @@ class NET_EXPORT SSLConfigService
// disabled_cipher_suites
// channel_id_enabled
// false_start_enabled
+ // require_forward_secrecy
virtual void OnSSLConfigChanged() = 0;
protected:
diff --git a/chromium/net/ssl/ssl_info.cc b/chromium/net/ssl/ssl_info.cc
index 6c3485bac3a..77ddb62e774 100644
--- a/chromium/net/ssl/ssl_info.cc
+++ b/chromium/net/ssl/ssl_info.cc
@@ -4,7 +4,9 @@
#include "net/ssl/ssl_info.h"
+#include "base/pickle.h"
#include "net/cert/cert_status_flags.h"
+#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/x509_certificate.h"
namespace net {
@@ -30,6 +32,7 @@ SSLInfo& SSLInfo::operator=(const SSLInfo& info) {
channel_id_sent = info.channel_id_sent;
handshake_type = info.handshake_type;
public_key_hashes = info.public_key_hashes;
+ signed_certificate_timestamps = info.signed_certificate_timestamps;
return *this;
}
@@ -43,8 +46,8 @@ void SSLInfo::Reset() {
client_cert_sent = false;
channel_id_sent = false;
handshake_type = HANDSHAKE_UNKNOWN;
-
public_key_hashes.clear();
+ signed_certificate_timestamps.clear();
}
void SSLInfo::SetCertError(int error) {
diff --git a/chromium/net/ssl/ssl_info.h b/chromium/net/ssl/ssl_info.h
index 3f1dd2df4e1..00a8815c79c 100644
--- a/chromium/net/ssl/ssl_info.h
+++ b/chromium/net/ssl/ssl_info.h
@@ -10,7 +10,12 @@
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
#include "net/cert/cert_status_flags.h"
+#include "net/cert/sct_status_flags.h"
#include "net/cert/x509_cert_types.h"
+#include "net/ssl/signed_certificate_timestamp_and_status.h"
+
+class Pickle;
+class PickleIterator;
namespace net {
@@ -74,6 +79,10 @@ class NET_EXPORT SSLInfo {
// The hashes, in several algorithms, of the SubjectPublicKeyInfos from
// each certificate in the chain.
HashValueVector public_key_hashes;
+
+ // List of SignedCertificateTimestamps and their corresponding validation
+ // status.
+ SignedCertificateTimestampAndStatusList signed_certificate_timestamps;
};
} // namespace net
diff --git a/chromium/net/test/cert_test_util.cc b/chromium/net/test/cert_test_util.cc
index 5ec07749d50..3ccfa65a5ad 100644
--- a/chromium/net/test/cert_test_util.cc
+++ b/chromium/net/test/cert_test_util.cc
@@ -26,6 +26,24 @@ CertificateList CreateCertificateListFromFile(
format);
}
+scoped_refptr<X509Certificate> CreateCertificateChainFromFile(
+ const base::FilePath& certs_dir,
+ const std::string& cert_file,
+ int format) {
+ CertificateList certs = CreateCertificateListFromFile(
+ certs_dir, cert_file, format);
+ if (certs.empty())
+ return NULL;
+
+ X509Certificate::OSCertHandles intermediates;
+ for (size_t i = 1; i < certs.size(); ++i)
+ intermediates.push_back(certs[i]->os_cert_handle());
+
+ scoped_refptr<X509Certificate> result(X509Certificate::CreateFromHandle(
+ certs[0]->os_cert_handle(), intermediates));
+ return result;
+}
+
scoped_refptr<X509Certificate> ImportCertFromFile(
const base::FilePath& certs_dir,
const std::string& cert_file) {
diff --git a/chromium/net/test/cert_test_util.h b/chromium/net/test/cert_test_util.h
index d4aa4d7d325..31b768ae583 100644
--- a/chromium/net/test/cert_test_util.h
+++ b/chromium/net/test/cert_test_util.h
@@ -19,12 +19,22 @@ namespace net {
class EVRootCAMetadata;
+// Imports all of the certificates in |cert_file|, a file in |certs_dir|,
+// // into a CertificateList.
CertificateList CreateCertificateListFromFile(const base::FilePath& certs_dir,
const std::string& cert_file,
int format);
-// Imports a certificate file in the directory net::GetTestCertsDirectory()
-// returns.
+// Imports all of the certificates in |cert_file|, a file in |certs_dir|, into
+// a new X509Certificate. The first certificate in the chain will be used for
+// the returned cert, with any additional certificates configured as
+// intermediate certificates.
+scoped_refptr<X509Certificate> CreateCertificateChainFromFile(
+ const base::FilePath& certs_dir,
+ const std::string& cert_file,
+ int format);
+
+// Imports a single certificate from |cert_file|.
// |certs_dir| represents the test certificates directory. |cert_file| is the
// name of the certificate file. If cert_file contains multiple certificates,
// the first certificate found will be returned.
diff --git a/chromium/net/test/ct_test_util.cc b/chromium/net/test/ct_test_util.cc
new file mode 100644
index 00000000000..4e95e190dae
--- /dev/null
+++ b/chromium/net/test/ct_test_util.cc
@@ -0,0 +1,245 @@
+// 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/test/ct_test_util.h"
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "net/cert/ct_serialization.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+
+namespace ct {
+
+namespace {
+
+std::string HexToBytes(const char* hex_data) {
+ std::vector<uint8> output;
+ std::string result;
+ if (base::HexStringToBytes(hex_data, &output))
+ result.assign(reinterpret_cast<const char*>(&output[0]), output.size());
+ return result;
+}
+
+// The following test vectors are from
+// http://code.google.com/p/certificate-transparency
+
+const char kDefaultDerCert[] =
+ "308202ca30820233a003020102020106300d06092a864886f70d01010505003055310b3009"
+ "06035504061302474231243022060355040a131b4365727469666963617465205472616e73"
+ "706172656e6379204341310e300c0603550408130557616c65733110300e06035504071307"
+ "4572772057656e301e170d3132303630313030303030305a170d3232303630313030303030"
+ "305a3052310b30090603550406130247423121301f060355040a1318436572746966696361"
+ "7465205472616e73706172656e6379310e300c0603550408130557616c65733110300e0603"
+ "55040713074572772057656e30819f300d06092a864886f70d010101050003818d00308189"
+ "02818100b1fa37936111f8792da2081c3fe41925008531dc7f2c657bd9e1de4704160b4c9f"
+ "19d54ada4470404c1c51341b8f1f7538dddd28d9aca48369fc5646ddcc7617f8168aae5b41"
+ "d43331fca2dadfc804d57208949061f9eef902ca47ce88c644e000f06eeeccabdc9dd2f68a"
+ "22ccb09dc76e0dbc73527765b1a37a8c676253dcc10203010001a381ac3081a9301d060355"
+ "1d0e041604146a0d982a3b62c44b6d2ef4e9bb7a01aa9cb798e2307d0603551d2304763074"
+ "80145f9d880dc873e654d4f80dd8e6b0c124b447c355a159a4573055310b30090603550406"
+ "1302474231243022060355040a131b4365727469666963617465205472616e73706172656e"
+ "6379204341310e300c0603550408130557616c65733110300e060355040713074572772057"
+ "656e82010030090603551d1304023000300d06092a864886f70d010105050003818100171c"
+ "d84aac414a9a030f22aac8f688b081b2709b848b4e5511406cd707fed028597a9faefc2eee"
+ "2978d633aaac14ed3235197da87e0f71b8875f1ac9e78b281749ddedd007e3ecf50645f8cb"
+ "f667256cd6a1647b5e13203bb8582de7d6696f656d1c60b95f456b7fcf338571908f1c6972"
+ "7d24c4fccd249295795814d1dac0e6";
+
+const char kDefaultIssuerKeyHash[] =
+ "02adddca08b8bf9861f035940c940156d8350fdff899a6239c6bd77255b8f8fc";
+
+const char kDefaultDerTbsCert[] =
+ "30820233a003020102020107300d06092a864886f70d01010505003055310b300906035504"
+ "061302474231243022060355040a131b4365727469666963617465205472616e7370617265"
+ "6e6379204341310e300c0603550408130557616c65733110300e0603550407130745727720"
+ "57656e301e170d3132303630313030303030305a170d3232303630313030303030305a3052"
+ "310b30090603550406130247423121301f060355040a131843657274696669636174652054"
+ "72616e73706172656e6379310e300c0603550408130557616c65733110300e060355040713"
+ "074572772057656e30819f300d06092a864886f70d010101050003818d0030818902818100"
+ "beef98e7c26877ae385f75325a0c1d329bedf18faaf4d796bf047eb7e1ce15c95ba2f80ee4"
+ "58bd7db86f8a4b252191a79bd700c38e9c0389b45cd4dc9a120ab21e0cb41cd0e72805a410"
+ "cd9c5bdb5d4927726daf1710f60187377ea25b1a1e39eed0b88119dc154dc68f7da8e30caf"
+ "158a33e6c9509f4a05b01409ff5dd87eb50203010001a381ac3081a9301d0603551d0e0416"
+ "04142031541af25c05ffd8658b6843794f5e9036f7b4307d0603551d230476307480145f9d"
+ "880dc873e654d4f80dd8e6b0c124b447c355a159a4573055310b3009060355040613024742"
+ "31243022060355040a131b4365727469666963617465205472616e73706172656e63792043"
+ "41310e300c0603550408130557616c65733110300e060355040713074572772057656e8201"
+ "0030090603551d1304023000";
+
+const char kTestDigitallySigned[] =
+ "0403004730450220606e10ae5c2d5a1b0aed49dc4937f48de71a4e9784e9c208dfbfe9ef53"
+ "6cf7f2022100beb29c72d7d06d61d06bdb38a069469aa86fe12e18bb7cc45689a2c0187ef5"
+ "a5";
+
+const char kTestSignedCertificateTimestamp[] =
+ "00df1c2ec11500945247a96168325ddc5c7959e8f7c6d388fc002e0bbd3f74d7640000013d"
+ "db27ded900000403004730450220606e10ae5c2d5a1b0aed49dc4937f48de71a4e9784e9c2"
+ "08dfbfe9ef536cf7f2022100beb29c72d7d06d61d06bdb38a069469aa86fe12e18bb7cc456"
+ "89a2c0187ef5a5";
+
+const char kEcP256PublicKey[] =
+ "3059301306072a8648ce3d020106082a8648ce3d0301070342000499783cb14533c0161a5a"
+ "b45bf95d08a29cd0ea8dd4c84274e2be59ad15c676960cf0afa1074a57ac644b23479e5b3f"
+ "b7b245eb4b420ef370210371a944beaceb";
+
+const char kTestKeyId[] =
+ "df1c2ec11500945247a96168325ddc5c7959e8f7c6d388fc002e0bbd3f74d764";
+
+const char kTestSCTSignatureData[] =
+ "30450220606e10ae5c2d5a1b0aed49dc4937f48de71a4e9784e9c208dfbfe9ef536cf7f202"
+ "2100beb29c72d7d06d61d06bdb38a069469aa86fe12e18bb7cc45689a2c0187ef5a5";
+
+const char kTestSCTPrecertSignatureData[] =
+ "30450220482f6751af35dba65436be1fd6640f3dbf9a41429495924530288fa3e5e23e0602"
+ "2100e4edc0db3ac572b1e2f5e8ab6a680653987dcf41027dfeffa105519d89edbf08";
+
+// A well-formed OCSP response with fake SCT contents. Does not come from
+// http://code.google.com/p/certificate-transparency, does not pertain to any
+// of the test certs here, and is only used to test extracting the extension
+// contents from the response.
+const char kFakeOCSPResponse[] =
+ "3082016e0a0100a08201673082016306092b060105050730010104820154308201503081ba"
+ "a21604144edfdf5ff9c90ffacfca66e7fbc436bc39ee3fc7180f3230313030313031303630"
+ "3030305a30818e30818b3049300906052b0e03021a050004141833a1e6a4f09577cca0e64c"
+ "e7d145ca4b93700904144edfdf5ff9c90ffacfca66e7fbc436bc39ee3fc7021001aef99bde"
+ "e0bb58c6f2b816bc3ae02f8000180f32303130303130313036303030305aa011180f323033"
+ "30303130313036303030305aa11830163014060a2b06010401d67902040504060404746573"
+ "74300d06092a864886f70d0101050500038181003586ffcf0794e64eb643d52a3d570a1c93"
+ "836395986a2f792dd4e9c70b05161186c55c1658e0607dc9ec0d0924ac37fb99506c870579"
+ "634be1de62ba2fced5f61f3b428f959fcee9bddf6f268c8e14c14fdf3b447786e638a5c8cc"
+ "b610893df17a60e4cff30f4780aeffe0086ef19910f0d9cd7414bc93d1945686f88ad0a3c3"
+ ;
+
+const char kFakeOCSPResponseCert[] =
+ "3082022930820192a003020102021001aef99bdee0bb58c6f2b816bc3ae02f300d06092a86"
+ "4886f70d01010505003015311330110603550403130a54657374696e67204341301e170d31"
+ "30303130313036303030305a170d3332313230313036303030305a30373112301006035504"
+ "0313093132372e302e302e31310b300906035504061302585831143012060355040a130b54"
+ "657374696e67204f726730819d300d06092a864886f70d010101050003818b003081870281"
+ "8100a71998f2930bfe73d031a87f133d2f378eeeeed52a77e44d0fc9ff6f07ff32cbf3da99"
+ "9de4ed65832afcb0807f98787506539d258a0ce3c2c77967653099a9034a9b115a876c39a8"
+ "c4e4ed4acd0c64095946fb39eeeb47a0704dbb018acf48c3a1c4b895fc409fb4a340a986b1"
+ "afc45519ab9eca47c30185c771c64aa5ecf07d020103a35a3058303a06082b060105050701"
+ "01010100042b3029302706082b06010505073001861b687474703a2f2f3132372e302e302e"
+ "313a35353038312f6f637370301a0603551d200101000410300e300c060a2b06010401d679"
+ "020401300d06092a864886f70d01010505000381810065e04fadd3484197f3412479d917e1"
+ "9d8f7db57b526f2d0e4c046f86cebe643bf568ea0cd6570b228842aa057c6a7c79f209dfcd"
+ "3419a4d93b1ecfb1c0224f33083c7d4da023499fbd00d81d6711ad58ffcf65f1545247fe9d"
+ "83203425fd706b4fc5e797002af3d88151be5901eef56ec30aacdfc404be1bd35865ff1943"
+ "2516";
+
+const char kFakeOCSPResponseIssuerCert[] =
+ "308201d13082013aa003020102020101300d06092a864886f70d0101050500301531133011"
+ "0603550403130a54657374696e67204341301e170d3130303130313036303030305a170d33"
+ "32313230313036303030305a3015311330110603550403130a54657374696e672043413081"
+ "9d300d06092a864886f70d010101050003818b0030818702818100a71998f2930bfe73d031"
+ "a87f133d2f378eeeeed52a77e44d0fc9ff6f07ff32cbf3da999de4ed65832afcb0807f9878"
+ "7506539d258a0ce3c2c77967653099a9034a9b115a876c39a8c4e4ed4acd0c64095946fb39"
+ "eeeb47a0704dbb018acf48c3a1c4b895fc409fb4a340a986b1afc45519ab9eca47c30185c7"
+ "71c64aa5ecf07d020103a333303130120603551d130101ff040830060101ff020100301b06"
+ "03551d200101000411300f300d060b2b06010401d6790201ce0f300d06092a864886f70d01"
+ "01050500038181003f4936f8d00e83fbdde331f2c64335dcf7dec8b1a2597683edeed61af0"
+ "fa862412fad848938fe7ab77f1f9a43671ff6fdb729386e26f49e7aca0c0ea216e5970d933"
+ "3ea1e11df2ccb357a5fed5220f9c6239e8946b9b7517707631d51ab996833d58a022cff5a6"
+ "2169ac9258ec110efee78da9ab4a641e3b3c9ee5e8bd291460";
+
+
+const char kFakeOCSPExtensionValue[] = "74657374"; // "test"
+
+} // namespace
+
+void GetX509CertLogEntry(LogEntry* entry) {
+ entry->type = ct::LogEntry::LOG_ENTRY_TYPE_X509;
+ entry->leaf_certificate = HexToBytes(kDefaultDerCert);
+}
+
+std::string GetDerEncodedX509Cert() { return HexToBytes(kDefaultDerCert); }
+
+void GetPrecertLogEntry(LogEntry* entry) {
+ entry->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT;
+ std::string issuer_hash(HexToBytes(kDefaultIssuerKeyHash));
+ memcpy(entry->issuer_key_hash.data, issuer_hash.data(), issuer_hash.size());
+ entry->tbs_certificate = HexToBytes(kDefaultDerTbsCert);
+}
+
+std::string GetTestDigitallySigned() {
+ return HexToBytes(kTestDigitallySigned);
+}
+
+std::string GetTestSignedCertificateTimestamp() {
+ return HexToBytes(kTestSignedCertificateTimestamp);
+}
+
+std::string GetTestPublicKey() {
+ return HexToBytes(kEcP256PublicKey);
+}
+
+std::string GetTestPublicKeyId() {
+ return HexToBytes(kTestKeyId);
+}
+
+void GetX509CertSCT(scoped_refptr<SignedCertificateTimestamp>* sct_ref) {
+ CHECK(sct_ref != NULL);
+ *sct_ref = new SignedCertificateTimestamp();
+ SignedCertificateTimestamp *const sct(sct_ref->get());
+ sct->version = ct::SignedCertificateTimestamp::SCT_VERSION_1;
+ sct->log_id = HexToBytes(kTestKeyId);
+ // Time the log issued a SCT for this certificate, which is
+ // Fri Apr 5 10:04:16.089 2013
+ sct->timestamp = base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(GG_INT64_C(1365181456089));
+ sct->extensions.clear();
+
+ sct->signature.hash_algorithm = ct::DigitallySigned::HASH_ALGO_SHA256;
+ sct->signature.signature_algorithm = ct::DigitallySigned::SIG_ALGO_ECDSA;
+ sct->signature.signature_data = HexToBytes(kTestSCTSignatureData);
+}
+
+void GetPrecertSCT(scoped_refptr<SignedCertificateTimestamp>* sct_ref) {
+ CHECK(sct_ref != NULL);
+ *sct_ref = new SignedCertificateTimestamp();
+ SignedCertificateTimestamp *const sct(sct_ref->get());
+ sct->version = ct::SignedCertificateTimestamp::SCT_VERSION_1;
+ sct->log_id = HexToBytes(kTestKeyId);
+ // Time the log issued a SCT for this Precertificate, which is
+ // Fri Apr 5 10:04:16.275 2013
+ sct->timestamp = base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(GG_INT64_C(1365181456275));
+ sct->extensions.clear();
+
+ sct->signature.hash_algorithm = ct::DigitallySigned::HASH_ALGO_SHA256;
+ sct->signature.signature_algorithm = ct::DigitallySigned::SIG_ALGO_ECDSA;
+ sct->signature.signature_data = HexToBytes(kTestSCTPrecertSignatureData);
+}
+
+std::string GetDefaultIssuerKeyHash() {
+ return HexToBytes(kDefaultIssuerKeyHash);
+}
+
+std::string GetDerEncodedFakeOCSPResponse() {
+return HexToBytes(kFakeOCSPResponse);
+}
+
+std::string GetFakeOCSPExtensionValue() {
+ return HexToBytes(kFakeOCSPExtensionValue);
+}
+
+std::string GetDerEncodedFakeOCSPResponseCert() {
+ return HexToBytes(kFakeOCSPResponseCert);
+}
+
+std::string GetDerEncodedFakeOCSPResponseIssuerCert() {
+ return HexToBytes(kFakeOCSPResponseIssuerCert);
+}
+
+} // namespace ct
+
+} // namespace net
diff --git a/chromium/net/test/ct_test_util.h b/chromium/net/test/ct_test_util.h
new file mode 100644
index 00000000000..87afc104102
--- /dev/null
+++ b/chromium/net/test/ct_test_util.h
@@ -0,0 +1,69 @@
+// 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_CERT_CT_TEST_UTIL_H_
+#define NET_CERT_CT_TEST_UTIL_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+
+namespace net {
+
+namespace ct {
+
+struct LogEntry;
+struct SignedCertificateTimestamp;
+
+// Note: unless specified otherwise, all test data is taken from Certificate
+// Transparency test data repository.
+
+// Fills |entry| with test data for an X.509 entry.
+void GetX509CertLogEntry(LogEntry* entry);
+
+// Returns a DER-encoded X509 cert. The SCT provided by
+// GetX509CertSCT is signed over this certificate.
+std::string GetDerEncodedX509Cert();
+
+// Fills |entry| with test data for a Precertificate entry.
+void GetPrecertLogEntry(LogEntry* entry);
+
+// Returns the binary representation of a test DigitallySigned
+std::string GetTestDigitallySigned();
+
+// Returns the binary representation of a test serialized SCT.
+std::string GetTestSignedCertificateTimestamp();
+
+// Test log key
+std::string GetTestPublicKey();
+
+// ID of test log key
+std::string GetTestPublicKeyId();
+
+// SCT for the X509Certificate provided above.
+void GetX509CertSCT(scoped_refptr<SignedCertificateTimestamp>* sct);
+
+// SCT for the Precertificate log entry provided above.
+void GetPrecertSCT(scoped_refptr<SignedCertificateTimestamp>* sct);
+
+// Issuer key hash
+std::string GetDefaultIssuerKeyHash();
+
+// Fake OCSP response with an embedded SCT list.
+std::string GetDerEncodedFakeOCSPResponse();
+
+// The SCT list embedded in the response above.
+std::string GetFakeOCSPExtensionValue();
+
+// The cert the OCSP response is for.
+std::string GetDerEncodedFakeOCSPResponseCert();
+
+// The issuer of the previous cert.
+std::string GetDerEncodedFakeOCSPResponseIssuerCert();
+
+} // namespace ct
+
+} // namespace net
+
+#endif // NET_CERT_CT_TEST_UTIL_H_
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.cc b/chromium/net/test/embedded_test_server/embedded_test_server.cc
index 07bad2813fa..b60cea44632 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.cc
@@ -9,6 +9,7 @@
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
+#include "base/process/process_metrics.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -99,12 +100,13 @@ HttpListenSocket::~HttpListenSocket() {
DCHECK(thread_checker_.CalledOnValidThread());
}
-EmbeddedTestServer::EmbeddedTestServer(
- const scoped_refptr<base::SingleThreadTaskRunner>& io_thread)
- : io_thread_(io_thread),
- port_(-1),
+void HttpListenSocket::DetachFromThread() {
+ thread_checker_.DetachFromThread();
+}
+
+EmbeddedTestServer::EmbeddedTestServer()
+ : port_(-1),
weak_factory_(this) {
- DCHECK(io_thread_.get());
DCHECK(thread_checker_.CalledOnValidThread());
}
@@ -117,16 +119,47 @@ EmbeddedTestServer::~EmbeddedTestServer() {
}
bool EmbeddedTestServer::InitializeAndWaitUntilReady() {
+ StartThread();
DCHECK(thread_checker_.CalledOnValidThread());
-
if (!PostTaskToIOThreadAndWait(base::Bind(
&EmbeddedTestServer::InitializeOnIOThread, base::Unretained(this)))) {
return false;
}
-
return Started() && base_url_.is_valid();
}
+void EmbeddedTestServer::StopThread() {
+ DCHECK(io_thread_ && io_thread_->IsRunning());
+
+#if defined(OS_LINUX)
+ const int thread_count =
+ base::GetNumberOfThreads(base::GetCurrentProcessHandle());
+#endif
+
+ io_thread_->Stop();
+ io_thread_.reset();
+ thread_checker_.DetachFromThread();
+ listen_socket_->DetachFromThread();
+
+#if defined(OS_LINUX)
+ // Busy loop to wait for thread count to decrease. This is needed because
+ // pthread_join does not guarantee that kernel stat is updated when it
+ // returns. Thus, GetNumberOfThreads does not immediately reflect the stopped
+ // thread and hits the thread number DCHECK in render_sandbox_host_linux.cc
+ // in browser_tests.
+ while (thread_count ==
+ base::GetNumberOfThreads(base::GetCurrentProcessHandle())) {
+ base::PlatformThread::YieldCurrentThread();
+ }
+#endif
+}
+
+void EmbeddedTestServer::RestartThreadAndListen() {
+ StartThread();
+ CHECK(PostTaskToIOThreadAndWait(base::Bind(
+ &EmbeddedTestServer::ListenOnIOThread, base::Unretained(this))));
+}
+
bool EmbeddedTestServer::ShutdownAndWaitUntilComplete() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -134,8 +167,16 @@ bool EmbeddedTestServer::ShutdownAndWaitUntilComplete() {
&EmbeddedTestServer::ShutdownOnIOThread, base::Unretained(this)));
}
+void EmbeddedTestServer::StartThread() {
+ DCHECK(!io_thread_.get());
+ base::Thread::Options thread_options;
+ thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
+ io_thread_.reset(new base::Thread("EmbeddedTestServer io thread"));
+ CHECK(io_thread_->StartWithOptions(thread_options));
+}
+
void EmbeddedTestServer::InitializeOnIOThread() {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
DCHECK(!Started());
SocketDescriptor socket_descriptor =
@@ -155,8 +196,14 @@ void EmbeddedTestServer::InitializeOnIOThread() {
}
}
+void EmbeddedTestServer::ListenOnIOThread() {
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
+ DCHECK(Started());
+ listen_socket_->Listen();
+}
+
void EmbeddedTestServer::ShutdownOnIOThread() {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
listen_socket_.reset();
STLDeleteContainerPairSecondPointers(connections_.begin(),
@@ -166,7 +213,7 @@ void EmbeddedTestServer::ShutdownOnIOThread() {
void EmbeddedTestServer::HandleRequest(HttpConnection* connection,
scoped_ptr<HttpRequest> request) {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
bool request_handled = false;
@@ -196,6 +243,7 @@ void EmbeddedTestServer::HandleRequest(HttpConnection* connection,
}
GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const {
+ DCHECK(Started()) << "You must start the server first.";
DCHECK(StartsWithASCII(relative_url, "/", true /* case_sensitive */))
<< relative_url;
return base_url_.Resolve(relative_url);
@@ -214,7 +262,7 @@ void EmbeddedTestServer::RegisterRequestHandler(
void EmbeddedTestServer::DidAccept(
StreamListenSocket* server,
scoped_ptr<StreamListenSocket> connection) {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
HttpConnection* http_connection = new HttpConnection(
connection.Pass(),
@@ -227,7 +275,7 @@ void EmbeddedTestServer::DidAccept(
void EmbeddedTestServer::DidRead(StreamListenSocket* connection,
const char* data,
int length) {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
HttpConnection* http_connection = FindConnection(connection);
if (http_connection == NULL) {
@@ -238,7 +286,7 @@ void EmbeddedTestServer::DidRead(StreamListenSocket* connection,
}
void EmbeddedTestServer::DidClose(StreamListenSocket* connection) {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
HttpConnection* http_connection = FindConnection(connection);
if (http_connection == NULL) {
@@ -251,7 +299,7 @@ void EmbeddedTestServer::DidClose(StreamListenSocket* connection) {
HttpConnection* EmbeddedTestServer::FindConnection(
StreamListenSocket* socket) {
- DCHECK(io_thread_->BelongsToCurrentThread());
+ DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread());
std::map<StreamListenSocket*, HttpConnection*>::iterator it =
connections_.find(socket);
@@ -276,8 +324,10 @@ bool EmbeddedTestServer::PostTaskToIOThreadAndWait(
temporary_loop.reset(new base::MessageLoop());
base::RunLoop run_loop;
- if (!io_thread_->PostTaskAndReply(FROM_HERE, closure, run_loop.QuitClosure()))
+ if (!io_thread_->message_loop_proxy()->PostTaskAndReply(
+ FROM_HERE, closure, run_loop.QuitClosure())) {
return false;
+ }
run_loop.Run();
return true;
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 f8c1bb5b3cb..1232388a6ca 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.h
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.h
@@ -14,6 +14,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "net/socket/tcp_listen_socket.h"
#include "url/gurl.h"
@@ -38,6 +39,10 @@ class HttpListenSocket : public TCPListenSocket {
virtual void Listen();
private:
+ friend class EmbeddedTestServer;
+
+ // Detaches the current from |thread_checker_|.
+ void DetachFromThread();
base::ThreadChecker thread_checker_;
};
@@ -47,18 +52,10 @@ class HttpListenSocket : public TCPListenSocket {
// it assumes that the request syntax is correct. It *does not* support
// a Chunked Transfer Encoding.
//
-// The common use case is below:
-//
-// base::Thread io_thread_;
-// scoped_ptr<EmbeddedTestServer> test_server_;
+// The common use case for unit tests is below:
//
// void SetUp() {
-// base::Thread::Options thread_options;
-// thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
-// ASSERT_TRUE(io_thread_.StartWithOptions(thread_options));
-//
-// test_server_.reset(
-// new EmbeddedTestServer(io_thread_.message_loop_proxy()));
+// test_server_.reset(new EmbeddedTestServer());
// ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
// test_server_->RegisterRequestHandler(
// base::Bind(&FooTest::HandleRequest, base::Unretained(this)));
@@ -76,16 +73,34 @@ class HttpListenSocket : public TCPListenSocket {
// return http_response.Pass();
// }
//
+// For a test that spawns another process such as browser_tests, it is
+// suggested to call InitializeAndWaitUntilReady in SetUpOnMainThread after
+// the process is spawned. If you have to do it before the process spawns,
+// you need to stop the server's thread so that there is no no other
+// threads running while spawning the process. To do so, please follow
+// the following example:
+//
+// void SetUp() {
+// ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+// // EmbeddedTestServer spawns a thread to initialize socket.
+// // Stop the thread in preparation for fork and exec.
+// embedded_test_server()->StopThread();
+// ...
+// InProcessBrowserTest::SetUp();
+// }
+//
+// void SetUpOnMainThread() {
+// embedded_test_server()->RestartThreadAndListen();
+// }
+//
class EmbeddedTestServer : public StreamListenSocket::Delegate {
public:
typedef base::Callback<scoped_ptr<HttpResponse>(
const HttpRequest& request)> HandleRequestCallback;
- // Creates a http test server. |io_thread| is a task runner
- // with IO message loop, used as a backend thread.
- // InitializeAndWaitUntilReady() must be called to start the server.
- explicit EmbeddedTestServer(
- const scoped_refptr<base::SingleThreadTaskRunner>& io_thread);
+ // Creates a http test server. InitializeAndWaitUntilReady() must be called
+ // to start the server.
+ EmbeddedTestServer();
virtual ~EmbeddedTestServer();
// Initializes and waits until the server is ready to accept requests.
@@ -123,10 +138,19 @@ class EmbeddedTestServer : public StreamListenSocket::Delegate {
// on UI thread.
void RegisterRequestHandler(const HandleRequestCallback& callback);
+ // Stops IO thread that handles http requests.
+ void StopThread();
+
+ // Restarts IO thread and listen on the socket.
+ void RestartThreadAndListen();
+
private:
+ void StartThread();
+
// Initializes and starts the server. If initialization succeeds, Starts()
// will return true.
void InitializeOnIOThread();
+ void ListenOnIOThread();
// Shuts down the server.
void ShutdownOnIOThread();
@@ -150,7 +174,7 @@ class EmbeddedTestServer : public StreamListenSocket::Delegate {
bool PostTaskToIOThreadAndWait(
const base::Closure& closure) WARN_UNUSED_RESULT;
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_;
+ scoped_ptr<base::Thread> io_thread_;
scoped_ptr<HttpListenSocket> listen_socket_;
int port_;
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 2c005186607..a9c2efba474 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
@@ -57,7 +57,7 @@ class EmbeddedTestServerTest: public testing::Test,
request_context_getter_ = new TestURLRequestContextGetter(
io_thread_.message_loop_proxy());
- server_.reset(new EmbeddedTestServer(io_thread_.message_loop_proxy()));
+ server_.reset(new EmbeddedTestServer);
ASSERT_TRUE(server_->InitializeAndWaitUntilReady());
}
@@ -273,7 +273,7 @@ class EmbeddedTestServerThreadingTestDelegate
loop.reset(new base::MessageLoop(base::MessageLoop::TYPE_IO));
// Create the test server instance.
- EmbeddedTestServer server(io_thread_runner);
+ EmbeddedTestServer server;
base::FilePath src_dir;
ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
ASSERT_TRUE(server.InitializeAndWaitUntilReady());
diff --git a/chromium/net/test/embedded_test_server/http_request.cc b/chromium/net/test/embedded_test_server/http_request.cc
index 8ac76d35923..f1bf302a3fd 100644
--- a/chromium/net/test/embedded_test_server/http_request.cc
+++ b/chromium/net/test/embedded_test_server/http_request.cc
@@ -21,7 +21,7 @@ size_t kRequestSizeLimit = 64 * 1024 * 1024; // 64 mb.
// Helper function used to trim tokens in http request headers.
std::string Trim(const std::string& value) {
std::string result;
- TrimString(value, " \t", &result);
+ base::TrimString(value, " \t", &result);
return result;
}
diff --git a/chromium/net/test/python_utils.cc b/chromium/net/test/python_utils.cc
index a9ac98b5317..e249a27f27a 100644
--- a/chromium/net/test/python_utils.cc
+++ b/chromium/net/test/python_utils.cc
@@ -41,6 +41,7 @@ void AppendToPythonPath(const base::FilePath& dir) {
namespace {
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
// Search for |to_try|, rolling up the directory tree from
// |start_dir|. If found, return true and put the path to |to_try| in
// |out_dir|. If not, return false and leave |out_dir| untouched.
@@ -59,6 +60,7 @@ bool TryRelativeToDir(const base::FilePath& start_dir,
*out_dir = dir;
return true;
}
+#endif // defined(OS_MACOSX) || defined(OS_CHROMEOS)
} // namespace
@@ -107,8 +109,14 @@ bool GetPyProtoPath(base::FilePath* dir) {
bool GetPythonCommand(CommandLine* python_cmd) {
DCHECK(python_cmd);
+#if defined(OS_WIN)
+ // This permits finding the proper python in path even if it is a .bat file.
+ python_cmd->SetProgram(base::FilePath(FILE_PATH_LITERAL("cmd.exe")));
+ python_cmd->AppendArg("/c");
+ python_cmd->AppendArg("python");
+#else
python_cmd->SetProgram(base::FilePath(FILE_PATH_LITERAL("python")));
-
+#endif // defined(OS_WIN)
// Launch python in unbuffered mode, so that python output doesn't mix with
// gtest output in buildbot log files. See http://crbug.com/147368.
python_cmd->AppendArg("-u");
diff --git a/chromium/net/test/run_all_unittests.cc b/chromium/net/test/run_all_unittests.cc
index 07aaeb63b5d..9b5dad2b0f7 100644
--- a/chromium/net/test/run_all_unittests.cc
+++ b/chromium/net/test/run_all_unittests.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "base/metrics/statistics_recorder.h"
-#include "base/test/unit_test_launcher.h"
+#include "base/test/launcher/unit_test_launcher.h"
#include "build/build_config.h"
#include "crypto/nss_util.h"
#include "net/socket/client_socket_pool_base.h"
@@ -13,6 +13,7 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
+#include "base/test/test_file_util.h"
#include "net/android/net_jni_registrar.h"
#endif
@@ -31,6 +32,7 @@ int main(int argc, char** argv) {
// Register JNI bindings for android. Doing it early as the test suite setup
// may initiate a call to Java.
net::android::RegisterJni(base::android::AttachCurrentThread());
+ file_util::RegisterContentUriTestUtils(base::android::AttachCurrentThread());
#endif
NetTestSuite test_suite(argc, argv);
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 b8697d49f51..ac37c70d21c 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.cc
+++ b/chromium/net/test/spawned_test_server/base_test_server.cc
@@ -60,7 +60,9 @@ BaseTestServer::SSLOptions::SSLOptions()
request_client_certificate(false),
bulk_ciphers(SSLOptions::BULK_CIPHER_ANY),
record_resume(false),
- tls_intolerant(TLS_INTOLERANT_NONE) {}
+ tls_intolerant(TLS_INTOLERANT_NONE),
+ fallback_scsv_enabled(false),
+ staple_ocsp_response(false) {}
BaseTestServer::SSLOptions::SSLOptions(
BaseTestServer::SSLOptions::ServerCertificate cert)
@@ -70,7 +72,9 @@ BaseTestServer::SSLOptions::SSLOptions(
request_client_certificate(false),
bulk_ciphers(SSLOptions::BULK_CIPHER_ANY),
record_resume(false),
- tls_intolerant(TLS_INTOLERANT_NONE) {}
+ tls_intolerant(TLS_INTOLERANT_NONE),
+ fallback_scsv_enabled(false),
+ staple_ocsp_response(false) {}
BaseTestServer::SSLOptions::~SSLOptions() {}
@@ -226,10 +230,8 @@ bool BaseTestServer::GetFilePathWithReplacements(
const std::string& new_text = it->second;
std::string base64_old;
std::string base64_new;
- if (!base::Base64Encode(old_text, &base64_old))
- return false;
- if (!base::Base64Encode(new_text, &base64_new))
- return false;
+ base::Base64Encode(old_text, &base64_old);
+ base::Base64Encode(new_text, &base64_new);
if (first_query_parameter) {
new_file_path += "?";
first_query_parameter = false;
@@ -398,6 +400,16 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const {
arguments->Set("tls-intolerant",
new base::FundamentalValue(ssl_options_.tls_intolerant));
}
+ if (ssl_options_.fallback_scsv_enabled)
+ arguments->Set("fallback-scsv", base::Value::CreateNullValue());
+ if (!ssl_options_.signed_cert_timestamps_tls_ext.empty()) {
+ std::string b64_scts_tls_ext;
+ base::Base64Encode(ssl_options_.signed_cert_timestamps_tls_ext,
+ &b64_scts_tls_ext);
+ arguments->SetString("signed-cert-timestamps-tls-ext", b64_scts_tls_ext);
+ }
+ if (ssl_options_.staple_ocsp_response)
+ arguments->Set("staple-ocsp-response", base::Value::CreateNullValue());
}
return GenerateAdditionalArguments(arguments);
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 ff395c56f8b..163808c17b3 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.h
+++ b/chromium/net/test/spawned_test_server/base_test_server.h
@@ -147,6 +147,24 @@ class BaseTestServer {
// If not TLS_INTOLERANT_NONE, the server will abort any handshake that
// negotiates an intolerant TLS version in order to test version fallback.
TLSIntolerantLevel tls_intolerant;
+
+ // fallback_scsv_enabled, if true, causes the server to process the
+ // TLS_FALLBACK_SCSV cipher suite. This cipher suite is sent by Chrome
+ // when performing TLS version fallback in response to an SSL handshake
+ // failure. If this option is enabled then the server will reject fallback
+ // connections.
+ bool fallback_scsv_enabled;
+
+ // Temporary glue for testing: validation of SCTs is application-controlled
+ // and can be appropriately mocked out, so sending fake data here does not
+ // affect handshaking behaviour.
+ // TODO(ekasper): replace with valid SCT files for test certs.
+ // (Fake) SignedCertificateTimestampList (as a raw binary string) to send in
+ // a TLS extension.
+ std::string signed_cert_timestamps_tls_ext;
+
+ // Whether to staple the OCSP response.
+ bool staple_ocsp_response;
};
// Pass as the 'host' parameter during construction to server on 127.0.0.1
@@ -156,7 +174,7 @@ class BaseTestServer {
BaseTestServer(Type type, const std::string& host);
// Initialize a TestServer with a specific set of SSLOptions for HTTPS or WSS.
- explicit BaseTestServer(Type type, const SSLOptions& ssl_options);
+ BaseTestServer(Type type, const SSLOptions& ssl_options);
// Returns the host port pair used by current Python based test server only
// if the server is started.
@@ -260,4 +278,3 @@ class BaseTestServer {
} // namespace net
#endif // NET_TEST_SPAWNED_TEST_SERVER_BASE_TEST_SERVER_H_
-
diff --git a/chromium/net/test/spawned_test_server/local_test_server.cc b/chromium/net/test/spawned_test_server/local_test_server.cc
index bf1b0590786..8679d7b1554 100644
--- a/chromium/net/test/spawned_test_server/local_test_server.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server.cc
@@ -124,10 +124,16 @@ bool LocalTestServer::Stop() {
if (!process_handle_)
return true;
+#if defined(OS_WIN)
+ // This kills all the processes in the job object.
+ job_handle_.Close();
+#endif
+
// First check if the process has already terminated.
bool ret = base::WaitForSingleProcess(process_handle_, base::TimeDelta());
- if (!ret)
+ if (!ret) {
ret = base::KillProcess(process_handle_, 1, true);
+ }
if (ret) {
base::CloseProcessHandle(process_handle_);
diff --git a/chromium/net/test/spawned_test_server/local_test_server_win.cc b/chromium/net/test/spawned_test_server/local_test_server_win.cc
index 08d68f80bf2..db067428348 100644
--- a/chromium/net/test/spawned_test_server/local_test_server_win.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server_win.cc
@@ -190,15 +190,6 @@ bool LocalTestServer::LaunchPython(const base::FilePath& testserver_path) {
return false;
}
- // Add our internal python to the path so it can be used if there is
- // no system python.
- base::FilePath python_dir;
- if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_dir)) {
- LOG(ERROR) << "Could not locate source root directory.";
- return false;
- }
- python_dir = python_dir.AppendASCII("third_party").AppendASCII("python_26");
- ScopedPath python_path(python_dir);
base::LaunchOptions launch_options;
launch_options.inherit_handles = true;
launch_options.job_handle = job_handle_.Get();
diff --git a/chromium/net/test/spawned_test_server/spawner_communicator.cc b/chromium/net/test/spawned_test_server/spawner_communicator.cc
index f93ff971d6f..38871571c96 100644
--- a/chromium/net/test/spawned_test_server/spawner_communicator.cc
+++ b/chromium/net/test/spawned_test_server/spawner_communicator.cc
@@ -13,6 +13,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/net_util.h"
+#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_response_headers.h"
@@ -171,9 +172,9 @@ void SpawnerCommunicator::SendCommandAndWaitForResultOnIOThread(
// Prepare the URLRequest for sending the command.
DCHECK(!cur_request_.get());
context_.reset(new TestURLRequestContext);
- cur_request_.reset(context_->CreateRequest(
- GenerateSpawnerCommandURL(command, port_), this));
- DCHECK(cur_request_.get());
+ cur_request_ = context_->CreateRequest(
+ GenerateSpawnerCommandURL(command, port_), DEFAULT_PRIORITY, this);
+ DCHECK(cur_request_);
int current_request_id = ++next_id_;
SpawnerRequestData* data = new SpawnerRequestData(current_request_id,
result_code,
diff --git a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp b/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
index 4cf47c42c17..f239cc14c3d 100644
--- a/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
+++ b/chromium/net/third_party/mozilla_security_manager/nsKeygenHandler.cpp
@@ -215,13 +215,9 @@ std::string GenKeyAndSignChallenge(int key_size_in_bits,
}
// Convert the signed public key and challenge into base64/ascii.
- if (!base::Base64Encode(std::string(reinterpret_cast<char*>(signedItem.data),
- signedItem.len),
- &result_blob)) {
- LOG(ERROR) << "Couldn't convert signed public key into base64";
- isSuccess = false;
- goto failure;
- }
+ base::Base64Encode(
+ std::string(reinterpret_cast<char*>(signedItem.data), signedItem.len),
+ &result_blob);
failure:
if (!isSuccess) {
diff --git a/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp b/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
index 6db75f3662a..bfbeae6a299 100644
--- a/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
+++ b/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp
@@ -44,8 +44,6 @@
#include <secerr.h>
#include "base/logging.h"
-#include "crypto/nss_util_internal.h"
-#include "crypto/scoped_nss_types.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util_nss.h"
@@ -61,19 +59,14 @@
namespace mozilla_security_manager {
// Based on nsNSSCertificateDB::handleCACertDownload, minus the UI bits.
-bool ImportCACerts(const net::CertificateList& certificates,
+bool ImportCACerts(PK11SlotInfo* slot,
+ const net::CertificateList& certificates,
net::X509Certificate* root,
net::NSSCertDatabase::TrustBits trustBits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) {
- if (certificates.empty() || !root)
+ if (!slot || certificates.empty() || !root)
return false;
- crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot());
- if (!slot.get()) {
- LOG(ERROR) << "Couldn't get internal key slot!";
- return false;
- }
-
// Mozilla had some code here to check if a perm version of the cert exists
// already and use that, but CERT_NewTempCertificate actually does that
// itself, so we skip it here.
@@ -93,13 +86,13 @@ bool ImportCACerts(const net::CertificateList& certificates,
// and it doesn't take the slot as an argument either. Instead, we use
// PK11_ImportCert and CERT_ChangeCertTrust.
SECStatus srv = PK11_ImportCert(
- slot.get(),
+ slot,
root->os_cert_handle(),
CK_INVALID_HANDLE,
net::x509_util::GetUniqueNicknameForSlot(
root->GetDefaultNickname(net::CA_CERT),
&root->os_cert_handle()->derSubject,
- slot.get()).c_str(),
+ slot).c_str(),
PR_FALSE /* includeTrust (unused) */);
if (srv != SECSuccess) {
LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError();
@@ -153,13 +146,13 @@ bool ImportCACerts(const net::CertificateList& certificates,
// Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use
// PK11_ImportCert instead.
SECStatus srv = PK11_ImportCert(
- slot.get(),
+ slot,
cert->os_cert_handle(),
CK_INVALID_HANDLE,
net::x509_util::GetUniqueNicknameForSlot(
cert->GetDefaultNickname(net::CA_CERT),
&cert->os_cert_handle()->derSubject,
- slot.get()).c_str(),
+ slot).c_str(),
PR_FALSE /* includeTrust (unused) */);
if (srv != SECSuccess) {
LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError();
@@ -176,31 +169,26 @@ bool ImportCACerts(const net::CertificateList& certificates,
// Based on nsNSSCertificateDB::ImportServerCertificate.
bool ImportServerCert(
+ PK11SlotInfo* slot,
const net::CertificateList& certificates,
net::NSSCertDatabase::TrustBits trustBits,
net::NSSCertDatabase::ImportCertFailureList* not_imported) {
- if (certificates.empty())
+ if (!slot || certificates.empty())
return false;
- crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot());
- if (!slot.get()) {
- LOG(ERROR) << "Couldn't get internal key slot!";
- return false;
- }
-
for (size_t i = 0; i < certificates.size(); ++i) {
const scoped_refptr<net::X509Certificate>& cert = certificates[i];
// Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use
// PK11_ImportCert instead.
SECStatus srv = PK11_ImportCert(
- slot.get(),
+ slot,
cert->os_cert_handle(),
CK_INVALID_HANDLE,
net::x509_util::GetUniqueNicknameForSlot(
cert->GetDefaultNickname(net::SERVER_CERT),
&cert->os_cert_handle()->derSubject,
- slot.get()).c_str(),
+ slot).c_str(),
PR_FALSE /* includeTrust (unused) */);
if (srv != SECSuccess) {
LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError();
diff --git a/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h b/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h
index aac991255f0..990fdbc4cff 100644
--- a/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h
+++ b/chromium/net/third_party/mozilla_security_manager/nsNSSCertificateDB.h
@@ -45,6 +45,7 @@
#include "net/cert/nss_cert_database.h"
typedef struct CERTCertificateStr CERTCertificate;
+typedef struct PK11SlotInfoStr PK11SlotInfo;
namespace net {
class X509Certificate;
typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
@@ -52,12 +53,14 @@ typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
namespace mozilla_security_manager {
-bool ImportCACerts(const net::CertificateList& certificates,
+bool ImportCACerts(PK11SlotInfo* slot,
+ const net::CertificateList& certificates,
net::X509Certificate* root,
net::NSSCertDatabase::TrustBits trustBits,
net::NSSCertDatabase::ImportCertFailureList* not_imported);
bool ImportServerCert(
+ PK11SlotInfo* slot,
const net::CertificateList& certificates,
net::NSSCertDatabase::TrustBits trustBits,
net::NSSCertDatabase::ImportCertFailureList* not_imported);
diff --git a/chromium/net/third_party/nss/README.chromium b/chromium/net/third_party/nss/README.chromium
index 4a0f2d3ec19..8c4e008c70c 100644
--- a/chromium/net/third_party/nss/README.chromium
+++ b/chromium/net/third_party/nss/README.chromium
@@ -57,6 +57,7 @@ Patches:
* Add support for TLS Channel IDs
patches/channelid.patch
+ patches/channelid2.patch
* Add support for extracting the tls-unique channel binding value
patches/tlsunique.patch
@@ -108,10 +109,13 @@ Patches:
libraries at run time.
patches/aesgcmchromium.patch
- * Prefer to generate SHA-1 signatures for TLS 1.2 client authentication if
- the client private key is in a CAPI service provider on Windows or if the
- client private key is a 1024-bit RSA or DSA key.
+ * Support generating SHA-1 signatures for TLS 1.2 client authentication. Use
+ SHA-1 instead of SHA-256 if the server's preferences do not allow for
+ SHA-256 or if the client private key may only support SHA-1 signatures. The
+ latter happens when the key is in a CAPI service provider on Windows or if
+ it is a 1024-bit RSA or DSA key.
patches/tls12backuphash.patch
+ patches/tls12backuphash2.patch
* Support ChaCha20+Poly1305 ciphersuites
http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-01
@@ -139,6 +143,36 @@ Patches:
https://bugzilla.mozilla.org/show_bug.cgi?id=934016
patches/nullcipher_934016.patch
+ * In the case that a ClientHello record is between 256 and 511 bytes long,
+ add an extension to make it 512 bytes. This works around a bug in F5
+ terminators.
+ patches/paddingextension.patch
+ patches/paddingextensionall.patch
+
+ * Support the Certificate Transparency (RFC 6962) TLS extension
+ signed_certificate_timestamp (client only).
+ patches/signedcertificatetimestamps.patch
+
+ * Add a function to allow the cipher suites preference order to be set.
+ patches/cipherorder.patch
+
+ * Add TLS_FALLBACK_SCSV cipher suite to version fallback connections.
+ patches/fallbackscsv.patch
+
+ * Disable session ticket renewal.
+ https://bugzilla.mozilla.org/show_bug.cgi?id=930857
+ patches/disableticketrenewal.patch
+
+ * Add explicit functions for managing the SSL/TLS session cache.
+ This is a temporary workaround until Chromium migrates to NSS's
+ asynchronous certificate verification.
+ patches/sessioncache.patch
+
+ * Remove static storage qualifier from variables in sslnonce.c. Due to
+ a clang codegen bug on Mac, this caused an infinite loop.
+ https://code.google.com/p/chromium/issues/detail?id=326011
+ patches/sslnoncestatics.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.
diff --git a/chromium/net/third_party/nss/patches/applypatches.sh b/chromium/net/third_party/nss/patches/applypatches.sh
index 947cf5e1b57..89d97bc922f 100755
--- a/chromium/net/third_party/nss/patches/applypatches.sh
+++ b/chromium/net/third_party/nss/patches/applypatches.sh
@@ -65,3 +65,23 @@ patch -p4 < $patches_dir/peercertchain2.patch
patch -p4 < $patches_dir/canfalsestart.patch
patch -p4 < $patches_dir/nullcipher_934016.patch
+
+patch -p4 < $patches_dir/paddingextension.patch
+
+patch -p4 < $patches_dir/paddingextensionall.patch
+
+patch -p4 < $patches_dir/channelid2.patch
+
+patch -p5 < $patches_dir/signedcertificatetimestamps.patch
+
+patch -p4 < $patches_dir/cipherorder.patch
+
+patch -p5 < $patches_dir/tls12backuphash2.patch
+
+patch -p4 < $patches_dir/fallbackscsv.patch
+
+patch -p4 < $patches_dir/disableticketrenewal.patch
+
+patch -p4 < $patches_dir/sessioncache.patch
+
+patch -p4 < $patches_dir/sslnoncestatics.patch
diff --git a/chromium/net/third_party/nss/patches/canfalsestart.patch b/chromium/net/third_party/nss/patches/canfalsestart.patch
index d2a9752c070..a3fb1813d21 100644
--- a/chromium/net/third_party/nss/patches/canfalsestart.patch
+++ b/chromium/net/third_party/nss/patches/canfalsestart.patch
@@ -1,8 +1,8 @@
Index: net/third_party/nss/ssl/ssl.h
===================================================================
---- net/third_party/nss/ssl/ssl.h (revision 227363)
+--- net/third_party/nss/ssl/ssl.h (revision 227672)
+++ net/third_party/nss/ssl/ssl.h (working copy)
-@@ -121,14 +121,22 @@
+@@ -121,14 +121,17 @@
#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
/* default, applies only to */
/* clients). False start is a */
@@ -22,62 +22,42 @@ Index: net/third_party/nss/ssl/ssl.h
+ * it saves a round trip for client-speaks-first protocols when performing a
+ * full handshake.
+ *
-+ * See SSL_DefaultCanFalseStart for the default criteria that NSS uses to
-+ * determine whether to false start or not. See SSL_SetCanFalseStartCallback
-+ * for how to change that criteria. In addition to those criteria, false start
-+ * will only be done when the server selects a cipher suite with an effective
-+ * key length of 80 bits or more (including RC4-128). Also, see
-+ * SSL_HandshakeCallback for a description on how false start affects when the
-+ * handshake callback gets called.
++ * In addition to enabling this option, the application must register a
++ * callback using the SSL_SetCanFalseStartCallback function.
+ */
/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
* on SSL CBC mode cipher suites (see RFC 4346 Section F.3) by splitting
-@@ -741,14 +749,59 @@
+@@ -741,14 +744,45 @@
SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
/*
-** Set the callback on a particular socket that gets called when we finish
-** performing a handshake.
-+** Set the callback that normally gets called when the TLS handshake
-+** is complete. If false start is not enabled, then the handshake callback is
-+** called after verifying the peer's Finished message and before sending
-+** outgoing application data and before processing incoming application data.
++** Set the callback that gets called when a TLS handshake is complete. The
++** handshake callback is called after verifying the peer's Finished message and
++** before processing incoming application data.
+**
-+** If false start is enabled and there is a custom CanFalseStartCallback
-+** callback set, then the handshake callback gets called after the peer's
-+** Finished message has been verified, which may be after application data is
-+** sent.
-+**
-+** If false start is enabled and there is not a custom CanFalseStartCallback
-+** callback established with SSL_SetCanFalseStartCallback then the handshake
-+** callback gets called before any application data is sent, which may be
-+** before the peer's Finished message has been verified.
++** For the initial handshake: If the handshake false started (see
++** SSL_ENABLE_FALSE_START), then application data may already have been sent
++** 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);
-+/* Applications that wish to customize TLS false start should set this callback
++/* Applications that wish to enable TLS false start must set this callback
+** function. NSS will invoke the functon to determine if a particular
+** connection should use false start or not. SECSuccess indicates that the
+** callback completed successfully, and if so *canFalseStart indicates if false
+** start can be used. If the callback does not return SECSuccess then the
-+** handshake will be canceled.
-+**
-+** Applications that do not set the callback will use an internal set of
-+** criteria to determine if the connection should false start. If
-+** the callback is set false start will never be used without invoking the
-+** callback function, but some connections (e.g. resumed connections) will
-+** never use false start and therefore will not invoke the callback.
-+**
-+** NSS's internal criteria for this connection can be evaluated by calling
-+** SSL_DefaultCanFalseStart() from the custom callback.
++** handshake will be canceled. NSS's recommended criteria can be evaluated by
++** calling SSL_RecommendedCanFalseStart.
+**
-+** See the description of SSL_HandshakeCallback for important information on
-+** how registering a custom false start callback affects when the handshake
-+** callback gets called.
++** 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)(
+ PRFileDesc *fd, void *arg, PRBool *canFalseStart);
@@ -85,62 +65,420 @@ Index: net/third_party/nss/ssl/ssl.h
+SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
+ PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
+
-+/* A utility function that can be called from a custom CanFalseStartCallback
-+** function to determine what NSS would have done for this connection if the
-+** custom callback was not implemented.
-+**/
-+SSL_IMPORT SECStatus SSL_DefaultCanFalseStart(PRFileDesc *fd,
-+ PRBool *canFalseStart);
++/* This function sets *canFalseStart according to the recommended criteria for
++** false start. These criteria may change from release to release and may depend
++** on which handshake features have been negotiated and/or properties of the
++** certifciates/keys used on the connection.
++*/
++SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
++ PRBool *canFalseStart);
+
/*
** 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
+Index: net/third_party/nss/ssl/ssl3con.c
+===================================================================
+--- net/third_party/nss/ssl/ssl3con.c (revision 227672)
++++ net/third_party/nss/ssl/ssl3con.c (working copy)
+@@ -2890,7 +2890,7 @@
+ SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
+ SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
+ nIn));
+- PRINT_BUF(3, (ss, "Send record (plain text)", pIn, nIn));
++ PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
+
+@@ -7344,36 +7344,72 @@
+ return rv;
+ }
+
++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 );
++
++ if (!ss->canFalseStartCallback) {
++ SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
++ SSL_GETPID(), ss->fd));
++ } else {
++ 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. */
++ 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 {
++ 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;
++ return SECSuccess;
++}
++
+ PRBool
+-ssl3_CanFalseStart(sslSocket *ss) {
+- PRBool rv;
++ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
++{
++ PRBool result;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
+
+- /* XXX: does not take into account whether we are waiting for
+- * SSL_AuthCertificateComplete or SSL_RestartHandshakeAfterCertReq. If/when
+- * that is done, this function could return different results each time it
+- * would be called.
+- */
++ 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;
++ }
+
+- ssl_GetSpecReadLock(ss);
+- rv = ss->opt.enableFalseStart &&
+- !ss->sec.isServer &&
+- !ss->ssl3.hs.isResuming &&
+- ss->ssl3.cwSpec &&
+-
+- /* 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 require an 80-bit cipher and a forward-secret key
+- * exchange. */
+- ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
+- (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);
+- ssl_ReleaseSpecReadLock(ss);
+- return rv;
++ return result;
+ }
+
+ static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
+@@ -7463,6 +7499,9 @@
+ }
+ 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;
+ }
+@@ -7500,20 +7539,59 @@
+ 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.
++ /* This must be done after we've set ss->ssl3.cwSpec in
++ * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information
++ * from cwSpec. This must be done before we call ssl3_CheckFalseStart
++ * because the false start callback (if any) may need the information from
++ * the functions that depend on this being set.
+ */
++ 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. */
+ }
+ }
++
+ rv = ssl3_SendEncryptedExtensions(ss);
+ if (rv != SECSuccess) {
+ 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));
++ }
++ }
++ }
++
+ rv = ssl3_SendFinished(ss, 0);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+@@ -7526,10 +7604,7 @@
+ else
+ ss->ssl3.hs.ws = wait_change_cipher;
+
+- /* Do the handshake callback for sslv3 here, if we can false start. */
+- if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
+- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+- }
++ PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss));
+
+ return SECSuccess;
+
+@@ -10147,13 +10222,6 @@
+
+ ss->ssl3.hs.authCertificatePending = PR_TRUE;
+ rv = SECSuccess;
+-
+- /* XXX: Async cert validation and False Start don't work together
+- * safely yet; if we leave False Start enabled, we may end up false
+- * starting (sending application data) before we
+- * SSL_AuthCertificateComplete has been called.
+- */
+- ss->opt.enableFalseStart = PR_FALSE;
+ }
+
+ if (rv != SECSuccess) {
+@@ -10278,6 +10346,12 @@
+ } 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
+@@ -10287,7 +10361,27 @@
+ rv = SECSuccess;
+ }
+ } 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->firstHsDone);
++ PORT_Assert(!ss->sec.isServer);
++ PORT_Assert(!ss->ssl3.hs.isResuming);
++ PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
++
++ if (ss->opt.enableFalseStart &&
++ !ss->firstHsDone &&
++ !ss->sec.isServer &&
++ !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;
++ }
+ }
+
+ done:
+@@ -10913,9 +11007,6 @@
+ return rv;
+ }
+
+- ss->gs.writeOffset = 0;
+- ss->gs.readOffset = 0;
+-
+ if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
+ effectiveExchKeyType = kt_rsa;
+ } else {
+@@ -10980,6 +11071,9 @@
+ return rv;
+ }
+
++/* The return type is SECStatus instead of void because this function needs
++ * to have type sslRestartTarget.
++ */
+ SECStatus
+ ssl3_FinishHandshake(sslSocket * ss)
+ {
+@@ -10989,19 +11083,16 @@
+
+ /* The first handshake is now completed. */
+ ss->handshake = NULL;
+- ss->firstHsDone = PR_TRUE;
+
+ if (ss->ssl3.hs.cacheSID) {
+ (*ss->sec.cache)(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
+ }
+
++ ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
+ ss->ssl3.hs.ws = idle_handshake;
+
+- /* Do the handshake callback for sslv3 here, if we cannot false start. */
+- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
+- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+- }
++ ssl_FinishHandshake(ss);
+
+ return SECSuccess;
+ }
+@@ -11966,7 +12057,6 @@
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ return rv;
+-
+ }
+
+ /*
Index: net/third_party/nss/ssl/ssl3gthr.c
===================================================================
---- net/third_party/nss/ssl/ssl3gthr.c (revision 227363)
+--- net/third_party/nss/ssl/ssl3gthr.c (revision 227672)
+++ net/third_party/nss/ssl/ssl3gthr.c (working copy)
-@@ -374,9 +374,7 @@
- */
- if (ss->opt.enableFalseStart) {
- ssl_GetSSL3HandshakeLock(ss);
+@@ -275,11 +275,17 @@
+ {
+ SSL3Ciphertext cText;
+ int rv;
+- PRBool canFalseStart = PR_FALSE;
++ PRBool keepGoing = PR_TRUE;
+
+ SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
+
++ /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
++ * 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) );
++
+ do {
+ PRBool handleRecordNow = PR_FALSE;
+
+@@ -364,24 +370,52 @@
+
+ cText.buf = &ss->gs.inbuf;
+ rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
++
++ if (rv == (int) SECSuccess && 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;
++ }
+ }
+ if (rv < 0) {
+ return ss->recvdCloseNotify ? 0 : rv;
+ }
+
+- /* If we kicked off a false start in ssl3_HandleServerHelloDone, break
+- * out of this loop early without finishing the handshake.
+- */
+- if (ss->opt.enableFalseStart) {
+- ssl_GetSSL3HandshakeLock(ss);
- canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_new_session_ticket) &&
- ssl3_CanFalseStart(ss);
-+ canFalseStart = ss->ssl3.hs.canFalseStart;
- ssl_ReleaseSSL3HandshakeLock(ss);
+- ssl_ReleaseSSL3HandshakeLock(ss);
++ 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;
++ }
}
- } while (ss->ssl3.hs.ws != idle_handshake &&
-Index: net/third_party/nss/ssl/sslinfo.c
-===================================================================
---- net/third_party/nss/ssl/sslinfo.c (revision 227363)
-+++ net/third_party/nss/ssl/sslinfo.c (working copy)
-@@ -26,7 +26,6 @@
- sslSocket * ss;
- SSLChannelInfo inf;
- sslSessionID * sid;
-- PRBool enoughFirstHsDone = PR_FALSE;
-
- if (!info || len < sizeof inf.length) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-@@ -43,14 +42,7 @@
- memset(&inf, 0, sizeof inf);
- inf.length = PR_MIN(sizeof inf, len);
+- } while (ss->ssl3.hs.ws != idle_handshake &&
+- !canFalseStart &&
+- ss->gs.buf.len == 0);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ } while (keepGoing);
+
+ ss->gs.readOffset = 0;
+ ss->gs.writeOffset = ss->gs.buf.len;
+@@ -404,7 +438,10 @@
+ {
+ int rv;
-- if (ss->firstHsDone) {
-- enoughFirstHsDone = PR_TRUE;
-- } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
-- ssl3_CanFalseStart(ss)) {
-- enoughFirstHsDone = PR_TRUE;
-- }
--
-- if (ss->opt.useSecurity && enoughFirstHsDone) {
-+ if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
- sid = ss->sec.ci.sid;
- inf.protocolVersion = ss->version;
- inf.authKeyBits = ss->sec.authKeyBits;
++ /* ssl3_GatherCompleteHandshake requires both of these locks. */
++ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
++
+ do {
+ rv = ssl3_GatherCompleteHandshake(ss, flags);
+ } while (rv > 0 && ss->gs.buf.len == 0);
Index: net/third_party/nss/ssl/sslauth.c
===================================================================
---- net/third_party/nss/ssl/sslauth.c (revision 227363)
+--- net/third_party/nss/ssl/sslauth.c (revision 227672)
+++ net/third_party/nss/ssl/sslauth.c (working copy)
@@ -100,7 +100,6 @@
sslSocket *ss;
@@ -168,7 +506,7 @@ Index: net/third_party/nss/ssl/sslauth.c
} else {
Index: net/third_party/nss/ssl/sslimpl.h
===================================================================
---- net/third_party/nss/ssl/sslimpl.h (revision 227363)
+--- net/third_party/nss/ssl/sslimpl.h (revision 227672)
+++ net/third_party/nss/ssl/sslimpl.h (working copy)
@@ -881,6 +881,8 @@
/* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
@@ -199,28 +537,69 @@ Index: net/third_party/nss/ssl/sslimpl.h
void *pkcs11PinArg;
SSLNextProtoCallback nextProtoCallback;
void *nextProtoArg;
-@@ -1423,7 +1431,6 @@
+@@ -1423,7 +1431,19 @@
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
-extern PRBool ssl3_CanFalseStart(sslSocket *ss);
++extern void ssl_FinishHandshake(sslSocket *ss);
++
++/* 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 PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss);
++
extern SECStatus
ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
PRBool isServer,
+Index: net/third_party/nss/ssl/sslinfo.c
+===================================================================
+--- net/third_party/nss/ssl/sslinfo.c (revision 227672)
++++ net/third_party/nss/ssl/sslinfo.c (working copy)
+@@ -26,7 +26,6 @@
+ sslSocket * ss;
+ SSLChannelInfo inf;
+ sslSessionID * sid;
+- PRBool enoughFirstHsDone = PR_FALSE;
+
+ if (!info || len < sizeof inf.length) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -43,14 +42,7 @@
+ memset(&inf, 0, sizeof inf);
+ inf.length = PR_MIN(sizeof inf, len);
+
+- if (ss->firstHsDone) {
+- enoughFirstHsDone = PR_TRUE;
+- } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+- ssl3_CanFalseStart(ss)) {
+- enoughFirstHsDone = PR_TRUE;
+- }
+-
+- if (ss->opt.useSecurity && enoughFirstHsDone) {
++ if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
+ sid = ss->sec.ci.sid;
+ inf.protocolVersion = ss->version;
+ inf.authKeyBits = ss->sec.authKeyBits;
Index: net/third_party/nss/ssl/sslsecur.c
===================================================================
---- net/third_party/nss/ssl/sslsecur.c (revision 227363)
+--- net/third_party/nss/ssl/sslsecur.c (revision 227672)
+++ net/third_party/nss/ssl/sslsecur.c (working copy)
-@@ -99,21 +99,12 @@
+@@ -97,23 +97,13 @@
+ ss->securityHandshake = 0;
+ }
if (ss->handshake == 0) {
- ssl_GetRecvBufLock(ss);
- ss->gs.recordLen = 0;
-+ ss->gs.writeOffset = 0;
-+ ss->gs.readOffset = 0;
- ssl_ReleaseRecvBufLock(ss);
-
- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
- SSL_GETPID(), ss->fd));
+- ssl_GetRecvBufLock(ss);
+- ss->gs.recordLen = 0;
+- ssl_ReleaseRecvBufLock(ss);
+-
+- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
+- SSL_GETPID(), ss->fd));
- /* call handshake callback for ssl v2 */
- /* for v3 this is done in ssl3_HandleFinished() */
- if ((ss->handshakeCallback != NULL) && /* has callback */
@@ -228,14 +607,45 @@ Index: net/third_party/nss/ssl/sslsecur.c
- (ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */
- ss->firstHsDone = PR_TRUE;
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
-- }
++ /* 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);
+ }
- ss->firstHsDone = PR_TRUE;
- ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
break;
}
rv = (*ss->handshake)(ss);
-@@ -206,6 +197,7 @@
+@@ -134,6 +124,24 @@
+ return rv;
+ }
+
++void
++ssl_FinishHandshake(sslSocket *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;
++
++ if (ss->handshakeCallback) {
++ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
++ }
++}
++
+ /*
+ * Handshake function that blocks. Used to force a
+ * retry on a connection on the next read/write.
+@@ -206,6 +214,7 @@
ssl_Get1stHandshakeLock(ss);
ss->firstHsDone = PR_FALSE;
@@ -243,7 +653,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
if ( asServer ) {
ss->handshake = ssl2_BeginServerHandshake;
ss->handshaking = sslHandshakingAsServer;
-@@ -221,6 +213,8 @@
+@@ -221,6 +230,8 @@
ssl_ReleaseRecvBufLock(ss);
ssl_GetSSL3HandshakeLock(ss);
@@ -252,16 +662,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
/*
** Blow away old security state and get a fresh setup.
-@@ -266,7 +260,7 @@
-
- /* SSL v2 protocol does not support subsequent handshakes. */
- if (ss->version < SSL_LIBRARY_VERSION_3_0) {
-- PORT_SetError(SEC_ERROR_INVALID_ARGS);
-+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
- rv = SECFailure;
- } else {
- ssl_GetSSL3HandshakeLock(ss);
-@@ -331,6 +325,75 @@
+@@ -331,6 +342,71 @@
return SECSuccess;
}
@@ -270,7 +671,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
+*/
+SECStatus
+SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
-+ void *client_data)
++ void *arg)
+{
+ sslSocket *ss;
+
@@ -290,7 +691,7 @@ Index: net/third_party/nss/ssl/sslsecur.c
+ ssl_GetSSL3HandshakeLock(ss);
+
+ ss->canFalseStartCallback = cb;
-+ ss->canFalseStartCallbackData = client_data;
++ ss->canFalseStartCallbackData = arg;
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
@@ -298,19 +699,15 @@ Index: net/third_party/nss/ssl/sslsecur.c
+ return SECSuccess;
+}
+
-+/* A utility function that can be called from a custom SSLCanFalseStartCallback
-+** function to determine what NSS would have done for this connection if the
-+** custom callback was not implemented.
-+*/
+SECStatus
-+SSL_DefaultCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
++SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
+{
+ sslSocket *ss;
+
+ *canFalseStart = PR_FALSE;
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
-+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DefaultCanFalseStart",
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
@@ -337,9 +734,43 @@ Index: net/third_party/nss/ssl/sslsecur.c
/* 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
-@@ -1195,12 +1258,7 @@
+@@ -524,6 +600,9 @@
+ int amount;
+ int available;
+
++ /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
++ * 1stHandshakeLock. */
++ ssl_Get1stHandshakeLock(ss);
+ ssl_GetRecvBufLock(ss);
+
+ available = ss->gs.writeOffset - ss->gs.readOffset;
+@@ -590,6 +669,7 @@
+
+ done:
+ ssl_ReleaseRecvBufLock(ss);
++ ssl_Release1stHandshakeLock(ss);
+ return rv;
+ }
+
+@@ -1156,7 +1236,8 @@
+ int
+ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
+ {
+- int rv = 0;
++ int rv = 0;
++ PRBool falseStart = PR_FALSE;
+
+ SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
+ SSL_GETPID(), ss->fd, len));
+@@ -1191,19 +1272,14 @@
+ ss->writerThread = PR_GetCurrentThread();
+ /* If any of these is non-zero, the initial handshake is not done. */
+ if (!ss->firstHsDone) {
+- PRBool canFalseStart = PR_FALSE;
ssl_Get1stHandshakeLock(ss);
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
+- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
++ if (ss->opt.enableFalseStart &&
++ ss->version >= SSL_LIBRARY_VERSION_3_0) {
ssl_GetSSL3HandshakeLock(ss);
- if ((ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_finished ||
@@ -347,15 +778,46 @@ Index: net/third_party/nss/ssl/sslsecur.c
- ssl3_CanFalseStart(ss)) {
- canFalseStart = PR_TRUE;
- }
-+ canFalseStart = ss->ssl3.hs.canFalseStart;
++ falseStart = ss->ssl3.hs.canFalseStart;
ssl_ReleaseSSL3HandshakeLock(ss);
}
- if (!canFalseStart &&
+- if (!canFalseStart &&
++ if (!falseStart &&
+ (ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
+ rv = ssl_Do1stHandshake(ss);
+ }
+@@ -1228,6 +1304,17 @@
+ goto done;
+ }
+
++ if (!ss->firstHsDone) {
++ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
++#ifdef DEBUG
++ 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));
++ }
++
+ /* Send out the data using one of these functions:
+ * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
+ * ssl3_SendApplicationData
Index: net/third_party/nss/ssl/sslsock.c
===================================================================
---- net/third_party/nss/ssl/sslsock.c (revision 227363)
+--- net/third_party/nss/ssl/sslsock.c (revision 227672)
+++ net/third_party/nss/ssl/sslsock.c (working copy)
-@@ -2457,10 +2457,14 @@
+@@ -366,6 +366,8 @@
+ 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;
+@@ -2457,10 +2459,14 @@
} 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
@@ -373,265 +835,3 @@ Index: net/third_party/nss/ssl/sslsock.c
}
}
} else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
-Index: net/third_party/nss/ssl/ssl3con.c
-===================================================================
---- net/third_party/nss/ssl/ssl3con.c (revision 227363)
-+++ net/third_party/nss/ssl/ssl3con.c (working copy)
-@@ -2890,7 +2890,7 @@
- SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
- SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
- nIn));
-- PRINT_BUF(3, (ss, "Send record (plain text)", pIn, nIn));
-+ PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
-
-@@ -7344,35 +7344,42 @@
- return rv;
- }
-
--PRBool
--ssl3_CanFalseStart(sslSocket *ss) {
-- PRBool rv;
-+static SECStatus
-+ssl3_CheckFalseStart(sslSocket *ss)
-+{
-+ SECStatus rv;
-+ PRBool maybeFalseStart = PR_TRUE;
-
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
-+ PORT_Assert( !ss->ssl3.hs.authCertificatePending );
-
-- /* XXX: does not take into account whether we are waiting for
-- * SSL_AuthCertificateComplete or SSL_RestartHandshakeAfterCertReq. If/when
-- * that is done, this function could return different results each time it
-- * would be called.
-- */
-+ /* 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);
-- rv = ss->opt.enableFalseStart &&
-- !ss->sec.isServer &&
-- !ss->ssl3.hs.isResuming &&
-- ss->ssl3.cwSpec &&
-+ if (ss->ssl3.cwSpec->cipher_def->secret_key_size < 10) {
-+ ss->ssl3.hs.canFalseStart = PR_FALSE;
-+ maybeFalseStart = PR_FALSE;
-+ }
-+ ssl_ReleaseSpecReadLock(ss);
-+ if (!maybeFalseStart) {
-+ return SECSuccess;
-+ }
-
-- /* 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 require an 80-bit cipher and a forward-secret key
-- * exchange. */
-- ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
-- (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);
-- ssl_ReleaseSpecReadLock(ss);
-+ if (!ss->canFalseStartCallback) {
-+ rv = SSL_DefaultCanFalseStart(ss->fd, &ss->ssl3.hs.canFalseStart);
-+ } else {
-+ rv = (ss->canFalseStartCallback)(ss->fd,
-+ ss->canFalseStartCallbackData,
-+ &ss->ssl3.hs.canFalseStart);
-+ }
-+
-+ if (rv != SECSuccess) {
-+ ss->ssl3.hs.canFalseStart = PR_FALSE;
-+ }
-+
- return rv;
- }
-
-@@ -7500,20 +7507,59 @@
- 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.
-+ /* This must be done after we've set ss->ssl3.cwSpec in
-+ * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information
-+ * from cwSpec. This must be done before we call ssl3_CheckFalseStart
-+ * because the false start callback (if any) may need the information from
-+ * the functions that depend on this being set.
- */
-+ 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. */
- }
- }
-+
- rv = ssl3_SendEncryptedExtensions(ss);
- if (rv != SECSuccess) {
- 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));
-+ }
-+ }
-+ }
-+
- rv = ssl3_SendFinished(ss, 0);
- if (rv != SECSuccess) {
- goto loser; /* err code was set. */
-@@ -7526,8 +7572,16 @@
- else
- ss->ssl3.hs.ws = wait_change_cipher;
-
-- /* Do the handshake callback for sslv3 here, if we can false start. */
-- if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
-+ if (ss->handshakeCallback &&
-+ (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
-+ /* Call the handshake callback here for backwards compatibility with
-+ * applications that were using false start before
-+ * canFalseStartCallback was added. Note that we do this after calling
-+ * ssl3_SendFinished, which includes a call to ssl3_FlushHandshake,
-+ * just in case the application is relying on having the handshake
-+ * messages flushed to the network before its handshake callback is
-+ * called.
-+ */
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
-
-@@ -10147,13 +10201,6 @@
-
- ss->ssl3.hs.authCertificatePending = PR_TRUE;
- rv = SECSuccess;
--
-- /* XXX: Async cert validation and False Start don't work together
-- * safely yet; if we leave False Start enabled, we may end up false
-- * starting (sending application data) before we
-- * SSL_AuthCertificateComplete has been called.
-- */
-- ss->opt.enableFalseStart = PR_FALSE;
- }
-
- if (rv != SECSuccess) {
-@@ -10278,6 +10325,12 @@
- } 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
-@@ -10287,7 +10340,39 @@
- rv = SECSuccess;
- }
- } 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->firstHsDone);
-+ PORT_Assert(!ss->sec.isServer);
-+ PORT_Assert(!ss->ssl3.hs.isResuming);
-+ PORT_Assert(ss->ssl3.hs.ws == wait_change_cipher ||
-+ ss->ssl3.hs.ws == wait_finished ||
-+ ss->ssl3.hs.ws == wait_new_session_ticket);
-+
-+ /* ssl3_SendClientSecondRound deferred the false start check because
-+ * certificate authentication was pending, so we have to do it now.
-+ */
-+ if (ss->opt.enableFalseStart &&
-+ !ss->firstHsDone &&
-+ !ss->sec.isServer &&
-+ !ss->ssl3.hs.isResuming &&
-+ (ss->ssl3.hs.ws == wait_change_cipher ||
-+ ss->ssl3.hs.ws == wait_finished ||
-+ ss->ssl3.hs.ws == wait_new_session_ticket)) {
-+ rv = ssl3_CheckFalseStart(ss);
-+ if (rv == SECSuccess &&
-+ ss->handshakeCallback &&
-+ (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
-+ /* Call the handshake callback here for backwards compatibility
-+ * with applications that were using false start before
-+ * canFalseStartCallback was added.
-+ */
-+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
-+ }
-+ } else {
-+ rv = SECSuccess;
-+ }
- }
-
- done:
-@@ -10983,6 +11068,8 @@
- SECStatus
- ssl3_FinishHandshake(sslSocket * ss)
- {
-+ PRBool falseStarted;
-+
- PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
- PORT_Assert( ss->ssl3.hs.restartTarget == NULL );
-@@ -10990,6 +11077,7 @@
- /* The first handshake is now completed. */
- ss->handshake = NULL;
- ss->firstHsDone = PR_TRUE;
-+ ss->enoughFirstHsDone = PR_TRUE;
-
- if (ss->ssl3.hs.cacheSID) {
- (*ss->sec.cache)(ss->sec.ci.sid);
-@@ -10997,9 +11085,14 @@
- }
-
- ss->ssl3.hs.ws = idle_handshake;
-+ falseStarted = ss->ssl3.hs.canFalseStart;
-+ ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
-
-- /* Do the handshake callback for sslv3 here, if we cannot false start. */
-- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
-+ /* Call the handshake callback for sslv3 here, unless we called it already
-+ * for the case where false start was done without a canFalseStartCallback.
-+ */
-+ if (ss->handshakeCallback &&
-+ !(falseStarted && !ss->canFalseStartCallback)) {
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
-
diff --git a/chromium/net/third_party/nss/patches/chacha20poly1305.patch b/chromium/net/third_party/nss/patches/chacha20poly1305.patch
index c858413f3c3..89a71bbf6d7 100644
--- a/chromium/net/third_party/nss/patches/chacha20poly1305.patch
+++ b/chromium/net/third_party/nss/patches/chacha20poly1305.patch
@@ -9,15 +9,15 @@ index 8be517c..53c29f0 100644
+/* 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 + 25)
++#define CKM_NSS_CHACHA20_POLY1305 (CKM_NSS + 26)
+
-+typedef struct CK_AEAD_PARAMS {
-+ CK_BYTE_PTR pIv; /* This is the nonce. */
-+ CK_ULONG ulIvLen;
-+ CK_BYTE_PTR pAAD;
-+ CK_ULONG ulAADLen;
-+ CK_ULONG ulTagBits;
-+} CK_AEAD_PARAMS;
++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
+
@@ -77,18 +77,18 @@ index 8be517c..53c29f0 100644
+ SECItem param;
+ SECStatus rv = SECFailure;
+ unsigned int uOutLen;
-+ CK_AEAD_PARAMS aeadParams;
++ 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(CK_AEAD_PARAMS));
++ memset(&aeadParams, 0, sizeof(aeadParams));
+ aeadParams.pIv = (unsigned char *) additionalData;
+ aeadParams.ulIvLen = 8;
+ aeadParams.pAAD = (unsigned char *) additionalData;
+ aeadParams.ulAADLen = additionalDataLen;
-+ aeadParams.ulTagBits = tagSize * 8;
++ aeadParams.ulTagLen = tagSize;
+
+ if (doDecrypt) {
+ rv = pk11_decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
diff --git a/chromium/net/third_party/nss/patches/channelid.patch b/chromium/net/third_party/nss/patches/channelid.patch
index 46554f9014f..b2ab19d2831 100644
--- a/chromium/net/third_party/nss/patches/channelid.patch
+++ b/chromium/net/third_party/nss/patches/channelid.patch
@@ -151,7 +151,7 @@ diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+ 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)) {
++ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
+ PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
+ rv = SECFailure;
+ goto loser;
diff --git a/chromium/net/third_party/nss/patches/channelid2.patch b/chromium/net/third_party/nss/patches/channelid2.patch
new file mode 100644
index 00000000000..1425c2a80b0
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/channelid2.patch
@@ -0,0 +1,155 @@
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index 882e356..396c408 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -7594,6 +7594,33 @@ ssl3_SendClientSecondRound(sslSocket *ss)
+
+ ssl_ReleaseXmitBufLock(ss); /*******************************/
+
++ if (!ss->ssl3.hs.isResuming &&
++ ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
++ /* If we are negotiating ChannelID on a full handshake then we record
++ * the handshake hashes in |sid| at this point. They will be needed in
++ * the event that we resume this session and use ChannelID on the
++ * resumption handshake. */
++ SSL3Hashes hashes;
++ SECItem *originalHandshakeHash =
++ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
++ PORT_Assert(ss->sec.ci.sid->cached == never_cached);
++
++ ssl_GetSpecReadLock(ss);
++ PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
++ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
++ ssl_ReleaseSpecReadLock(ss);
++ if (rv != SECSuccess) {
++ return rv;
++ }
++
++ PORT_Assert(originalHandshakeHash->len == 0);
++ originalHandshakeHash->data = PORT_Alloc(hashes.len);
++ if (!originalHandshakeHash->data)
++ return SECFailure;
++ originalHandshakeHash->len = hashes.len;
++ memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
++ }
++
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
+ ss->ssl3.hs.ws = wait_new_session_ticket;
+ else
+@@ -10590,6 +10617,7 @@ static SECStatus
+ ssl3_SendEncryptedExtensions(sslSocket *ss)
+ {
+ static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
++ static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
+ /* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
+ * SEQUENCE
+ * SEQUENCE
+@@ -10615,7 +10643,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
+ SECItem *spki = NULL;
+ SSL3Hashes hashes;
+ const unsigned char *pub_bytes;
+- unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + sizeof(SSL3Hashes)];
++ unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
++ sizeof(SSL3Hashes)*2];
++ size_t signed_data_len;
+ unsigned char digest[SHA256_LENGTH];
+ SECItem digest_item;
+ unsigned char signature[64];
+@@ -10665,11 +10696,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
+
+ pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
+
+- memcpy(signed_data, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC));
+- memcpy(signed_data + sizeof(CHANNEL_ID_MAGIC), hashes.u.raw, hashes.len);
++ signed_data_len = 0;
++ memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
++ sizeof(CHANNEL_ID_MAGIC));
++ signed_data_len += sizeof(CHANNEL_ID_MAGIC);
++ if (ss->ssl3.hs.isResuming) {
++ SECItem *originalHandshakeHash =
++ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
++ PORT_Assert(originalHandshakeHash->len > 0);
+
+- rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data,
+- sizeof(CHANNEL_ID_MAGIC) + hashes.len);
++ memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
++ signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
++ memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
++ originalHandshakeHash->len);
++ signed_data_len += originalHandshakeHash->len;
++ }
++ memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
++ signed_data_len += hashes.len;
++
++ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
+ if (rv != SECSuccess)
+ goto loser;
+
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
+index 03cf05c..166022c 100644
+--- a/nss/lib/ssl/ssl3ext.c
++++ b/nss/lib/ssl/ssl3ext.c
+@@ -812,6 +812,15 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
+ return 0;
+ }
+
++ if (ss->sec.ci.sid->cached != never_cached &&
++ ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
++ /* We can't do ChannelID on a connection if we're resuming and didn't
++ * 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;
++ }
++
+ if (append) {
+ SECStatus rv;
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 9c789bf..ca68727 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -705,6 +705,14 @@ struct sslSessionIDStr {
+ */
+ NewSessionTicket sessionTicket;
+ SECItem srvName;
++
++ /* originalHandshakeHash contains the hash of the original, full
++ * handshake prior to the server's final flow. This is either a
++ * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
++ * 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;
+ } ssl3;
+ } u;
+ };
+diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c
+index a6f7349..eb5004c 100644
+--- a/nss/lib/ssl/sslnonce.c
++++ b/nss/lib/ssl/sslnonce.c
+@@ -148,6 +148,9 @@ 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);
++ }
+
+ PORT_ZFree(sid, sizeof(sslSessionID));
+ }
+diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
+index e4d188f..b813c04 100644
+--- a/nss/lib/ssl/sslt.h
++++ b/nss/lib/ssl/sslt.h
+@@ -204,7 +204,7 @@ typedef enum {
+ ssl_app_layer_protocol_xtn = 16,
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+- ssl_channel_id_xtn = 30031,
++ ssl_channel_id_xtn = 30032,
+ ssl_padding_xtn = 35655,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
diff --git a/chromium/net/third_party/nss/patches/cipherorder.patch b/chromium/net/third_party/nss/patches/cipherorder.patch
new file mode 100644
index 00000000000..16d4745dcd8
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/cipherorder.patch
@@ -0,0 +1,106 @@
+diff --git a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
+index 4cf02aa..24627ed 100644
+--- a/nss/lib/ssl/ssl.h
++++ b/nss/lib/ssl/ssl.h
+@@ -265,6 +265,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled);
+ SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
+ SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
+
++/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|,
++ * which must be an array of cipher suite ids of length |len|. All the given
++ * cipher suite ids must appear in the array that is returned by
++ * |SSL_GetImplementedCiphers| and may only appear once, at most. */
++SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers,
++ unsigned int len);
++
+ /* SSLChannelBindingType enumerates the types of supported channel binding
+ * values. See RFC 5929. */
+ typedef enum SSLChannelBindingType {
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index c2d9eeb..350d09c 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -12423,6 +12423,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
+ return rv;
+ }
+
++SECStatus
++ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
++{
++ /* |i| iterates over |ciphers| while |done| and |j| iterate over
++ * |ss->cipherSuites|. */
++ 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++;
++ }
++
++ /* Disable all cipher suites that weren't included. */
++ for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
++ ss->cipherSuites[done].enabled = 0;
++ }
++
++ return SECSuccess;
++}
++
+ /* copy global default policy into socket. */
+ void
+ ssl3_InitSocketPolicy(sslSocket *ss)
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 1e4655f..7521dba 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -1711,6 +1711,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);
+
+ extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
+ extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
+diff --git a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
+index 965215d..9f8286c 100644
+--- a/nss/lib/ssl/sslsock.c
++++ b/nss/lib/ssl/sslsock.c
+@@ -1344,6 +1344,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
+ return rv;
+ }
+
++SECStatus
++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;
++ }
++ return ssl3_CipherOrderSet(ss, ciphers, len);
++}
++
+ SECStatus
+ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
+ {
diff --git a/chromium/net/third_party/nss/patches/disableticketrenewal.patch b/chromium/net/third_party/nss/patches/disableticketrenewal.patch
new file mode 100644
index 00000000000..ec40174bc3f
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/disableticketrenewal.patch
@@ -0,0 +1,17 @@
+Index: net/third_party/nss/ssl/sslnonce.c
+===================================================================
+--- net/third_party/nss/ssl/sslnonce.c (revision 240143)
++++ net/third_party/nss/ssl/sslnonce.c (working copy)
+@@ -438,6 +438,12 @@
+ /* We need to lock the cache, as this sid might already be in the cache. */
+ LOCK_CACHE;
+
++ /* Don't modify sid if it has ever been cached. */
++ if (sid->cached != never_cached) {
++ UNLOCK_CACHE;
++ return SECSuccess;
++ }
++
+ /* A server might have sent us an empty ticket, which has the
+ * effect of clearing the previously known ticket.
+ */
diff --git a/chromium/net/third_party/nss/patches/fallbackscsv.patch b/chromium/net/third_party/nss/patches/fallbackscsv.patch
new file mode 100644
index 00000000000..f8acb2575d8
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/fallbackscsv.patch
@@ -0,0 +1,207 @@
+diff --git a/nss/lib/ssl/SSLerrs.h b/nss/lib/ssl/SSLerrs.h
+index c0d26cc..4ff0b7d 100644
+--- a/nss/lib/ssl/SSLerrs.h
++++ b/nss/lib/ssl/SSLerrs.h
+@@ -421,3 +421,8 @@ ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 130),
+
+ ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 131),
+ "The application could not get a TLS Channel ID.")
++
++ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 132),
++"The connection was using a lesser TLS version as a result of a previous"
++" handshake failure, but the server indicated that it should not have been"
++" needed.")
+diff --git a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
+index 24627ed..067938c 100644
+--- a/nss/lib/ssl/ssl.h
++++ b/nss/lib/ssl/ssl.h
+@@ -163,6 +163,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
+ #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
+ /* Request Signed Certificate Timestamps via TLS extension (client) */
+ #define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
++#define SSL_ENABLE_FALLBACK_SCSV 26 /* Send fallback SCSV in
++ * handshakes. */
+
+ #ifdef SSL_DEPRECATED_FUNCTION
+ /* Old deprecated function names */
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index cf7ef32..946f780 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -3469,6 +3469,9 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
+ 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;
+@@ -4973,7 +4976,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ int num_suites;
+ int actual_count = 0;
+ PRBool isTLS = PR_FALSE;
+- PRBool requestingResume = PR_FALSE;
++ PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
+ PRInt32 total_exten_len = 0;
+ unsigned paddingExtensionLen;
+ unsigned numCompressionMethods;
+@@ -5223,8 +5226,15 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
+ if (!num_suites)
+ return SECFailure; /* count_cipher_suites has set error code. */
++
++ fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
++ ss->version < sid->version);
++ /* make room for SCSV */
+ if (ss->ssl3.hs.sendingSCSV) {
+- ++num_suites; /* make room for SCSV */
++ ++num_suites;
++ }
++ if (fallbackSCSV) {
++ ++num_suites;
+ }
+
+ /* count compression methods */
+@@ -5322,6 +5332,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ }
+ actual_count++;
+ }
++ if (fallbackSCSV) {
++ rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
++ sizeof(ssl3CipherSuite));
++ if (rv != SECSuccess) {
++ 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)) {
+@@ -8037,6 +8055,19 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ 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;
++ }
++ }
++
+ /* grab the list of compression methods. */
+ rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
+ if (rv != SECSuccess) {
+diff --git a/nss/lib/ssl/ssl3prot.h b/nss/lib/ssl/ssl3prot.h
+index 0eab970..4c19ade 100644
+--- a/nss/lib/ssl/ssl3prot.h
++++ b/nss/lib/ssl/ssl3prot.h
+@@ -98,6 +98,7 @@ typedef enum {
+ protocol_version = 70,
+ insufficient_security = 71,
+ internal_error = 80,
++ inappropriate_fallback = 86, /* could also be sent for SSLv3 */
+ user_canceled = 90,
+ no_renegotiation = 100,
+
+diff --git a/nss/lib/ssl/sslerr.h b/nss/lib/ssl/sslerr.h
+index 5a949c9..82ae7df 100644
+--- a/nss/lib/ssl/sslerr.h
++++ b/nss/lib/ssl/sslerr.h
+@@ -196,6 +196,7 @@ SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
+ SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 129),
+ SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 130),
+ SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 131),
++SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 132),
+
+ SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
+ } SSLErrorCodes;
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 7521dba..6d0bc15 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -336,6 +336,7 @@ typedef struct sslOptionsStr {
+ unsigned int cbcRandomIV : 1; /* 24 */
+ unsigned int enableOCSPStapling : 1; /* 25 */
+ unsigned int enableSignedCertTimestamps : 1; /* 26 */
++ unsigned int enableFallbackSCSV : 1; /* 27 */
+ } sslOptions;
+
+ typedef enum { sslHandshakingUndetermined = 0,
+diff --git a/nss/lib/ssl/sslproto.h b/nss/lib/ssl/sslproto.h
+index 6b60a28..621ef37 100644
+--- a/nss/lib/ssl/sslproto.h
++++ b/nss/lib/ssl/sslproto.h
+@@ -172,6 +172,11 @@
+ */
+ #define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
+
++/* TLS_FALLBACK_SCSV is a signaling cipher suite value that indicates that a
++ * handshake is the result of TLS version fallback. This value is not IANA
++ * assigned. */
++#define TLS_FALLBACK_SCSV 0x5600
++
+ /* Cipher Suite Values starting with 0xC000 are defined in informational
+ * RFCs.
+ */
+diff --git a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
+index 9f8286c..f7d44d4 100644
+--- a/nss/lib/ssl/sslsock.c
++++ b/nss/lib/ssl/sslsock.c
+@@ -174,7 +174,8 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* enableFalseStart */
+ PR_TRUE, /* cbcRandomIV */
+ PR_FALSE, /* enableOCSPStapling */
+- PR_FALSE /* enableSignedCertTimestamps */
++ PR_FALSE, /* enableSignedCertTimestamps */
++ PR_FALSE /* enableFallbackSCSV */
+ };
+
+ /*
+@@ -870,6 +871,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+ ss->opt.enableSignedCertTimestamps = on;
+ break;
+
++ case SSL_ENABLE_FALLBACK_SCSV:
++ ss->opt.enableFallbackSCSV = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -943,6 +948,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ss->opt.enableSignedCertTimestamps;
+ break;
++ case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1007,6 +1013,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ssl_defaults.enableSignedCertTimestamps;
+ break;
++ case SSL_ENABLE_FALLBACK_SCSV:
++ on = ssl_defaults.enableFallbackSCSV;
++ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1178,6 +1187,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
+ ssl_defaults.enableSignedCertTimestamps = on;
+ break;
+
++ case SSL_ENABLE_FALLBACK_SCSV:
++ ssl_defaults.enableFallbackSCSV = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
diff --git a/chromium/net/third_party/nss/patches/paddingextension.patch b/chromium/net/third_party/nss/patches/paddingextension.patch
new file mode 100644
index 00000000000..966c4903b21
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/paddingextension.patch
@@ -0,0 +1,142 @@
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index 8b8b758..882e356 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -4975,6 +4975,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ PRBool isTLS = PR_FALSE;
+ PRBool requestingResume = PR_FALSE;
+ PRInt32 total_exten_len = 0;
++ unsigned paddingExtensionLen;
+ unsigned numCompressionMethods;
+ PRInt32 flags;
+
+@@ -5241,6 +5242,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ length += 1 + ss->ssl3.hs.cookieLen;
+ }
+
++ /* A padding extension may be included to ensure that the record containing
++ * the ClientHello doesn't have a length between 256 and 511 bytes
++ * (inclusive). Initial, ClientHello records with such lengths trigger bugs
++ * in F5 devices.
++ *
++ * This is not done for DTLS nor for renegotiation. */
++ if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
++ paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
++ total_exten_len += paddingExtensionLen;
++ length += paddingExtensionLen;
++ } else {
++ paddingExtensionLen = 0;
++ }
++
+ rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
+ if (rv != SECSuccess) {
+ return rv; /* err set by ssl3_AppendHandshake* */
+@@ -5360,6 +5375,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
+ return SECFailure;
+ }
+ maxBytes -= extLen;
++
++ extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
++ if (extLen < 0) {
++ return SECFailure;
++ }
++ maxBytes -= extLen;
++
+ PORT_Assert(!maxBytes);
+ }
+ if (ss->ssl3.hs.sendingSCSV) {
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
+index 0415770..cdebcc9 100644
+--- a/nss/lib/ssl/ssl3ext.c
++++ b/nss/lib/ssl/ssl3ext.c
+@@ -2297,3 +2297,56 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+ loser:
+ return -1;
+ }
++
++unsigned int
++ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
++{
++ unsigned int recordLength = 1 /* handshake message type */ +
++ 3 /* handshake message length */ +
++ clientHelloLength;
++ unsigned int extensionLength;
++
++ if (recordLength < 256 || recordLength >= 512) {
++ return 0;
++ }
++
++ extensionLength = 512 - recordLength;
++ /* Extensions take at least four bytes to encode. */
++ if (extensionLength < 4) {
++ extensionLength = 4;
++ }
++
++ return extensionLength;
++}
++
++/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
++ * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
++ * that we don't trigger bugs in F5 products. */
++PRInt32
++ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
++ PRUint32 maxBytes)
++{
++ unsigned int paddingLen = extensionLen - 4;
++ unsigned char padding[256];
++
++ if (extensionLen == 0) {
++ return 0;
++ }
++
++ if (extensionLen < 4 ||
++ extensionLen > maxBytes ||
++ paddingLen > sizeof(padding)) {
++ PORT_Assert(0);
++ return -1;
++ }
++
++ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
++ return -1;
++ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
++ return -1;
++ memset(padding, 0, paddingLen);
++ if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
++ return -1;
++
++ return extensionLen;
++}
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index 614eed1..9c789bf 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -237,6 +237,13 @@ extern PRInt32
+ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
+ const ssl3HelloExtensionSender *sender);
+
++extern unsigned int
++ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
++
++extern PRInt32
++ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
++ PRUint32 maxBytes);
++
+ /* Socket ops */
+ struct sslSocketOpsStr {
+ int (*connect) (sslSocket *, const PRNetAddr *);
+diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
+index a8007d8..e4d188f 100644
+--- a/nss/lib/ssl/sslt.h
++++ b/nss/lib/ssl/sslt.h
+@@ -205,9 +205,10 @@ typedef enum {
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_channel_id_xtn = 30031,
++ ssl_padding_xtn = 35655,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 11
++#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */
+
+ #endif /* __sslt_h_ */
diff --git a/chromium/net/third_party/nss/patches/paddingextensionall.patch b/chromium/net/third_party/nss/patches/paddingextensionall.patch
new file mode 100644
index 00000000000..f226aacaf68
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/paddingextensionall.patch
@@ -0,0 +1,26 @@
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
+index cdebcc9..03cf05c 100644
+--- a/nss/lib/ssl/ssl3ext.c
++++ b/nss/lib/ssl/ssl3ext.c
+@@ -2306,7 +2306,11 @@ ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
+ clientHelloLength;
+ unsigned int extensionLength;
+
+- if (recordLength < 256 || recordLength >= 512) {
++ /* This condition should be:
++ * if (recordLength < 256 || recordLength >= 512) {
++ * It has been changed, temporarily, to test whether 512 byte ClientHellos
++ * are a compatibility problem. */
++ if (recordLength >= 512) {
+ return 0;
+ }
+
+@@ -2327,7 +2331,7 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes)
+ {
+ unsigned int paddingLen = extensionLen - 4;
+- unsigned char padding[256];
++ unsigned char padding[512];
+
+ if (extensionLen == 0) {
+ return 0;
diff --git a/chromium/net/third_party/nss/patches/sessioncache.patch b/chromium/net/third_party/nss/patches/sessioncache.patch
new file mode 100644
index 00000000000..11fd9fc8e2c
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/sessioncache.patch
@@ -0,0 +1,100 @@
+diff --git a/net/third_party/nss/ssl/exports_win.def b/net/third_party/nss/ssl/exports_win.def
+index e0624f1..a1045bb 100644
+--- a/net/third_party/nss/ssl/exports_win.def
++++ b/net/third_party/nss/ssl/exports_win.def
+@@ -62,3 +62,5 @@ SSL_RestartHandshakeAfterChannelIDReq
+ SSL_GetChannelBinding
+ SSL_PeerSignedCertTimestamps
+ SSL_CipherOrderSet
++SSL_CacheSession
++SSL_CacheSessionUnlocked
+diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
+index bef33fc..6f7c988 100644
+--- a/net/third_party/nss/ssl/ssl.h
++++ b/net/third_party/nss/ssl/ssl.h
+@@ -872,6 +872,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
+ SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
+
+ /*
++** Cache the SSL session associated with fd, if it has not already been cached.
++*/
++SSL_IMPORT SECStatus SSL_CacheSession(PRFileDesc *fd);
++
++/*
++** Cache the SSL session associated with fd, if it has not already been cached.
++** This function may only be called when processing within a callback assigned
++** via SSL_HandshakeCallback
++*/
++SSL_IMPORT SECStatus SSL_CacheSessionUnlocked(PRFileDesc *fd);
++
++/*
+ ** Return a SECItem containing the SSL session ID associated with the fd.
+ */
+ SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
+diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 307a0fe..e2be5e6 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -11240,7 +11240,7 @@ ssl3_FinishHandshake(sslSocket * ss)
+ /* The first handshake is now completed. */
+ ss->handshake = NULL;
+
+- if (ss->ssl3.hs.cacheSID) {
++ if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
+ (*ss->sec.cache)(ss->sec.ci.sid);
+ ss->ssl3.hs.cacheSID = PR_FALSE;
+ }
+diff --git a/net/third_party/nss/ssl/sslsecur.c b/net/third_party/nss/ssl/sslsecur.c
+index 31c343f..99538e5 100644
+--- a/net/third_party/nss/ssl/sslsecur.c
++++ b/net/third_party/nss/ssl/sslsecur.c
+@@ -1474,6 +1474,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
+ return rv;
+ }
+
++static void
++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;
++ }
++}
++
++SECStatus
++SSL_CacheSession(PRFileDesc *fd)
++{
++ sslSocket * ss = ssl_FindSocket(fd);
++ SECStatus rv = SECFailure;
++
++ if (ss) {
++ ssl_Get1stHandshakeLock(ss);
++ ssl_GetSSL3HandshakeLock(ss);
++
++ ssl3_CacheSessionUnlocked(ss);
++ rv = SECSuccess;
++
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ ssl_Release1stHandshakeLock(ss);
++ }
++ return rv;
++}
++
++SECStatus
++SSL_CacheSessionUnlocked(PRFileDesc *fd)
++{
++ sslSocket * ss = ssl_FindSocket(fd);
++ SECStatus rv = SECFailure;
++
++ if (ss) {
++ ssl3_CacheSessionUnlocked(ss);
++ rv = SECSuccess;
++ }
++ return rv;
++}
++
+ SECItem *
+ SSL_GetSessionID(PRFileDesc *fd)
+ {
diff --git a/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch b/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch
new file mode 100644
index 00000000000..8ac3079f19f
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/signedcertificatetimestamps.patch
@@ -0,0 +1,421 @@
+diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
+index 67cc3a7..4cf02aa 100644
+--- a/net/third_party/nss/ssl/ssl.h
++++ b/net/third_party/nss/ssl/ssl.h
+@@ -161,6 +161,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
+ */
+ #define SSL_CBC_RANDOM_IV 23
+ #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
++/* Request Signed Certificate Timestamps via TLS extension (client) */
++#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
+
+ #ifdef SSL_DEPRECATED_FUNCTION
+ /* Old deprecated function names */
+@@ -464,6 +466,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/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 0f1eea4..c2d9eeb 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -6639,10 +6639,22 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+ sid->u.ssl3.sessionIDLength = sidBytes.len;
+ PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
+
++ /* 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;
+ ss->ssl3.hs.ws = wait_server_cert;
+
+ 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. */
+@@ -6668,6 +6680,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/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
+index adb81ed..02e104d 100644
+--- a/net/third_party/nss/ssl/ssl3ext.c
++++ b/net/third_party/nss/ssl/ssl3ext.c
+@@ -81,6 +81,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);
+
+ /*
+ * Write bytes. Using this function means the SECItem structure
+@@ -259,6 +265,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
++ { ssl_signed_certificate_timestamp_xtn,
++ &ssl3_ClientHandleSignedCertTimestampXtn },
+ { -1, NULL }
+ };
+
+@@ -287,7 +295,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
+ { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
+ { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
+- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
++ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
++ { ssl_signed_certificate_timestamp_xtn,
++ &ssl3_ClientSendSignedCertTimestampXtn }
+ /* any extra entries will appear as { 0, NULL } */
+ };
+
+@@ -2364,3 +2374,65 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+
+ return extensionLen;
+ }
++
++/* 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_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;
++ } 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)
++{
++ /* 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/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
+index 79aca60..1e4655f 100644
+--- a/net/third_party/nss/ssl/sslimpl.h
++++ b/net/third_party/nss/ssl/sslimpl.h
+@@ -312,29 +312,30 @@ typedef struct sslOptionsStr {
+ * 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 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 enableSignedCertTimestamps : 1; /* 26 */
+ } sslOptions;
+
+ typedef enum { sslHandshakingUndetermined = 0,
+@@ -713,6 +714,11 @@ struct sslSessionIDStr {
+ * 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;
+ } ssl3;
+ } u;
+ };
+@@ -804,6 +810,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/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c
+index eb5004c..1ca19ca 100644
+--- a/net/third_party/nss/ssl/sslnonce.c
++++ b/net/third_party/nss/ssl/sslnonce.c
+@@ -122,7 +122,21 @@ ssl_DestroySID(sslSessionID *sid)
+ if (sid->version < SSL_LIBRARY_VERSION_3_0) {
+ SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
+ SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
++ } else {
++ if (sid->u.ssl3.sessionTicket.ticket.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
++ }
++ if (sid->u.ssl3.srvName.data) {
++ SECITEM_FreeItem(&sid->u.ssl3.srvName, 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->peerID != NULL)
+ PORT_Free((void *)sid->peerID); /* CONST */
+
+@@ -142,16 +156,7 @@ ssl_DestroySID(sslSessionID *sid)
+ if ( sid->localCert ) {
+ CERT_DestroyCertificate(sid->localCert);
+ }
+- if (sid->u.ssl3.sessionTicket.ticket.data) {
+- SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
+- }
+- 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);
+- }
+-
++
+ PORT_ZFree(sid, sizeof(sslSessionID));
+ }
+
+diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
+index b5c17f0..965215d 100644
+--- a/net/third_party/nss/ssl/sslsock.c
++++ b/net/third_party/nss/ssl/sslsock.c
+@@ -173,7 +173,8 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* requireSafeNegotiation */
+ PR_FALSE, /* enableFalseStart */
+ PR_TRUE, /* cbcRandomIV */
+- PR_FALSE /* enableOCSPStapling */
++ PR_FALSE, /* enableOCSPStapling */
++ PR_FALSE /* enableSignedCertTimestamps */
+ };
+
+ /*
+@@ -865,6 +866,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+ ss->opt.enableOCSPStapling = on;
+ break;
+
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ ss->opt.enableSignedCertTimestamps = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -935,6 +940,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+ 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_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_OCSP_STAPLING:
+ on = ssl_defaults.enableOCSPStapling;
+ break;
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ on = ssl_defaults.enableSignedCertTimestamps;
++ break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -1163,6 +1174,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
+ ssl_defaults.enableOCSPStapling = on;
+ break;
+
++ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
++ ssl_defaults.enableSignedCertTimestamps = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+@@ -1993,6 +2008,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);
+@@ -3133,4 +3171,3 @@ loser:
+ }
+ return ss;
+ }
+-
+diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h
+index b813c04..1f5e2c6 100644
+--- a/net/third_party/nss/ssl/sslt.h
++++ b/net/third_party/nss/ssl/sslt.h
+@@ -202,6 +202,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_session_ticket_xtn = 35,
+ ssl_next_proto_nego_xtn = 13172,
+ ssl_channel_id_xtn = 30032,
+@@ -209,6 +210,6 @@ typedef enum {
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */
++#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */
+
+ #endif /* __sslt_h_ */
diff --git a/chromium/net/third_party/nss/patches/sslnoncestatics.patch b/chromium/net/third_party/nss/patches/sslnoncestatics.patch
new file mode 100644
index 00000000000..336fe1d5587
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/sslnoncestatics.patch
@@ -0,0 +1,15 @@
+diff --git a/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c
+index 758aa4e..a3e6e0a 100644
+--- a/net/third_party/nss/ssl/sslnonce.c
++++ b/net/third_party/nss/ssl/sslnonce.c
+@@ -21,8 +21,8 @@
+ PRUint32 ssl_sid_timeout = 100;
+ PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
+
+-static sslSessionID *cache = NULL;
+-static PZLock * cacheLock = NULL;
++sslSessionID *cache = NULL;
++PZLock * cacheLock = NULL;
+
+ /* sids can be in one of 4 states:
+ *
diff --git a/chromium/net/third_party/nss/patches/tls12backuphash2.patch b/chromium/net/third_party/nss/patches/tls12backuphash2.patch
new file mode 100644
index 00000000000..85e5308db6b
--- /dev/null
+++ b/chromium/net/third_party/nss/patches/tls12backuphash2.patch
@@ -0,0 +1,127 @@
+diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
+index 06992e0..cf7ef32 100644
+--- a/net/third_party/nss/ssl/ssl3con.c
++++ b/net/third_party/nss/ssl/ssl3con.c
+@@ -6973,14 +6973,27 @@ no_memory: /* no-memory error has already been set. */
+
+
+ /*
+- * Returns true if the client authentication key is an RSA or DSA key that
+- * may be able to sign only SHA-1 hashes.
++ * Returns the TLS signature algorithm for the client authentication key and
++ * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes.
+ */
+-static PRBool
+-ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
++static SECStatus
++ssl3_ExtractClientKeyInfo(sslSocket *ss,
++ TLSSignatureAlgorithm *sigAlg,
++ PRBool *preferSha1)
+ {
++ SECStatus rv = SECSuccess;
+ SECKEYPublicKey *pubk;
+- PRBool prefer_sha1 = PR_FALSE;
++
++ pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
++ if (pubk == NULL) {
++ rv = SECFailure;
++ goto done;
++ }
++
++ rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg);
++ if (rv != SECSuccess) {
++ goto done;
++ }
+
+ #if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
+ /* If the key is in CAPI, assume conservatively that the CAPI service
+@@ -6989,7 +7002,8 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
+ 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. */
+- return PR_TRUE;
++ *preferSha1 = PR_TRUE;
++ goto done;
+ }
+ #endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
+
+@@ -6999,38 +7013,61 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
+ * older, DSA key size is at most 1024 bits and the hash function must
+ * be SHA-1.
+ */
+- pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
+- if (pubk == NULL) {
+- return PR_FALSE;
+- }
+ if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
+- prefer_sha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
++ *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
++ } else {
++ *preferSha1 = PR_FALSE;
+ }
+- SECKEY_DestroyPublicKey(pubk);
+- return prefer_sha1;
++
++ done:
++ if (pubk)
++ SECKEY_DestroyPublicKey(pubk);
++ return rv;
+ }
+
+-/* Destroys the backup handshake hash context if we don't need it. */
++/* Destroys the backup handshake hash context if we don't need it. Note that
++ * this function selects the hash algorithm for client authentication
++ * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
++ * to determine whether to use SHA-1 or SHA-256. */
+ static void
+ ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
+ const SECItem *algorithms)
+ {
+- PRBool need_backup_hash = PR_FALSE;
++ SECStatus rv;
++ TLSSignatureAlgorithm sigAlg;
++ PRBool preferSha1;
++ PRBool supportsSha1 = PR_FALSE;
++ PRBool supportsSha256 = PR_FALSE;
++ PRBool needBackupHash = PR_FALSE;
+ unsigned int i;
+
+ PORT_Assert(ss->ssl3.hs.md5);
+- if (ssl3_ClientKeyPrefersSHA1(ss)) {
+- /* Use SHA-1 if the server supports it. */
+- for (i = 0; i < algorithms->len; i += 2) {
+- if (algorithms->data[i] == tls_hash_sha1 &&
+- (algorithms->data[i+1] == tls_sig_rsa ||
+- algorithms->data[i+1] == tls_sig_dsa)) {
+- need_backup_hash = PR_TRUE;
+- break;
++
++ /* Determine the key's signature algorithm and whether it prefers SHA-1. */
++ rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
++ if (rv != SECSuccess) {
++ 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] == tls_hash_sha1) {
++ supportsSha1 = PR_TRUE;
++ } else if (algorithms->data[i] == tls_hash_sha256) {
++ supportsSha256 = PR_TRUE;
+ }
+ }
+ }
+- if (!need_backup_hash) {
++
++ /* 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;
++ }
++
++done:
++ if (!needBackupHash) {
+ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
+ ss->ssl3.hs.md5 = NULL;
+ }
diff --git a/chromium/net/third_party/nss/ssl/SSLerrs.h b/chromium/net/third_party/nss/ssl/SSLerrs.h
index c0d26ccfadc..4ff0b7ddda4 100644
--- a/chromium/net/third_party/nss/ssl/SSLerrs.h
+++ b/chromium/net/third_party/nss/ssl/SSLerrs.h
@@ -421,3 +421,8 @@ ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 130),
ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 131),
"The application could not get a TLS Channel ID.")
+
+ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 132),
+"The connection was using a lesser TLS version as a result of a previous"
+" handshake failure, but the server indicated that it should not have been"
+" needed.")
diff --git a/chromium/net/third_party/nss/ssl/exports_win.def b/chromium/net/third_party/nss/ssl/exports_win.def
index 09c70b0b410..a1045bb9212 100644
--- a/chromium/net/third_party/nss/ssl/exports_win.def
+++ b/chromium/net/third_party/nss/ssl/exports_win.def
@@ -50,6 +50,8 @@ SSL_ExportKeyingMaterial
SSL_VersionRangeSet
SSL_GetSRTPCipher
SSL_SetSRTPCiphers
+SSL_RecommendedCanFalseStart
+SSL_SetCanFalseStartCallback
; Chromium patches
SSL_PeerCertificateChain
@@ -58,3 +60,7 @@ 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/ssl.h b/chromium/net/third_party/nss/ssl/ssl.h
index 47468a0a289..6f7c9889f00 100644
--- a/chromium/net/third_party/nss/ssl/ssl.h
+++ b/chromium/net/third_party/nss/ssl/ssl.h
@@ -129,13 +129,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
* it saves a round trip for client-speaks-first protocols when performing a
* full handshake.
*
- * See SSL_DefaultCanFalseStart for the default criteria that NSS uses to
- * determine whether to false start or not. See SSL_SetCanFalseStartCallback
- * for how to change that criteria. In addition to those criteria, false start
- * will only be done when the server selects a cipher suite with an effective
- * key length of 80 bits or more (including RC4-128). Also, see
- * SSL_HandshakeCallback for a description on how false start affects when the
- * handshake callback gets called.
+ * In addition to enabling this option, the application must register a
+ * callback using the SSL_SetCanFalseStartCallback function.
*/
/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
@@ -166,6 +161,10 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
*/
#define SSL_CBC_RANDOM_IV 23
#define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
+/* Request Signed Certificate Timestamps via TLS extension (client) */
+#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
+#define SSL_ENABLE_FALLBACK_SCSV 26 /* Send fallback SCSV in
+ * handshakes. */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
@@ -268,6 +267,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled);
SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy);
SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
+/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|,
+ * which must be an array of cipher suite ids of length |len|. All the given
+ * cipher suite ids must appear in the array that is returned by
+ * |SSL_GetImplementedCiphers| and may only appear once, at most. */
+SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers,
+ unsigned int len);
+
/* SSLChannelBindingType enumerates the types of supported channel binding
* values. See RFC 5929. */
typedef enum SSLChannelBindingType {
@@ -469,6 +475,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
@@ -749,45 +772,30 @@ SSL_IMPORT SECStatus SSL_SetMaxServerCacheLocks(PRUint32 maxLocks);
SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
/*
-** Set the callback that normally gets called when the TLS handshake
-** is complete. If false start is not enabled, then the handshake callback is
-** called after verifying the peer's Finished message and before sending
-** outgoing application data and before processing incoming application data.
-**
-** If false start is enabled and there is a custom CanFalseStartCallback
-** callback set, then the handshake callback gets called after the peer's
-** Finished message has been verified, which may be after application data is
-** sent.
+** Set the callback that gets called when a TLS handshake is complete. The
+** handshake callback is called after verifying the peer's Finished message and
+** before processing incoming application data.
**
-** If false start is enabled and there is not a custom CanFalseStartCallback
-** callback established with SSL_SetCanFalseStartCallback then the handshake
-** callback gets called before any application data is sent, which may be
-** before the peer's Finished message has been verified.
+** For the initial handshake: If the handshake false started (see
+** SSL_ENABLE_FALSE_START), then application data may already have been sent
+** 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);
-/* Applications that wish to customize TLS false start should set this callback
+/* Applications that wish to enable TLS false start must set this callback
** function. NSS will invoke the functon to determine if a particular
** connection should use false start or not. SECSuccess indicates that the
** callback completed successfully, and if so *canFalseStart indicates if false
** start can be used. If the callback does not return SECSuccess then the
-** handshake will be canceled.
-**
-** Applications that do not set the callback will use an internal set of
-** criteria to determine if the connection should false start. If
-** the callback is set false start will never be used without invoking the
-** callback function, but some connections (e.g. resumed connections) will
-** never use false start and therefore will not invoke the callback.
-**
-** NSS's internal criteria for this connection can be evaluated by calling
-** SSL_DefaultCanFalseStart() from the custom callback.
+** handshake will be canceled. NSS's recommended criteria can be evaluated by
+** calling SSL_RecommendedCanFalseStart.
**
-** See the description of SSL_HandshakeCallback for important information on
-** how registering a custom false start callback affects when the handshake
-** callback gets called.
+** 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)(
PRFileDesc *fd, void *arg, PRBool *canFalseStart);
@@ -795,12 +803,13 @@ typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
-/* A utility function that can be called from a custom CanFalseStartCallback
-** function to determine what NSS would have done for this connection if the
-** custom callback was not implemented.
-**/
-SSL_IMPORT SECStatus SSL_DefaultCanFalseStart(PRFileDesc *fd,
- PRBool *canFalseStart);
+/* This function sets *canFalseStart according to the recommended criteria for
+** false start. These criteria may change from release to release and may depend
+** on which handshake features have been negotiated and/or properties of the
+** certifciates/keys used on the connection.
+*/
+SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
+ PRBool *canFalseStart);
/*
** For the server, request a new handshake. For the client, begin a new
@@ -863,6 +872,18 @@ SSL_IMPORT int SSL_DataPending(PRFileDesc *fd);
SSL_IMPORT SECStatus SSL_InvalidateSession(PRFileDesc *fd);
/*
+** Cache the SSL session associated with fd, if it has not already been cached.
+*/
+SSL_IMPORT SECStatus SSL_CacheSession(PRFileDesc *fd);
+
+/*
+** Cache the SSL session associated with fd, if it has not already been cached.
+** This function may only be called when processing within a callback assigned
+** via SSL_HandshakeCallback
+*/
+SSL_IMPORT SECStatus SSL_CacheSessionUnlocked(PRFileDesc *fd);
+
+/*
** Return a SECItem containing the SSL session ID associated with the fd.
*/
SSL_IMPORT SECItem *SSL_GetSessionID(PRFileDesc *fd);
diff --git a/chromium/net/third_party/nss/ssl/ssl3con.c b/chromium/net/third_party/nss/ssl/ssl3con.c
index 8b8b758c0b4..e2be5e6f5da 100644
--- a/chromium/net/third_party/nss/ssl/ssl3con.c
+++ b/chromium/net/third_party/nss/ssl/ssl3con.c
@@ -3469,6 +3469,9 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
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;
@@ -4973,8 +4976,9 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
int num_suites;
int actual_count = 0;
PRBool isTLS = PR_FALSE;
- PRBool requestingResume = PR_FALSE;
+ PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE;
PRInt32 total_exten_len = 0;
+ unsigned paddingExtensionLen;
unsigned numCompressionMethods;
PRInt32 flags;
@@ -5222,8 +5226,15 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
if (!num_suites)
return SECFailure; /* count_cipher_suites has set error code. */
+
+ fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume ||
+ ss->version < sid->version);
+ /* make room for SCSV */
if (ss->ssl3.hs.sendingSCSV) {
- ++num_suites; /* make room for SCSV */
+ ++num_suites;
+ }
+ if (fallbackSCSV) {
+ ++num_suites;
}
/* count compression methods */
@@ -5241,6 +5252,20 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
length += 1 + ss->ssl3.hs.cookieLen;
}
+ /* A padding extension may be included to ensure that the record containing
+ * the ClientHello doesn't have a length between 256 and 511 bytes
+ * (inclusive). Initial, ClientHello records with such lengths trigger bugs
+ * in F5 devices.
+ *
+ * This is not done for DTLS nor for renegotiation. */
+ if (!IS_DTLS(ss) && isTLS && !ss->firstHsDone) {
+ paddingExtensionLen = ssl3_CalculatePaddingExtensionLength(length);
+ total_exten_len += paddingExtensionLen;
+ length += paddingExtensionLen;
+ } else {
+ paddingExtensionLen = 0;
+ }
+
rv = ssl3_AppendHandshakeHeader(ss, client_hello, length);
if (rv != SECSuccess) {
return rv; /* err set by ssl3_AppendHandshake* */
@@ -5307,6 +5332,14 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
}
actual_count++;
}
+ if (fallbackSCSV) {
+ rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV,
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess) {
+ 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)) {
@@ -5360,6 +5393,13 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
return SECFailure;
}
maxBytes -= extLen;
+
+ extLen = ssl3_AppendPaddingExtension(ss, paddingExtensionLen, maxBytes);
+ if (extLen < 0) {
+ return SECFailure;
+ }
+ maxBytes -= extLen;
+
PORT_Assert(!maxBytes);
}
if (ss->ssl3.hs.sendingSCSV) {
@@ -6617,10 +6657,22 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
sid->u.ssl3.sessionIDLength = sidBytes.len;
PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
+ /* 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;
ss->ssl3.hs.ws = wait_server_cert;
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. */
@@ -6646,6 +6698,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;
}
@@ -6936,14 +6991,27 @@ no_memory: /* no-memory error has already been set. */
/*
- * Returns true if the client authentication key is an RSA or DSA key that
- * may be able to sign only SHA-1 hashes.
+ * Returns the TLS signature algorithm for the client authentication key and
+ * whether it is an RSA or DSA key that may be able to sign only SHA-1 hashes.
*/
-static PRBool
-ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
+static SECStatus
+ssl3_ExtractClientKeyInfo(sslSocket *ss,
+ TLSSignatureAlgorithm *sigAlg,
+ PRBool *preferSha1)
{
+ SECStatus rv = SECSuccess;
SECKEYPublicKey *pubk;
- PRBool prefer_sha1 = PR_FALSE;
+
+ pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
+ if (pubk == NULL) {
+ rv = SECFailure;
+ goto done;
+ }
+
+ rv = ssl3_TLSSignatureAlgorithmForKeyType(pubk->keyType, sigAlg);
+ if (rv != SECSuccess) {
+ goto done;
+ }
#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
/* If the key is in CAPI, assume conservatively that the CAPI service
@@ -6952,7 +7020,8 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
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. */
- return PR_TRUE;
+ *preferSha1 = PR_TRUE;
+ goto done;
}
#endif /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
@@ -6962,38 +7031,61 @@ ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
* older, DSA key size is at most 1024 bits and the hash function must
* be SHA-1.
*/
- pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
- if (pubk == NULL) {
- return PR_FALSE;
- }
if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
- prefer_sha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
+ *preferSha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
+ } else {
+ *preferSha1 = PR_FALSE;
}
- SECKEY_DestroyPublicKey(pubk);
- return prefer_sha1;
+
+ done:
+ if (pubk)
+ SECKEY_DestroyPublicKey(pubk);
+ return rv;
}
-/* Destroys the backup handshake hash context if we don't need it. */
+/* Destroys the backup handshake hash context if we don't need it. Note that
+ * this function selects the hash algorithm for client authentication
+ * signatures; ssl3_SendCertificateVerify uses the presence of the backup hash
+ * to determine whether to use SHA-1 or SHA-256. */
static void
ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
const SECItem *algorithms)
{
- PRBool need_backup_hash = PR_FALSE;
+ SECStatus rv;
+ TLSSignatureAlgorithm sigAlg;
+ PRBool preferSha1;
+ PRBool supportsSha1 = PR_FALSE;
+ PRBool supportsSha256 = PR_FALSE;
+ PRBool needBackupHash = PR_FALSE;
unsigned int i;
PORT_Assert(ss->ssl3.hs.md5);
- if (ssl3_ClientKeyPrefersSHA1(ss)) {
- /* Use SHA-1 if the server supports it. */
- for (i = 0; i < algorithms->len; i += 2) {
- if (algorithms->data[i] == tls_hash_sha1 &&
- (algorithms->data[i+1] == tls_sig_rsa ||
- algorithms->data[i+1] == tls_sig_dsa)) {
- need_backup_hash = PR_TRUE;
- break;
+
+ /* Determine the key's signature algorithm and whether it prefers SHA-1. */
+ rv = ssl3_ExtractClientKeyInfo(ss, &sigAlg, &preferSha1);
+ if (rv != SECSuccess) {
+ 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] == tls_hash_sha1) {
+ supportsSha1 = PR_TRUE;
+ } else if (algorithms->data[i] == tls_hash_sha256) {
+ supportsSha256 = PR_TRUE;
}
}
}
- if (!need_backup_hash) {
+
+ /* 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;
+ }
+
+done:
+ if (!needBackupHash) {
PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
ss->ssl3.hs.md5 = NULL;
}
@@ -7352,40 +7444,69 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
static SECStatus
ssl3_CheckFalseStart(sslSocket *ss)
{
- SECStatus rv;
- PRBool maybeFalseStart = PR_TRUE;
-
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
PORT_Assert( !ss->ssl3.hs.authCertificatePending );
-
- /* 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);
- if (ss->ssl3.cwSpec->cipher_def->secret_key_size < 10) {
- ss->ssl3.hs.canFalseStart = PR_FALSE;
- maybeFalseStart = PR_FALSE;
- }
- ssl_ReleaseSpecReadLock(ss);
- if (!maybeFalseStart) {
- return SECSuccess;
- }
+ PORT_Assert( !ss->ssl3.hs.canFalseStart );
if (!ss->canFalseStartCallback) {
- rv = SSL_DefaultCanFalseStart(ss->fd, &ss->ssl3.hs.canFalseStart);
+ SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
+ SSL_GETPID(), ss->fd));
} else {
- rv = (ss->canFalseStartCallback)(ss->fd,
- ss->canFalseStartCallbackData,
- &ss->ssl3.hs.canFalseStart);
+ 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. */
+ 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 {
+ 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;
+ }
}
- if (rv != SECSuccess) {
- ss->ssl3.hs.canFalseStart = PR_FALSE;
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
+ return SECSuccess;
+}
+
+PRBool
+ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
+{
+ PRBool result;
+
+ 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;
}
- return rv;
+ return result;
}
static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
@@ -7475,6 +7596,9 @@ ssl3_SendClientSecondRound(sslSocket *ss)
}
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;
}
@@ -7544,7 +7668,7 @@ ssl3_SendClientSecondRound(sslSocket *ss)
* 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.
+ * done before its false start callback is called.
*/
ssl_ReleaseXmitBufLock(ss);
rv = ssl3_CheckFalseStart(ss);
@@ -7572,23 +7696,39 @@ ssl3_SendClientSecondRound(sslSocket *ss)
ssl_ReleaseXmitBufLock(ss); /*******************************/
+ if (!ss->ssl3.hs.isResuming &&
+ ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
+ /* If we are negotiating ChannelID on a full handshake then we record
+ * the handshake hashes in |sid| at this point. They will be needed in
+ * the event that we resume this session and use ChannelID on the
+ * resumption handshake. */
+ SSL3Hashes hashes;
+ SECItem *originalHandshakeHash =
+ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
+ PORT_Assert(ss->sec.ci.sid->cached == never_cached);
+
+ ssl_GetSpecReadLock(ss);
+ PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
+ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
+ ssl_ReleaseSpecReadLock(ss);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ PORT_Assert(originalHandshakeHash->len == 0);
+ originalHandshakeHash->data = PORT_Alloc(hashes.len);
+ if (!originalHandshakeHash->data)
+ return SECFailure;
+ originalHandshakeHash->len = hashes.len;
+ memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
+ }
+
if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
ss->ssl3.hs.ws = wait_new_session_ticket;
else
ss->ssl3.hs.ws = wait_change_cipher;
- if (ss->handshakeCallback &&
- (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
- /* Call the handshake callback here for backwards compatibility with
- * applications that were using false start before
- * canFalseStartCallback was added. Note that we do this after calling
- * ssl3_SendFinished, which includes a call to ssl3_FlushHandshake,
- * just in case the application is relying on having the handshake
- * messages flushed to the network before its handshake callback is
- * called.
- */
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
+ PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss));
return SECSuccess;
@@ -7915,6 +8055,19 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
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;
+ }
+ }
+
/* grab the list of compression methods. */
rv = ssl3_ConsumeHandshakeVariable(ss, &comps, 1, &b, &length);
if (rv != SECSuccess) {
@@ -10345,36 +10498,24 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
rv = SECSuccess;
}
} else {
- SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race"
- " with peer's finished message", SSL_GETPID(), ss->fd));
+ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
+ " peer's finished message", SSL_GETPID(), ss->fd));
PORT_Assert(!ss->firstHsDone);
PORT_Assert(!ss->sec.isServer);
PORT_Assert(!ss->ssl3.hs.isResuming);
- PORT_Assert(ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_finished ||
- ss->ssl3.hs.ws == wait_new_session_ticket);
+ PORT_Assert(ss->ssl3.hs.ws != idle_handshake);
- /* ssl3_SendClientSecondRound deferred the false start check because
- * certificate authentication was pending, so we have to do it now.
- */
if (ss->opt.enableFalseStart &&
!ss->firstHsDone &&
!ss->sec.isServer &&
!ss->ssl3.hs.isResuming &&
- (ss->ssl3.hs.ws == wait_change_cipher ||
- ss->ssl3.hs.ws == wait_finished ||
- ss->ssl3.hs.ws == wait_new_session_ticket)) {
+ 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);
- if (rv == SECSuccess &&
- ss->handshakeCallback &&
- (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
- /* Call the handshake callback here for backwards compatibility
- * with applications that were using false start before
- * canFalseStartCallback was added.
- */
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
} else {
rv = SECSuccess;
}
@@ -10568,6 +10709,7 @@ static SECStatus
ssl3_SendEncryptedExtensions(sslSocket *ss)
{
static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
+ static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
/* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
* SEQUENCE
* SEQUENCE
@@ -10593,7 +10735,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
SECItem *spki = NULL;
SSL3Hashes hashes;
const unsigned char *pub_bytes;
- unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + sizeof(SSL3Hashes)];
+ unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
+ sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
+ sizeof(SSL3Hashes)*2];
+ size_t signed_data_len;
unsigned char digest[SHA256_LENGTH];
SECItem digest_item;
unsigned char signature[64];
@@ -10635,7 +10780,7 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
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)) {
+ memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) {
PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY);
rv = SECFailure;
goto loser;
@@ -10643,11 +10788,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
- memcpy(signed_data, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC));
- memcpy(signed_data + sizeof(CHANNEL_ID_MAGIC), hashes.u.raw, hashes.len);
-
- rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data,
- sizeof(CHANNEL_ID_MAGIC) + hashes.len);
+ signed_data_len = 0;
+ memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
+ sizeof(CHANNEL_ID_MAGIC));
+ signed_data_len += sizeof(CHANNEL_ID_MAGIC);
+ if (ss->ssl3.hs.isResuming) {
+ SECItem *originalHandshakeHash =
+ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
+ PORT_Assert(originalHandshakeHash->len > 0);
+
+ memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
+ sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
+ signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
+ memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
+ originalHandshakeHash->len);
+ signed_data_len += originalHandshakeHash->len;
+ }
+ memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
+ signed_data_len += hashes.len;
+
+ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
if (rv != SECSuccess)
goto loser;
@@ -11003,9 +11163,6 @@ xmit_loser:
return rv;
}
- ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
-
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
effectiveExchKeyType = kt_rsa;
} else {
@@ -11070,36 +11227,28 @@ xmit_loser:
return rv;
}
+/* The return type is SECStatus instead of void because this function needs
+ * to have type sslRestartTarget.
+ */
SECStatus
ssl3_FinishHandshake(sslSocket * ss)
{
- PRBool falseStarted;
-
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->firstHsDone = PR_TRUE;
- ss->enoughFirstHsDone = PR_TRUE;
- if (ss->ssl3.hs.cacheSID) {
+ if (ss->ssl3.hs.cacheSID && ss->sec.isServer) {
(*ss->sec.cache)(ss->sec.ci.sid);
ss->ssl3.hs.cacheSID = PR_FALSE;
}
- ss->ssl3.hs.ws = idle_handshake;
- falseStarted = ss->ssl3.hs.canFalseStart;
ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
+ ss->ssl3.hs.ws = idle_handshake;
- /* Call the handshake callback for sslv3 here, unless we called it already
- * for the case where false start was done without a canFalseStartCallback.
- */
- if (ss->handshakeCallback &&
- !(falseStarted && !ss->canFalseStartCallback)) {
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
- }
+ ssl_FinishHandshake(ss);
return SECSuccess;
}
@@ -12064,7 +12213,6 @@ process_it:
ssl_ReleaseSSL3HandshakeLock(ss);
return rv;
-
}
/*
@@ -12343,6 +12491,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
return rv;
}
+SECStatus
+ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len)
+{
+ /* |i| iterates over |ciphers| while |done| and |j| iterate over
+ * |ss->cipherSuites|. */
+ 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++;
+ }
+
+ /* Disable all cipher suites that weren't included. */
+ for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) {
+ ss->cipherSuites[done].enabled = 0;
+ }
+
+ return SECSuccess;
+}
+
/* copy global default policy into socket. */
void
ssl3_InitSocketPolicy(sslSocket *ss)
diff --git a/chromium/net/third_party/nss/ssl/ssl3ext.c b/chromium/net/third_party/nss/ssl/ssl3ext.c
index 04157701e90..f2db28c924f 100644
--- a/chromium/net/third_party/nss/ssl/ssl3ext.c
+++ b/chromium/net/third_party/nss/ssl/ssl3ext.c
@@ -81,6 +81,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);
/*
* Write bytes. Using this function means the SECItem structure
@@ -259,6 +265,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
{ ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
{ ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
{ ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
+ { ssl_signed_certificate_timestamp_xtn,
+ &ssl3_ClientHandleSignedCertTimestampXtn },
{ -1, NULL }
};
@@ -287,7 +295,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
{ ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
{ ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
{ ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
- { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
+ { ssl_signed_certificate_timestamp_xtn,
+ &ssl3_ClientSendSignedCertTimestampXtn }
/* any extra entries will appear as { 0, NULL } */
};
@@ -812,6 +822,15 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
return 0;
}
+ if (ss->sec.ci.sid->cached != never_cached &&
+ ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
+ /* We can't do ChannelID on a connection if we're resuming and didn't
+ * 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;
+ }
+
if (append) {
SECStatus rv;
rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
@@ -2297,3 +2316,118 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
loser:
return -1;
}
+
+unsigned int
+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength)
+{
+ unsigned int recordLength = 1 /* handshake message type */ +
+ 3 /* handshake message length */ +
+ clientHelloLength;
+ unsigned int extensionLength;
+
+ if (recordLength < 256 || recordLength >= 512) {
+ return 0;
+ }
+
+ extensionLength = 512 - recordLength;
+ /* Extensions take at least four bytes to encode. */
+ if (extensionLength < 4) {
+ extensionLength = 4;
+ }
+
+ return extensionLength;
+}
+
+/* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a
+ * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures
+ * that we don't trigger bugs in F5 products. */
+PRInt32
+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes)
+{
+ unsigned int paddingLen = extensionLen - 4;
+ unsigned char padding[256];
+
+ if (extensionLen == 0) {
+ return 0;
+ }
+
+ if (extensionLen < 4 ||
+ extensionLen > maxBytes ||
+ paddingLen > sizeof(padding)) {
+ PORT_Assert(0);
+ return -1;
+ }
+
+ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2))
+ return -1;
+ if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2))
+ return -1;
+ memset(padding, 0, paddingLen);
+ if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen))
+ return -1;
+
+ return extensionLen;
+}
+
+/* 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_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;
+ } 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)
+{
+ /* 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/chromium/net/third_party/nss/ssl/ssl3gthr.c b/chromium/net/third_party/nss/ssl/ssl3gthr.c
index 7385d6504e8..39cefa7c310 100644
--- a/chromium/net/third_party/nss/ssl/ssl3gthr.c
+++ b/chromium/net/third_party/nss/ssl/ssl3gthr.c
@@ -275,11 +275,17 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
{
SSL3Ciphertext cText;
int rv;
- PRBool canFalseStart = PR_FALSE;
+ PRBool keepGoing = PR_TRUE;
SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
+ /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
+ * 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) );
+
do {
PRBool handleRecordNow = PR_FALSE;
@@ -364,22 +370,52 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
cText.buf = &ss->gs.inbuf;
rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
+
+ if (rv == (int) SECSuccess && 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;
+ }
}
if (rv < 0) {
return ss->recvdCloseNotify ? 0 : rv;
}
- /* If we kicked off a false start in ssl3_HandleServerHelloDone, break
- * out of this loop early without finishing the handshake.
- */
- if (ss->opt.enableFalseStart) {
- ssl_GetSSL3HandshakeLock(ss);
- canFalseStart = ss->ssl3.hs.canFalseStart;
- ssl_ReleaseSSL3HandshakeLock(ss);
+ 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;
+ }
}
- } while (ss->ssl3.hs.ws != idle_handshake &&
- !canFalseStart &&
- ss->gs.buf.len == 0);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ } while (keepGoing);
ss->gs.readOffset = 0;
ss->gs.writeOffset = ss->gs.buf.len;
@@ -402,7 +438,10 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
{
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) );
+
do {
rv = ssl3_GatherCompleteHandshake(ss, flags);
} while (rv > 0 && ss->gs.buf.len == 0);
diff --git a/chromium/net/third_party/nss/ssl/ssl3prot.h b/chromium/net/third_party/nss/ssl/ssl3prot.h
index 0eab970bc6a..4c19ade8d6a 100644
--- a/chromium/net/third_party/nss/ssl/ssl3prot.h
+++ b/chromium/net/third_party/nss/ssl/ssl3prot.h
@@ -98,6 +98,7 @@ typedef enum {
protocol_version = 70,
insufficient_security = 71,
internal_error = 80,
+ inappropriate_fallback = 86, /* could also be sent for SSLv3 */
user_canceled = 90,
no_renegotiation = 100,
diff --git a/chromium/net/third_party/nss/ssl/sslerr.h b/chromium/net/third_party/nss/ssl/sslerr.h
index 5a949c9a248..82ae7dfb1f0 100644
--- a/chromium/net/third_party/nss/ssl/sslerr.h
+++ b/chromium/net/third_party/nss/ssl/sslerr.h
@@ -196,6 +196,7 @@ SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128),
SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 129),
SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 130),
SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 131),
+SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT = (SSL_ERROR_BASE + 132),
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
diff --git a/chromium/net/third_party/nss/ssl/sslimpl.h b/chromium/net/third_party/nss/ssl/sslimpl.h
index 614eed145ec..6d0bc154aaf 100644
--- a/chromium/net/third_party/nss/ssl/sslimpl.h
+++ b/chromium/net/third_party/nss/ssl/sslimpl.h
@@ -237,6 +237,13 @@ extern PRInt32
ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
const ssl3HelloExtensionSender *sender);
+extern unsigned int
+ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength);
+
+extern PRInt32
+ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen,
+ PRUint32 maxBytes);
+
/* Socket ops */
struct sslSocketOpsStr {
int (*connect) (sslSocket *, const PRNetAddr *);
@@ -305,29 +312,31 @@ typedef struct sslOptionsStr {
* 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 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 enableSignedCertTimestamps : 1; /* 26 */
+ unsigned int enableFallbackSCSV : 1; /* 27 */
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
@@ -698,6 +707,19 @@ struct sslSessionIDStr {
*/
NewSessionTicket sessionTicket;
SECItem srvName;
+
+ /* originalHandshakeHash contains the hash of the original, full
+ * handshake prior to the server's final flow. This is either a
+ * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
+ * 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;
} ssl3;
} u;
};
@@ -789,6 +811,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 *);
@@ -1431,6 +1465,19 @@ extern void ssl3_SetAlwaysBlock(sslSocket *ss);
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
+extern void ssl_FinishHandshake(sslSocket *ss);
+
+/* 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 PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss);
+
extern SECStatus
ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
PRBool isServer,
@@ -1665,6 +1712,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);
extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy);
extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy);
diff --git a/chromium/net/third_party/nss/ssl/sslnonce.c b/chromium/net/third_party/nss/ssl/sslnonce.c
index a6f734948a3..a3e6e0a33f9 100644
--- a/chromium/net/third_party/nss/ssl/sslnonce.c
+++ b/chromium/net/third_party/nss/ssl/sslnonce.c
@@ -21,8 +21,8 @@
PRUint32 ssl_sid_timeout = 100;
PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
-static sslSessionID *cache = NULL;
-static PZLock * cacheLock = NULL;
+sslSessionID *cache = NULL;
+PZLock * cacheLock = NULL;
/* sids can be in one of 4 states:
*
@@ -122,7 +122,21 @@ ssl_DestroySID(sslSessionID *sid)
if (sid->version < SSL_LIBRARY_VERSION_3_0) {
SECITEM_ZfreeItem(&sid->u.ssl2.masterKey, PR_FALSE);
SECITEM_ZfreeItem(&sid->u.ssl2.cipherArg, PR_FALSE);
+ } else {
+ if (sid->u.ssl3.sessionTicket.ticket.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
+ }
+ if (sid->u.ssl3.srvName.data) {
+ SECITEM_FreeItem(&sid->u.ssl3.srvName, 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->peerID != NULL)
PORT_Free((void *)sid->peerID); /* CONST */
@@ -142,13 +156,7 @@ ssl_DestroySID(sslSessionID *sid)
if ( sid->localCert ) {
CERT_DestroyCertificate(sid->localCert);
}
- if (sid->u.ssl3.sessionTicket.ticket.data) {
- SECITEM_FreeItem(&sid->u.ssl3.sessionTicket.ticket, PR_FALSE);
- }
- if (sid->u.ssl3.srvName.data) {
- SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
- }
-
+
PORT_ZFree(sid, sizeof(sslSessionID));
}
@@ -430,6 +438,12 @@ ssl3_SetSIDSessionTicket(sslSessionID *sid, NewSessionTicket *session_ticket)
/* We need to lock the cache, as this sid might already be in the cache. */
LOCK_CACHE;
+ /* Don't modify sid if it has ever been cached. */
+ if (sid->cached != never_cached) {
+ UNLOCK_CACHE;
+ return SECSuccess;
+ }
+
/* A server might have sent us an empty ticket, which has the
* effect of clearing the previously known ticket.
*/
diff --git a/chromium/net/third_party/nss/ssl/sslproto.h b/chromium/net/third_party/nss/ssl/sslproto.h
index 6b60a28616f..621ef375460 100644
--- a/chromium/net/third_party/nss/ssl/sslproto.h
+++ b/chromium/net/third_party/nss/ssl/sslproto.h
@@ -172,6 +172,11 @@
*/
#define TLS_EMPTY_RENEGOTIATION_INFO_SCSV 0x00FF
+/* TLS_FALLBACK_SCSV is a signaling cipher suite value that indicates that a
+ * handshake is the result of TLS version fallback. This value is not IANA
+ * assigned. */
+#define TLS_FALLBACK_SCSV 0x5600
+
/* Cipher Suite Values starting with 0xC000 are defined in informational
* RFCs.
*/
diff --git a/chromium/net/third_party/nss/ssl/sslsecur.c b/chromium/net/third_party/nss/ssl/sslsecur.c
index 6c7532e2552..99538e532a6 100644
--- a/chromium/net/third_party/nss/ssl/sslsecur.c
+++ b/chromium/net/third_party/nss/ssl/sslsecur.c
@@ -97,14 +97,13 @@ ssl_Do1stHandshake(sslSocket *ss)
ss->securityHandshake = 0;
}
if (ss->handshake == 0) {
- ssl_GetRecvBufLock(ss);
- ss->gs.recordLen = 0;
- ss->gs.writeOffset = 0;
- ss->gs.readOffset = 0;
- ssl_ReleaseRecvBufLock(ss);
-
- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
- SSL_GETPID(), ss->fd));
+ /* 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);
@@ -125,6 +124,24 @@ ssl_Do1stHandshake(sslSocket *ss)
return rv;
}
+void
+ssl_FinishHandshake(sslSocket *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;
+
+ if (ss->handshakeCallback) {
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+ }
+}
+
/*
* Handshake function that blocks. Used to force a
* retry on a connection on the next read/write.
@@ -260,7 +277,7 @@ SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
/* 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);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
} else {
ssl_GetSSL3HandshakeLock(ss);
@@ -330,7 +347,7 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
*/
SECStatus
SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
- void *client_data)
+ void *arg)
{
sslSocket *ss;
@@ -350,7 +367,7 @@ SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
ssl_GetSSL3HandshakeLock(ss);
ss->canFalseStartCallback = cb;
- ss->canFalseStartCallbackData = client_data;
+ ss->canFalseStartCallbackData = arg;
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
@@ -358,19 +375,15 @@ SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
return SECSuccess;
}
-/* A utility function that can be called from a custom SSLCanFalseStartCallback
-** function to determine what NSS would have done for this connection if the
-** custom callback was not implemented.
-*/
SECStatus
-SSL_DefaultCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
+SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
{
sslSocket *ss;
*canFalseStart = PR_FALSE;
ss = ssl_FindSocket(fd);
if (!ss) {
- SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DefaultCanFalseStart",
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
SSL_GETPID(), fd));
return SECFailure;
}
@@ -587,6 +600,9 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
int amount;
int available;
+ /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
+ * 1stHandshakeLock. */
+ ssl_Get1stHandshakeLock(ss);
ssl_GetRecvBufLock(ss);
available = ss->gs.writeOffset - ss->gs.readOffset;
@@ -653,6 +669,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
done:
ssl_ReleaseRecvBufLock(ss);
+ ssl_Release1stHandshakeLock(ss);
return rv;
}
@@ -1219,7 +1236,8 @@ ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
int
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
{
- int rv = 0;
+ int rv = 0;
+ PRBool falseStart = PR_FALSE;
SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
SSL_GETPID(), ss->fd, len));
@@ -1254,14 +1272,14 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
ss->writerThread = PR_GetCurrentThread();
/* If any of these is non-zero, the initial handshake is not done. */
if (!ss->firstHsDone) {
- PRBool canFalseStart = PR_FALSE;
ssl_Get1stHandshakeLock(ss);
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
+ if (ss->opt.enableFalseStart &&
+ ss->version >= SSL_LIBRARY_VERSION_3_0) {
ssl_GetSSL3HandshakeLock(ss);
- canFalseStart = ss->ssl3.hs.canFalseStart;
+ falseStart = ss->ssl3.hs.canFalseStart;
ssl_ReleaseSSL3HandshakeLock(ss);
}
- if (!canFalseStart &&
+ if (!falseStart &&
(ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
rv = ssl_Do1stHandshake(ss);
}
@@ -1286,6 +1304,17 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
goto done;
}
+ if (!ss->firstHsDone) {
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
+#ifdef DEBUG
+ 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));
+ }
+
/* Send out the data using one of these functions:
* ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
* ssl3_SendApplicationData
@@ -1445,6 +1474,49 @@ SSL_InvalidateSession(PRFileDesc *fd)
return rv;
}
+static void
+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;
+ }
+}
+
+SECStatus
+SSL_CacheSession(PRFileDesc *fd)
+{
+ sslSocket * ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
+
+ if (ss) {
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+
+ ssl3_CacheSessionUnlocked(ss);
+ rv = SECSuccess;
+
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+ }
+ return rv;
+}
+
+SECStatus
+SSL_CacheSessionUnlocked(PRFileDesc *fd)
+{
+ sslSocket * ss = ssl_FindSocket(fd);
+ SECStatus rv = SECFailure;
+
+ if (ss) {
+ ssl3_CacheSessionUnlocked(ss);
+ rv = SECSuccess;
+ }
+ return rv;
+}
+
SECItem *
SSL_GetSessionID(PRFileDesc *fd)
{
diff --git a/chromium/net/third_party/nss/ssl/sslsock.c b/chromium/net/third_party/nss/ssl/sslsock.c
index 072fad5ba0b..998c1371999 100644
--- a/chromium/net/third_party/nss/ssl/sslsock.c
+++ b/chromium/net/third_party/nss/ssl/sslsock.c
@@ -173,7 +173,9 @@ static sslOptions ssl_defaults = {
PR_FALSE, /* requireSafeNegotiation */
PR_FALSE, /* enableFalseStart */
PR_TRUE, /* cbcRandomIV */
- PR_FALSE /* enableOCSPStapling */
+ PR_FALSE, /* enableOCSPStapling */
+ PR_FALSE, /* enableSignedCertTimestamps */
+ PR_FALSE /* enableFallbackSCSV */
};
/*
@@ -366,6 +368,8 @@ ssl_DupSocket(sslSocket *os)
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;
@@ -863,6 +867,14 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
ss->opt.enableOCSPStapling = on;
break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ ss->opt.enableSignedCertTimestamps = on;
+ break;
+
+ case SSL_ENABLE_FALLBACK_SCSV:
+ ss->opt.enableFallbackSCSV = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -933,6 +945,10 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
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_SIGNED_CERT_TIMESTAMPS:
+ on = ss->opt.enableSignedCertTimestamps;
+ break;
+ case SSL_ENABLE_FALLBACK_SCSV: on = ss->opt.enableFallbackSCSV; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -994,6 +1010,12 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
case SSL_ENABLE_OCSP_STAPLING:
on = ssl_defaults.enableOCSPStapling;
break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ on = ssl_defaults.enableSignedCertTimestamps;
+ break;
+ case SSL_ENABLE_FALLBACK_SCSV:
+ on = ssl_defaults.enableFallbackSCSV;
+ break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -1161,6 +1183,14 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
ssl_defaults.enableOCSPStapling = on;
break;
+ case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
+ ssl_defaults.enableSignedCertTimestamps = on;
+ break;
+
+ case SSL_ENABLE_FALLBACK_SCSV:
+ ssl_defaults.enableFallbackSCSV = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -1327,6 +1357,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
return rv;
}
+SECStatus
+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;
+ }
+ return ssl3_CipherOrderSet(ss, ciphers, len);
+}
+
SECStatus
SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled)
{
@@ -1991,6 +2034,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);
@@ -3131,4 +3197,3 @@ loser:
}
return ss;
}
-
diff --git a/chromium/net/third_party/nss/ssl/sslt.h b/chromium/net/third_party/nss/ssl/sslt.h
index a8007d8b4cf..1f5e2c659ff 100644
--- a/chromium/net/third_party/nss/ssl/sslt.h
+++ b/chromium/net/third_party/nss/ssl/sslt.h
@@ -202,12 +202,14 @@ 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_session_ticket_xtn = 35,
ssl_next_proto_nego_xtn = 13172,
- ssl_channel_id_xtn = 30031,
+ ssl_channel_id_xtn = 30032,
+ ssl_padding_xtn = 35655,
ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
} SSLExtensionType;
-#define SSL_MAX_EXTENSIONS 11
+#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */
#endif /* __sslt_h_ */
diff --git a/chromium/net/tools/DEPS b/chromium/net/tools/DEPS
index 90fa4c0e138..1ea12e4c3b9 100644
--- a/chromium/net/tools/DEPS
+++ b/chromium/net/tools/DEPS
@@ -1,3 +1,4 @@
skip_child_includes = [
+ "balsa",
"flip_server",
]
diff --git a/chromium/net/tools/flip_server/balsa_enums.h b/chromium/net/tools/balsa/balsa_enums.h
index 4273ee4871d..a59dcda687c 100644
--- a/chromium/net/tools/flip_server/balsa_enums.h
+++ b/chromium/net/tools/balsa/balsa_enums.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_BALSA_ENUMS_H_
-#define NET_TOOLS_FLIP_SERVER_BALSA_ENUMS_H_
+#ifndef NET_TOOLS_BALSA_BALSA_ENUMS_H_
+#define NET_TOOLS_BALSA_BALSA_ENUMS_H_
namespace net {
@@ -107,5 +107,5 @@ struct BalsaHeadersEnums {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_BALSA_ENUMS_H_
+#endif // NET_TOOLS_BALSA_BALSA_ENUMS_H_
diff --git a/chromium/net/tools/flip_server/balsa_frame.cc b/chromium/net/tools/balsa/balsa_frame.cc
index dead665771b..96e91935597 100644
--- a/chromium/net/tools/flip_server/balsa_frame.cc
+++ b/chromium/net/tools/balsa/balsa_frame.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/flip_server/balsa_frame.h"
+#include "net/tools/balsa/balsa_frame.h"
#include <assert.h>
#if __SSE2__
@@ -18,13 +18,13 @@
#include "base/logging.h"
#include "base/port.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
-#include "net/tools/flip_server/buffer_interface.h"
-#include "net/tools/flip_server/simple_buffer.h"
-#include "net/tools/flip_server/split.h"
-#include "net/tools/flip_server/string_piece_utils.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/balsa_headers.h"
+#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"
namespace net {
@@ -745,44 +745,11 @@ void ProcessChunkExtensionsManual(base::StringPiece all_extensions,
}
}
-// TODO(phython): Fix this function to properly deal with quoted values.
-// E.g. ";;foo", "\";;\"", or \"aa;
-// The last example, the semi-colon is a separator between extensions.
-void ProcessChunkExtensionsGoogle3(const char* input, size_t size,
- BalsaHeaders* extensions) {
- std::vector<base::StringPiece> key_values;
- SplitStringPieceToVector(base::StringPiece(input, size), ";",
- &key_values, true);
- for (unsigned int i = 0; i < key_values.size(); ++i) {
- base::StringPiece key = key_values[i].substr(0, key_values[i].find('='));
- base::StringPiece value;
- if (key.length() < key_values[i].length()) {
- value = key_values[i].substr(key.length() + 1);
- // Remove any leading and trailing whitespace.
- StringPieceUtils::RemoveWhitespaceContext(&value);
-
- // Strip quotation marks if they exist.
- if (!value.empty() && value[0] == '"')
- value.remove_prefix(1);
- if (!value.empty() && value[value.length() - 1] == '"')
- value.remove_suffix(1);
- }
-
- // Strip the key whitespace after checking that there is a value.
- StringPieceUtils::RemoveWhitespaceContext(&key);
- extensions->AppendHeader(key, value);
- }
-}
-
} // anonymous namespace
void BalsaFrame::ProcessChunkExtensions(const char* input, size_t size,
BalsaHeaders* extensions) {
-#if 0
- ProcessChunkExtensionsGoogle3(input, size, extensions);
-#else
ProcessChunkExtensionsManual(base::StringPiece(input, size), extensions);
-#endif
}
void BalsaFrame::ProcessHeaderLines() {
diff --git a/chromium/net/tools/flip_server/balsa_frame.h b/chromium/net/tools/balsa/balsa_frame.h
index 0d3b372ef9f..8e1240c86e9 100644
--- a/chromium/net/tools/flip_server/balsa_frame.h
+++ b/chromium/net/tools/balsa/balsa_frame.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_BALSA_FRAME_H_
-#define NET_TOOLS_FLIP_SERVER_BALSA_FRAME_H_
+#ifndef NET_TOOLS_BALSA_BALSA_FRAME_H_
+#define NET_TOOLS_BALSA_BALSA_FRAME_H_
#include <strings.h>
@@ -12,12 +12,12 @@
#include "base/compiler_specific.h"
#include "base/port.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
-#include "net/tools/flip_server/buffer_interface.h"
-#include "net/tools/flip_server/http_message_constants.h"
-#include "net/tools/flip_server/simple_buffer.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/balsa/balsa_visitor_interface.h"
+#include "net/tools/balsa/buffer_interface.h"
+#include "net/tools/balsa/http_message_constants.h"
+#include "net/tools/balsa/simple_buffer.h"
// For additional debug output, uncomment the following:
// #define DEBUGFRAMER 1
@@ -261,5 +261,5 @@ class BalsaFrame {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_BALSA_FRAME_H_
+#endif // NET_TOOLS_BALSA_BALSA_FRAME_H_
diff --git a/chromium/net/tools/flip_server/balsa_frame_test.cc b/chromium/net/tools/balsa/balsa_frame_test.cc
index 3bb9a420b7e..2582721b3a9 100644
--- a/chromium/net/tools/flip_server/balsa_frame_test.cc
+++ b/chromium/net/tools/balsa/balsa_frame_test.cc
@@ -2,14 +2,14 @@
// 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/balsa_frame.h"
+#include "net/tools/balsa/balsa_frame.h"
#include <iterator>
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/tools/flip_server/balsa_headers.cc b/chromium/net/tools/balsa/balsa_headers.cc
index 040c0128e11..27bfd24a514 100644
--- a/chromium/net/tools/flip_server/balsa_headers.cc
+++ b/chromium/net/tools/balsa/balsa_headers.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
#include <stdio.h>
#include <algorithm>
@@ -13,14 +13,12 @@
#include "base/logging.h"
#include "base/port.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/buffer_interface.h"
-#include "net/tools/flip_server/simple_buffer.h"
+#include "base/strings/stringprintf.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/buffer_interface.h"
+#include "net/tools/balsa/simple_buffer.h"
#include "third_party/tcmalloc/chromium/src/base/googleinit.h"
-// #include "util/gtl/iterator_adaptors-inl.h"
-// #include "util/gtl/map-util.h"
namespace {
diff --git a/chromium/net/tools/flip_server/balsa_headers.h b/chromium/net/tools/balsa/balsa_headers.h
index 2c8b08362c7..47cf388b8ab 100644
--- a/chromium/net/tools/flip_server/balsa_headers.h
+++ b/chromium/net/tools/balsa/balsa_headers.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_BALSA_HEADERS_H_
-#define NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_H_
+#ifndef NET_TOOLS_BALSA_BALSA_HEADERS_H_
+#define NET_TOOLS_BALSA_BALSA_HEADERS_H_
#include <algorithm>
#include <iosfwd>
@@ -15,8 +15,8 @@
#include "base/logging.h"
#include "base/port.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/string_piece_utils.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/string_piece_utils.h"
namespace net {
@@ -1135,4 +1135,4 @@ class BalsaHeaders {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_H_
+#endif // NET_TOOLS_BALSA_BALSA_HEADERS_H_
diff --git a/chromium/net/tools/flip_server/balsa_headers_test.cc b/chromium/net/tools/balsa/balsa_headers_test.cc
index 241fee17792..da2ad198a4d 100644
--- a/chromium/net/tools/flip_server/balsa_headers_test.cc
+++ b/chromium/net/tools/balsa/balsa_headers_test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
#include <iterator>
#include <string>
@@ -10,7 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
+#include "net/tools/balsa/balsa_enums.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/tools/flip_server/balsa_headers_token_utils.cc b/chromium/net/tools/balsa/balsa_headers_token_utils.cc
index b47debf89ab..c807e05c9ab 100644
--- a/chromium/net/tools/flip_server/balsa_headers_token_utils.cc
+++ b/chromium/net/tools/balsa/balsa_headers_token_utils.cc
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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/flip_server/balsa_headers_token_utils.h"
-#include "net/tools/flip_server/string_piece_utils.h"
+#include "net/tools/balsa/balsa_headers_token_utils.h"
+#include "net/tools/balsa/string_piece_utils.h"
namespace net {
diff --git a/chromium/net/tools/flip_server/balsa_headers_token_utils.h b/chromium/net/tools/balsa/balsa_headers_token_utils.h
index f50c6065bbd..aaa0e30cec5 100644
--- a/chromium/net/tools/flip_server/balsa_headers_token_utils.h
+++ b/chromium/net/tools/balsa/balsa_headers_token_utils.h
@@ -1,15 +1,15 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
// Utility class that performs basic operations on header value tokens: parsing
// them out, checking for presense of certain tokens, and removing them.
-#ifndef NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_TOKEN_UTILS_H_
-#define NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_TOKEN_UTILS_H_
+#ifndef NET_TOOLS_BALSA_BALSA_HEADERS_TOKEN_UTILS_H_
+#define NET_TOOLS_BALSA_BALSA_HEADERS_TOKEN_UTILS_H_
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
namespace net {
@@ -57,5 +57,5 @@ class BalsaHeadersTokenUtils {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_TOKEN_UTILS_H_
+#endif // NET_TOOLS_BALSA_BALSA_HEADERS_TOKEN_UTILS_H_
diff --git a/chromium/net/tools/flip_server/balsa_visitor_interface.h b/chromium/net/tools/balsa/balsa_visitor_interface.h
index 75283acf7e2..1f24e6d565e 100644
--- a/chromium/net/tools/flip_server/balsa_visitor_interface.h
+++ b/chromium/net/tools/balsa/balsa_visitor_interface.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_BALSA_VISITOR_INTERFACE_H_
-#define NET_TOOLS_FLIP_SERVER_BALSA_VISITOR_INTERFACE_H_
+#ifndef NET_TOOLS_BALSA_BALSA_VISITOR_INTERFACE_H_
+#define NET_TOOLS_BALSA_BALSA_VISITOR_INTERFACE_H_
#include <cstddef>
@@ -177,5 +177,4 @@ class BalsaVisitorInterface {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_BALSA_VISITOR_INTERFACE_H_
-
+#endif // NET_TOOLS_BALSA_BALSA_VISITOR_INTERFACE_H_
diff --git a/chromium/net/tools/flip_server/buffer_interface.h b/chromium/net/tools/balsa/buffer_interface.h
index ec061c94aee..9c01a062b99 100644
--- a/chromium/net/tools/flip_server/buffer_interface.h
+++ b/chromium/net/tools/balsa/buffer_interface.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_BUFFER_INTERFACE_H__
-#define NET_TOOLS_FLIP_SERVER_BUFFER_INTERFACE_H__
+#ifndef NET_TOOLS_BALSA_BUFFER_INTERFACE_H__
+#define NET_TOOLS_BALSA_BUFFER_INTERFACE_H__
namespace net {
@@ -117,5 +117,5 @@ class BufferInterface {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_BUFFER_INTERFACE__H__
+#endif // NET_TOOLS_BALSA_BUFFER_INTERFACE__H__
diff --git a/chromium/net/tools/balsa/http_message_constants.cc b/chromium/net/tools/balsa/http_message_constants.cc
new file mode 100644
index 00000000000..96a9725201e
--- /dev/null
+++ b/chromium/net/tools/balsa/http_message_constants.cc
@@ -0,0 +1,146 @@
+// 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/http_message_constants.h"
+
+namespace net {
+
+const char* get_http_status_message(int status_message) {
+ switch (status_message) {
+ case 100:
+ return "Continue";
+ case 101:
+ return "Switching Protocols";
+ case 200:
+ return "OK";
+ case 201:
+ return "Created";
+ case 202:
+ return "Accepted";
+ case 203:
+ return "Non-Authoritative Information";
+ case 204:
+ return "No Content";
+ case 205:
+ return "Reset Content";
+ case 206:
+ return "Partial Content";
+ case 300:
+ return "Multiple Choices";
+ case 301:
+ return "Moved Permanently";
+ case 302:
+ return "Found";
+ case 303:
+ return "See Other";
+ case 304:
+ return "Not Modified";
+ case 305:
+ return "Use Proxy";
+ case 307:
+ return "Temporary Redirect";
+ case 400:
+ return "Bad Request";
+ case 401:
+ return "Unauthorized";
+ case 402:
+ return "Payment Required";
+ case 403:
+ return "Forbidden";
+ case 404:
+ return "Not Found";
+ case 405:
+ return "Method Not Allowed";
+ case 406:
+ return "Not Acceptable";
+ case 407:
+ return "Proxy Authentication Required";
+ case 408:
+ return "Request Time-out";
+ case 409:
+ return "Conflict";
+ case 410:
+ return "Gone";
+ case 411:
+ return "Length Required";
+ case 412:
+ return "Precondition Failed";
+ case 413:
+ return "Request Entity Too Large";
+ case 414:
+ return "Request-URI Too Large";
+ case 415:
+ return "Unsupported Media Type";
+ case 416:
+ return "Requested range not satisfiable";
+ case 417:
+ return "Expectation Failed";
+ case 500:
+ return "Internal Server Error";
+ case 501:
+ return "Not Implemented";
+ case 502:
+ return "Bad Gateway";
+ case 503:
+ return "Service Unavailable";
+ case 504:
+ return "Gateway Time-out";
+ case 505:
+ return "HTTP Version not supported";
+ }
+ return "unknown";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+const int http_status_codes[] = {
+ 100,
+ 101,
+ 200,
+ 201,
+ 202,
+ 203,
+ 204,
+ 205,
+ 206,
+ 300,
+ 301,
+ 302,
+ 303,
+ 304,
+ 305,
+ 307,
+ 400,
+ 401,
+ 402,
+ 403,
+ 404,
+ 405,
+ 406,
+ 407,
+ 408,
+ 409,
+ 410,
+ 411,
+ 412,
+ 413,
+ 414,
+ 415,
+ 416,
+ 417,
+ 500,
+ 501,
+ 502,
+ 503,
+ 504,
+ 505
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+const int http_status_code_count = sizeof(http_status_codes) /
+ sizeof(http_status_codes[0]);
+
+} // namespace net
+
diff --git a/chromium/net/tools/flip_server/http_message_constants.h b/chromium/net/tools/balsa/http_message_constants.h
index de700ccedd8..16f7aa392cc 100644
--- a/chromium/net/tools/flip_server/http_message_constants.h
+++ b/chromium/net/tools/balsa/http_message_constants.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_HTTP_MESSAGE_CONSTANTS_H__
-#define NET_TOOLS_FLIP_SERVER_HTTP_MESSAGE_CONSTANTS_H__
+#ifndef NET_TOOLS_BALSA_HTTP_MESSAGE_CONSTANTS_H__
+#define NET_TOOLS_BALSA_HTTP_MESSAGE_CONSTANTS_H__
namespace net {
@@ -13,5 +13,5 @@ extern const int http_status_code_count;
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_HTTP_MESSAGE_CONSTANTS_H__
+#endif // NET_TOOLS_BALSA_HTTP_MESSAGE_CONSTANTS_H__
diff --git a/chromium/net/tools/balsa/noop_balsa_visitor.h b/chromium/net/tools/balsa/noop_balsa_visitor.h
new file mode 100644
index 00000000000..c0136f12488
--- /dev/null
+++ b/chromium/net/tools/balsa/noop_balsa_visitor.h
@@ -0,0 +1,60 @@
+// 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.
+//
+// Provides empty BalsaVisitorInterface overrides for convenience.
+// Intended to be used as a base class for BalsaVisitorInterface subclasses that
+// only need to override a small number of methods.
+
+#ifndef NET_TOOLS_BALSA_NOOP_BALSA_VISITOR_H_
+#define NET_TOOLS_BALSA_NOOP_BALSA_VISITOR_H_
+
+#include "net/tools/balsa/balsa_visitor_interface.h"
+
+namespace net {
+
+// See file comment above.
+class NoOpBalsaVisitor : public BalsaVisitorInterface {
+ public:
+ NoOpBalsaVisitor() { }
+ virtual ~NoOpBalsaVisitor() { }
+
+ virtual void ProcessBodyInput(const char* input, size_t size) OVERRIDE { }
+ virtual void ProcessBodyData(const char* input, size_t size) OVERRIDE { }
+ virtual void ProcessHeaderInput(const char* input, size_t size) OVERRIDE { }
+ virtual void ProcessTrailerInput(const char* input, size_t size) OVERRIDE { }
+ virtual void ProcessHeaders(const BalsaHeaders& headers) OVERRIDE { }
+
+ virtual void ProcessRequestFirstLine(const char* line_input,
+ size_t line_length,
+ const char* method_input,
+ size_t method_length,
+ const char* request_uri_input,
+ size_t request_uri_length,
+ const char* version_input,
+ size_t version_length) OVERRIDE { }
+ virtual void ProcessResponseFirstLine(const char* line_input,
+ size_t line_length,
+ const char* version_input,
+ size_t version_length,
+ const char* status_input,
+ size_t status_length,
+ const char* reason_input,
+ size_t reason_length) OVERRIDE { }
+ virtual void ProcessChunkLength(size_t chunk_length) OVERRIDE { }
+ virtual void ProcessChunkExtensions(const char* input, size_t size) OVERRIDE {
+ }
+ virtual void HeaderDone() OVERRIDE { }
+ virtual void MessageDone() OVERRIDE { }
+ virtual void HandleHeaderError(BalsaFrame* framer) OVERRIDE { }
+ virtual void HandleHeaderWarning(BalsaFrame* framer) OVERRIDE { }
+ virtual void HandleChunkingError(BalsaFrame* framer) OVERRIDE { }
+ virtual void HandleBodyError(BalsaFrame* framer) OVERRIDE { }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NoOpBalsaVisitor);
+};
+
+} // namespace net
+
+#endif // NET_TOOLS_BALSA_NOOP_BALSA_VISITOR_H_
diff --git a/chromium/net/tools/flip_server/simple_buffer.cc b/chromium/net/tools/balsa/simple_buffer.cc
index d94153b29ec..5e02a7b8d68 100644
--- a/chromium/net/tools/flip_server/simple_buffer.cc
+++ b/chromium/net/tools/balsa/simple_buffer.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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/flip_server/simple_buffer.h"
+#include "net/tools/balsa/simple_buffer.h"
#include "base/logging.h"
// Some of the following member functions are marked inlined, even though they
diff --git a/chromium/net/tools/flip_server/simple_buffer.h b/chromium/net/tools/balsa/simple_buffer.h
index 08f7d3819ba..a5506178240 100644
--- a/chromium/net/tools/flip_server/simple_buffer.h
+++ b/chromium/net/tools/balsa/simple_buffer.h
@@ -1,14 +1,14 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_SIMPLE_BUFFER_H__
-#define NET_TOOLS_FLIP_SERVER_SIMPLE_BUFFER_H__
+#ifndef NET_TOOLS_BALSA_SIMPLE_BUFFER_H__
+#define NET_TOOLS_BALSA_SIMPLE_BUFFER_H__
#include <string>
#include "base/compiler_specific.h"
-#include "net/tools/flip_server/buffer_interface.h"
+#include "net/tools/balsa/buffer_interface.h"
namespace net {
@@ -89,4 +89,4 @@ class SimpleBuffer : public BufferInterface {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_SIMPLE_BUFFER_H__
+#endif // NET_TOOLS_BALSA_SIMPLE_BUFFER_H__
diff --git a/chromium/net/tools/flip_server/split.cc b/chromium/net/tools/balsa/split.cc
index 790051384d5..20be430d731 100644
--- a/chromium/net/tools/flip_server/split.cc
+++ b/chromium/net/tools/balsa/split.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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/flip_server/split.h"
+#include "net/tools/balsa/split.h"
#include <string.h>
diff --git a/chromium/net/tools/flip_server/split.h b/chromium/net/tools/balsa/split.h
index aae20b062a5..6901c2d5651 100644
--- a/chromium/net/tools/flip_server/split.h
+++ b/chromium/net/tools/balsa/split.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_SPLIT_H_
-#define NET_TOOLS_FLIP_SERVER_SPLIT_H_
+#ifndef NET_TOOLS_BALSA_SPLIT_H_
+#define NET_TOOLS_BALSA_SPLIT_H_
#include <vector>
#include "base/strings/string_piece.h"
@@ -19,5 +19,5 @@ void SplitStringPieceToVector(const base::StringPiece& full,
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_SPLIT_H_
+#endif // NET_TOOLS_BALSA_SPLIT_H_
diff --git a/chromium/net/tools/flip_server/string_piece_utils.h b/chromium/net/tools/balsa/string_piece_utils.h
index 3c46dd91904..eb0eaf365c8 100644
--- a/chromium/net/tools/flip_server/string_piece_utils.h
+++ b/chromium/net/tools/balsa/string_piece_utils.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_STRING_PIECE_UTILS_H_
-#define NET_TOOLS_FLIP_SERVER_STRING_PIECE_UTILS_H_
+#ifndef NET_TOOLS_BALSA_STRING_PIECE_UTILS_H_
+#define NET_TOOLS_BALSA_STRING_PIECE_UTILS_H_
#include <ctype.h>
@@ -79,5 +79,5 @@ struct StringPieceCaseEqual {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_STRING_PIECE_UTILS_H_
+#endif // NET_TOOLS_BALSA_STRING_PIECE_UTILS_H_
diff --git a/chromium/net/tools/crash_cache/crash_cache.cc b/chromium/net/tools/crash_cache/crash_cache.cc
index 700e822aeba..32934a6a870 100644
--- a/chromium/net/tools/crash_cache/crash_cache.cc
+++ b/chromium/net/tools/crash_cache/crash_cache.cc
@@ -123,7 +123,7 @@ bool CreateTargetFolder(const base::FilePath& path, RankCrashes action,
if (base::PathExists(*full_path))
return false;
- return file_util::CreateDirectory(*full_path);
+ return base::CreateDirectory(*full_path);
}
// Makes sure that any pending task is processed.
@@ -268,7 +268,7 @@ int LoadOperations(const base::FilePath& path, RankCrashes action,
// Work with a tiny index table (16 entries).
disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(
path, 0xf, cache_thread->message_loop_proxy().get(), NULL);
- if (!cache || !cache->SetMaxSize(0x100000))
+ if (!cache->SetMaxSize(0x100000))
return GENERIC;
// No experiments and use a simple LRU.
diff --git a/chromium/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc b/chromium/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc
index 6bb14c221ef..aafd2caf216 100644
--- a/chromium/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc
+++ b/chromium/net/tools/disk_cache_memory_test/disk_cache_memory_test.cc
@@ -157,14 +157,23 @@ bool ParseRangeLine(const std::string& line,
// Parses range property lines from /proc/<PID>/smaps, e.g.:
// Private_Dirty: 16 kB
+//
+// Returns |false| iff it recognizes a new range line. Outputs non-zero |size|
+// only if parsing succeeded.
bool ParseRangeProperty(const std::string& line,
std::vector<std::string>* tokens,
uint64* size,
bool* is_private_dirty) {
tokens->clear();
base::SplitStringAlongWhitespace(line, tokens);
- if (tokens->size() != 3)
+
+ // If the line is long, attempt to parse new range outside of this scope.
+ if (tokens->size() > 3)
return false;
+
+ // Skip the line on other parsing error occasions.
+ if (tokens->size() < 3)
+ return true;
const std::string& type = (*tokens)[0];
if (type != kPrivateDirty)
return true;
@@ -176,7 +185,7 @@ bool ParseRangeProperty(const std::string& line,
const std::string& size_str = (*tokens)[1];
uint64 map_size = 0;
if (!base::StringToUint64(size_str, &map_size))
- return false;
+ return true;
*is_private_dirty = true;
*size = map_size;
return true;
diff --git a/chromium/net/tools/dump_cache/cache_dumper.cc b/chromium/net/tools/dump_cache/cache_dumper.cc
index e6bac0aeda7..7d29a5c1785 100644
--- a/chromium/net/tools/dump_cache/cache_dumper.cc
+++ b/chromium/net/tools/dump_cache/cache_dumper.cc
@@ -65,13 +65,13 @@ bool SafeCreateDirectory(const base::FilePath& path) {
// Now create the full path
return CreateDirectoryW(path.value().c_str(), NULL) == TRUE;
#else
- return file_util::CreateDirectory(path);
+ return base::CreateDirectory(path);
#endif
}
DiskDumper::DiskDumper(const base::FilePath& path)
: path_(path), entry_(NULL) {
- file_util::CreateDirectory(path);
+ base::CreateDirectory(path);
}
int DiskDumper::CreateEntry(const std::string& key,
@@ -108,7 +108,7 @@ int DiskDumper::CreateEntry(const std::string& key,
wprintf(L"CreateFileW (%s) failed: %d\n", file.c_str(), GetLastError());
return (entry_ != INVALID_HANDLE_VALUE) ? net::OK : net::ERR_FAILED;
#else
- entry_ = file_util::OpenFile(entry_path_, "w+");
+ entry_ = base::OpenFile(entry_path_, "w+");
return (entry_ != NULL) ? net::OK : net::ERR_FAILED;
#endif
}
@@ -218,6 +218,6 @@ void DiskDumper::CloseEntry(disk_cache::Entry* entry, base::Time last_used,
#ifdef WIN32_LARGE_FILENAME_SUPPORT
CloseHandle(entry_);
#else
- file_util::CloseFile(entry_);
+ base::CloseFile(entry_);
#endif
}
diff --git a/chromium/net/tools/dump_cache/dump_cache.cc b/chromium/net/tools/dump_cache/dump_cache.cc
index dd423b7a950..d4ccc294448 100644
--- a/chromium/net/tools/dump_cache/dump_cache.cc
+++ b/chromium/net/tools/dump_cache/dump_cache.cc
@@ -32,6 +32,7 @@ enum Errors {
TOOL_NOT_FOUND,
};
+#if defined(OS_WIN)
const char kUpgradeHelp[] =
"\nIn order to use the upgrade function, a version of this tool that\n"
"understands the file format of the files to upgrade is needed. For\n"
@@ -39,6 +40,7 @@ const char kUpgradeHelp[] =
"a version of this program that was compiled with version 3.4 has to be\n"
"located beside this executable, and named dump_cache_3.exe, and this\n"
"executable should be compiled with version 5.2 being the current one.";
+#endif // defined(OS_WIN)
// Folders to read and write cache files.
const char kInputPath[] = "input";
@@ -58,7 +60,9 @@ const char kUpgrade[] = "upgrade";
// Internal use:
const char kSlave[] = "slave";
+#if defined(OS_WIN)
const char kPipe[] = "pipe";
+#endif // defined(OS_WIN)
int Help() {
printf("warning: input files are modified by this tool\n");
diff --git a/chromium/net/tools/flip_server/epoll_server.cc b/chromium/net/tools/epoll_server/epoll_server.cc
index 0e09a6d7d03..a382dbae994 100644
--- a/chromium/net/tools/flip_server/epoll_server.cc
+++ b/chromium/net/tools/epoll_server/epoll_server.cc
@@ -1,8 +1,8 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include <unistd.h> // For read, pipe, close and write.
#include <stdlib.h> // for abort
diff --git a/chromium/net/tools/flip_server/epoll_server.h b/chromium/net/tools/epoll_server/epoll_server.h
index 2fb7c62089a..88224508600 100644
--- a/chromium/net/tools/flip_server/epoll_server.h
+++ b/chromium/net/tools/epoll_server/epoll_server.h
@@ -1,16 +1,16 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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_FLIP_SERVER_EPOLL_SERVER_H_
-#define NET_TOOLS_FLIP_SERVER_EPOLL_SERVER_H_
+#ifndef NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
+#define NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
#include <fcntl.h>
#include <sys/queue.h>
#include <map>
+#include <set>
#include <string>
#include <utility>
-#include <set>
#include <vector>
// #define EPOLL_SERVER_EVENT_TRACING 1
@@ -1050,5 +1050,4 @@ class EpollAlarm : public EpollAlarmCallbackInterface {
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_EPOLL_SERVER_H_
-
+#endif // NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_
diff --git a/chromium/net/tools/flip_server/acceptor_thread.cc b/chromium/net/tools/flip_server/acceptor_thread.cc
index ed8a3ec86f3..5dfece1dede 100644
--- a/chromium/net/tools/flip_server/acceptor_thread.cc
+++ b/chromium/net/tools/flip_server/acceptor_thread.cc
@@ -20,7 +20,7 @@
namespace net {
-SMAcceptorThread::SMAcceptorThread(FlipAcceptor *acceptor,
+SMAcceptorThread::SMAcceptorThread(FlipAcceptor* acceptor,
MemoryCache* memory_cache)
: SimpleThread("SMAcceptorThread"),
acceptor_(acceptor),
@@ -48,7 +48,7 @@ SMAcceptorThread::SMAcceptorThread(FlipAcceptor *acceptor,
SMAcceptorThread::~SMAcceptorThread() {
for (std::vector<SMConnection*>::iterator i =
- allocated_server_connections_.begin();
+ allocated_server_connections_.begin();
i != allocated_server_connections_.end();
++i) {
delete *i;
@@ -57,10 +57,8 @@ SMAcceptorThread::~SMAcceptorThread() {
}
SMConnection* SMAcceptorThread::NewConnection() {
- SMConnection* server =
- SMConnection::NewSMConnection(&epoll_server_, ssl_state_,
- memory_cache_, acceptor_,
- "client_conn: ");
+ SMConnection* server = SMConnection::NewSMConnection(
+ &epoll_server_, ssl_state_, memory_cache_, acceptor_, "client_conn: ");
allocated_server_connections_.push_back(server);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Making new server.";
return server;
@@ -81,12 +79,15 @@ void SMAcceptorThread::InitWorker() {
}
void SMAcceptorThread::HandleConnection(int server_fd,
- struct sockaddr_in *remote_addr) {
+ 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));
+ rc = setsockopt(server_fd,
+ IPPROTO_TCP,
+ TCP_NODELAY,
+ reinterpret_cast<char*>(&on),
+ sizeof(on));
if (rc < 0) {
close(server_fd);
LOG(ERROR) << "setsockopt() failed fd=" << server_fd;
@@ -128,7 +129,7 @@ void SMAcceptorThread::AcceptFromListenFD() {
break;
}
VLOG(1) << ACCEPTOR_CLIENT_IDENT << " Accepted connection";
- HandleConnection(fd, (struct sockaddr_in *)&address);
+ HandleConnection(fd, (struct sockaddr_in*)&address);
}
} else {
while (true) {
@@ -144,7 +145,7 @@ void SMAcceptorThread::AcceptFromListenFD() {
break;
}
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Accepted connection";
- HandleConnection(fd, (struct sockaddr_in *)&address);
+ HandleConnection(fd, (struct sockaddr_in*)&address);
}
}
}
@@ -162,7 +163,7 @@ void SMAcceptorThread::HandleConnectionIdleTimeout() {
// is already in-order.
std::list<SMConnection*>::iterator iter = active_server_connections_.begin();
while (iter != active_server_connections_.end()) {
- SMConnection *conn = *iter;
+ SMConnection* conn = *iter;
int elapsed_time = (cur_time - conn->last_read_time_);
if (elapsed_time > idle_socket_timeout_s_) {
conn->Cleanup("Connection idle timeout reached.");
@@ -208,5 +209,3 @@ void SMAcceptorThread::SMConnectionDone(SMConnection* sc) {
}
} // namespace net
-
-
diff --git a/chromium/net/tools/flip_server/acceptor_thread.h b/chromium/net/tools/flip_server/acceptor_thread.h
index f967fac94fa..bcaa43e3a11 100644
--- a/chromium/net/tools/flip_server/acceptor_thread.h
+++ b/chromium/net/tools/flip_server/acceptor_thread.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "base/threading/simple_thread.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/flip_server/sm_interface.h"
#include "openssl/ssl.h"
@@ -28,25 +28,25 @@ struct SSLState;
// a bool cross threads - especially one which only is set once...
class Notification {
public:
- explicit Notification(bool value) : value_(value) {}
-
- void Notify() {
- base::AutoLock al(lock_);
- value_ = true;
- }
- bool HasBeenNotified() {
- base::AutoLock al(lock_);
- return value_;
- }
- bool value_;
- base::Lock lock_;
+ explicit Notification(bool value) : value_(value) {}
+
+ void Notify() {
+ base::AutoLock al(lock_);
+ value_ = true;
+ }
+ bool HasBeenNotified() {
+ base::AutoLock al(lock_);
+ return value_;
+ }
+ bool value_;
+ base::Lock lock_;
};
class SMAcceptorThread : public base::SimpleThread,
public EpollCallbackInterface,
public SMConnectionPoolInterface {
public:
- SMAcceptorThread(FlipAcceptor *acceptor, MemoryCache* memory_cache);
+ SMAcceptorThread(FlipAcceptor* acceptor, MemoryCache* memory_cache);
virtual ~SMAcceptorThread();
// EpollCallbackInteface interface
@@ -65,7 +65,7 @@ class SMAcceptorThread : public base::SimpleThread,
SMConnection* NewConnection();
SMConnection* FindOrMakeNewSMConnection();
void InitWorker();
- void HandleConnection(int server_fd, struct sockaddr_in *remote_addr);
+ void HandleConnection(int server_fd, struct sockaddr_in* remote_addr);
void AcceptFromListenFD();
// Notify the Accept thread that it is time to terminate.
diff --git a/chromium/net/tools/flip_server/constants.h b/chromium/net/tools/flip_server/constants.h
index 8b770a60773..551650909c4 100644
--- a/chromium/net/tools/flip_server/constants.h
+++ b/chromium/net/tools/flip_server/constants.h
@@ -15,12 +15,7 @@ const int kSSLSegmentSize = (1 * kMSS) - kSSLOverhead;
const int kSpdySegmentSize = kSSLSegmentSize - kSpdyOverhead;
#define ACCEPTOR_CLIENT_IDENT \
- acceptor_->listen_ip_ << ":" \
- << acceptor_->listen_port_ << " "
-
-#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0"
-
-#define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
+ acceptor_->listen_ip_ << ":" << acceptor_->listen_port_ << " "
#define IPV4_PRINTABLE_FORMAT(IP) (((IP)>>0)&0xff), (((IP)>>8)&0xff), \
(((IP)>>16)&0xff), (((IP)>>24)&0xff)
diff --git a/chromium/net/tools/flip_server/create_listener.cc b/chromium/net/tools/flip_server/create_listener.cc
index 21867a918b9..c1c08963aa0 100644
--- a/chromium/net/tools/flip_server/create_listener.cc
+++ b/chromium/net/tools/flip_server/create_listener.cc
@@ -4,17 +4,16 @@
#include "net/tools/flip_server/create_listener.h"
-#include <arpa/inet.h> // for inet_ntop
-#include <errno.h> // for strerror
-#include <netdb.h> // for getaddrinfo and getnameinfo
-#include <netinet/in.h> // for IPPROTO_*, etc.
-#include <stdlib.h> // for EXIT_FAILURE
-#include <netinet/tcp.h> // For TCP_NODELAY
-#include <sys/socket.h> // for getaddrinfo and getnameinfo
-#include <sys/types.h> // "
+#include <arpa/inet.h>
+#include <errno.h>
#include <fcntl.h>
-#include <unistd.h> // for exit()
-#include <ostream>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
#include "base/logging.h"
@@ -24,20 +23,15 @@ namespace net {
// alloc'd by getaddrinfo
class AddrinfoGuard {
protected:
- struct addrinfo * addrinfo_ptr_;
- public:
+ struct addrinfo* addrinfo_ptr_;
- explicit AddrinfoGuard(struct addrinfo* addrinfo_ptr) :
- addrinfo_ptr_(addrinfo_ptr) {}
+ public:
+ explicit AddrinfoGuard(struct addrinfo* addrinfo_ptr)
+ : addrinfo_ptr_(addrinfo_ptr) {}
- ~AddrinfoGuard() {
- freeaddrinfo(addrinfo_ptr_);
- }
+ ~AddrinfoGuard() { freeaddrinfo(addrinfo_ptr_); }
};
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
// Summary:
// Closes a socket, with option to attempt it multiple times.
// Why do this? Well, if the system-call gets interrupted, close
@@ -53,7 +47,7 @@ class AddrinfoGuard {
// Side-effects:
// sets *fd to -1 if socket was closed.
//
-bool CloseSocket(int *fd, int tries) {
+bool CloseSocket(int* fd, int tries) {
for (int i = 0; i < tries; ++i) {
if (!close(*fd)) {
*fd = -1;
@@ -63,32 +57,28 @@ 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;
+ CHECK_NE(fcntl_return, -1) << "error doing fcntl(fd, F_GETFL, 0) fd: " << fd
+ << " errno=" << errno;
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;
+ << "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));
+ 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;
@@ -106,17 +96,19 @@ int CreateListeningSocket(const std::string& host,
bool reuseport,
bool wait_for_iface,
bool disable_nagle,
- int * listen_fd ) {
+ int* listen_fd) {
// start out by assuming things will fail.
*listen_fd = -1;
const char* node = NULL;
const char* service = NULL;
- if (!host.empty()) node = host.c_str();
- if (!port.empty()) service = port.c_str();
+ if (!host.empty())
+ node = host.c_str();
+ if (!port.empty())
+ service = port.c_str();
- struct addrinfo *results = 0;
+ struct addrinfo* results = 0;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@@ -129,21 +121,21 @@ int CreateListeningSocket(const std::string& host,
hints.ai_socktype = SOCK_STREAM;
int err = 0;
- if ((err=getaddrinfo(node, service, &hints, &results))) {
+ if ((err = getaddrinfo(node, service, &hints, &results))) {
// gai_strerror -is- threadsafe, so we get to use it here.
- LOG(ERROR) << "getaddrinfo " << " for (" << host << ":" << port
- << ") " << gai_strerror(err) << "\n";
+ LOG(ERROR) << "getaddrinfo "
+ << " for (" << host << ":" << port << ") " << gai_strerror(err)
+ << "\n";
return -1;
}
// this will delete the addrinfo memory when we return from this function.
AddrinfoGuard addrinfo_guard(results);
- int sock = socket(results->ai_family,
- results->ai_socktype,
- results->ai_protocol);
+ int sock =
+ socket(results->ai_family, results->ai_socktype, results->ai_protocol);
if (sock == -1) {
- LOG(ERROR) << "Unable to create socket for (" << host << ":"
- << port << "): " << strerror(errno) << "\n";
+ LOG(ERROR) << "Unable to create socket for (" << host << ":" << port
+ << "): " << strerror(errno) << "\n";
return -1;
}
@@ -151,8 +143,11 @@ int CreateListeningSocket(const std::string& host,
// set SO_REUSEADDR on the listening socket.
int on = 1;
int rc;
- rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- reinterpret_cast<char *>(&on), sizeof(on));
+ rc = setsockopt(sock,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ reinterpret_cast<char*>(&on),
+ sizeof(on));
if (rc < 0) {
close(sock);
LOG(FATAL) << "setsockopt() failed fd=" << listen_fd << "\n";
@@ -165,8 +160,11 @@ int CreateListeningSocket(const std::string& host,
// set SO_REUSEADDR on the listening socket.
int on = 1;
int rc;
- rc = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
- reinterpret_cast<char *>(&on), sizeof(on));
+ rc = setsockopt(sock,
+ SOL_SOCKET,
+ SO_REUSEPORT,
+ reinterpret_cast<char*>(&on),
+ sizeof(on));
if (rc < 0) {
close(sock);
LOG(FATAL) << "setsockopt() failed fd=" << listen_fd << "\n";
@@ -177,21 +175,21 @@ int CreateListeningSocket(const std::string& host,
// If we are waiting for the interface to be raised, such as in an
// HA environment, ignore reporting any errors.
int saved_errno = errno;
- if ( !wait_for_iface || errno != EADDRNOTAVAIL) {
- LOG(ERROR) << "Bind was unsuccessful for (" << host << ":"
- << port << "): " << strerror(errno) << "\n";
+ if (!wait_for_iface || errno != EADDRNOTAVAIL) {
+ LOG(ERROR) << "Bind was unsuccessful for (" << host << ":" << port
+ << "): " << strerror(errno) << "\n";
}
// if we knew that we were not multithreaded, we could do the following:
// " : " << strerror(errno) << "\n";
if (CloseSocket(&sock, 100)) {
- if ( saved_errno == EADDRNOTAVAIL ) {
+ if (saved_errno == EADDRNOTAVAIL) {
return -3;
}
return -2;
} else {
// couldn't even close the dang socket?!
LOG(ERROR) << "Unable to close the socket.. Considering this a fatal "
- "error, and exiting\n";
+ "error, and exiting\n";
exit(EXIT_FAILURE);
return -1;
}
@@ -205,8 +203,8 @@ int CreateListeningSocket(const std::string& host,
if (listen(sock, backlog)) {
// listen was unsuccessful.
- LOG(ERROR) << "Listen was unsuccessful for (" << host << ":"
- << port << "): " << strerror(errno) << "\n";
+ LOG(ERROR) << "Listen was unsuccessful for (" << host << ":" << port
+ << "): " << strerror(errno) << "\n";
// if we knew that we were not multithreaded, we could do the following:
// " : " << strerror(errno) << "\n";
@@ -216,7 +214,7 @@ int CreateListeningSocket(const std::string& host,
} else {
// couldn't even close the dang socket?!
LOG(FATAL) << "Unable to close the socket.. Considering this a fatal "
- "error, and exiting\n";
+ "error, and exiting\n";
}
}
@@ -226,11 +224,11 @@ int CreateListeningSocket(const std::string& host,
return 0;
}
-int CreateConnectedSocket( int *connect_fd,
- const std::string& host,
- const std::string& port,
- bool is_numeric_host_address,
- bool disable_nagle ) {
+int CreateConnectedSocket(int* connect_fd,
+ const std::string& host,
+ const std::string& port,
+ bool is_numeric_host_address,
+ bool disable_nagle) {
const char* node = NULL;
const char* service = NULL;
@@ -240,7 +238,7 @@ int CreateConnectedSocket( int *connect_fd,
if (!port.empty())
service = port.c_str();
- struct addrinfo *results = 0;
+ struct addrinfo* results = 0;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
@@ -252,25 +250,24 @@ int CreateConnectedSocket( int *connect_fd,
hints.ai_socktype = SOCK_STREAM;
int err = 0;
- if ((err=getaddrinfo(node, service, &hints, &results))) {
+ if ((err = getaddrinfo(node, service, &hints, &results))) {
// gai_strerror -is- threadsafe, so we get to use it here.
- LOG(ERROR) << "getaddrinfo for (" << node << ":" << service << "): "
- << gai_strerror(err);
+ LOG(ERROR) << "getaddrinfo for (" << node << ":" << service
+ << "): " << gai_strerror(err);
return -1;
}
// this will delete the addrinfo memory when we return from this function.
AddrinfoGuard addrinfo_guard(results);
- int sock = socket(results->ai_family,
- results->ai_socktype,
- results->ai_protocol);
+ int sock =
+ socket(results->ai_family, results->ai_socktype, results->ai_protocol);
if (sock == -1) {
LOG(ERROR) << "Unable to create socket for (" << node << ":" << service
- << "): " << strerror( errno );
+ << "): " << strerror(errno);
return -1;
}
- FlipSetNonBlocking( sock );
+ FlipSetNonBlocking(sock);
if (disable_nagle) {
if (!SetDisableNagle(sock)) {
@@ -279,11 +276,11 @@ int CreateConnectedSocket( int *connect_fd,
}
int ret_val = 0;
- if ( connect( sock, results->ai_addr, results->ai_addrlen ) ) {
- if ( errno != EINPROGRESS ) {
+ if (connect(sock, results->ai_addr, results->ai_addrlen)) {
+ if (errno != EINPROGRESS) {
LOG(ERROR) << "Connect was unsuccessful for (" << node << ":" << service
<< "): " << strerror(errno);
- close( sock );
+ close(sock);
return -1;
}
} else {
diff --git a/chromium/net/tools/flip_server/create_listener.h b/chromium/net/tools/flip_server/create_listener.h
index a3f5a87e6a3..8ab619c1dfd 100644
--- a/chromium/net/tools/flip_server/create_listener.h
+++ b/chromium/net/tools/flip_server/create_listener.h
@@ -44,9 +44,9 @@ int CreateListeningSocket(const std::string& host,
bool reuseport,
bool wait_for_iface,
bool disable_nagle,
- int * listen_fd);
+ int* listen_fd);
-int CreateConnectedSocket(int *connect_fd,
+int CreateConnectedSocket(int* connect_fd,
const std::string& host,
const std::string& port,
bool is_numeric_host_address,
diff --git a/chromium/net/tools/flip_server/flip_config.cc b/chromium/net/tools/flip_server/flip_config.cc
index 3de302856f1..8be1fe03291 100644
--- a/chromium/net/tools/flip_server/flip_config.cc
+++ b/chromium/net/tools/flip_server/flip_config.cc
@@ -23,7 +23,7 @@ FlipAcceptor::FlipAcceptor(enum FlipHandlerType flip_handler_type,
int accepts_per_wake,
bool reuseport,
bool wait_for_iface,
- void *memory_cache)
+ void* memory_cache)
: flip_handler_type_(flip_handler_type),
listen_ip_(listen_ip),
listen_port_(listen_port),
@@ -58,16 +58,15 @@ FlipAcceptor::FlipAcceptor(enum FlipHandlerType flip_handler_type,
wait_for_iface,
disable_nagle_,
&listen_fd_);
- if ( ret == 0 ) {
+ if (ret == 0) {
break;
- } else if ( ret == -3 && wait_for_iface ) {
+ } else if (ret == -3 && wait_for_iface) {
// Binding error EADDRNOTAVAIL was encounted. We need
// to wait for the interfaces to raised. try again.
usleep(200000);
} else {
LOG(ERROR) << "Unable to create listening socket for: ret = " << ret
- << ": " << listen_ip_.c_str() << ":"
- << listen_port_.c_str();
+ << ": " << listen_ip_.c_str() << ":" << listen_port_.c_str();
return;
}
}
@@ -82,15 +81,14 @@ FlipAcceptor::FlipAcceptor(enum FlipHandlerType flip_handler_type,
VLOG(1) << "\tType : HTTP Server";
VLOG(1) << "\tIP : " << listen_ip_;
VLOG(1) << "\tPort : " << listen_port_;
- VLOG(1) << "\tHTTP Server : " << http_server_ip_ << ":"
- << http_server_port_;
+ VLOG(1) << "\tHTTP Server : " << http_server_ip_ << ":" << http_server_port_;
VLOG(1) << "\tHTTPS Server : " << https_server_ip_ << ":"
<< https_server_port_;
- VLOG(1) << "\tSSL : "
- << (ssl_cert_filename.size()?"true":"false");
+ VLOG(1) << "\tSSL : " << (ssl_cert_filename.size() ? "true"
+ : "false");
VLOG(1) << "\tCertificate : " << ssl_cert_filename;
VLOG(1) << "\tKey : " << ssl_key_filename;
- VLOG(1) << "\tSpdy Only : " << (spdy_only?"true":"flase");
+ VLOG(1) << "\tSpdy Only : " << (spdy_only ? "true" : "false");
}
FlipAcceptor::~FlipAcceptor() {}
@@ -98,8 +96,7 @@ FlipAcceptor::~FlipAcceptor() {}
FlipConfig::FlipConfig()
: server_think_time_in_s_(0),
log_destination_(logging::LOG_TO_SYSTEM_DEBUG_LOG),
- wait_for_iface_(false) {
-}
+ wait_for_iface_(false) {}
FlipConfig::~FlipConfig() {}
@@ -118,7 +115,7 @@ void FlipConfig::AddAcceptor(enum FlipHandlerType flip_handler_type,
int accepts_per_wake,
bool reuseport,
bool wait_for_iface,
- void *memory_cache) {
+ void* memory_cache) {
// TODO(mbelshe): create a struct FlipConfigArgs{} for the arguments.
acceptors_.push_back(new FlipAcceptor(flip_handler_type,
listen_ip,
@@ -138,4 +135,4 @@ void FlipConfig::AddAcceptor(enum FlipHandlerType flip_handler_type,
memory_cache));
}
-} // namespace
+} // namespace net
diff --git a/chromium/net/tools/flip_server/flip_config.h b/chromium/net/tools/flip_server/flip_config.h
index 454c4bf6469..90a4199f935 100644
--- a/chromium/net/tools/flip_server/flip_config.h
+++ b/chromium/net/tools/flip_server/flip_config.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_TOOLS_FLIP_PROXY_CONFIG_H
-#define NET_TOOLS_FLIP_PROXY_CONFIG_H
+#ifndef NET_TOOLS_FLIP_SERVER_FLIP_CONFIG_H_
+#define NET_TOOLS_FLIP_SERVER_FLIP_CONFIG_H_
-#include <arpa/inet.h> // in_addr_t
+#include <arpa/inet.h>
#include <string>
#include <vector>
@@ -16,9 +16,9 @@
namespace net {
enum FlipHandlerType {
- FLIP_HANDLER_PROXY,
- FLIP_HANDLER_SPDY_SERVER,
- FLIP_HANDLER_HTTP_SERVER
+ FLIP_HANDLER_PROXY,
+ FLIP_HANDLER_SPDY_SERVER,
+ FLIP_HANDLER_HTTP_SERVER
};
class FlipAcceptor {
@@ -38,7 +38,7 @@ class FlipAcceptor {
int accepts_per_wake,
bool reuseport,
bool wait_for_iface,
- void *memory_cache);
+ void* memory_cache);
~FlipAcceptor();
enum FlipHandlerType flip_handler_type_;
@@ -81,7 +81,7 @@ class FlipConfig {
int accepts_per_wake,
bool reuseport,
bool wait_for_iface,
- void *memory_cache);
+ void* memory_cache);
std::vector<FlipAcceptor*> acceptors_;
double server_think_time_in_s_;
@@ -93,7 +93,6 @@ class FlipConfig {
int idle_socket_timeout_s_;
};
-} // namespace
-
-#endif // NET_TOOLS_FLIP_PROXY_CONFIG_H
+} // namespace net
+#endif // NET_TOOLS_FLIP_SERVER_FLIP_CONFIG_H_
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 ce7ffb8b056..ef1cefd6125 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
@@ -4,10 +4,10 @@
#include <errno.h>
#include <signal.h>
+#include <stdio.h>
#include <sys/file.h>
#include <sys/stat.h>
-#include <iostream>
#include <string>
#include <vector>
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/synchronization/lock.h"
#include "base/timer/timer.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"
@@ -22,12 +23,8 @@
#include "net/tools/flip_server/sm_connection.h"
#include "net/tools/flip_server/sm_interface.h"
#include "net/tools/flip_server/spdy_interface.h"
-#include "net/tools/flip_server/split.h"
#include "net/tools/flip_server/streamer_interface.h"
-using std::cout;
-using std::cerr;
-
// If true, then disables the nagle algorithm);
bool FLAGS_disable_nagle = true;
@@ -55,20 +52,18 @@ double FLAGS_server_think_time_in_s = 0;
net::FlipConfig g_proxy_config;
-////////////////////////////////////////////////////////////////////////////////
-
-std::vector<std::string> &split(const std::string &s,
+std::vector<std::string>& split(const std::string& s,
char delim,
- std::vector<std::string> &elems) {
+ std::vector<std::string>& elems) {
std::stringstream ss(s);
std::string item;
- while(std::getline(ss, item, delim)) {
+ while (std::getline(ss, item, delim)) {
elems.push_back(item);
}
return elems;
}
-std::vector<std::string> split(const std::string &s, char delim) {
+std::vector<std::string> split(const std::string& s, char delim) {
std::vector<std::string> elems;
return split(s, delim, elems);
}
@@ -85,8 +80,7 @@ bool GotQuitFromStdin() {
VLOG(1) << "scanning string: \"" << maybequit << "\"";
}
return (maybequit.size() > 1 &&
- (maybequit.c_str()[0] == 'q' ||
- maybequit.c_str()[0] == 'Q'));
+ (maybequit.c_str()[0] == 'q' || maybequit.c_str()[0] == 'Q'));
}
const char* BoolToStr(bool b) {
@@ -95,13 +89,10 @@ const char* BoolToStr(bool b) {
return "false";
}
-////////////////////////////////////////////////////////////////////////////////
-
static bool wantExit = false;
static bool wantLogClose = false;
-void SignalHandler(int signum)
-{
- switch(signum) {
+void SignalHandler(int signum) {
+ switch (signum) {
case SIGTERM:
case SIGINT:
wantExit = true;
@@ -112,36 +103,39 @@ void SignalHandler(int signum)
}
}
-static int OpenPidFile(const char *pidfile)
-{
+static int OpenPidFile(const char* pidfile) {
int fd;
struct stat pid_stat;
int ret;
fd = open(pidfile, O_RDWR | O_CREAT, 0600);
if (fd == -1) {
- cerr << "Could not open pid file '" << pidfile << "' for reading.\n";
- exit(1);
+ fprintf(stderr, "Could not open pid file '%s' for reading.\n", pidfile);
+ exit(1);
}
ret = flock(fd, LOCK_EX | LOCK_NB);
if (ret == -1) {
if (errno == EWOULDBLOCK) {
- cerr << "Flip server is already running.\n";
+ fprintf(stderr, "Flip server is already running.\n");
} else {
- cerr << "Error getting lock on pid file: " << strerror(errno) << "\n";
+ perror("Error getting lock on pid file");
}
exit(1);
}
if (fstat(fd, &pid_stat) == -1) {
- cerr << "Could not stat pid file '" << pidfile << "': " << strerror(errno)
- << "\n";
+ fprintf(
+ stderr, "Could not stat pid file '%s': %s\n", pidfile, strerror(errno));
+ exit(1);
}
if (pid_stat.st_size != 0) {
if (ftruncate(fd, pid_stat.st_size) == -1) {
- cerr << "Could not truncate pid file '" << pidfile << "': "
- << strerror(errno) << "\n";
+ fprintf(stderr,
+ "Could not truncate pid file '%s': %s\n",
+ pidfile,
+ strerror(errno));
+ exit(1);
}
}
@@ -149,7 +143,7 @@ static int OpenPidFile(const char *pidfile)
snprintf(pid_str, sizeof(pid_str), "%d", getpid());
int bytes = static_cast<int>(strlen(pid_str));
if (write(fd, pid_str, strlen(pid_str)) != bytes) {
- cerr << "Could not write pid file: " << strerror(errno) << "\n";
+ perror("Could not write pid file");
close(fd);
exit(1);
}
@@ -157,8 +151,7 @@ static int OpenPidFile(const char *pidfile)
return fd;
}
-int main (int argc, char**argv)
-{
+int main(int argc, char** argv) {
unsigned int i = 0;
bool wait_for_iface = false;
int pidfile_fd;
@@ -172,40 +165,41 @@ int main (int argc, char**argv)
CommandLine cl(argc, argv);
if (cl.HasSwitch("help") || argc < 2) {
- cout << argv[0] << " <options>\n";
- cout << " Proxy options:\n";
- cout << "\t--proxy<1..n>=\"<listen ip>,<listen port>,"
- << "<ssl cert filename>,\n"
- << "\t <ssl key filename>,<http server ip>,"
- << "<http server port>,\n"
- << "\t [https server ip],[https server port],"
- << "<spdy only 0|1>\"\n";
- cout << "\t * The https server ip and port may be left empty if they are"
- << " the same as\n"
- << "\t the http server fields.\n";
- cout << "\t * spdy only prevents non-spdy https connections from being"
- << " passed\n"
- << "\t through the proxy listen ip:port.\n";
- cout << "\t--forward-ip-header=<header name>\n";
- cout << "\n Server options:\n";
- cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],"
- << "\n\t [ssl key filename]\"\n";
- cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],"
- << "\n\t [ssl key filename]\"\n";
- cout << "\t * Leaving the ssl cert and key fields empty will disable ssl"
- << " for the\n"
- << "\t http and spdy flip servers\n";
- cout << "\n Global options:\n";
- cout << "\t--logdest=<file|system|both>\n";
- cout << "\t--logfile=<logfile>\n";
- cout << "\t--wait-for-iface\n";
- cout << "\t * The flip server will block until the listen ip has been"
- << " raised.\n";
- cout << "\t--ssl-session-expiry=<seconds> (default is 300)\n";
- cout << "\t--ssl-disable-compression\n";
- cout << "\t--idle-timeout=<seconds> (default is 300)\n";
- cout << "\t--pidfile=<filepath> (default /var/run/flip-server.pid)\n";
- cout << "\t--help\n";
+ printf("%s <options>\n", argv[0]);
+ printf(" Proxy options:\n");
+ printf(
+ "\t--proxy<1..n>=\"<listen ip>,<listen port>,"
+ "<ssl cert filename>,\n"
+ "\t <ssl key filename>,<http server ip>,"
+ "<http server port>,\n"
+ "\t [https server ip],[https server port],"
+ "<spdy only 0|1>\"\n"
+ "\t * The https server ip and port may be left empty if they are"
+ " the same as\n"
+ "\t the http server fields.\n"
+ "\t * spdy only prevents non-spdy https connections from being"
+ " passed\n"
+ "\t through the proxy listen ip:port.\n"
+ "\t--forward-ip-header=<header name>\n"
+ "\n Server options:\n"
+ "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],"
+ "\n\t [ssl key filename]\"\n"
+ "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],"
+ "\n\t [ssl key filename]\"\n"
+ "\t * Leaving the ssl cert and key fields empty will disable ssl"
+ " for the\n"
+ "\t http and spdy flip servers\n"
+ "\n Global options:\n"
+ "\t--logdest=<file|system|both>\n"
+ "\t--logfile=<logfile>\n"
+ "\t--wait-for-iface\n"
+ "\t * The flip server will block until the listen ip has been"
+ " raised.\n"
+ "\t--ssl-session-expiry=<seconds> (default is 300)\n"
+ "\t--ssl-disable-compression\n"
+ "\t--idle-timeout=<seconds> (default is 300)\n"
+ "\t--pidfile=<filepath> (default /var/run/flip-server.pid)\n"
+ "\t--help\n");
exit(0);
}
@@ -263,7 +257,7 @@ int main (int argc, char**argv)
if (cl.HasSwitch("idle-timeout")) {
g_proxy_config.idle_socket_timeout_s_ =
- atoi(cl.GetSwitchValueASCII("idle-timeout").c_str());
+ atoi(cl.GetSwitchValueASCII("idle-timeout").c_str());
}
if (cl.HasSwitch("force_spdy"))
@@ -279,17 +273,19 @@ int main (int argc, char**argv)
LOG(INFO) << "Logging destination : " << g_proxy_config.log_destination_;
LOG(INFO) << "Log file : " << g_proxy_config.log_filename_;
LOG(INFO) << "Forward IP Header : "
- << (net::SpdySM::forward_ip_header().length() ?
- net::SpdySM::forward_ip_header() : "<disabled>");
- LOG(INFO) << "Wait for interfaces : " << (wait_for_iface?"true":"false");
+ << (net::SpdySM::forward_ip_header().length()
+ ? net::SpdySM::forward_ip_header()
+ : "<disabled>");
+ LOG(INFO) << "Wait for interfaces : " << (wait_for_iface ? "true"
+ : "false");
LOG(INFO) << "Accept backlog size : " << FLAGS_accept_backlog_size;
LOG(INFO) << "Accepts per wake : " << FLAGS_accepts_per_wake;
- LOG(INFO) << "Disable nagle : "
- << (FLAGS_disable_nagle?"true":"false");
- LOG(INFO) << "Reuseport : "
- << (FLAGS_reuseport?"true":"false");
- LOG(INFO) << "Force SPDY : "
- << (FLAGS_force_spdy?"true":"false");
+ LOG(INFO) << "Disable nagle : " << (FLAGS_disable_nagle ? "true"
+ : "false");
+ LOG(INFO) << "Reuseport : " << (FLAGS_reuseport ? "true"
+ : "false");
+ LOG(INFO) << "Force SPDY : " << (FLAGS_force_spdy ? "true"
+ : "false");
LOG(INFO) << "SSL session expiry : "
<< g_proxy_config.ssl_session_expiry_;
LOG(INFO) << "SSL disable compression : "
@@ -312,10 +308,14 @@ int main (int argc, char**argv)
// 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],
+ valueArgs[0],
+ valueArgs[1],
+ valueArgs[2],
+ valueArgs[3],
+ valueArgs[4],
+ valueArgs[5],
+ valueArgs[6],
+ valueArgs[7],
spdy_only,
FLAGS_accept_backlog_size,
FLAGS_disable_nagle,
@@ -380,11 +380,10 @@ int main (int argc, char**argv)
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];
+ net::FlipAcceptor* acceptor = g_proxy_config.acceptors_[i];
- sm_worker_threads_.push_back(
- new net::SMAcceptorThread(acceptor,
- (net::MemoryCache *)acceptor->memory_cache_));
+ 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,
// we either must make the MemoryCache threadsafe, or use
@@ -400,7 +399,7 @@ int main (int argc, char**argv)
while (!wantExit) {
// Close logfile when HUP signal is received. Logging system will
// automatically reopen on next log message.
- if ( wantLogClose ) {
+ if (wantLogClose) {
wantLogClose = false;
VLOG(1) << "HUP received, reopening log file.";
logging::CloseLogFile();
@@ -414,11 +413,10 @@ int main (int argc, char**argv)
}
break;
}
- usleep(1000*10); // 10 ms
+ usleep(1000 * 10); // 10 ms
}
unlink(PIDFILE);
close(pidfile_fd);
return 0;
}
-
diff --git a/chromium/net/tools/flip_server/flip_test_utils.cc b/chromium/net/tools/flip_server/flip_test_utils.cc
index d9846cf5ac7..c99d7d63377 100644
--- a/chromium/net/tools/flip_server/flip_test_utils.cc
+++ b/chromium/net/tools/flip_server/flip_test_utils.cc
@@ -6,10 +6,8 @@
namespace net {
-MockSMInterface::MockSMInterface() {
-}
+MockSMInterface::MockSMInterface() {}
-MockSMInterface::~MockSMInterface() {
-}
+MockSMInterface::~MockSMInterface() {}
} // namespace net
diff --git a/chromium/net/tools/flip_server/flip_test_utils.h b/chromium/net/tools/flip_server/flip_test_utils.h
index 8a10b9563d1..0a61a60f771 100644
--- a/chromium/net/tools/flip_server/flip_test_utils.h
+++ b/chromium/net/tools/flip_server/flip_test_utils.h
@@ -19,14 +19,15 @@ class MockSMInterface : public SMInterface {
virtual ~MockSMInterface();
MOCK_METHOD2(InitSMInterface, void(SMInterface*, int32));
- MOCK_METHOD8(InitSMConnection, void(SMConnectionPoolInterface*,
- SMInterface*,
- EpollServer*,
- int,
- std::string,
- std::string,
- std::string,
- bool));
+ MOCK_METHOD8(InitSMConnection,
+ void(SMConnectionPoolInterface*,
+ SMInterface*,
+ EpollServer*,
+ int,
+ std::string,
+ std::string,
+ std::string,
+ bool));
MOCK_METHOD2(ProcessReadInput, size_t(const char*, size_t));
MOCK_METHOD2(ProcessWriteInput, size_t(const char*, size_t));
MOCK_METHOD1(SetStreamID, void(uint32 stream_id));
diff --git a/chromium/net/tools/flip_server/http_interface.cc b/chromium/net/tools/flip_server/http_interface.cc
index 916ba51f6ab..b939c5ff87b 100644
--- a/chromium/net/tools/flip_server/http_interface.cc
+++ b/chromium/net/tools/flip_server/http_interface.cc
@@ -4,8 +4,8 @@
#include "net/tools/flip_server/http_interface.h"
+#include "net/tools/balsa/balsa_frame.h"
#include "net/tools/dump_cache/url_utilities.h"
-#include "net/tools/flip_server/balsa_frame.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/sm_connection.h"
#include "net/tools/flip_server/spdy_util.h"
@@ -46,18 +46,19 @@ void HttpSM::ProcessBodyData(const char* input, size_t size) {
void HttpSM::ProcessHeaders(const BalsaHeaders& headers) {
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
std::string host =
- UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string());
+ UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string());
std::string method = headers.request_method().as_string();
- VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Received Request: "
- << headers.request_uri().as_string() << " " << method;
- std::string filename = EncodeURL(headers.request_uri().as_string(),
- host, method);
+ VLOG(1) << ACCEPTOR_CLIENT_IDENT
+ << "Received Request: " << headers.request_uri().as_string() << " "
+ << method;
+ std::string filename =
+ EncodeURL(headers.request_uri().as_string(), host, method);
NewStream(stream_id_, 0, filename);
stream_id_ += 2;
} else {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Received Response from "
- << connection_->server_ip_ << ":"
- << connection_->server_port_ << " ";
+ << connection_->server_ip_ << ":" << connection_->server_port_
+ << " ";
sm_spdy_interface_->SendSynReply(stream_id_, headers);
}
}
@@ -72,17 +73,11 @@ void HttpSM::MessageDone() {
}
}
-void HttpSM::HandleHeaderError(BalsaFrame* framer) {
- HandleError();
-}
+void HttpSM::HandleHeaderError(BalsaFrame* framer) { HandleError(); }
-void HttpSM::HandleChunkingError(BalsaFrame* framer) {
- HandleError();
-}
+void HttpSM::HandleChunkingError(BalsaFrame* framer) { HandleError(); }
-void HttpSM::HandleBodyError(BalsaFrame* framer) {
- HandleError();
-}
+void HttpSM::HandleBodyError(BalsaFrame* framer) { HandleError(); }
void HttpSM::HandleError() {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
@@ -92,8 +87,7 @@ void HttpSM::AddToOutputOrder(const MemCacheIter& mci) {
output_ordering_.AddToOutputOrder(mci);
}
-void HttpSM::InitSMInterface(SMInterface* sm_spdy_interface,
- int32 server_idx) {
+void HttpSM::InitSMInterface(SMInterface* sm_spdy_interface, int32 server_idx) {
sm_spdy_interface_ = sm_spdy_interface;
server_idx_ = server_idx;
}
@@ -141,29 +135,24 @@ bool HttpSM::MessageFullyRead() const {
return http_framer_->MessageFullyRead();
}
-void HttpSM::SetStreamID(uint32 stream_id) {
- stream_id_ = stream_id;
-}
+void HttpSM::SetStreamID(uint32 stream_id) { stream_id_ = stream_id; }
-bool HttpSM::Error() const {
- return http_framer_->Error();
-}
+bool HttpSM::Error() const { return http_framer_->Error(); }
const char* HttpSM::ErrorAsString() const {
return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode());
}
void HttpSM::Reset() {
- VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream "
- << stream_id_;
+ VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream " << stream_id_;
http_framer_->Reset();
}
void HttpSM::ResetForNewConnection() {
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
- << "to: " << connection_->server_ip_ << ":"
- << connection_->server_port_ << " ";
+ << "to: " << connection_->server_ip_ << ":"
+ << connection_->server_port_ << " ";
}
// Message has not been fully read, either it is incomplete or the
// server is closing the connection to signal message end.
@@ -186,11 +175,10 @@ void HttpSM::Cleanup() {
}
}
-int HttpSM::PostAcceptHook() {
- return 1;
-}
+int HttpSM::PostAcceptHook() { return 1; }
-void HttpSM::NewStream(uint32 stream_id, uint32 priority,
+void HttpSM::NewStream(uint32 stream_id,
+ uint32 priority,
const std::string& filename) {
MemCacheIter mci;
mci.stream_id = stream_id;
@@ -223,8 +211,11 @@ size_t HttpSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
return SendSynReplyImpl(stream_id, headers);
}
-void HttpSM::SendDataFrame(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) {
+void HttpSM::SendDataFrame(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) {
SendDataFrameImpl(stream_id, data, len, flags, compress);
}
@@ -283,8 +274,11 @@ size_t HttpSM::SendSynStreamImpl(uint32 stream_id,
return df_size;
}
-void HttpSM::SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) {
+void HttpSM::SendDataFrameImpl(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) {
char chunk_buf[128];
snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len);
std::string chunk_description(chunk_buf);
@@ -313,8 +307,8 @@ void HttpSM::GetOutput() {
return;
}
if (!mci->transformed_header) {
- mci->bytes_sent = SendSynReply(mci->stream_id,
- *(mci->file_data->headers()));
+ mci->bytes_sent =
+ SendSynReply(mci->stream_id, *(mci->file_data->headers()));
mci->transformed_header = true;
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
<< "header stream_id: [" << mci->stream_id << "]";
@@ -334,7 +328,9 @@ void HttpSM::GetOutput() {
SendDataFrame(mci->stream_id,
mci->file_data->body().data() + mci->body_bytes_consumed,
- num_to_write, 0, true);
+ num_to_write,
+ 0,
+ true);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
<< mci->stream_id << "]: " << num_to_write;
mci->body_bytes_consumed += num_to_write;
diff --git a/chromium/net/tools/flip_server/http_interface.h b/chromium/net/tools/flip_server/http_interface.h
index 18e616da205..30b79792791 100644
--- a/chromium/net/tools/flip_server/http_interface.h
+++ b/chromium/net/tools/flip_server/http_interface.h
@@ -8,8 +8,8 @@
#include <string>
#include "base/compiler_specific.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/balsa/balsa_visitor_interface.h"
#include "net/tools/flip_server/output_ordering.h"
#include "net/tools/flip_server/sm_connection.h"
#include "net/tools/flip_server/sm_interface.h"
@@ -22,8 +22,7 @@ class EpollServer;
class FlipAcceptor;
class MemoryCache;
-class HttpSM : public BalsaVisitorInterface,
- public SMInterface {
+class HttpSM : public BalsaVisitorInterface, public SMInterface {
public:
HttpSM(SMConnection* connection,
SMInterface* sm_spdy_interface,
@@ -33,10 +32,10 @@ class HttpSM : public BalsaVisitorInterface,
private:
// BalsaVisitorInterface:
- virtual void ProcessBodyInput(const char *input, size_t size) OVERRIDE {}
- virtual void ProcessBodyData(const char *input, size_t size) OVERRIDE;
- virtual void ProcessHeaderInput(const char *input, size_t size) OVERRIDE {}
- virtual void ProcessTrailerInput(const char *input, size_t size) OVERRIDE {}
+ virtual void ProcessBodyInput(const char* input, size_t size) OVERRIDE {}
+ virtual void ProcessBodyData(const char* input, size_t size) OVERRIDE;
+ virtual void ProcessHeaderInput(const char* input, size_t size) OVERRIDE {}
+ virtual void ProcessTrailerInput(const char* input, size_t size) OVERRIDE {}
virtual void ProcessHeaders(const BalsaHeaders& headers) OVERRIDE;
virtual void ProcessRequestFirstLine(const char* line_input,
size_t line_length,
@@ -46,17 +45,17 @@ class HttpSM : public BalsaVisitorInterface,
size_t request_uri_length,
const char* version_input,
size_t version_length) OVERRIDE {}
- virtual void ProcessResponseFirstLine(const char *line_input,
+ virtual void ProcessResponseFirstLine(const char* line_input,
size_t line_length,
- const char *version_input,
+ const char* version_input,
size_t version_length,
- const char *status_input,
+ const char* status_input,
size_t status_length,
- const char *reason_input,
+ const char* reason_input,
size_t reason_length) OVERRIDE {}
virtual void ProcessChunkLength(size_t chunk_length) OVERRIDE {}
- virtual void ProcessChunkExtensions(const char *input,
- size_t size) OVERRIDE {}
+ virtual void ProcessChunkExtensions(const char* input, size_t size) OVERRIDE {
+ }
virtual void HeaderDone() OVERRIDE {}
virtual void MessageDone() OVERRIDE;
virtual void HandleHeaderError(BalsaFrame* framer) OVERRIDE;
@@ -95,7 +94,8 @@ class HttpSM : public BalsaVisitorInterface,
virtual void Cleanup() OVERRIDE;
virtual int PostAcceptHook() OVERRIDE;
- virtual void NewStream(uint32 stream_id, uint32 priority,
+ virtual void NewStream(uint32 stream_id,
+ uint32 priority,
const std::string& filename) OVERRIDE;
virtual void SendEOF(uint32 stream_id) OVERRIDE;
virtual void SendErrorNotFound(uint32 stream_id) OVERRIDE;
@@ -103,8 +103,11 @@ class HttpSM : public BalsaVisitorInterface,
const BalsaHeaders& headers) OVERRIDE;
virtual size_t SendSynReply(uint32 stream_id,
const BalsaHeaders& headers) OVERRIDE;
- virtual void SendDataFrame(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) OVERRIDE;
+ virtual void SendDataFrame(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) OVERRIDE;
private:
void SendEOFImpl(uint32 stream_id);
@@ -112,8 +115,11 @@ class HttpSM : public BalsaVisitorInterface,
void SendOKResponseImpl(uint32 stream_id, const std::string& output);
size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers);
size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers);
- void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress);
+ void SendDataFrameImpl(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress);
void EnqueueDataFrame(DataFrame* df);
virtual void GetOutput() OVERRIDE;
diff --git a/chromium/net/tools/flip_server/http_interface_test.cc b/chromium/net/tools/flip_server/http_interface_test.cc
index ba9b3aa36bb..969607b6fa1 100644
--- a/chromium/net/tools/flip_server/http_interface_test.cc
+++ b/chromium/net/tools/flip_server/http_interface_test.cc
@@ -9,9 +9,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_frame.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/balsa_frame.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/flip_test_utils.h"
#include "net/tools/flip_server/mem_cache.h"
@@ -40,14 +40,15 @@ class MockSMConnection : public SMConnection {
log_prefix) {}
MOCK_METHOD0(Cleanup, void());
- MOCK_METHOD8(InitSMConnection, void(SMConnectionPoolInterface*,
- SMInterface*,
- EpollServer*,
- int,
- std::string,
- std::string,
- std::string,
- bool));
+ MOCK_METHOD8(InitSMConnection,
+ void(SMConnectionPoolInterface*,
+ SMInterface*,
+ EpollServer*,
+ int,
+ std::string,
+ std::string,
+ std::string,
+ bool));
};
class FlipHttpSMTest : public ::testing::Test {
@@ -167,10 +168,11 @@ TEST_F(FlipHttpSMTest, InitSMConnection) {
}
TEST_F(FlipHttpSMTest, ProcessReadInput) {
- std::string data = "HTTP/1.1 200 OK\r\n"
+ std::string data =
+ "HTTP/1.1 200 OK\r\n"
"Content-Length: 14\r\n\r\n"
"hello, world\r\n";
- testing::MockFunction<void(int)> checkpoint;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
{
InSequence s;
EXPECT_CALL(*mock_another_interface_, SendSynReply(_, _));
@@ -205,7 +207,7 @@ TEST_F(FlipHttpSMTest, ProcessWriteInput) {
TEST_F(FlipHttpSMTest, Reset) {
std::string data = "HTTP/1.1 200 OK\r\n\r\n";
- testing::MockFunction<void(int)> checkpoint;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
{
InSequence s;
EXPECT_CALL(*mock_another_interface_, SendSynReply(_, _));
@@ -228,7 +230,7 @@ TEST_F(FlipHttpSMTest, Reset) {
TEST_F(FlipHttpSMTest, ResetForNewConnection) {
std::string data = "HTTP/1.1 200 OK\r\n\r\n";
- testing::MockFunction<void(int)> checkpoint;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
{
InSequence s;
EXPECT_CALL(*mock_another_interface_, SendSynReply(_, _));
@@ -264,7 +266,8 @@ TEST_F(FlipHttpSMTest, NewStream) {
}
TEST_F(FlipHttpSMTest, NewStreamError) {
- std::string syn_reply = "HTTP/1.1 404 Not Found\r\n"
+ std::string syn_reply =
+ "HTTP/1.1 404 Not Found\r\n"
"transfer-encoding: chunked\r\n\r\n";
std::string body = "e\r\npage not found\r\n";
uint32 stream_id = 4;
@@ -284,7 +287,8 @@ TEST_F(FlipHttpSMTest, NewStreamError) {
}
TEST_F(FlipHttpSMTest, SendErrorNotFound) {
- std::string syn_reply = "HTTP/1.1 404 Not Found\r\n"
+ std::string syn_reply =
+ "HTTP/1.1 404 Not Found\r\n"
"transfer-encoding: chunked\r\n\r\n";
std::string body = "e\r\npage not found\r\n";
uint32 stream_id = 13;
@@ -314,7 +318,8 @@ TEST_F(FlipHttpSMTest, SendErrorNotFound) {
}
TEST_F(FlipHttpSMTest, SendSynStream) {
- std::string expected = "GET / HTTP/1.0\r\n"
+ std::string expected =
+ "GET / HTTP/1.0\r\n"
"key1: value1\r\n\r\n";
BalsaHeaders headers;
headers.SetResponseFirstlineFromStringPieces("GET", "/path", "HTTP/1.0");
@@ -326,7 +331,8 @@ TEST_F(FlipHttpSMTest, SendSynStream) {
}
TEST_F(FlipHttpSMTest, SendSynReply) {
- std::string expected = "HTTP/1.1 200 OK\r\n"
+ std::string expected =
+ "HTTP/1.1 200 OK\r\n"
"key1: value1\r\n\r\n";
BalsaHeaders headers;
headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
@@ -409,9 +415,7 @@ TEST_F(FlipHttpSMHttpTest, ProcessHeaders) {
BalsaHeaders headers;
headers.AppendHeader("Host", "example.com");
- headers.SetRequestFirstlineFromStringPieces("GET",
- "/path/file",
- "HTTP/1.0");
+ headers.SetRequestFirstlineFromStringPieces("GET", "/path/file", "HTTP/1.0");
uint32 stream_id = 133;
interface_->SetStreamID(stream_id);
ASSERT_FALSE(HasStream(stream_id));
diff --git a/chromium/net/tools/flip_server/http_message_constants.cc b/chromium/net/tools/flip_server/http_message_constants.cc
index e60fb1cd451..a4a8b4deb7d 100644
--- a/chromium/net/tools/flip_server/http_message_constants.cc
+++ b/chromium/net/tools/flip_server/http_message_constants.cc
@@ -92,55 +92,12 @@ const char* get_http_status_message(int status_message) {
return "unknown";
}
-////////////////////////////////////////////////////////////////////////////////
-
const int http_status_codes[] = {
- 100,
- 101,
- 200,
- 201,
- 202,
- 203,
- 204,
- 205,
- 206,
- 300,
- 301,
- 302,
- 303,
- 304,
- 305,
- 307,
- 400,
- 401,
- 402,
- 403,
- 404,
- 405,
- 406,
- 407,
- 408,
- 409,
- 410,
- 411,
- 412,
- 413,
- 414,
- 415,
- 416,
- 417,
- 500,
- 501,
- 502,
- 503,
- 504,
- 505
-};
-
-////////////////////////////////////////////////////////////////////////////////
+ 100, 101, 200, 201, 202, 203, 204, 205, 206, 300, 301, 302, 303, 304,
+ 305, 307, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411,
+ 412, 413, 414, 415, 416, 417, 500, 501, 502, 503, 504, 505};
-const int http_status_code_count = sizeof(http_status_codes) /
- sizeof(http_status_codes[0]);
+const int http_status_code_count =
+ sizeof(http_status_codes) / sizeof(http_status_codes[0]);
} // namespace net
-
diff --git a/chromium/net/tools/flip_server/loadtime_measurement.h b/chromium/net/tools/flip_server/loadtime_measurement.h
index b46217e4fe1..ccbb2e53234 100644
--- a/chromium/net/tools/flip_server/loadtime_measurement.h
+++ b/chromium/net/tools/flip_server/loadtime_measurement.h
@@ -44,7 +44,7 @@ class LoadtimeMeasurement {
}
if (action.find("get_total_iteration") == 0) {
char buffer[16];
- snprintf(buffer, 16, "%d", num_urls_);
+ snprintf(buffer, sizeof(buffer), "%d", num_urls_);
output.append(buffer, strlen(buffer));
return;
}
@@ -60,7 +60,8 @@ class LoadtimeMeasurement {
}
if (action.find("test_complete") == 0) {
for (std::map<std::string, int>::const_iterator it = loadtimes_.begin();
- it != loadtimes_.end(); ++it) {
+ it != loadtimes_.end();
+ ++it) {
LOG(INFO) << it->first << " " << it->second;
}
loadtimes_.clear();
@@ -99,7 +100,8 @@ class LoadtimeMeasurement {
close(fd);
}
- void split_string(std::string& str, char sepa,
+ void split_string(const std::string& str,
+ char sepa,
std::vector<std::string>* sub_strs) {
size_t b = 0;
size_t e = str.find_first_of(sepa, b);
@@ -120,4 +122,3 @@ class LoadtimeMeasurement {
};
#endif // NET_TOOLS_FLIP_SERVER_LOADTIME_MEASUREMENT_H__
-
diff --git a/chromium/net/tools/flip_server/mem_cache.cc b/chromium/net/tools/flip_server/mem_cache.cc
index d1e0e58be41..521f56cbf71 100644
--- a/chromium/net/tools/flip_server/mem_cache.cc
+++ b/chromium/net/tools/flip_server/mem_cache.cc
@@ -17,10 +17,10 @@
#include <string>
#include "base/strings/string_util.h"
+#include "net/tools/balsa/balsa_frame.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/dump_cache/url_to_filename_encoder.h"
#include "net/tools/dump_cache/url_utilities.h"
-#include "net/tools/flip_server/balsa_frame.h"
-#include "net/tools/flip_server/balsa_headers.h"
namespace {
// The directory where cache locates);
@@ -29,7 +29,7 @@ const char FLAGS_cache_base_dir[] = ".";
namespace net {
-void StoreBodyAndHeadersVisitor::ProcessBodyData(const char *input,
+void StoreBodyAndHeadersVisitor::ProcessBodyData(const char* input,
size_t size) {
body.append(input, size);
}
@@ -53,8 +53,7 @@ void StoreBodyAndHeadersVisitor::HandleBodyError(BalsaFrame* framer) {
FileData::FileData(const BalsaHeaders* headers,
const std::string& filename,
const std::string& body)
- : filename_(filename)
- , body_(body) {
+ : filename_(filename), body_(body) {
if (headers) {
headers_.reset(new BalsaHeaders);
headers_->CopyFrom(*headers);
@@ -67,9 +66,7 @@ FileData::~FileData() {}
MemoryCache::MemoryCache() : cwd_(FLAGS_cache_base_dir) {}
-MemoryCache::~MemoryCache() {
- ClearFiles();
-}
+MemoryCache::~MemoryCache() { ClearFiles(); }
void MemoryCache::CloneFrom(const MemoryCache& mc) {
DCHECK_NE(this, &mc);
@@ -97,11 +94,10 @@ void MemoryCache::AddFiles() {
if (current_dir) {
VLOG(1) << "Succeeded opening";
- for (struct dirent* dir_data = readdir(current_dir);
- dir_data != NULL;
+ for (struct dirent* dir_data = readdir(current_dir); dir_data != NULL;
dir_data = readdir(current_dir)) {
std::string current_entry_name =
- current_dir_name + "/" + dir_data->d_name;
+ current_dir_name + "/" + dir_data->d_name;
if (dir_data->d_type == DT_REG) {
VLOG(1) << "Found file: " << current_entry_name;
ReadAndStoreFileContents(current_entry_name.c_str());
@@ -158,7 +154,7 @@ void MemoryCache::ReadAndStoreFileContents(const char* filename) {
filename_contents.size() - pos);
if (framer.Error() || pos == old_pos) {
LOG(ERROR) << "Unable to make forward progress, or error"
- " framing file: " << filename;
+ " framing file: " << filename;
if (framer.Error()) {
LOG(INFO) << "********************************************ERROR!";
return;
@@ -180,9 +176,9 @@ void MemoryCache::ReadAndStoreFileContents(const char* filename) {
visitor.headers.AppendHeader("transfer-encoding", "chunked");
visitor.headers.AppendHeader("connection", "keep-alive");
- // Experiment with changing headers for forcing use of cached
- // versions of content.
- // TODO(mbelshe) REMOVE ME
+// Experiment with changing headers for forcing use of cached
+// versions of content.
+// TODO(mbelshe) REMOVE ME
#if 0
// TODO(mbelshe) append current date.
visitor.headers.RemoveAllOfHeader("date");
@@ -196,15 +192,14 @@ void MemoryCache::ReadAndStoreFileContents(const char* filename) {
DCHECK_EQ(std::string(filename).substr(0, cwd_.size()), cwd_);
DCHECK_EQ(filename[cwd_.size()], '/');
std::string filename_stripped = std::string(filename).substr(cwd_.size() + 1);
- LOG(INFO) << "Adding file (" << visitor.body.length() << " bytes): "
- << filename_stripped;
+ LOG(INFO) << "Adding file (" << visitor.body.length()
+ << " bytes): " << filename_stripped;
size_t slash_pos = filename_stripped.find('/');
if (slash_pos == std::string::npos) {
slash_pos = filename_stripped.size();
}
- InsertFile(&visitor.headers,
- filename_stripped.substr(0, slash_pos),
- visitor.body);
+ InsertFile(
+ &visitor.headers, filename_stripped.substr(0, slash_pos), visitor.body);
}
FileData* MemoryCache::GetFileData(const std::string& filename) {
diff --git a/chromium/net/tools/flip_server/mem_cache.h b/chromium/net/tools/flip_server/mem_cache.h
index 300c84a3fe0..76ffc95e36b 100644
--- a/chromium/net/tools/flip_server/mem_cache.h
+++ b/chromium/net/tools/flip_server/mem_cache.h
@@ -10,21 +10,21 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/balsa/balsa_visitor_interface.h"
#include "net/tools/flip_server/constants.h"
namespace net {
-class StoreBodyAndHeadersVisitor: public BalsaVisitorInterface {
+class StoreBodyAndHeadersVisitor : public BalsaVisitorInterface {
public:
void HandleError() { error_ = true; }
// BalsaVisitorInterface:
- virtual void ProcessBodyInput(const char *input, size_t size) OVERRIDE {}
- virtual void ProcessBodyData(const char *input, size_t size) OVERRIDE;
- virtual void ProcessHeaderInput(const char *input, size_t size) OVERRIDE {}
- virtual void ProcessTrailerInput(const char *input, size_t size) OVERRIDE {}
+ virtual void ProcessBodyInput(const char* input, size_t size) OVERRIDE {}
+ virtual void ProcessBodyData(const char* input, size_t size) OVERRIDE;
+ virtual void ProcessHeaderInput(const char* input, size_t size) OVERRIDE {}
+ virtual void ProcessTrailerInput(const char* input, size_t size) OVERRIDE {}
virtual void ProcessHeaders(const BalsaHeaders& headers) OVERRIDE {
// nothing to do here-- we're assuming that the BalsaFrame has
// been handed our headers.
@@ -37,17 +37,17 @@ class StoreBodyAndHeadersVisitor: public BalsaVisitorInterface {
size_t request_uri_length,
const char* version_input,
size_t version_length) OVERRIDE {}
- virtual void ProcessResponseFirstLine(const char *line_input,
+ virtual void ProcessResponseFirstLine(const char* line_input,
size_t line_length,
- const char *version_input,
+ const char* version_input,
size_t version_length,
- const char *status_input,
+ const char* status_input,
size_t status_length,
- const char *reason_input,
+ const char* reason_input,
size_t reason_length) OVERRIDE {}
virtual void ProcessChunkLength(size_t chunk_length) OVERRIDE {}
- virtual void ProcessChunkExtensions(const char *input,
- size_t size) OVERRIDE {}
+ virtual void ProcessChunkExtensions(const char* input, size_t size) OVERRIDE {
+ }
virtual void HeaderDone() OVERRIDE {}
virtual void MessageDone() OVERRIDE {}
virtual void HandleHeaderError(BalsaFrame* framer) OVERRIDE;
@@ -60,7 +60,6 @@ class StoreBodyAndHeadersVisitor: public BalsaVisitorInterface {
bool error_;
};
-////////////////////////////////////////////////////////////////////////////////
class FileData {
public:
FileData();
@@ -83,26 +82,24 @@ class FileData {
DISALLOW_COPY_AND_ASSIGN(FileData);
};
-////////////////////////////////////////////////////////////////////////////////
-
class MemCacheIter {
public:
- MemCacheIter() :
- file_data(NULL),
- priority(0),
- transformed_header(false),
- body_bytes_consumed(0),
- stream_id(0),
- max_segment_size(kInitialDataSendersThreshold),
- bytes_sent(0) {}
- explicit MemCacheIter(FileData* fd) :
- file_data(fd),
- priority(0),
- transformed_header(false),
- body_bytes_consumed(0),
- stream_id(0),
- max_segment_size(kInitialDataSendersThreshold),
- bytes_sent(0) {}
+ MemCacheIter()
+ : file_data(NULL),
+ priority(0),
+ transformed_header(false),
+ body_bytes_consumed(0),
+ stream_id(0),
+ max_segment_size(kInitialDataSendersThreshold),
+ bytes_sent(0) {}
+ explicit MemCacheIter(FileData* fd)
+ : file_data(fd),
+ priority(0),
+ transformed_header(false),
+ body_bytes_consumed(0),
+ stream_id(0),
+ max_segment_size(kInitialDataSendersThreshold),
+ bytes_sent(0) {}
FileData* file_data;
int priority;
bool transformed_header;
@@ -112,8 +109,6 @@ class MemCacheIter {
size_t bytes_sent;
};
-////////////////////////////////////////////////////////////////////////////////
-
class MemoryCache {
public:
typedef std::map<std::string, FileData*> Files;
diff --git a/chromium/net/tools/flip_server/mem_cache_test.cc b/chromium/net/tools/flip_server/mem_cache_test.cc
index d5601ac14f5..5e45bb53ec7 100644
--- a/chromium/net/tools/flip_server/mem_cache_test.cc
+++ b/chromium/net/tools/flip_server/mem_cache_test.cc
@@ -4,7 +4,7 @@
#include "net/tools/flip_server/mem_cache.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -15,8 +15,8 @@ class MemoryCacheWithFakeReadToString : public MemoryCache {
public:
virtual ~MemoryCacheWithFakeReadToString() {}
- virtual void ReadToString(const char* filename, std::string* output)
- OVERRIDE {
+ virtual void ReadToString(const char* filename,
+ std::string* output) OVERRIDE {
*output = data_map_[filename];
}
@@ -25,7 +25,7 @@ class MemoryCacheWithFakeReadToString : public MemoryCache {
class FlipMemoryCacheTest : public ::testing::Test {
public:
- FlipMemoryCacheTest(): mem_cache_(new MemoryCacheWithFakeReadToString) {}
+ FlipMemoryCacheTest() : mem_cache_(new MemoryCacheWithFakeReadToString) {}
protected:
scoped_ptr<MemoryCacheWithFakeReadToString> mem_cache_;
@@ -44,7 +44,8 @@ TEST_F(FlipMemoryCacheTest, ReadAndStoreFileContents) {
FileData* hello;
mem_cache_->data_map_["./foo"] = "bar";
- mem_cache_->data_map_["./hello"] = "HTTP/1.0 200 OK\r\n"
+ mem_cache_->data_map_["./hello"] =
+ "HTTP/1.0 200 OK\r\n"
"key1: value1\r\n"
"key2: value2\r\n\r\n"
"body: body\r\n";
@@ -63,8 +64,9 @@ TEST_F(FlipMemoryCacheTest, ReadAndStoreFileContents) {
ASSERT_EQ("HTTP/1.1", hello->headers()->response_version());
ASSERT_EQ("200", hello->headers()->response_code());
ASSERT_EQ("OK", hello->headers()->response_reason_phrase());
- ASSERT_EQ(4, std::distance(hello->headers()->header_lines_begin(),
- hello->headers()->header_lines_end()));
+ ASSERT_EQ(4,
+ std::distance(hello->headers()->header_lines_begin(),
+ hello->headers()->header_lines_end()));
ASSERT_TRUE(hello->headers()->HasHeader("key1"));
ASSERT_TRUE(hello->headers()->HasHeader("key2"));
ASSERT_TRUE(hello->headers()->HasHeader("transfer-encoding"));
@@ -82,7 +84,8 @@ TEST_F(FlipMemoryCacheTest, ReadAndStoreFileContents) {
TEST_F(FlipMemoryCacheTest, GetFileDataForHtmlFile) {
FileData* hello_html;
- mem_cache_->data_map_["./hello.http"] = "HTTP/1.0 200 OK\r\n"
+ mem_cache_->data_map_["./hello.http"] =
+ "HTTP/1.0 200 OK\r\n"
"key1: value1\r\n"
"key2: value2\r\n\r\n"
"body: body\r\n";
diff --git a/chromium/net/tools/flip_server/output_ordering.cc b/chromium/net/tools/flip_server/output_ordering.cc
index 6a42869bc8e..9659954f48b 100644
--- a/chromium/net/tools/flip_server/output_ordering.cc
+++ b/chromium/net/tools/flip_server/output_ordering.cc
@@ -9,13 +9,12 @@
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/sm_connection.h"
-
namespace net {
OutputOrdering::PriorityMapPointer::PriorityMapPointer()
- : ring(NULL),
- alarm_enabled(false) {
-}
+ : ring(NULL), alarm_enabled(false) {}
+
+OutputOrdering::PriorityMapPointer::~PriorityMapPointer() {}
// static
double OutputOrdering::server_think_time_in_s_ = 0.0;
@@ -27,9 +26,7 @@ OutputOrdering::OutputOrdering(SMConnectionInterface* connection)
epoll_server_ = connection->epoll_server();
}
-OutputOrdering::~OutputOrdering() {
- Reset();
-}
+OutputOrdering::~OutputOrdering() { Reset(); }
void OutputOrdering::Reset() {
while (!stream_ids_.empty()) {
@@ -53,11 +50,7 @@ OutputOrdering::BeginOutputtingAlarm::BeginOutputtingAlarm(
OutputOrdering* oo,
OutputOrdering::PriorityMapPointer* pmp,
const MemCacheIter& mci)
- : output_ordering_(oo),
- pmp_(pmp),
- mci_(mci),
- epoll_server_(NULL) {
-}
+ : output_ordering_(oo), pmp_(pmp), mci_(mci), epoll_server_(NULL) {}
OutputOrdering::BeginOutputtingAlarm::~BeginOutputtingAlarm() {
if (epoll_server_ && pmp_->alarm_enabled)
@@ -110,35 +103,31 @@ void OutputOrdering::AddToOutputOrder(const MemCacheIter& mci) {
double tmp_think_time_in_s = strtod(x_server_latency.c_str(), &endp);
if (endp != x_server_latency.c_str() + x_server_latency.size()) {
LOG(ERROR) << "Unable to understand X-Server-Latency of: "
- << x_server_latency << " for resource: "
- << mci.file_data->filename().c_str();
+ << x_server_latency
+ << " for resource: " << mci.file_data->filename().c_str();
} else {
think_time_in_s = tmp_think_time_in_s;
}
}
StreamIdToPriorityMap::iterator sitpmi;
- sitpmi = stream_ids_.insert(
- std::pair<uint32, PriorityMapPointer>(mci.stream_id,
- PriorityMapPointer())).first;
+ sitpmi = stream_ids_.insert(std::pair<uint32, PriorityMapPointer>(
+ mci.stream_id, PriorityMapPointer())).first;
PriorityMapPointer& pmp = sitpmi->second;
BeginOutputtingAlarm* boa = new BeginOutputtingAlarm(this, &pmp, mci);
VLOG(1) << "Server think time: " << think_time_in_s;
- epoll_server_->RegisterAlarmApproximateDelta(
- think_time_in_s * 1000000, boa);
+ epoll_server_->RegisterAlarmApproximateDelta(think_time_in_s * 1000000, boa);
}
void OutputOrdering::SpliceToPriorityRing(PriorityRing::iterator pri) {
MemCacheIter& mci = *pri;
PriorityMap::iterator pmi = priority_map_.find(mci.priority);
if (pmi == priority_map_.end()) {
- pmi = priority_map_.insert(
- std::pair<uint32, PriorityRing>(mci.priority, PriorityRing())).first;
+ pmi = priority_map_.insert(std::pair<uint32, PriorityRing>(
+ mci.priority, PriorityRing())).first;
}
- pmi->second.splice(pmi->second.end(),
- first_data_senders_,
- pri);
+ pmi->second.splice(pmi->second.end(), first_data_senders_, pri);
StreamIdToPriorityMap::iterator sitpmi = stream_ids_.find(mci.stream_id);
sitpmi->second.ring = &(pmi->second);
}
@@ -150,8 +139,8 @@ MemCacheIter* OutputOrdering::GetIter() {
SpliceToPriorityRing(first_data_senders_.begin());
} else {
first_data_senders_.splice(first_data_senders_.end(),
- first_data_senders_,
- first_data_senders_.begin());
+ first_data_senders_,
+ first_data_senders_.begin());
mci.max_segment_size = kInitialDataSendersThreshold;
return &mci;
}
@@ -163,9 +152,7 @@ MemCacheIter* OutputOrdering::GetIter() {
continue;
}
MemCacheIter& mci = first_ring.front();
- first_ring.splice(first_ring.end(),
- first_ring,
- first_ring.begin());
+ first_ring.splice(first_ring.end(), first_ring, first_ring.begin());
mci.max_segment_size = kSpdySegmentSize;
return &mci;
}
diff --git a/chromium/net/tools/flip_server/output_ordering.h b/chromium/net/tools/flip_server/output_ordering.h
index 922d03fc864..596f3824110 100644
--- a/chromium/net/tools/flip_server/output_ordering.h
+++ b/chromium/net/tools/flip_server/output_ordering.h
@@ -11,8 +11,8 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/flip_server/constants.h"
-#include "net/tools/flip_server/epoll_server.h"
#include "net/tools/flip_server/mem_cache.h"
namespace net {
@@ -26,6 +26,7 @@ class OutputOrdering {
struct PriorityMapPointer {
PriorityMapPointer();
+ ~PriorityMapPointer();
PriorityRing* ring;
PriorityRing::iterator it;
bool alarm_enabled;
diff --git a/chromium/net/tools/flip_server/ring_buffer.cc b/chromium/net/tools/flip_server/ring_buffer.cc
index 81e9e9ee481..16c278bcdef 100644
--- a/chromium/net/tools/flip_server/ring_buffer.cc
+++ b/chromium/net/tools/flip_server/ring_buffer.cc
@@ -12,42 +12,19 @@ RingBuffer::RingBuffer(int buffer_size)
buffer_size_(buffer_size),
bytes_used_(0),
read_idx_(0),
- write_idx_(0) {
-}
+ write_idx_(0) {}
RingBuffer::~RingBuffer() {}
-////////////////////////////////////////////////////////////////////////////////
-
-int RingBuffer::ReadableBytes() const {
- return bytes_used_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-int RingBuffer::BufferSize() const {
- return buffer_size_;
-}
+int RingBuffer::ReadableBytes() const { return bytes_used_; }
-////////////////////////////////////////////////////////////////////////////////
-
-int RingBuffer::BytesFree() const {
- return BufferSize() - ReadableBytes();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-bool RingBuffer::Empty() const {
- return ReadableBytes() == 0;
-}
+int RingBuffer::BufferSize() const { return buffer_size_; }
-////////////////////////////////////////////////////////////////////////////////
+int RingBuffer::BytesFree() const { return BufferSize() - ReadableBytes(); }
-bool RingBuffer::Full() const {
- return ReadableBytes() == BufferSize();
-}
+bool RingBuffer::Empty() const { return ReadableBytes() == 0; }
-////////////////////////////////////////////////////////////////////////////////
+bool RingBuffer::Full() const { return ReadableBytes() == BufferSize(); }
// Returns the number of characters written.
// Appends up-to-'size' bytes to the ringbuffer.
@@ -94,8 +71,6 @@ int RingBuffer::Write(const char* bytes, int size) {
#endif
}
-////////////////////////////////////////////////////////////////////////////////
-
// Sets *ptr to the beginning of writable memory, and sets *size to the size
// available for writing using this pointer.
void RingBuffer::GetWritablePtr(char** ptr, int* size) const {
@@ -110,8 +85,6 @@ void RingBuffer::GetWritablePtr(char** ptr, int* size) const {
}
}
-////////////////////////////////////////////////////////////////////////////////
-
// Sets *ptr to the beginning of readable memory, and sets *size to the size
// available for reading using this pointer.
void RingBuffer::GetReadablePtr(char** ptr, int* size) const {
@@ -126,8 +99,6 @@ void RingBuffer::GetReadablePtr(char** ptr, int* size) const {
}
}
-////////////////////////////////////////////////////////////////////////////////
-
// returns the number of bytes read into
int RingBuffer::Read(char* bytes, int size) {
CHECK_GE(size, 0);
@@ -171,18 +142,14 @@ int RingBuffer::Read(char* bytes, int size) {
#endif
}
-////////////////////////////////////////////////////////////////////////////////
-
void RingBuffer::Clear() {
bytes_used_ = 0;
write_idx_ = 0;
read_idx_ = 0;
}
-////////////////////////////////////////////////////////////////////////////////
-
bool RingBuffer::Reserve(int size) {
- DCHECK(size > 0);
+ DCHECK_GT(size, 0);
char* write_ptr = NULL;
int write_size = 0;
GetWritablePtr(&write_ptr, &write_size);
@@ -197,8 +164,8 @@ bool RingBuffer::Reserve(int size) {
// possible if the read_idx < write_idx. If write_idx < read_idx, then
// the writeable region must be contiguous: [write_idx, read_idx). There
// is no work to be done for the latter.
- DCHECK(read_idx_ <= write_idx_);
- DCHECK(read_size == ReadableBytes());
+ DCHECK_LE(read_idx_, write_idx_);
+ DCHECK_EQ(read_size, ReadableBytes());
if (read_idx_ < write_idx_) {
// Writeable area fragmented, consolidate it.
memmove(buffer_.get(), read_ptr, read_size);
@@ -206,7 +173,7 @@ bool RingBuffer::Reserve(int size) {
write_idx_ = read_size;
} else if (read_idx_ == write_idx_) {
// No unconsumed data in the buffer, simply reset the indexes.
- DCHECK(ReadableBytes() == 0);
+ DCHECK_EQ(ReadableBytes(), 0);
read_idx_ = 0;
write_idx_ = 0;
}
@@ -218,8 +185,6 @@ bool RingBuffer::Reserve(int size) {
return true;
}
-////////////////////////////////////////////////////////////////////////////////
-
void RingBuffer::AdvanceReadablePtr(int amount_to_consume) {
CHECK_GE(amount_to_consume, 0);
if (amount_to_consume >= bytes_used_) {
@@ -231,8 +196,6 @@ void RingBuffer::AdvanceReadablePtr(int amount_to_consume) {
bytes_used_ -= amount_to_consume;
}
-////////////////////////////////////////////////////////////////////////////////
-
void RingBuffer::AdvanceWritablePtr(int amount_to_produce) {
CHECK_GE(amount_to_produce, 0);
CHECK_LE(amount_to_produce, BytesFree());
@@ -241,11 +204,10 @@ void RingBuffer::AdvanceWritablePtr(int amount_to_produce) {
bytes_used_ += amount_to_produce;
}
-////////////////////////////////////////////////////////////////////////////////
-
void RingBuffer::Resize(int buffer_size) {
CHECK_GE(buffer_size, 0);
- if (buffer_size == buffer_size_) return;
+ if (buffer_size == buffer_size_)
+ return;
char* new_buffer = new char[buffer_size];
if (buffer_size < bytes_used_) {
@@ -259,7 +221,8 @@ void RingBuffer::Resize(int buffer_size) {
int size;
char* ptr;
GetReadablePtr(&ptr, &size);
- if (size == 0) break;
+ if (size == 0)
+ break;
if (size > buffer_size) {
size = buffer_size;
}
@@ -276,4 +239,3 @@ void RingBuffer::Resize(int buffer_size) {
}
} // namespace net
-
diff --git a/chromium/net/tools/flip_server/ring_buffer.h b/chromium/net/tools/flip_server/ring_buffer.h
index 03cbde7c8dd..b129ee8d014 100644
--- a/chromium/net/tools/flip_server/ring_buffer.h
+++ b/chromium/net/tools/flip_server/ring_buffer.h
@@ -7,7 +7,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "net/tools/flip_server/buffer_interface.h"
+#include "net/tools/balsa/buffer_interface.h"
namespace net {
@@ -47,7 +47,7 @@ class RingBuffer : public BufferInterface {
// returns the number of characters written.
// appends up-to-'size' bytes to the ringbuffer.
- virtual int Write(const char * bytes, int size) OVERRIDE;
+ virtual int Write(const char* bytes, int size) OVERRIDE;
// Stores a pointer into the ring buffer in *ptr, and stores the number of
// characters which are allowed to be written in *size.
@@ -110,4 +110,3 @@ class RingBuffer : public BufferInterface {
} // namespace net
#endif // NET_TOOLS_FLIP_SERVER_RING_BUFFER_H__
-
diff --git a/chromium/net/tools/flip_server/run_all_tests.cc b/chromium/net/tools/flip_server/run_all_tests.cc
new file mode 100644
index 00000000000..6acc286b9fd
--- /dev/null
+++ b/chromium/net/tools/flip_server/run_all_tests.cc
@@ -0,0 +1,8 @@
+// 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 "base/test/test_suite.h"
+#include "build/build_config.h"
+
+int main(int argc, char** argv) { return base::TestSuite(argc, argv).Run(); }
diff --git a/chromium/net/tools/flip_server/sm_connection.cc b/chromium/net/tools/flip_server/sm_connection.cc
index 375bc2ec79d..158cd30ff4f 100644
--- a/chromium/net/tools/flip_server/sm_connection.cc
+++ b/chromium/net/tools/flip_server/sm_connection.cc
@@ -54,17 +54,14 @@ SMConnection::SMConnection(EpollServer* epoll_server,
sm_interface_(NULL),
log_prefix_(log_prefix),
max_bytes_sent_per_dowrite_(4096),
- ssl_(NULL) {
-}
+ ssl_(NULL) {}
SMConnection::~SMConnection() {
if (initialized())
Reset();
}
-EpollServer* SMConnection::epoll_server() {
- return epoll_server_;
-}
+EpollServer* SMConnection::epoll_server() { return epoll_server_; }
void SMConnection::ReadyToSend() {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
@@ -104,11 +101,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 = CreateConnectedSocket(
+ &fd_, server_ip, server_port, true, acceptor_->disable_nagle_);
if (ret < 0) {
LOG(ERROR) << "-1 Could not create connected socket";
@@ -117,12 +111,12 @@ void SMConnection::InitSMConnection(SMConnectionPoolInterface* connection_pool,
DCHECK_NE(-1, fd_);
connection_complete_ = true;
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "Connection complete to: " << server_ip_ << ":"
- << server_port_ << " ";
+ << "Connection complete to: " << server_ip_ << ":" << server_port_
+ << " ";
}
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "Connecting to server: " << server_ip_ << ":"
- << server_port_ << " ";
+ << "Connecting to server: " << server_ip_ << ":" << server_port_
+ << " ";
} else {
// If fd != -1 then we are initializing a connection that has just been
// accepted from the listen socket.
@@ -132,7 +126,7 @@ void SMConnection::InitSMConnection(SMConnectionPoolInterface* connection_pool,
}
if (fd_ != -1) {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "Closing pre-existing fd";
+ << "Closing pre-existing fd";
close(fd_);
fd_ = -1;
}
@@ -261,8 +255,8 @@ void SMConnection::Cleanup(const char* cleanup) {
}
void SMConnection::HandleEvents() {
- VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Received: "
- << EpollServer::EventMaskToString(events_).c_str();
+ VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
+ << "Received: " << EpollServer::EventMaskToString(events_).c_str();
if (events_ & EPOLLIN) {
if (!DoRead())
@@ -274,8 +268,8 @@ void SMConnection::HandleEvents() {
if (connection_complete_ == false) {
int sock_error;
socklen_t sock_error_len = sizeof(sock_error);
- int ret = getsockopt(fd_, SOL_SOCKET, SO_ERROR, &sock_error,
- &sock_error_len);
+ int ret =
+ getsockopt(fd_, SOL_SOCKET, SO_ERROR, &sock_error, &sock_error_len);
if (ret != 0) {
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
<< "getsockopt error: " << errno << ": " << strerror(errno);
@@ -285,7 +279,7 @@ void SMConnection::HandleEvents() {
connection_complete_ = true;
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
<< "Connection complete to " << server_ip_ << ":"
- << server_port_ << " ";
+ << server_port_ << " ";
} else if (sock_error == EINPROGRESS) {
return;
} else {
@@ -304,27 +298,43 @@ void SMConnection::HandleEvents() {
}
return;
- handle_close_or_error:
+ handle_close_or_error:
Cleanup("HandleEvents");
}
// Decide if SPDY was negotiated.
-bool SMConnection::WasSpdyNegotiated() {
+bool SMConnection::WasSpdyNegotiated(SpdyMajorVersion* version_negotiated) {
+ *version_negotiated = SPDY3;
if (force_spdy())
return true;
// If this is an SSL connection, check if NPN specifies SPDY.
if (ssl_) {
- const unsigned char *npn_proto;
+ const unsigned char* npn_proto;
unsigned int npn_proto_len;
SSL_get0_next_proto_negotiated(ssl_, &npn_proto, &npn_proto_len);
if (npn_proto_len > 0) {
- std::string npn_proto_str((const char *)npn_proto, npn_proto_len);
+ std::string npn_proto_str((const char*)npn_proto, npn_proto_len);
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
<< "NPN protocol detected: " << npn_proto_str;
if (!strncmp(reinterpret_cast<const char*>(npn_proto),
- "spdy/2", npn_proto_len))
+ "spdy/2",
+ npn_proto_len)) {
+ *version_negotiated = SPDY2;
+ return true;
+ }
+ if (!strncmp(reinterpret_cast<const char*>(npn_proto),
+ "spdy/3",
+ npn_proto_len)) {
+ *version_negotiated = SPDY3;
return true;
+ }
+ if (!strncmp(reinterpret_cast<const char*>(npn_proto),
+ "spdy/4a2",
+ npn_proto_len)) {
+ *version_negotiated = SPDY4;
+ return true;
+ }
}
}
@@ -335,7 +345,8 @@ bool SMConnection::SetupProtocolInterfaces() {
DCHECK(!protocol_detected_);
protocol_detected_ = true;
- bool spdy_negotiated = WasSpdyNegotiated();
+ SpdyMajorVersion version;
+ bool spdy_negotiated = WasSpdyNegotiated(&version);
bool using_ssl = ssl_ != NULL;
if (using_ssl)
@@ -349,54 +360,43 @@ bool SMConnection::SetupProtocolInterfaces() {
}
switch (acceptor_->flip_handler_type_) {
- case FLIP_HANDLER_HTTP_SERVER:
- {
- DCHECK(!spdy_negotiated);
- VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << (sm_http_interface_ ? "Creating" : "Reusing")
- << " HTTP interface.";
- if (!sm_http_interface_)
- sm_http_interface_ = new HttpSM(this,
- NULL,
- memory_cache_,
- acceptor_);
- sm_interface_ = sm_http_interface_;
- }
+ case FLIP_HANDLER_HTTP_SERVER: {
+ DCHECK(!spdy_negotiated);
+ VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
+ << (sm_http_interface_ ? "Creating" : "Reusing")
+ << " HTTP interface.";
+ if (!sm_http_interface_)
+ sm_http_interface_ = new HttpSM(this, NULL, memory_cache_, acceptor_);
+ sm_interface_ = sm_http_interface_;
break;
- case FLIP_HANDLER_PROXY:
- {
- VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << (sm_streamer_interface_ ? "Creating" : "Reusing")
- << " PROXY Streamer interface.";
- if (!sm_streamer_interface_) {
- sm_streamer_interface_ = new StreamerSM(this,
- NULL,
- epoll_server_,
- acceptor_);
- sm_streamer_interface_->set_is_request();
- }
- sm_interface_ = sm_streamer_interface_;
- // If spdy is not negotiated, the streamer interface will proxy all
- // data to the origin server.
- if (!spdy_negotiated)
- break;
- }
- // Otherwise fall through into the case below.
- case FLIP_HANDLER_SPDY_SERVER:
- {
- DCHECK(spdy_negotiated);
- VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << (sm_spdy_interface_ ? "Creating" : "Reusing")
- << " SPDY interface.";
- if (!sm_spdy_interface_)
- sm_spdy_interface_ = new SpdySM(this,
- NULL,
- epoll_server_,
- memory_cache_,
- acceptor_);
- sm_interface_ = sm_spdy_interface_;
+ }
+ case FLIP_HANDLER_PROXY: {
+ VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
+ << (sm_streamer_interface_ ? "Creating" : "Reusing")
+ << " PROXY Streamer interface.";
+ if (!sm_streamer_interface_) {
+ sm_streamer_interface_ =
+ new StreamerSM(this, NULL, epoll_server_, acceptor_);
+ sm_streamer_interface_->set_is_request();
}
+ sm_interface_ = sm_streamer_interface_;
+ // If spdy is not negotiated, the streamer interface will proxy all
+ // data to the origin server.
+ if (!spdy_negotiated)
+ break;
+ }
+ // Otherwise fall through into the case below.
+ case FLIP_HANDLER_SPDY_SERVER: {
+ DCHECK(spdy_negotiated);
+ VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
+ << (sm_spdy_interface_ ? "Creating" : "Reusing")
+ << " SPDY interface.";
+ if (!sm_spdy_interface_)
+ sm_spdy_interface_ = new SpdySM(
+ this, NULL, epoll_server_, memory_cache_, acceptor_, version);
+ sm_interface_ = sm_spdy_interface_;
break;
+ }
}
CorkSocket();
@@ -454,12 +454,12 @@ bool SMConnection::DoRead() {
default:
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
<< "While calling recv, got error: "
- << (ssl_?"(ssl error)":strerror(stored_errno));
+ << (ssl_ ? "(ssl error)" : strerror(stored_errno));
goto error_or_close;
}
} else if (bytes_read > 0) {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "read " << bytes_read
- << " bytes";
+ << " bytes";
last_read_time_ = time(NULL);
// If the protocol hasn't been detected yet, set up the handlers
// we'll need.
@@ -483,7 +483,7 @@ bool SMConnection::DoRead() {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "DoRead done!";
return true;
- error_or_close:
+ error_or_close:
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
<< "DoRead(): error_or_close. "
<< "Cleaning up, then returning false";
@@ -521,9 +521,7 @@ bool SMConnection::DoConsumeReadData() {
return true;
}
-void SMConnection::HandleResponseFullyRead() {
- sm_interface_->Cleanup();
-}
+void SMConnection::HandleResponseFullyRead() { sm_interface_->Cleanup(); }
bool SMConnection::DoWrite() {
size_t bytes_sent = 0;
@@ -543,8 +541,8 @@ bool SMConnection::DoWrite() {
}
}
while (!output_list_.empty()) {
- VLOG(2) << log_prefix_ << "DoWrite: Items in output list: "
- << output_list_.size();
+ VLOG(2) << log_prefix_
+ << "DoWrite: Items in output list: " << output_list_.size();
if (bytes_sent >= max_bytes_sent_per_dowrite_) {
VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
<< " byte sent >= max bytes sent per write: Setting EPOLLOUT: "
@@ -556,7 +554,7 @@ bool SMConnection::DoWrite() {
sm_interface_->GetOutput();
}
DataFrame* data_frame = output_list_.front();
- const char* bytes = data_frame->data;
+ const char* bytes = data_frame->data;
int size = data_frame->size;
bytes += data_frame->index;
size -= data_frame->index;
@@ -591,13 +589,13 @@ bool SMConnection::DoWrite() {
continue;
default:
VLOG(1) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
- << "While calling send, got error: " << stored_errno
- << ": " << (ssl_?"":strerror(stored_errno));
+ << "While calling send, got error: " << stored_errno << ": "
+ << (ssl_ ? "" : strerror(stored_errno));
goto error_or_close;
}
} else if (bytes_written > 0) {
- VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT << "Wrote: "
- << bytes_written << " bytes";
+ VLOG(2) << log_prefix_ << ACCEPTOR_CLIENT_IDENT
+ << "Wrote: " << bytes_written << " bytes";
data_frame->index += bytes_written;
bytes_sent += bytes_written;
continue;
@@ -645,8 +643,7 @@ void SMConnection::Reset() {
initialized_ = false;
protocol_detected_ = false;
events_ = 0;
- for (std::list<DataFrame*>::iterator i =
- output_list_.begin();
+ for (std::list<DataFrame*>::iterator i = output_list_.begin();
i != output_list_.end();
++i) {
delete *i;
@@ -656,12 +653,12 @@ void SMConnection::Reset() {
// static
SMConnection* SMConnection::NewSMConnection(EpollServer* epoll_server,
- SSLState *ssl_state,
+ SSLState* ssl_state,
MemoryCache* memory_cache,
- FlipAcceptor *acceptor,
+ FlipAcceptor* acceptor,
std::string log_prefix) {
- return new SMConnection(epoll_server, ssl_state, memory_cache,
- acceptor, log_prefix);
+ return new SMConnection(
+ epoll_server, ssl_state, memory_cache, acceptor, log_prefix);
}
} // namespace net
diff --git a/chromium/net/tools/flip_server/sm_connection.h b/chromium/net/tools/flip_server/sm_connection.h
index 3e217729a52..93ad42e7e5a 100644
--- a/chromium/net/tools/flip_server/sm_connection.h
+++ b/chromium/net/tools/flip_server/sm_connection.h
@@ -12,8 +12,9 @@
#include <string>
#include "base/compiler_specific.h"
+#include "net/spdy/spdy_protocol.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/flip_server/create_listener.h"
-#include "net/tools/flip_server/epoll_server.h"
#include "net/tools/flip_server/mem_cache.h"
#include "net/tools/flip_server/ring_buffer.h"
#include "net/tools/flip_server/sm_interface.h"
@@ -45,9 +46,9 @@ class SMConnection : public SMConnectionInterface,
virtual ~SMConnection();
static SMConnection* NewSMConnection(EpollServer* epoll_server,
- SSLState *ssl_state,
+ SSLState* ssl_state,
MemoryCache* memory_cache,
- FlipAcceptor *acceptor,
+ FlipAcceptor* acceptor,
std::string log_prefix);
// TODO(mbelshe): Make these private.
@@ -99,7 +100,7 @@ class SMConnection : public SMConnectionInterface,
private:
// Decide if SPDY was negotiated.
- bool WasSpdyNegotiated();
+ bool WasSpdyNegotiated(SpdyMajorVersion* version_negotiated);
// Initialize the protocol interfaces we'll need for this connection.
// Returns true if successful, false otherwise.
@@ -124,6 +125,7 @@ class SMConnection : public SMConnectionInterface,
MemoryCache* memory_cache,
FlipAcceptor* acceptor,
std::string log_prefix);
+
private:
int fd_;
int events_;
@@ -135,10 +137,10 @@ class SMConnection : public SMConnectionInterface,
SMConnectionPoolInterface* connection_pool_;
- EpollServer *epoll_server_;
- SSLState *ssl_state_;
+ EpollServer* epoll_server_;
+ SSLState* ssl_state_;
MemoryCache* memory_cache_;
- FlipAcceptor *acceptor_;
+ FlipAcceptor* acceptor_;
std::string client_ip_;
RingBuffer read_buffer_;
diff --git a/chromium/net/tools/flip_server/sm_interface.h b/chromium/net/tools/flip_server/sm_interface.h
index 5bc942f8fa0..389c683602c 100644
--- a/chromium/net/tools/flip_server/sm_interface.h
+++ b/chromium/net/tools/flip_server/sm_interface.h
@@ -9,7 +9,7 @@
#include <string>
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
namespace net {
@@ -28,7 +28,7 @@ class SMInterface {
std::string server_ip,
std::string server_port,
std::string remote_ip,
- bool use_ssl) = 0;
+ bool use_ssl) = 0;
virtual size_t ProcessReadInput(const char* data, size_t len) = 0;
virtual size_t ProcessWriteInput(const char* data, size_t len) = 0;
virtual void SetStreamID(uint32 stream_id) = 0;
@@ -46,16 +46,20 @@ class SMInterface {
virtual int PostAcceptHook() = 0;
- virtual void NewStream(uint32 stream_id, uint32 priority,
+ virtual void NewStream(uint32 stream_id,
+ uint32 priority,
const std::string& filename) = 0;
virtual void SendEOF(uint32 stream_id) = 0;
virtual void SendErrorNotFound(uint32 stream_id) = 0;
virtual size_t SendSynStream(uint32 stream_id,
- const BalsaHeaders& headers) = 0;
+ const BalsaHeaders& headers) = 0;
virtual size_t SendSynReply(uint32 stream_id,
const BalsaHeaders& headers) = 0;
- virtual void SendDataFrame(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) = 0;
+ virtual void SendDataFrame(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) = 0;
virtual void GetOutput() = 0;
virtual void set_is_request() = 0;
@@ -64,9 +68,9 @@ class SMInterface {
class SMConnectionInterface {
public:
- virtual ~SMConnectionInterface() {}
- virtual void ReadyToSend() = 0;
- virtual EpollServer* epoll_server() = 0;
+ virtual ~SMConnectionInterface() {}
+ virtual void ReadyToSend() = 0;
+ virtual EpollServer* epoll_server() = 0;
};
class SMConnectionPoolInterface {
@@ -78,4 +82,3 @@ class SMConnectionPoolInterface {
} // namespace net
#endif // NET_TOOLS_FLIP_SERVER_SM_INTERFACE_H_
-
diff --git a/chromium/net/tools/flip_server/spdy_interface.cc b/chromium/net/tools/flip_server/spdy_interface.cc
index 359eab810a7..41ad43025e2 100644
--- a/chromium/net/tools/flip_server/spdy_interface.cc
+++ b/chromium/net/tools/flip_server/spdy_interface.cc
@@ -22,15 +22,12 @@ std::string SpdySM::forward_ip_header_;
class SpdyFrameDataFrame : public DataFrame {
public:
- explicit SpdyFrameDataFrame(SpdyFrame* spdy_frame)
- : frame(spdy_frame) {
+ explicit SpdyFrameDataFrame(SpdyFrame* spdy_frame) : frame(spdy_frame) {
data = spdy_frame->data();
size = spdy_frame->size();
}
- virtual ~SpdyFrameDataFrame() {
- delete frame;
- }
+ virtual ~SpdyFrameDataFrame() { delete frame; }
const SpdyFrame* frame;
};
@@ -39,8 +36,9 @@ SpdySM::SpdySM(SMConnection* connection,
SMInterface* sm_http_interface,
EpollServer* epoll_server,
MemoryCache* memory_cache,
- FlipAcceptor* acceptor)
- : buffered_spdy_framer_(new BufferedSpdyFramer(SPDY2, true)),
+ FlipAcceptor* acceptor,
+ SpdyMajorVersion spdy_version)
+ : buffered_spdy_framer_(new BufferedSpdyFramer(spdy_version, true)),
valid_spdy_session_(false),
connection_(connection),
client_output_list_(connection->output_list()),
@@ -53,9 +51,7 @@ SpdySM::SpdySM(SMConnection* connection,
buffered_spdy_framer_->set_visitor(this);
}
-SpdySM::~SpdySM() {
- delete buffered_spdy_framer_;
-}
+SpdySM::~SpdySM() { delete buffered_spdy_framer_; }
void SpdySM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
SMInterface* sm_interface,
@@ -65,44 +61,45 @@ void SpdySM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
std::string server_port,
std::string remote_ip,
bool use_ssl) {
- VLOG(2) << ACCEPTOR_CLIENT_IDENT
- << "SpdySM: Initializing server connection.";
- connection_->InitSMConnection(connection_pool, sm_interface,
- epoll_server, fd, server_ip, server_port,
- remote_ip, use_ssl);
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Initializing server connection.";
+ connection_->InitSMConnection(connection_pool,
+ sm_interface,
+ epoll_server,
+ fd,
+ server_ip,
+ server_port,
+ remote_ip,
+ use_ssl);
}
SMInterface* SpdySM::NewConnectionInterface() {
SMConnection* server_connection =
- SMConnection::NewSMConnection(epoll_server_,
- NULL,
- memory_cache_,
- acceptor_,
- "http_conn: ");
+ SMConnection::NewSMConnection(epoll_server_,
+ NULL,
+ memory_cache_,
+ acceptor_,
+ "http_conn: ");
if (server_connection == NULL) {
LOG(ERROR) << "SpdySM: Could not create server connection";
return NULL;
}
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Creating new HTTP interface";
- SMInterface *sm_http_interface = new HttpSM(server_connection,
- this,
- memory_cache_,
- acceptor_);
+ SMInterface* sm_http_interface =
+ new HttpSM(server_connection, this, memory_cache_, acceptor_);
return sm_http_interface;
}
SMInterface* SpdySM::FindOrMakeNewSMConnectionInterface(
const std::string& server_ip,
const std::string& server_port) {
- SMInterface *sm_http_interface;
+ SMInterface* sm_http_interface;
int32 server_idx;
if (unused_server_interface_list.empty()) {
sm_http_interface = NewConnectionInterface();
server_idx = server_interface_list.size();
server_interface_list.push_back(sm_http_interface);
VLOG(2) << ACCEPTOR_CLIENT_IDENT
- << "SpdySM: Making new server connection on index: "
- << server_idx;
+ << "SpdySM: Making new server connection on index: " << server_idx;
} else {
server_idx = unused_server_interface_list.back();
unused_server_interface_list.pop_back();
@@ -124,61 +121,96 @@ SMInterface* SpdySM::FindOrMakeNewSMConnectionInterface(
return sm_http_interface;
}
-int SpdySM::SpdyHandleNewStream(
- SpdyStreamId stream_id,
- SpdyPriority priority,
- const SpdyHeaderBlock& headers,
- std::string &http_data,
- bool* is_https_scheme) {
+int SpdySM::SpdyHandleNewStream(SpdyStreamId stream_id,
+ SpdyPriority priority,
+ const SpdyHeaderBlock& headers,
+ std::string& http_data,
+ bool* is_https_scheme) {
*is_https_scheme = false;
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSyn("
- << stream_id << ")";
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: # headers: "
- << headers.size();
-
- SpdyHeaderBlock::const_iterator url = headers.find("url");
- SpdyHeaderBlock::const_iterator method = headers.find("method");
- if (url == headers.end() || method == headers.end()) {
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: didn't find method or url "
- << "or method. Not creating stream";
- return 0;
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSyn(" << stream_id << ")";
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: # headers: " << headers.size();
+
+ SpdyHeaderBlock supplement;
+ SpdyHeaderBlock::const_iterator method = headers.end();
+ SpdyHeaderBlock::const_iterator host = headers.end();
+ SpdyHeaderBlock::const_iterator path = headers.end();
+ SpdyHeaderBlock::const_iterator scheme = headers.end();
+ SpdyHeaderBlock::const_iterator version = headers.end();
+ SpdyHeaderBlock::const_iterator url = headers.end();
+
+ if (spdy_version() == SPDY2) {
+ url = headers.find("url");
+ method = headers.find("method");
+ version = headers.find("version");
+ scheme = headers.find("scheme");
+ if (url == headers.end() || method == headers.end() ||
+ version == headers.end() || scheme == headers.end()) {
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: A mandatory header is "
+ << "missing. Not creating stream";
+ return 0;
+ }
+ // url->second here only ever seems to contain just the path. When this
+ // path contains a query string with a http:// in one of its values,
+ // UrlUtilities::GetUrlPath will fail and always return a / breaking
+ // the request. GetUrlPath assumes the absolute URL is being passed in.
+ std::string path_string = UrlUtilities::GetUrlPath(url->second);
+ std::string host_string = UrlUtilities::GetUrlHost(url->second);
+ path = supplement.insert(std::make_pair(":path", path_string)).first;
+ host = supplement.insert(std::make_pair(":host", host_string)).first;
+ } else {
+ method = headers.find(":method");
+ host = headers.find(":host");
+ path = headers.find(":path");
+ scheme = headers.find(":scheme");
+ version = supplement.insert(std::make_pair(":version", "HTTP/1.1")).first;
+ if (method == headers.end() || host == headers.end() ||
+ path == headers.end() || scheme == headers.end()) {
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: A mandatory header is "
+ << "missing. Not creating stream";
+ return 0;
+ }
}
- SpdyHeaderBlock::const_iterator scheme = headers.find("scheme");
if (scheme->second.compare("https") == 0) {
*is_https_scheme = true;
}
- // url->second here only ever seems to contain just the path. When this
- // path contains a query string with a http:// in one of its values,
- // UrlUtilities::GetUrlPath will fail and always return a / breaking
- // the request. GetUrlPath assumes the absolute URL is being passed in.
- std::string uri;
- if (url->second.compare(0, 4, "http") == 0)
- uri = UrlUtilities::GetUrlPath(url->second);
- else
- uri = std::string(url->second);
if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) {
- std::string host = UrlUtilities::GetUrlHost(url->second);
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second
- << " " << uri;
- std::string filename = EncodeURL(uri, host, method->second);
+ << " " << path->second;
+ std::string filename = EncodeURL(path->second,
+ host->second,
+ method->second);
NewStream(stream_id, priority, filename);
} else {
- SpdyHeaderBlock::const_iterator version = headers.find("version");
- http_data += method->second + " " + uri + " " + version->second + "\r\n";
+ http_data +=
+ method->second + " " + path->second + " " + version->second + "\r\n";
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second << " "
- << uri << " " << version->second;
+ << path->second << " " << version->second;
+ http_data += "Host: " + (*is_https_scheme ?
+ acceptor_->https_server_ip_ :
+ acceptor_->http_server_ip_) + "\r\n";
for (SpdyHeaderBlock::const_iterator i = headers.begin();
i != headers.end(); ++i) {
- http_data += i->first + ": " + i->second + "\r\n";
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":"
- << i->second.c_str();
+ if ((i->first.size() > 0 && i->first[0] == ':') ||
+ i->first == "host" ||
+ i == method ||
+ i == host ||
+ i == path ||
+ i == scheme ||
+ i == version ||
+ i == url) {
+ // Ignore the entry.
+ } else {
+ http_data += i->first + ": " + i->second + "\r\n";
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":"
+ << i->second.c_str();
+ }
}
if (forward_ip_header_.length()) {
// X-Client-Cluster-IP header
http_data += forward_ip_header_ + ": " +
- connection_->client_ip() + "\r\n";
+ connection_->client_ip() + "\r\n";
}
http_data += "\r\n";
}
@@ -215,8 +247,8 @@ void SpdySM::OnSynStream(SpdyStreamId stream_id,
const SpdyHeaderBlock& headers) {
std::string http_data;
bool is_https_scheme;
- int ret = SpdyHandleNewStream(stream_id, priority, headers, http_data,
- &is_https_scheme);
+ int ret = SpdyHandleNewStream(
+ stream_id, priority, headers, http_data, &is_https_scheme);
if (!ret) {
LOG(ERROR) << "SpdySM: Could not convert spdy into http.";
return;
@@ -239,8 +271,7 @@ void SpdySM::OnSynStream(SpdyStreamId stream_id,
FindOrMakeNewSMConnectionInterface(server_ip, server_port);
stream_to_smif_[stream_id] = sm_http_interface;
sm_http_interface->SetStreamID(stream_id);
- sm_http_interface->ProcessWriteInput(http_data.c_str(),
- http_data.size());
+ sm_http_interface->ProcessWriteInput(http_data.c_str(), http_data.size());
}
}
@@ -249,21 +280,18 @@ void SpdySM::OnSynReply(SpdyStreamId stream_id,
const SpdyHeaderBlock& headers) {
// TODO(willchan): if there is an error parsing headers, we
// should send a RST_STREAM.
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSynReply("
- << stream_id << ")";
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSynReply(" << stream_id << ")";
}
void SpdySM::OnHeaders(SpdyStreamId stream_id,
bool fin,
const SpdyHeaderBlock& headers) {
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnHeaders("
- << stream_id << ")";
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnHeaders(" << stream_id << ")";
}
-void SpdySM::OnRstStream(SpdyStreamId stream_id,
- SpdyRstStreamStatus status) {
- VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnRstStream("
- << stream_id << ")";
+void SpdySM::OnRstStream(SpdyStreamId stream_id, SpdyRstStreamStatus status) {
+ VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnRstStream(" << stream_id
+ << ")";
client_output_ordering_.RemoveStreamId(stream_id);
}
@@ -271,9 +299,7 @@ size_t SpdySM::ProcessReadInput(const char* data, size_t len) {
return buffered_spdy_framer_->ProcessInput(data, len);
}
-size_t SpdySM::ProcessWriteInput(const char* data, size_t len) {
- return 0;
-}
+size_t SpdySM::ProcessWriteInput(const char* data, size_t len) { return 0; }
bool SpdySM::MessageFullyRead() const {
return buffered_spdy_framer_->MessageFullyRead();
@@ -309,8 +335,7 @@ int SpdySM::PostAcceptHook() {
SettingsMap settings;
settings[SETTINGS_MAX_CONCURRENT_STREAMS] =
SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 100);
- SpdyFrame* settings_frame =
- buffered_spdy_framer_->CreateSettings(settings);
+ SpdyFrame* settings_frame = buffered_spdy_framer_->CreateSettings(settings);
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending Settings Frame";
EnqueueDataFrame(new SpdyFrameDataFrame(settings_frame));
@@ -343,9 +368,7 @@ void SpdySM::AddToOutputOrder(const MemCacheIter& mci) {
client_output_ordering_.AddToOutputOrder(mci);
}
-void SpdySM::SendEOF(uint32 stream_id) {
- SendEOFImpl(stream_id);
-}
+void SpdySM::SendEOF(uint32 stream_id) { SendEOFImpl(stream_id); }
void SpdySM::SendErrorNotFound(uint32 stream_id) {
SendErrorNotFoundImpl(stream_id);
@@ -359,8 +382,11 @@ size_t SpdySM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
return SendSynReplyImpl(stream_id, headers);
}
-void SpdySM::SendDataFrame(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) {
+void SpdySM::SendDataFrame(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) {
SpdyDataFlags spdy_flags = static_cast<SpdyDataFlags>(flags);
SendDataFrameImpl(stream_id, data, len, spdy_flags, compress);
}
@@ -386,7 +412,7 @@ void SpdySM::KillStream(uint32 stream_id) {
void SpdySM::CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) {
for (BalsaHeaders::const_header_lines_iterator hi =
- headers.header_lines_begin();
+ headers.header_lines_begin();
hi != headers.header_lines_end();
++hi) {
// It is illegal to send SPDY headers with empty value or header
@@ -401,33 +427,50 @@ void SpdySM::CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) {
if (fhi == dest.end()) {
dest[key] = hi->second.as_string();
} else {
- dest[key] = (
- std::string(fhi->second.data(), fhi->second.size()) + "\0" +
- std::string(hi->second.data(), hi->second.size()));
+ dest[key] = (std::string(fhi->second.data(), fhi->second.size()) + "\0" +
+ std::string(hi->second.data(), hi->second.size()));
}
}
// These headers have no value
dest.erase("X-Associated-Content"); // TODO(mbelshe): case-sensitive
- dest.erase("X-Original-Url"); // TODO(mbelshe): case-sensitive
+ dest.erase("X-Original-Url"); // TODO(mbelshe): case-sensitive
}
size_t SpdySM::SendSynStreamImpl(uint32 stream_id,
const BalsaHeaders& headers) {
SpdyHeaderBlock block;
- block["method"] = headers.request_method().as_string();
- if (!headers.HasHeader("version"))
- block["version"] =headers.request_version().as_string();
- if (headers.HasHeader("X-Original-Url")) {
- std::string original_url = headers.GetHeader("X-Original-Url").as_string();
- block["url"] = UrlUtilities::GetUrlPath(original_url);
+ CopyHeaders(block, headers);
+ if (spdy_version() == SPDY2) {
+ block["method"] = headers.request_method().as_string();
+ if (!headers.HasHeader("version"))
+ block["version"] = headers.request_version().as_string();
+ if (headers.HasHeader("X-Original-Url")) {
+ std::string original_url =
+ headers.GetHeader("X-Original-Url").as_string();
+ block["url"] = UrlUtilities::GetUrlPath(original_url);
+ } else {
+ block["url"] = headers.request_uri().as_string();
+ }
} else {
- block["url"] = headers.request_uri().as_string();
+ block[":method"] = headers.request_method().as_string();
+ block[":version"] = headers.request_version().as_string();
+ if (headers.HasHeader("X-Original-Url")) {
+ std::string original_url =
+ headers.GetHeader("X-Original-Url").as_string();
+ block[":path"] = UrlUtilities::GetUrlPath(original_url);
+ block[":host"] = UrlUtilities::GetUrlPath(original_url);
+ } else {
+ block[":path"] = headers.request_uri().as_string();
+ if (block.find("host") != block.end()) {
+ block[":host"] = headers.GetHeader("Host").as_string();
+ block.erase("host");
+ }
+ }
}
- CopyHeaders(block, headers);
SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynStream(
- stream_id, 0, 0, 0, CONTROL_FLAG_NONE, true, &block);
+ stream_id, 0, 0, 0, CONTROL_FLAG_NONE, &block);
size_t df_size = fsrcf->size();
EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf));
@@ -439,12 +482,18 @@ size_t SpdySM::SendSynStreamImpl(uint32 stream_id,
size_t SpdySM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
SpdyHeaderBlock block;
CopyHeaders(block, headers);
- block["status"] = headers.response_code().as_string() + " " +
- headers.response_reason_phrase().as_string();
- block["version"] = headers.response_version().as_string();
+ if (spdy_version() == SPDY2) {
+ block["status"] = headers.response_code().as_string() + " " +
+ headers.response_reason_phrase().as_string();
+ block["version"] = headers.response_version().as_string();
+ } else {
+ block[":status"] = headers.response_code().as_string() + " " +
+ headers.response_reason_phrase().as_string();
+ block[":version"] = headers.response_version().as_string();
+ }
SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynReply(
- stream_id, CONTROL_FLAG_NONE, true, &block);
+ stream_id, CONTROL_FLAG_NONE, &block);
size_t df_size = fsrcf->size();
EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf));
@@ -453,14 +502,17 @@ size_t SpdySM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
return df_size;
}
-void SpdySM::SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
- SpdyDataFlags flags, bool compress) {
+void SpdySM::SendDataFrameImpl(uint32 stream_id,
+ const char* data,
+ int64 len,
+ SpdyDataFlags flags,
+ bool compress) {
// TODO(mbelshe): We can't compress here - before going into the
// priority queue. Compression needs to be done
// with late binding.
if (len == 0) {
- SpdyFrame* fdf = buffered_spdy_framer_->CreateDataFrame(
- stream_id, data, len, flags);
+ SpdyFrame* fdf =
+ buffered_spdy_framer_->CreateDataFrame(stream_id, data, len, flags);
EnqueueDataFrame(new SpdyFrameDataFrame(fdf));
return;
}
@@ -512,9 +564,8 @@ void SpdySM::GetOutput() {
headers.CopyFrom(*(mci->file_data->headers()));
headers.ReplaceOrAppendHeader("status", "200");
headers.ReplaceOrAppendHeader("version", "http/1.1");
- headers.SetRequestFirstlineFromStringPieces("PUSH",
- mci->file_data->filename(),
- "");
+ headers.SetRequestFirstlineFromStringPieces(
+ "PUSH", mci->file_data->filename(), "");
mci->bytes_sent = SendSynStream(mci->stream_id, headers);
} else {
BalsaHeaders headers;
@@ -546,7 +597,9 @@ void SpdySM::GetOutput() {
SendDataFrame(mci->stream_id,
mci->file_data->body().data() + mci->body_bytes_consumed,
- num_to_write, 0, should_compress);
+ num_to_write,
+ 0,
+ should_compress);
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput SendDataFrame["
<< mci->stream_id << "]: " << num_to_write;
mci->body_bytes_consumed += num_to_write;
diff --git a/chromium/net/tools/flip_server/spdy_interface.h b/chromium/net/tools/flip_server/spdy_interface.h
index 3ce1f3bd0aa..6e5ad0b0a8f 100644
--- a/chromium/net/tools/flip_server/spdy_interface.h
+++ b/chromium/net/tools/flip_server/spdy_interface.h
@@ -12,8 +12,8 @@
#include "base/compiler_specific.h"
#include "net/spdy/buffered_spdy_framer.h"
#include "net/spdy/spdy_protocol.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/balsa/balsa_visitor_interface.h"
#include "net/tools/flip_server/output_ordering.h"
#include "net/tools/flip_server/sm_connection.h"
#include "net/tools/flip_server/sm_interface.h"
@@ -23,14 +23,14 @@ namespace net {
class FlipAcceptor;
class MemoryCache;
-class SpdySM : public BufferedSpdyFramerVisitorInterface,
- public SMInterface {
+class SpdySM : public BufferedSpdyFramerVisitorInterface, public SMInterface {
public:
SpdySM(SMConnection* connection,
SMInterface* sm_http_interface,
EpollServer* epoll_server,
MemoryCache* memory_cache,
- FlipAcceptor* acceptor);
+ FlipAcceptor* acceptor,
+ SpdyMajorVersion spdy_version);
virtual ~SpdySM();
virtual void InitSMInterface(SMInterface* sm_http_interface,
@@ -81,6 +81,11 @@ class SpdySM : public BufferedSpdyFramerVisitorInterface,
bool fin,
const SpdyHeaderBlock& headers) OVERRIDE;
+ // Called when data frame header is received.
+ virtual void OnDataFrameHeader(SpdyStreamId stream_id,
+ size_t length,
+ bool fin) OVERRIDE {}
+
// Called when data is received.
// |stream_id| The stream receiving data.
// |data| A buffer containing the data received.
@@ -149,8 +154,11 @@ class SpdySM : public BufferedSpdyFramerVisitorInterface,
const BalsaHeaders& headers) OVERRIDE;
virtual size_t SendSynReply(uint32 stream_id,
const BalsaHeaders& headers) OVERRIDE;
- virtual void SendDataFrame(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) OVERRIDE;
+ virtual void SendDataFrame(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) OVERRIDE;
BufferedSpdyFramer* spdy_framer() { return buffered_spdy_framer_; }
const OutputOrdering& output_ordering() const {
@@ -161,6 +169,9 @@ class SpdySM : public BufferedSpdyFramerVisitorInterface,
static void set_forward_ip_header(const std::string& value) {
forward_ip_header_ = value;
}
+ SpdyMajorVersion spdy_version() const {
+ return buffered_spdy_framer_->protocol_version();
+ }
private:
void SendEOFImpl(uint32 stream_id);
@@ -169,8 +180,11 @@ class SpdySM : public BufferedSpdyFramerVisitorInterface,
void CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers);
size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers);
size_t SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers);
- void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
- SpdyDataFlags flags, bool compress);
+ void SendDataFrameImpl(uint32 stream_id,
+ const char* data,
+ int64 len,
+ SpdyDataFlags flags,
+ bool compress);
void EnqueueDataFrame(DataFrame* df);
virtual void GetOutput() OVERRIDE;
diff --git a/chromium/net/tools/flip_server/spdy_interface_test.cc b/chromium/net/tools/flip_server/spdy_interface_test.cc
index 7a1c6e97e3b..3b988520158 100644
--- a/chromium/net/tools/flip_server/spdy_interface_test.cc
+++ b/chromium/net/tools/flip_server/spdy_interface_test.cc
@@ -9,8 +9,8 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "net/spdy/buffered_spdy_framer.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/flip_test_utils.h"
#include "net/tools/flip_server/mem_cache.h"
@@ -25,15 +25,14 @@ using ::testing::InSequence;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::SaveArg;
+using ::testing::Values;
namespace {
struct StringSaver {
public:
StringSaver() : data(NULL), size(0) {}
- void Save() {
- string = std::string(data, size);
- }
+ void Save() { string = std::string(data, size); }
const char* data;
size_t size;
@@ -45,24 +44,25 @@ class SpdyFramerVisitor : public BufferedSpdyFramerVisitorInterface {
virtual ~SpdyFramerVisitor() {}
MOCK_METHOD1(OnError, void(SpdyFramer::SpdyError));
MOCK_METHOD2(OnStreamError, void(SpdyStreamId, const std::string&));
- MOCK_METHOD7(OnSynStream, void(SpdyStreamId,
- SpdyStreamId,
- SpdyPriority,
- uint8,
- bool,
- bool,
- const SpdyHeaderBlock&));
+ MOCK_METHOD7(OnSynStream,
+ void(SpdyStreamId,
+ SpdyStreamId,
+ SpdyPriority,
+ uint8,
+ bool,
+ bool,
+ const SpdyHeaderBlock&));
MOCK_METHOD3(OnSynStream, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
MOCK_METHOD3(OnSynReply, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
MOCK_METHOD3(OnHeaders, void(SpdyStreamId, bool, const SpdyHeaderBlock&));
+ MOCK_METHOD3(OnDataFrameHeader, void(SpdyStreamId, size_t, bool));
MOCK_METHOD4(OnStreamFrameData, void(SpdyStreamId,
const char*,
size_t,
bool));
- MOCK_METHOD1(OnStreamFrameData, void(bool));
- MOCK_METHOD1(OnSettings, void(bool));
+ MOCK_METHOD1(OnSettings, void(bool clear_persisted));
MOCK_METHOD3(OnSetting, void(SpdySettingsIds, uint8, uint32));
- MOCK_METHOD1(OnPing, void(uint32));
+ MOCK_METHOD1(OnPing, void(uint32 unique_id));
MOCK_METHOD2(OnRstStream, void(SpdyStreamId, SpdyRstStreamStatus));
MOCK_METHOD2(OnGoAway, void(SpdyStreamId, SpdyGoAwayStatus));
MOCK_METHOD2(OnWindowUpdate, void(SpdyStreamId, uint32));
@@ -83,39 +83,42 @@ class FakeSMConnection : public SMConnection {
log_prefix) {}
MOCK_METHOD0(Cleanup, void());
- MOCK_METHOD8(InitSMConnection, void(SMConnectionPoolInterface*,
- SMInterface*,
- EpollServer*,
- int,
- std::string,
- std::string,
- std::string,
- bool));
+ MOCK_METHOD8(InitSMConnection,
+ void(SMConnectionPoolInterface*,
+ SMInterface*,
+ EpollServer*,
+ int,
+ std::string,
+ std::string,
+ std::string,
+ bool));
};
-class SpdySMWithMockSMInterfaceFactory : public SpdySM {
+// This class is almost SpdySM, except one function.
+// This class is the test target of tests in this file.
+class TestSpdySM : public SpdySM {
public:
- virtual ~SpdySMWithMockSMInterfaceFactory() {}
- SpdySMWithMockSMInterfaceFactory(SMConnection* connection,
- SMInterface* sm_http_interface,
- EpollServer* epoll_server,
- MemoryCache* memory_cache,
- FlipAcceptor* acceptor)
+ virtual ~TestSpdySM() {}
+ TestSpdySM(SMConnection* connection,
+ SMInterface* sm_http_interface,
+ EpollServer* epoll_server,
+ MemoryCache* memory_cache,
+ FlipAcceptor* acceptor,
+ SpdyMajorVersion version)
: SpdySM(connection,
sm_http_interface,
epoll_server,
memory_cache,
- acceptor) {}
+ acceptor,
+ version) {}
MOCK_METHOD2(FindOrMakeNewSMConnectionInterface,
SMInterface*(const std::string&, const std::string&));
};
-class FlipSpdySMTest : public ::testing::Test {
+class SpdySMTestBase : public ::testing::TestWithParam<SpdyMajorVersion> {
public:
- FlipSpdySMTest(SpdyMajorVersion version = SPDY2,
- FlipHandlerType type = FLIP_HANDLER_PROXY)
- : spdy_version_(version) {
+ explicit SpdySMTestBase(FlipHandlerType type) {
SSLState* ssl_state = NULL;
mock_another_interface_.reset(new MockSMInterface);
memory_cache_.reset(new MemoryCache);
@@ -142,19 +145,19 @@ class FlipSpdySMTest : public ::testing::Test {
acceptor_.get(),
"log_prefix"));
- interface_.reset(new SpdySMWithMockSMInterfaceFactory(
- connection_.get(),
- mock_another_interface_.get(),
- epoll_server_.get(),
- memory_cache_.get(),
- acceptor_.get()));
+ interface_.reset(new TestSpdySM(connection_.get(),
+ mock_another_interface_.get(),
+ epoll_server_.get(),
+ memory_cache_.get(),
+ acceptor_.get(),
+ GetParam()));
- spdy_framer_.reset(new BufferedSpdyFramer(spdy_version_, true));
+ spdy_framer_.reset(new BufferedSpdyFramer(GetParam(), true));
spdy_framer_visitor_.reset(new SpdyFramerVisitor);
spdy_framer_->set_visitor(spdy_framer_visitor_.get());
}
- virtual void TearDown() OVERRIDE {
+ virtual ~SpdySMTestBase() {
if (acceptor_->listen_fd_ >= 0) {
epoll_server_->UnregisterFD(acceptor_->listen_fd_);
close(acceptor_->listen_fd_);
@@ -174,59 +177,94 @@ class FlipSpdySMTest : public ::testing::Test {
}
protected:
- SpdyMajorVersion spdy_version_;
scoped_ptr<MockSMInterface> mock_another_interface_;
scoped_ptr<MemoryCache> memory_cache_;
scoped_ptr<FlipAcceptor> acceptor_;
scoped_ptr<EpollServer> epoll_server_;
scoped_ptr<FakeSMConnection> connection_;
- scoped_ptr<SpdySMWithMockSMInterfaceFactory> interface_;
+ scoped_ptr<TestSpdySM> interface_;
scoped_ptr<BufferedSpdyFramer> spdy_framer_;
scoped_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
};
-class FlipSpdy2SMTest : public FlipSpdySMTest {
+class SpdySMProxyTest : public SpdySMTestBase {
public:
- FlipSpdy2SMTest(): FlipSpdySMTest(SPDY2) {}
- virtual ~FlipSpdy2SMTest() {}
+ SpdySMProxyTest() : SpdySMTestBase(FLIP_HANDLER_PROXY) {}
+ virtual ~SpdySMProxyTest() {}
};
-class FlipSpdy2SMTestNonProxy : public FlipSpdySMTest {
+class SpdySMServerTest : public SpdySMTestBase {
public:
- FlipSpdy2SMTestNonProxy(): FlipSpdySMTest(SPDY2, FLIP_HANDLER_SPDY_SERVER) {}
- virtual ~FlipSpdy2SMTestNonProxy() {}
+ SpdySMServerTest() : SpdySMTestBase(FLIP_HANDLER_SPDY_SERVER) {}
+ virtual ~SpdySMServerTest() {}
};
-TEST_F(FlipSpdySMTest, InitSMConnection) {
+INSTANTIATE_TEST_CASE_P(SpdySMProxyTest,
+ SpdySMProxyTest,
+ Values(SPDY2, SPDY3, SPDY4));
+INSTANTIATE_TEST_CASE_P(SpdySMServerTest, SpdySMServerTest, Values(SPDY2));
+
+TEST_P(SpdySMProxyTest, InitSMConnection) {
{
InSequence s;
EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _));
}
- interface_->InitSMConnection(NULL,
- NULL,
- epoll_server_.get(),
- -1,
- "",
- "",
- "",
- false);
+ interface_->InitSMConnection(
+ NULL, NULL, epoll_server_.get(), -1, "", "", "", false);
}
-TEST_F(FlipSpdySMTest, OnSynStream) {
+TEST_P(SpdySMProxyTest, OnSynStream_SPDY2) {
+ if (GetParam() != SPDY2) {
+ // This test case is for SPDY2.
+ return;
+ }
BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
uint32 stream_id = 92;
uint32 associated_id = 43;
std::string expected = "GET /path HTTP/1.0\r\n"
- "method: GET\r\n"
- "scheme: http\r\n"
- "url: http://www.example.com/path\r\n"
- "version: HTTP/1.0\r\n\r\n";
+ "Host: 127.0.0.1\r\n"
+ "hoge: fuga\r\n\r\n";
SpdyHeaderBlock block;
block["method"] = "GET";
- block["url"] = "http://www.example.com/path";
+ block["url"] = "/path";
block["scheme"] = "http";
block["version"] = "HTTP/1.0";
+ block["hoge"] = "fuga";
+ StringSaver saver;
+ {
+ InSequence s;
+ EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
+ .WillOnce(Return(mock_interface.get()));
+ EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
+ EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&saver.data),
+ SaveArg<1>(&saver.size),
+ InvokeWithoutArgs(&saver, &StringSaver::Save),
+ Return(0)));
+ }
+ visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block);
+ ASSERT_EQ(expected, saver.string);
+}
+
+TEST_P(SpdySMProxyTest, OnSynStream) {
+ if (GetParam() == SPDY2) {
+ // This test case is not for SPDY2.
+ return;
+ }
+ BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
+ scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
+ uint32 stream_id = 92;
+ uint32 associated_id = 43;
+ std::string expected = "GET /path HTTP/1.1\r\n"
+ "Host: 127.0.0.1\r\n"
+ "foo: bar\r\n\r\n";
+ SpdyHeaderBlock block;
+ block[":method"] = "GET";
+ block[":host"] = "www.example.com";
+ block[":path"] = "/path";
+ block[":scheme"] = "http";
+ block["foo"] = "bar";
StringSaver saver;
{
InSequence s;
@@ -244,13 +282,17 @@ TEST_F(FlipSpdySMTest, OnSynStream) {
ASSERT_EQ(expected, saver.string);
}
-TEST_F(FlipSpdySMTest, OnStreamFrameData) {
+TEST_P(SpdySMProxyTest, OnStreamFrameData_SPDY2) {
+ if (GetParam() != SPDY2) {
+ // This test case is for SPDY2.
+ return;
+ }
BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
uint32 stream_id = 92;
uint32 associated_id = 43;
SpdyHeaderBlock block;
- testing::MockFunction<void(int)> checkpoint;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12));
block["method"] = "GET";
@@ -259,6 +301,40 @@ TEST_F(FlipSpdySMTest, OnStreamFrameData) {
block["version"] = "HTTP/1.0";
{
InSequence s;
+ EXPECT_CALL(*interface_, FindOrMakeNewSMConnectionInterface(_, _))
+ .WillOnce(Return(mock_interface.get()));
+ EXPECT_CALL(*mock_interface, SetStreamID(stream_id));
+ EXPECT_CALL(*mock_interface, ProcessWriteInput(_, _)).Times(1);
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(*mock_interface,
+ ProcessWriteInput(frame->data(), frame->size())).Times(1);
+ }
+
+ visitor->OnSynStream(stream_id, associated_id, 0, 0, false, false, block);
+ checkpoint.Call(0);
+ visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
+}
+
+TEST_P(SpdySMProxyTest, OnStreamFrameData) {
+ if (GetParam() == SPDY2) {
+ // This test case is not for SPDY2.
+ return;
+ }
+ BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
+ scoped_ptr<MockSMInterface> mock_interface(new MockSMInterface);
+ uint32 stream_id = 92;
+ uint32 associated_id = 43;
+ SpdyHeaderBlock block;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
+
+ scoped_ptr<SpdyFrame> frame(spdy_framer_->CreatePingFrame(12));
+ block[":method"] = "GET";
+ block[":host"] = "www.example.com";
+ block[":path"] = "/path";
+ block[":scheme"] = "http";
+ block["foo"] = "bar";
+ {
+ InSequence s;
EXPECT_CALL(*interface_,
FindOrMakeNewSMConnectionInterface(_, _))
.WillOnce(Return(mock_interface.get()));
@@ -274,7 +350,7 @@ TEST_F(FlipSpdySMTest, OnStreamFrameData) {
visitor->OnStreamFrameData(stream_id, frame->data(), frame->size(), true);
}
-TEST_F(FlipSpdySMTest, OnRstStream) {
+TEST_P(SpdySMProxyTest, OnRstStream) {
BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
uint32 stream_id = 82;
MemCacheIter mci;
@@ -293,14 +369,14 @@ TEST_F(FlipSpdySMTest, OnRstStream) {
ASSERT_FALSE(HasStream(stream_id));
}
-TEST_F(FlipSpdySMTest, ProcessReadInput) {
+TEST_P(SpdySMProxyTest, ProcessReadInput) {
ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
interface_->ProcessReadInput("", 1);
ASSERT_EQ(SpdyFramer::SPDY_READING_COMMON_HEADER,
interface_->spdy_framer()->state());
}
-TEST_F(FlipSpdySMTest, ResetForNewConnection) {
+TEST_P(SpdySMProxyTest, ResetForNewConnection) {
uint32 stream_id = 13;
MemCacheIter mci;
mci.stream_id = stream_id;
@@ -324,7 +400,7 @@ TEST_F(FlipSpdySMTest, ResetForNewConnection) {
ASSERT_EQ(SpdyFramer::SPDY_RESET, interface_->spdy_framer()->state());
}
-TEST_F(FlipSpdySMTest, PostAcceptHook) {
+TEST_P(SpdySMProxyTest, PostAcceptHook) {
interface_->PostAcceptHook();
ASSERT_EQ(1u, connection_->output_list()->size());
@@ -334,19 +410,19 @@ TEST_F(FlipSpdySMTest, PostAcceptHook) {
{
InSequence s;
EXPECT_CALL(*spdy_framer_visitor_, OnSettings(false));
- EXPECT_CALL(*spdy_framer_visitor_, OnSetting(
- SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u));
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0u, 100u));
}
spdy_framer_->ProcessInput(df->data, df->size);
}
-TEST_F(FlipSpdySMTest, NewStream) {
+TEST_P(SpdySMProxyTest, NewStream) {
// TODO(yhirano): SpdySM::NewStream leads to crash when
// acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER.
// It should be fixed though I don't know the solution now.
}
-TEST_F(FlipSpdySMTest, AddToOutputOrder) {
+TEST_P(SpdySMProxyTest, AddToOutputOrder) {
uint32 stream_id = 13;
MemCacheIter mci;
mci.stream_id = stream_id;
@@ -362,12 +438,16 @@ TEST_F(FlipSpdySMTest, AddToOutputOrder) {
ASSERT_TRUE(HasStream(stream_id));
}
-TEST_F(FlipSpdySMTest, SendErrorNotFound) {
+TEST_P(SpdySMProxyTest, SendErrorNotFound_SPDY2) {
+ if (GetParam() != SPDY2) {
+ // This test is for SPDY2.
+ return;
+ }
uint32 stream_id = 82;
SpdyHeaderBlock actual_header_block;
const char* actual_data;
size_t actual_size;
- testing::MockFunction<void(int)> checkpoint;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
interface_->SendErrorNotFound(stream_id);
@@ -375,11 +455,12 @@ TEST_F(FlipSpdySMTest, SendErrorNotFound) {
{
InSequence s;
- EXPECT_CALL(*spdy_framer_visitor_,
- OnSynReply(stream_id, false, _))
+ EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
.WillOnce(SaveArg<2>(&actual_header_block));
EXPECT_CALL(checkpoint, Call(0));
EXPECT_CALL(*spdy_framer_visitor_,
+ OnDataFrameHeader(stream_id, _, true));
+ EXPECT_CALL(*spdy_framer_visitor_,
OnStreamFrameData(stream_id, _, _, false)).Times(1)
.WillOnce(DoAll(SaveArg<1>(&actual_data),
SaveArg<2>(&actual_size)));
@@ -401,7 +482,56 @@ TEST_F(FlipSpdySMTest, SendErrorNotFound) {
ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
}
-TEST_F(FlipSpdySMTest, SendSynStream) {
+TEST_P(SpdySMProxyTest, SendErrorNotFound) {
+ if (GetParam() == SPDY2) {
+ // This test is not for SPDY2.
+ return;
+ }
+ uint32 stream_id = 82;
+ SpdyHeaderBlock actual_header_block;
+ const char* actual_data;
+ size_t actual_size;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
+
+ interface_->SendErrorNotFound(stream_id);
+
+ ASSERT_EQ(2u, connection_->output_list()->size());
+
+ {
+ InSequence s;
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnSynReply(stream_id, false, _))
+ .WillOnce(SaveArg<2>(&actual_header_block));
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnDataFrameHeader(stream_id, _, true));
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnStreamFrameData(stream_id, _, _, false)).Times(1)
+ .WillOnce(DoAll(SaveArg<1>(&actual_data),
+ SaveArg<2>(&actual_size)));
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnStreamFrameData(stream_id, NULL, 0, true)).Times(1);
+ }
+
+ std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
+ DataFrame* df = *i++;
+ spdy_framer_->ProcessInput(df->data, df->size);
+ checkpoint.Call(0);
+ df = *i++;
+ spdy_framer_->ProcessInput(df->data, df->size);
+
+ ASSERT_EQ(2, spdy_framer_->frames_received());
+ ASSERT_EQ(2u, actual_header_block.size());
+ ASSERT_EQ("404 Not Found", actual_header_block[":status"]);
+ ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
+ ASSERT_EQ("wtf?", StringPiece(actual_data, actual_size));
+}
+
+TEST_P(SpdySMProxyTest, SendSynStream_SPDY2) {
+ if (GetParam() != SPDY2) {
+ // This test is for SPDY2.
+ return;
+ }
uint32 stream_id = 82;
BalsaHeaders headers;
SpdyHeaderBlock actual_header_block;
@@ -430,7 +560,46 @@ TEST_F(FlipSpdySMTest, SendSynStream) {
ASSERT_EQ("value1", actual_header_block["key1"]);
}
-TEST_F(FlipSpdySMTest, SendSynReply) {
+TEST_P(SpdySMProxyTest, SendSynStream) {
+ if (GetParam() == SPDY2) {
+ // This test is not for SPDY2.
+ return;
+ }
+ uint32 stream_id = 82;
+ BalsaHeaders headers;
+ SpdyHeaderBlock actual_header_block;
+ headers.AppendHeader("key1", "value1");
+ headers.AppendHeader("Host", "www.example.com");
+ headers.SetRequestFirstlineFromStringPieces("GET", "/path", "HTTP/1.1");
+
+ interface_->SendSynStream(stream_id, headers);
+
+ ASSERT_EQ(1u, connection_->output_list()->size());
+ std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
+ DataFrame* df = *i++;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnSynStream(stream_id, 0, _, _, false, false, _))
+ .WillOnce(SaveArg<6>(&actual_header_block));
+ }
+
+ spdy_framer_->ProcessInput(df->data, df->size);
+ ASSERT_EQ(1, spdy_framer_->frames_received());
+ ASSERT_EQ(5u, actual_header_block.size());
+ ASSERT_EQ("GET", actual_header_block[":method"]);
+ ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
+ ASSERT_EQ("/path", actual_header_block[":path"]);
+ ASSERT_EQ("www.example.com", actual_header_block[":host"]);
+ ASSERT_EQ("value1", actual_header_block["key1"]);
+}
+
+TEST_P(SpdySMProxyTest, SendSynReply_SPDY2) {
+ if (GetParam() != SPDY2) {
+ // This test is for SPDY2.
+ return;
+ }
uint32 stream_id = 82;
BalsaHeaders headers;
SpdyHeaderBlock actual_header_block;
@@ -457,7 +626,38 @@ TEST_F(FlipSpdySMTest, SendSynReply) {
ASSERT_EQ("value1", actual_header_block["key1"]);
}
-TEST_F(FlipSpdySMTest, SendDataFrame) {
+TEST_P(SpdySMProxyTest, SendSynReply) {
+ if (GetParam() == SPDY2) {
+ // This test is not for SPDY2.
+ return;
+ }
+ uint32 stream_id = 82;
+ BalsaHeaders headers;
+ SpdyHeaderBlock actual_header_block;
+ headers.AppendHeader("key1", "value1");
+ headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
+
+ interface_->SendSynReply(stream_id, headers);
+
+ ASSERT_EQ(1u, connection_->output_list()->size());
+ std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin();
+ DataFrame* df = *i++;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
+ .WillOnce(SaveArg<2>(&actual_header_block));
+ }
+
+ spdy_framer_->ProcessInput(df->data, df->size);
+ ASSERT_EQ(1, spdy_framer_->frames_received());
+ ASSERT_EQ(3u, actual_header_block.size());
+ ASSERT_EQ("200 OK", actual_header_block[":status"]);
+ ASSERT_EQ("HTTP/1.1", actual_header_block[":version"]);
+ ASSERT_EQ("value1", actual_header_block["key1"]);
+}
+
+TEST_P(SpdySMProxyTest, SendDataFrame) {
uint32 stream_id = 133;
SpdyDataFlags flags = DATA_FLAG_NONE;
const char* actual_data;
@@ -472,9 +672,10 @@ TEST_F(FlipSpdySMTest, SendDataFrame) {
{
InSequence s;
EXPECT_CALL(*spdy_framer_visitor_,
+ OnDataFrameHeader(stream_id, _, false));
+ EXPECT_CALL(*spdy_framer_visitor_,
OnStreamFrameData(stream_id, _, _, false))
- .WillOnce(DoAll(SaveArg<1>(&actual_data),
- SaveArg<2>(&actual_size)));
+ .WillOnce(DoAll(SaveArg<1>(&actual_data), SaveArg<2>(&actual_size)));
}
spdy_framer_->ProcessInput(df->data, df->size);
@@ -482,24 +683,26 @@ TEST_F(FlipSpdySMTest, SendDataFrame) {
ASSERT_EQ("hello", StringPiece(actual_data, actual_size));
}
-TEST_F(FlipSpdySMTest, SendLongDataFrame) {
+TEST_P(SpdySMProxyTest, SendLongDataFrame) {
uint32 stream_id = 133;
SpdyDataFlags flags = DATA_FLAG_NONE;
const char* actual_data;
size_t actual_size;
- std::string data =
- std::string(kSpdySegmentSize, 'a') +
- std::string(kSpdySegmentSize, 'b') +
- "c";
+ std::string data = std::string(kSpdySegmentSize, 'a') +
+ std::string(kSpdySegmentSize, 'b') + "c";
interface_->SendDataFrame(stream_id, data.data(), data.size(), flags, true);
{
InSequence s;
- EXPECT_CALL(*spdy_framer_visitor_,
- OnStreamFrameData(stream_id, _, _, false)).Times(3)
- .WillRepeatedly(DoAll(SaveArg<1>(&actual_data),
- SaveArg<2>(&actual_size)));
+ for (int i = 0; i < 3; ++i) {
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnDataFrameHeader(stream_id, _, false));
+ EXPECT_CALL(*spdy_framer_visitor_,
+ OnStreamFrameData(stream_id, _, _, false))
+ .WillOnce(DoAll(SaveArg<1>(&actual_data),
+ SaveArg<2>(&actual_size)));
+ }
}
ASSERT_EQ(3u, connection_->output_list()->size());
@@ -519,7 +722,12 @@ TEST_F(FlipSpdySMTest, SendLongDataFrame) {
ASSERT_EQ("c", StringPiece(actual_data, actual_size));
}
-TEST_F(FlipSpdy2SMTest, SendEOF) {
+TEST_P(SpdySMProxyTest, SendEOF_SPDY2) {
+ // This test is for SPDY2.
+ if (GetParam() != SPDY2) {
+ return;
+ }
+
uint32 stream_id = 82;
// SPDY2 data frame
char empty_data_frame[] = {'\0', '\0', '\0', '\x52', '\x1', '\0', '\0', '\0'};
@@ -545,7 +753,12 @@ TEST_F(FlipSpdy2SMTest, SendEOF) {
StringPiece(df->data, df->size));
}
-TEST_F(FlipSpdy2SMTest, SendEmptyDataFrame) {
+TEST_P(SpdySMProxyTest, SendEmptyDataFrame_SPDY2) {
+ // This test is for SPDY2.
+ if (GetParam() != SPDY2) {
+ return;
+ }
+
uint32 stream_id = 133;
SpdyDataFlags flags = DATA_FLAG_NONE;
// SPDY2 data frame
@@ -561,13 +774,14 @@ TEST_F(FlipSpdy2SMTest, SendEmptyDataFrame) {
StringPiece(df->data, df->size));
}
-TEST_F(FlipSpdy2SMTestNonProxy, OnSynStream) {
+TEST_P(SpdySMServerTest, OnSynStream) {
BufferedSpdyFramerVisitorInterface* visitor = interface_.get();
uint32 stream_id = 82;
SpdyHeaderBlock spdy_headers;
spdy_headers["url"] = "http://www.example.com/path";
spdy_headers["method"] = "GET";
spdy_headers["scheme"] = "http";
+ spdy_headers["version"] = "HTTP/1.1";
{
BalsaHeaders headers;
@@ -577,7 +791,7 @@ TEST_F(FlipSpdy2SMTestNonProxy, OnSynStream) {
ASSERT_TRUE(HasStream(stream_id));
}
-TEST_F(FlipSpdy2SMTestNonProxy, NewStream) {
+TEST_P(SpdySMServerTest, NewStream) {
uint32 stream_id = 13;
std::string filename = "foobar";
@@ -590,12 +804,12 @@ TEST_F(FlipSpdy2SMTestNonProxy, NewStream) {
ASSERT_TRUE(HasStream(stream_id));
}
-TEST_F(FlipSpdy2SMTestNonProxy, NewStreamError) {
+TEST_P(SpdySMServerTest, NewStreamError) {
uint32 stream_id = 82;
SpdyHeaderBlock actual_header_block;
const char* actual_data;
size_t actual_size;
- testing::MockFunction<void(int)> checkpoint;
+ testing::MockFunction<void(int)> checkpoint; // NOLINT
interface_->NewStream(stream_id, 0, "nonexistingfile");
@@ -603,11 +817,12 @@ TEST_F(FlipSpdy2SMTestNonProxy, NewStreamError) {
{
InSequence s;
- EXPECT_CALL(*spdy_framer_visitor_,
- OnSynReply(stream_id, false, _))
+ EXPECT_CALL(*spdy_framer_visitor_, OnSynReply(stream_id, false, _))
.WillOnce(SaveArg<2>(&actual_header_block));
EXPECT_CALL(checkpoint, Call(0));
EXPECT_CALL(*spdy_framer_visitor_,
+ OnDataFrameHeader(stream_id, _, true));
+ EXPECT_CALL(*spdy_framer_visitor_,
OnStreamFrameData(stream_id, _, _, false)).Times(1)
.WillOnce(DoAll(SaveArg<1>(&actual_data),
SaveArg<2>(&actual_size)));
diff --git a/chromium/net/tools/flip_server/spdy_ssl.cc b/chromium/net/tools/flip_server/spdy_ssl.cc
index 292bbe0eb0e..1f18a0b30ff 100644
--- a/chromium/net/tools/flip_server/spdy_ssl.cc
+++ b/chromium/net/tools/flip_server/spdy_ssl.cc
@@ -10,15 +10,21 @@
namespace net {
-#define NEXT_PROTO_STRING "\x06spdy/2\x08http/1.1\x08http/1.0"
+// Each element consists of <the length of the string><string> .
+#define NEXT_PROTO_STRING \
+ "\x08spdy/4a2" \
+ "\x06spdy/3" \
+ "\x06spdy/2" \
+ "\x08http/1.1" \
+ "\x08http/1.0"
#define SSL_CIPHER_LIST "!aNULL:!ADH:!eNull:!LOW:!EXP:RC4+RSA:MEDIUM:HIGH"
-int ssl_set_npn_callback(SSL *s,
- const unsigned char **data,
- unsigned int *len,
- void *arg) {
- VLOG(1) << "SSL NPN callback: advertising protocols.";
- *data = (const unsigned char *) NEXT_PROTO_STRING;
+int ssl_set_npn_callback(SSL* s,
+ const unsigned char** data,
+ unsigned int* len,
+ void* arg) {
+ VLOG(1) << "SSL NPN callback: advertising protocols.";
+ *data = (const unsigned char*)NEXT_PROTO_STRING;
*len = strlen(NEXT_PROTO_STRING);
return SSL_TLSEXT_ERR_OK;
}
@@ -51,9 +57,8 @@ void InitSSL(SSLState* state,
PrintSslError();
LOG(FATAL) << "Unable to use cert.pem as SSL cert.";
}
- if (SSL_CTX_use_PrivateKey_file(state->ssl_ctx,
- ssl_key_name.c_str(),
- SSL_FILETYPE_PEM) <= 0) {
+ if (SSL_CTX_use_PrivateKey_file(
+ state->ssl_ctx, ssl_key_name.c_str(), SSL_FILETYPE_PEM) <= 0) {
PrintSslError();
LOG(FATAL) << "Unable to use key.pem as SSL key.";
}
@@ -62,8 +67,8 @@ void InitSSL(SSLState* state,
LOG(FATAL) << "The cert.pem and key.pem files don't match";
}
if (use_npn) {
- SSL_CTX_set_next_protos_advertised_cb(state->ssl_ctx,
- ssl_set_npn_callback, NULL);
+ SSL_CTX_set_next_protos_advertised_cb(
+ state->ssl_ctx, ssl_set_npn_callback, NULL);
}
VLOG(1) << "SSL CTX default cipher list: " << SSL_CIPHER_LIST;
SSL_CTX_set_cipher_list(state->ssl_ctx, SSL_CIPHER_LIST);
@@ -80,7 +85,7 @@ void InitSSL(SSLState* state,
// Proper methods to disable compression don't exist until 0.9.9+. For now
// we must manipulate the stack of compression methods directly.
if (disable_ssl_compression) {
- STACK_OF(SSL_COMP) *ssl_comp_methods = SSL_COMP_get_compression_methods();
+ STACK_OF(SSL_COMP)* ssl_comp_methods = SSL_COMP_get_compression_methods();
int num_methods = sk_SSL_COMP_num(ssl_comp_methods);
int i;
for (i = 0; i < num_methods; i++) {
@@ -107,4 +112,3 @@ void PrintSslError() {
}
} // namespace net
-
diff --git a/chromium/net/tools/flip_server/spdy_ssl.h b/chromium/net/tools/flip_server/spdy_ssl.h
index 8db0d8ccc95..8b5573353fb 100644
--- a/chromium/net/tools/flip_server/spdy_ssl.h
+++ b/chromium/net/tools/flip_server/spdy_ssl.h
@@ -28,4 +28,3 @@ void PrintSslError();
} // namespace net
#endif // NET_TOOLS_FLIP_SERVER_SPDY_SSL_H_
-
diff --git a/chromium/net/tools/flip_server/spdy_util.cc b/chromium/net/tools/flip_server/spdy_util.cc
index d4a789a9735..311bdb94d41 100644
--- a/chromium/net/tools/flip_server/spdy_util.cc
+++ b/chromium/net/tools/flip_server/spdy_util.cc
@@ -31,4 +31,3 @@ std::string EncodeURL(std::string uri, std::string host, std::string method) {
}
} // namespace net
-
diff --git a/chromium/net/tools/flip_server/spdy_util.h b/chromium/net/tools/flip_server/spdy_util.h
index 537053d50bc..6f002000089 100644
--- a/chromium/net/tools/flip_server/spdy_util.h
+++ b/chromium/net/tools/flip_server/spdy_util.h
@@ -18,4 +18,3 @@ std::string EncodeURL(std::string uri, std::string host, std::string method);
} // namespace net
#endif // NET_TOOLS_FLIP_SERVER_SPDY_UTIL_H_
-
diff --git a/chromium/net/tools/flip_server/streamer_interface.cc b/chromium/net/tools/flip_server/streamer_interface.cc
index b1612e73321..25a496497ba 100644
--- a/chromium/net/tools/flip_server/streamer_interface.cc
+++ b/chromium/net/tools/flip_server/streamer_interface.cc
@@ -6,7 +6,7 @@
#include <string>
-#include "net/tools/flip_server/balsa_frame.h"
+#include "net/tools/balsa/balsa_frame.h"
#include "net/tools/flip_server/constants.h"
#include "net/tools/flip_server/flip_config.h"
#include "net/tools/flip_server/sm_connection.h"
@@ -57,9 +57,14 @@ void StreamerSM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
bool use_ssl) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Initializing server "
<< "connection.";
- connection_->InitSMConnection(connection_pool, sm_interface,
- epoll_server, fd, server_ip,
- server_port, remote_ip, use_ssl);
+ connection_->InitSMConnection(connection_pool,
+ sm_interface,
+ epoll_server,
+ fd,
+ server_ip,
+ server_port,
+ remote_ip,
+ use_ssl);
}
size_t StreamerSM::ProcessReadInput(const char* data, size_t len) {
@@ -72,23 +77,19 @@ size_t StreamerSM::ProcessReadInput(const char* data, size_t len) {
}
size_t StreamerSM::ProcessWriteInput(const char* data, size_t len) {
- char * dataPtr = new char[len];
+ char* dataPtr = new char[len];
memcpy(dataPtr, data, len);
DataFrame* df = new DataFrame;
- df->data = (const char *)dataPtr;
+ df->data = (const char*)dataPtr;
df->size = len;
df->delete_when_done = true;
connection_->EnqueueDataFrame(df);
return len;
}
-bool StreamerSM::Error() const {
- return false;
-}
+bool StreamerSM::Error() const { return false; }
-const char* StreamerSM::ErrorAsString() const {
- return "(none)";
-}
+const char* StreamerSM::ErrorAsString() const { return "(none)"; }
bool StreamerSM::MessageFullyRead() const {
if (is_request_) {
@@ -116,17 +117,16 @@ void StreamerSM::Cleanup() {
int StreamerSM::PostAcceptHook() {
if (!sm_other_interface_) {
- SMConnection *server_connection =
- SMConnection::NewSMConnection(epoll_server_, NULL, NULL,
- acceptor_, "server_conn: ");
+ SMConnection* server_connection = SMConnection::NewSMConnection(
+ epoll_server_, NULL, NULL, acceptor_, "server_conn: ");
if (server_connection == NULL) {
LOG(ERROR) << "StreamerSM: Could not create server conenction.";
return 0;
}
VLOG(2) << ACCEPTOR_CLIENT_IDENT << "StreamerSM: Creating new server "
<< "connection.";
- sm_other_interface_ = new StreamerSM(server_connection, this,
- epoll_server_, acceptor_);
+ sm_other_interface_ =
+ new StreamerSM(server_connection, this, epoll_server_, acceptor_);
sm_other_interface_->InitSMInterface(this, 0);
}
// The Streamer interface is used to stream HTTPS connections, so we
@@ -152,7 +152,7 @@ size_t StreamerSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
return 0;
}
-void StreamerSM::ProcessBodyInput(const char *input, size_t size) {
+void StreamerSM::ProcessBodyInput(const char* input, size_t size) {
VLOG(2) << ACCEPTOR_CLIENT_IDENT
<< "StreamerHttpSM: Process Body Input Data: "
<< "size " << size;
@@ -187,21 +187,14 @@ void StreamerSM::ProcessHeaders(const BalsaHeaders& headers) {
sm_other_interface_->ProcessWriteInput(buffer, size);
}
-void StreamerSM::HandleHeaderError(BalsaFrame* framer) {
- HandleError();
-}
+void StreamerSM::HandleHeaderError(BalsaFrame* framer) { HandleError(); }
-void StreamerSM::HandleChunkingError(BalsaFrame* framer) {
- HandleError();
-}
+void StreamerSM::HandleChunkingError(BalsaFrame* framer) { HandleError(); }
-void StreamerSM::HandleBodyError(BalsaFrame* framer) {
- HandleError();
-}
+void StreamerSM::HandleBodyError(BalsaFrame* framer) { HandleError(); }
void StreamerSM::HandleError() {
VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
}
} // namespace net
-
diff --git a/chromium/net/tools/flip_server/streamer_interface.h b/chromium/net/tools/flip_server/streamer_interface.h
index 4f09b4558e8..0114491de49 100644
--- a/chromium/net/tools/flip_server/streamer_interface.h
+++ b/chromium/net/tools/flip_server/streamer_interface.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_TOOLS_FLIP_SERVER_STREAMER_INTERFACE_
-#define NET_TOOLS_FLIP_SERVER_STREAMER_INTERFACE_
+#ifndef NET_TOOLS_FLIP_SERVER_STREAMER_INTERFACE_H_
+#define NET_TOOLS_FLIP_SERVER_STREAMER_INTERFACE_H_
#include <string>
#include "base/compiler_specific.h"
-#include "net/tools/flip_server/balsa_headers.h"
-#include "net/tools/flip_server/balsa_visitor_interface.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/balsa/balsa_visitor_interface.h"
#include "net/tools/flip_server/sm_interface.h"
namespace net {
@@ -20,8 +20,7 @@ class MemCacheIter;
class SMConnection;
class EpollServer;
-class StreamerSM : public BalsaVisitorInterface,
- public SMInterface {
+class StreamerSM : public BalsaVisitorInterface, public SMInterface {
public:
StreamerSM(SMConnection* connection,
SMInterface* sm_other_interface,
@@ -53,7 +52,8 @@ class StreamerSM : public BalsaVisitorInterface,
virtual void ResetForNewConnection() OVERRIDE;
virtual void Cleanup() OVERRIDE;
virtual int PostAcceptHook() OVERRIDE;
- virtual void NewStream(uint32 stream_id, uint32 priority,
+ virtual void NewStream(uint32 stream_id,
+ uint32 priority,
const std::string& filename) OVERRIDE {}
virtual void SendEOF(uint32 stream_id) OVERRIDE {}
virtual void SendErrorNotFound(uint32 stream_id) OVERRIDE {}
@@ -62,8 +62,11 @@ class StreamerSM : public BalsaVisitorInterface,
const BalsaHeaders& headers) OVERRIDE;
virtual size_t SendSynReply(uint32 stream_id,
const BalsaHeaders& headers) OVERRIDE;
- virtual void SendDataFrame(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) OVERRIDE {}
+ virtual void SendDataFrame(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) OVERRIDE {}
virtual void set_is_request() OVERRIDE;
static std::string forward_ip_header() { return forward_ip_header_; }
static void set_forward_ip_header(std::string value) {
@@ -80,16 +83,19 @@ class StreamerSM : public BalsaVisitorInterface,
size_t SendSynStreamImpl(uint32 stream_id, const BalsaHeaders& headers) {
return 0;
}
- void SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
- uint32 flags, bool compress) {}
+ void SendDataFrameImpl(uint32 stream_id,
+ const char* data,
+ int64 len,
+ uint32 flags,
+ bool compress) {}
virtual void GetOutput() OVERRIDE {}
- virtual void ProcessBodyInput(const char *input, size_t size) OVERRIDE;
+ virtual void ProcessBodyInput(const char* input, size_t size) OVERRIDE;
virtual void MessageDone() OVERRIDE;
virtual void ProcessHeaders(const BalsaHeaders& headers) OVERRIDE;
- virtual void ProcessBodyData(const char *input, size_t size) OVERRIDE {}
- virtual void ProcessHeaderInput(const char *input, size_t size) OVERRIDE {}
- virtual void ProcessTrailerInput(const char *input, size_t size) OVERRIDE {}
+ virtual void ProcessBodyData(const char* input, size_t size) OVERRIDE {}
+ virtual void ProcessHeaderInput(const char* input, size_t size) OVERRIDE {}
+ virtual void ProcessTrailerInput(const char* input, size_t size) OVERRIDE {}
virtual void ProcessRequestFirstLine(const char* line_input,
size_t line_length,
const char* method_input,
@@ -98,17 +104,17 @@ class StreamerSM : public BalsaVisitorInterface,
size_t request_uri_length,
const char* version_input,
size_t version_length) OVERRIDE {}
- virtual void ProcessResponseFirstLine(const char *line_input,
+ virtual void ProcessResponseFirstLine(const char* line_input,
size_t line_length,
- const char *version_input,
+ const char* version_input,
size_t version_length,
- const char *status_input,
+ const char* status_input,
size_t status_length,
- const char *reason_input,
+ const char* reason_input,
size_t reason_length) OVERRIDE {}
virtual void ProcessChunkLength(size_t chunk_length) OVERRIDE {}
- virtual void ProcessChunkExtensions(const char *input,
- size_t size) OVERRIDE {}
+ virtual void ProcessChunkExtensions(const char* input, size_t size) OVERRIDE {
+ }
virtual void HeaderDone() OVERRIDE {}
virtual void HandleHeaderError(BalsaFrame* framer) OVERRIDE;
virtual void HandleHeaderWarning(BalsaFrame* framer) OVERRIDE {}
@@ -128,5 +134,4 @@ class StreamerSM : public BalsaVisitorInterface,
} // namespace net
-#endif // NET_TOOLS_FLIP_SERVER_STREAMER_INTERFACE_
-
+#endif // NET_TOOLS_FLIP_SERVER_STREAMER_INTERFACE_H_
diff --git a/chromium/net/tools/gdig/gdig.cc b/chromium/net/tools/gdig/gdig.cc
index 54f05091c01..db0704c5a84 100644
--- a/chromium/net/tools/gdig/gdig.cc
+++ b/chromium/net/tools/gdig/gdig.cc
@@ -126,7 +126,7 @@ bool LoadReplayLog(const base::FilePath& file_path, ReplayLog* replay_log) {
// smarter line splitter, but this particular use does not need to target
// efficiency.
std::string replay_log_contents;
- RemoveChars(original_replay_log_contents, "\r", &replay_log_contents);
+ base::RemoveChars(original_replay_log_contents, "\r", &replay_log_contents);
std::vector<std::string> lines;
base::SplitString(replay_log_contents, '\n', &lines);
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 3fe6129b66c..19a2010d83e 100644
--- a/chromium/net/tools/get_server_time/get_server_time.cc
+++ b/chromium/net/tools/get_server_time/get_server_time.cc
@@ -83,17 +83,6 @@ class QuitDelegate : public net::URLFetcherDelegate {
NOTREACHED();
}
- virtual void OnURLFetchDownloadData(
- const net::URLFetcher* source,
- scoped_ptr<std::string> download_data) OVERRIDE{
- NOTREACHED();
- }
-
- virtual bool ShouldSendDownloadData() OVERRIDE {
- NOTREACHED();
- return false;
- }
-
virtual void OnURLFetchUploadProgress(const net::URLFetcher* source,
int64 current, int64 total) OVERRIDE {
NOTREACHED();
diff --git a/chromium/net/tools/net_watcher/net_watcher.cc b/chromium/net/tools/net_watcher/net_watcher.cc
index 0a8b4dfbb7d..67eb124f8ac 100644
--- a/chromium/net/tools/net_watcher/net_watcher.cc
+++ b/chromium/net/tools/net_watcher/net_watcher.cc
@@ -21,7 +21,7 @@
#include "net/proxy/proxy_config_service.h"
#include "net/proxy/proxy_service.h"
-#if (defined(OS_LINUX) || defined(OS_OPENBSD)) && !defined(OS_CHROMEOS)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
#include <glib-object.h>
#endif
@@ -131,26 +131,16 @@ int main(int argc, char* argv[]) {
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool pool;
#endif
-#if (defined(OS_LINUX) || defined(OS_OPENBSD)) && !defined(OS_CHROMEOS)
+#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ // g_type_init will be deprecated in 2.36. 2.35 is the development
+ // version for 2.36, hence do not call g_type_init starting 2.35.
+ // http://developer.gnome.org/gobject/unstable/gobject-Type-Information.html#g-type-init
+#if !GLIB_CHECK_VERSION(2, 35, 0)
// Needed so ProxyConfigServiceLinux can use gconf.
// Normally handled by BrowserMainLoop::InitializeToolkit().
- // From glib version 2.36 onwards, g_type_init is implicitly called and it is
- // deprecated.
- // TODO(yael) Simplify this once Ubuntu 10.04 is no longer supported.
-#if defined(G_GNUC_BEGIN_IGNORE_DEPRECATIONS) && \
- defined(G_GNUC_END_IGNORE_DEPRECATIONS)
-#define USE_GLIB_DEPRECATIONS_MACROS
-#endif
-
-#if defined(USE_GLIB_DEPRECATIONS_MACROS)
-G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-#endif
g_type_init();
-#if defined(USE_GLIB_DEPRECATIONS_MACROS)
-G_GNUC_END_IGNORE_DEPRECATIONS
#endif
-#undef USE_GLIB_DEPRECATIONS_MACROS
-#endif // (defined(OS_LINUX) || defined(OS_OPENBSD)) && !defined(OS_CHROMEOS)
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
base::AtExitManager exit_manager;
CommandLine::Init(argc, argv);
logging::LoggingSettings settings;
diff --git a/chromium/net/tools/quic/end_to_end_test.cc b/chromium/net/tools/quic/end_to_end_test.cc
index 7b61be6d149..2b94b0f2fd1 100644
--- a/chromium/net/tools/quic/end_to_end_test.cc
+++ b/chromium/net/tools/quic/end_to_end_test.cc
@@ -4,37 +4,51 @@
#include <stddef.h>
#include <string>
+#include <vector>
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
-#include "base/threading/simple_thread.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_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_sent_packet_manager.h"
#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_session_peer.h"
+#include "net/quic/test_tools/quic_test_writer.h"
#include "net/quic/test_tools/reliable_quic_stream_peer.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_in_memory_cache.h"
#include "net/tools/quic/quic_server.h"
#include "net/tools/quic/quic_socket_utils.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/test_tools/http_message_test_utils.h"
+#include "net/tools/quic/test_tools/packet_dropping_test_writer.h"
#include "net/tools/quic/test_tools/quic_client_peer.h"
-#include "net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h"
+#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
+#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
+#include "net/tools/quic/test_tools/quic_server_peer.h"
#include "net/tools/quic/test_tools/quic_test_client.h"
+#include "net/tools/quic/test_tools/server_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
using base::WaitableEvent;
using net::test::QuicConnectionPeer;
using net::test::QuicSessionPeer;
+using net::test::QuicTestWriter;
using net::test::ReliableQuicStreamPeer;
+using net::tools::test::PacketDroppingTestWriter;
+using net::tools::test::QuicDispatcherPeer;
+using net::tools::test::QuicServerPeer;
+using std::ostream;
using std::string;
+using std::vector;
namespace net {
namespace tools {
@@ -43,11 +57,6 @@ namespace {
const char* kFooResponseBody = "Artichoke hearts make me happy.";
const char* kBarResponseBody = "Palm hearts are pretty delicious, also.";
-const size_t kCongestionFeedbackFrameSize = 25;
-// If kCongestionFeedbackFrameSize increase we need to expand this string
-// accordingly.
-const char* kLargeRequest =
- "https://www.google.com/foo/test/a/request/string/longer/than/25/bytes";
void GenerateBody(string* body, int length) {
body->clear();
@@ -57,67 +66,76 @@ void GenerateBody(string* body, int length) {
}
}
+// Run all tests with the cross products of all versions.
+struct TestParams {
+ TestParams(const QuicVersionVector& client_supported_versions,
+ const QuicVersionVector& server_supported_versions,
+ QuicVersion negotiated_version,
+ bool use_pacing)
+ : client_supported_versions(client_supported_versions),
+ server_supported_versions(server_supported_versions),
+ negotiated_version(negotiated_version),
+ use_pacing(use_pacing) {
+ }
+
+ friend ostream& operator<<(ostream& os, const TestParams& p) {
+ os << "{ server_supported_versions: "
+ << QuicVersionVectorToString(p.server_supported_versions);
+ os << " client_supported_versions: "
+ << QuicVersionVectorToString(p.client_supported_versions);
+ os << " negotiated_version: " << QuicVersionToString(p.negotiated_version);
+ os << " use_pacing: " << p.use_pacing << " }";
+ return os;
+ }
+
+ QuicVersionVector client_supported_versions;
+ QuicVersionVector server_supported_versions;
+ QuicVersion negotiated_version;
+ bool use_pacing;
+};
-// Simple wrapper class to run server in a thread.
-class ServerThread : public base::SimpleThread {
- public:
- ServerThread(IPEndPoint address,
- const QuicConfig& config,
- bool strike_register_no_startup_period)
- : SimpleThread("server_thread"),
- listening_(true, false),
- quit_(true, false),
- server_(config),
- address_(address),
- port_(0) {
- if (strike_register_no_startup_period) {
- server_.SetStrikeRegisterNoStartupPeriod();
+// Constructs various test permutations.
+vector<TestParams> GetTestParams() {
+ vector<TestParams> params;
+ QuicVersionVector all_supported_versions = QuicSupportedVersions();
+
+ for (int use_pacing = 0; use_pacing < 2; ++use_pacing) {
+ // Add an entry for server and client supporting all versions.
+ params.push_back(TestParams(all_supported_versions,
+ all_supported_versions,
+ all_supported_versions[0],
+ use_pacing != 0));
+
+ // Test client supporting 1 version and server supporting all versions.
+ // Simulate an old client and exercise version downgrade in the server.
+ // No 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 < all_supported_versions.size(); ++i) {
+ QuicVersionVector client_supported_versions;
+ client_supported_versions.push_back(all_supported_versions[i]);
+ params.push_back(TestParams(client_supported_versions,
+ all_supported_versions,
+ client_supported_versions[0],
+ use_pacing != 0));
}
- }
- virtual ~ServerThread() {
- }
-
- virtual void Run() OVERRIDE {
- server_.Listen(address_);
- port_lock_.Acquire();
- port_ = server_.port();
- port_lock_.Release();
-
- listening_.Signal();
- while (!quit_.IsSignaled()) {
- server_.WaitForEvents();
+ // 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 < all_supported_versions.size(); ++i) {
+ QuicVersionVector server_supported_versions;
+ server_supported_versions.push_back(all_supported_versions[i]);
+ params.push_back(TestParams(all_supported_versions,
+ server_supported_versions,
+ server_supported_versions[0],
+ use_pacing != 0));
}
- server_.Shutdown();
- }
-
- int GetPort() {
- port_lock_.Acquire();
- int rc = port_;
- port_lock_.Release();
- return rc;
- }
-
- WaitableEvent* listening() { return &listening_; }
- WaitableEvent* quit() { return &quit_; }
-
- private:
- WaitableEvent listening_;
- WaitableEvent quit_;
- base::Lock port_lock_;
- QuicServer server_;
- IPEndPoint address_;
- int port_;
-
- DISALLOW_COPY_AND_ASSIGN(ServerThread);
-};
-
-class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
- public:
- static void SetUpTestCase() {
- QuicInMemoryCache::GetInstance()->ResetForTests();
}
+ return params;
+}
+class EndToEndTest : public ::testing::TestWithParam<TestParams> {
protected:
EndToEndTest()
: server_hostname_("example.com"),
@@ -126,23 +144,39 @@ class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
net::IPAddressNumber ip;
CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
server_address_ = IPEndPoint(ip, 0);
+
+ client_supported_versions_ = GetParam().client_supported_versions;
+ server_supported_versions_ = GetParam().server_supported_versions;
+ negotiated_version_ = GetParam().negotiated_version;
+ FLAGS_limit_rto_increase_for_tests = true;
+ FLAGS_enable_quic_pacing = GetParam().use_pacing;
+ LOG(INFO) << "Using Configuration: " << GetParam();
+
client_config_.SetDefaults();
server_config_.SetDefaults();
+ server_config_.set_initial_round_trip_time_us(kMaxInitialRoundTripTimeUs,
+ 0);
- AddToCache("GET", kLargeRequest, "HTTP/1.1", "200", "OK", kFooResponseBody);
+ QuicInMemoryCachePeer::ResetForTests();
AddToCache("GET", "https://www.google.com/foo",
"HTTP/1.1", "200", "OK", kFooResponseBody);
AddToCache("GET", "https://www.google.com/bar",
"HTTP/1.1", "200", "OK", kBarResponseBody);
- version_ = GetParam();
}
- virtual QuicTestClient* CreateQuicClient() {
+ virtual ~EndToEndTest() {
+ // TODO(rtenneti): port RecycleUnusedPort if needed.
+ // RecycleUnusedPort(server_address_.port());
+ QuicInMemoryCachePeer::ResetForTests();
+ }
+
+ virtual QuicTestClient* CreateQuicClient(QuicTestWriter* writer) {
QuicTestClient* client = new QuicTestClient(server_address_,
server_hostname_,
false, // not secure
client_config_,
- version_);
+ client_supported_versions_);
+ client->UseWriter(writer);
client->Connect();
return client;
}
@@ -151,21 +185,39 @@ class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
// Start the server first, because CreateQuicClient() attempts
// to connect to the server.
StartServer();
- client_.reset(CreateQuicClient());
+ client_.reset(CreateQuicClient(client_writer_));
+ QuicEpollConnectionHelper* helper =
+ reinterpret_cast<QuicEpollConnectionHelper*>(
+ QuicConnectionPeer::GetHelper(
+ client_->client()->session()->connection()));
+ client_writer_->SetConnectionHelper(helper);
return client_->client()->connected();
}
+ virtual void SetUp() {
+ // The ownership of these gets transferred to the QuicTestWriter and
+ // QuicDispatcher when Initialize() is executed.
+ client_writer_ = new PacketDroppingTestWriter();
+ server_writer_ = new PacketDroppingTestWriter();
+ }
+
virtual void TearDown() {
StopServer();
}
void StartServer() {
server_thread_.reset(new ServerThread(server_address_, server_config_,
+ server_supported_versions_,
strike_register_no_startup_period_));
server_thread_->Start();
- server_thread_->listening()->Wait();
+ server_thread_->WaitForServerStartup();
server_address_ = IPEndPoint(server_address_.address(),
server_thread_->GetPort());
+ QuicDispatcher* dispatcher =
+ QuicServerPeer::GetDispatcher(server_thread_->server());
+ server_writer_->SetConnectionHelper(
+ QuicDispatcherPeer::GetHelper(dispatcher));
+ QuicDispatcherPeer::UseWriter(dispatcher, server_writer_);
server_started_ = true;
}
@@ -173,65 +225,63 @@ class EndToEndTest : public ::testing::TestWithParam<QuicVersion> {
if (!server_started_)
return;
if (server_thread_.get()) {
- server_thread_->quit()->Signal();
+ server_thread_->Quit();
server_thread_->Join();
}
}
- void AddToCache(const StringPiece& method,
- const StringPiece& path,
- const StringPiece& version,
- const StringPiece& response_code,
- const StringPiece& response_detail,
- const StringPiece& body) {
- BalsaHeaders request_headers, response_headers;
- request_headers.SetRequestFirstlineFromStringPieces(method,
- path,
- version);
- response_headers.SetRequestFirstlineFromStringPieces(version,
- response_code,
- response_detail);
- response_headers.AppendHeader("content-length",
- base::IntToString(body.length()));
-
- // Check if response already exists and matches.
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
- const QuicInMemoryCache::Response* cached_response =
- cache->GetResponse(request_headers);
- if (cached_response != NULL) {
- string cached_response_headers_str, response_headers_str;
- cached_response->headers().DumpToString(&cached_response_headers_str);
- response_headers.DumpToString(&response_headers_str);
- CHECK_EQ(cached_response_headers_str, response_headers_str);
- CHECK_EQ(cached_response->body(), body);
- return;
- }
- cache->AddResponse(request_headers, response_headers, body);
+ void AddToCache(StringPiece method,
+ StringPiece path,
+ StringPiece version,
+ StringPiece response_code,
+ StringPiece response_detail,
+ StringPiece body) {
+ QuicInMemoryCache::GetInstance()->AddSimpleResponse(
+ method, path, version, response_code, response_detail, body);
+ }
+
+ void SetPacketLossPercentage(int32 loss) {
+ // TODO(rtenneti): enable when we can do random packet loss tests in
+ // chrome's tree.
+ // client_writer_->set_fake_packet_loss_percentage(loss);
+ // server_writer_->set_fake_packet_loss_percentage(loss);
+ }
+
+ void SetPacketSendDelay(QuicTime::Delta delay) {
+ // TODO(rtenneti): enable when we can do random packet send delay tests in
+ // chrome's tree.
+ // client_writer_->set_fake_packet_delay(delay);
+ // server_writer_->set_fake_packet_delay(delay);
+ }
+
+ void SetReorderPercentage(int32 reorder) {
+ // TODO(rtenneti): enable when we can do random packet reorder tests in
+ // chrome's tree.
+ // client_writer_->set_fake_reorder_percentage(reorder);
+ // server_writer_->set_fake_reorder_percentage(reorder);
}
IPEndPoint server_address_;
string server_hostname_;
scoped_ptr<ServerThread> server_thread_;
scoped_ptr<QuicTestClient> client_;
+ PacketDroppingTestWriter* client_writer_;
+ PacketDroppingTestWriter* server_writer_;
bool server_started_;
QuicConfig client_config_;
QuicConfig server_config_;
- QuicVersion version_;
+ QuicVersionVector client_supported_versions_;
+ QuicVersionVector server_supported_versions_;
+ QuicVersion negotiated_version_;
bool strike_register_no_startup_period_;
};
// Run all end to end tests with all supported versions.
INSTANTIATE_TEST_CASE_P(EndToEndTests,
EndToEndTest,
- ::testing::ValuesIn(kSupportedQuicVersions));
+ ::testing::ValuesIn(GetTestParams()));
TEST_P(EndToEndTest, SimpleRequestResponse) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -241,12 +291,6 @@ TEST_P(EndToEndTest, SimpleRequestResponse) {
// TODO(rch): figure out how to detect missing v6 supprt (like on the linux
// try bots) and selectively disable this test.
TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
IPAddressNumber ip;
CHECK(net::ParseIPLiteralToNumber("::1", &ip));
server_address_ = IPEndPoint(ip, server_address_.port());
@@ -257,12 +301,6 @@ TEST_P(EndToEndTest, DISABLED_SimpleRequestResponsev6) {
}
TEST_P(EndToEndTest, SeparateFinPacket) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
HTTPMessage request(HttpConstants::HTTP_1_1,
@@ -287,12 +325,6 @@ TEST_P(EndToEndTest, SeparateFinPacket) {
}
TEST_P(EndToEndTest, MultipleRequestResponse) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
@@ -302,14 +334,8 @@ TEST_P(EndToEndTest, MultipleRequestResponse) {
}
TEST_P(EndToEndTest, MultipleClients) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
- scoped_ptr<QuicTestClient> client2(CreateQuicClient());
+ scoped_ptr<QuicTestClient> client2(CreateQuicClient(NULL));
HTTPMessage request(HttpConstants::HTTP_1_1,
HttpConstants::POST, "/foo");
@@ -331,83 +357,32 @@ TEST_P(EndToEndTest, MultipleClients) {
}
TEST_P(EndToEndTest, RequestOverMultiplePackets) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
+ // Send a large enough request to guarantee fragmentation.
+ string huge_request =
+ "https://www.google.com/some/path?query=" + string(kMaxPacketSize, '.');
+ AddToCache("GET", huge_request, "HTTP/1.1", "200", "OK", kBarResponseBody);
ASSERT_TRUE(Initialize());
- // Set things up so we have a small payload, to guarantee fragmentation.
- // A congestion feedback frame can't be split into multiple packets, make sure
- // that our packet have room for at least this amount after the normal headers
- // are added.
-
- // TODO(rch) handle this better when we have different encryption options.
- const size_t kStreamDataLength = 3;
- const QuicStreamId kStreamId = 1u;
- const QuicStreamOffset kStreamOffset = 0u;
- size_t stream_payload_size =
- QuicFramer::GetMinStreamFrameSize(
- GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
- size_t min_payload_size =
- std::max(kCongestionFeedbackFrameSize, stream_payload_size);
- size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
- // TODO(satyashekhar): Fix this when versioning is implemented.
- client_->options()->max_packet_length =
- GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
- PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
- ciphertext_size;
-
- // Make sure our request is too large to fit in one packet.
- EXPECT_GT(strlen(kLargeRequest), min_payload_size);
- EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
+
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest(huge_request));
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}
-TEST_P(EndToEndTest, MultipleFramesRandomOrder) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
+TEST_P(EndToEndTest, MultiplePacketsRandomOrder) {
+ // Send a large enough request to guarantee fragmentation.
+ string huge_request =
+ "https://www.google.com/some/path?query=" + string(kMaxPacketSize, '.');
+ AddToCache("GET", huge_request, "HTTP/1.1", "200", "OK", kBarResponseBody);
ASSERT_TRUE(Initialize());
- // Set things up so we have a small payload, to guarantee fragmentation.
- // A congestion feedback frame can't be split into multiple packets, make sure
- // that our packet have room for at least this amount after the normal headers
- // are added.
-
- // TODO(rch) handle this better when we have different encryption options.
- const size_t kStreamDataLength = 3;
- const QuicStreamId kStreamId = 1u;
- const QuicStreamOffset kStreamOffset = 0u;
- size_t stream_payload_size =
- QuicFramer::GetMinStreamFrameSize(
- GetParam(), kStreamId, kStreamOffset, true) + kStreamDataLength;
- size_t min_payload_size =
- std::max(kCongestionFeedbackFrameSize, stream_payload_size);
- size_t ciphertext_size = NullEncrypter().GetCiphertextSize(min_payload_size);
- // TODO(satyashekhar): Fix this when versioning is implemented.
- client_->options()->max_packet_length =
- GetPacketHeaderSize(PACKET_8BYTE_GUID, !kIncludeVersion,
- PACKET_6BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
- ciphertext_size;
- client_->options()->random_reorder = true;
-
- // Make sure our request is too large to fit in one packet.
- EXPECT_GT(strlen(kLargeRequest), min_payload_size);
- EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest(kLargeRequest));
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(50);
+
+ EXPECT_EQ(kBarResponseBody, client_->SendSynchronousRequest(huge_request));
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
}
TEST_P(EndToEndTest, PostMissingBytes) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
// Add a content length header with no body.
@@ -424,12 +399,6 @@ TEST_P(EndToEndTest, PostMissingBytes) {
}
TEST_P(EndToEndTest, LargePostNoPacketLoss) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
client_->client()->WaitForCryptoHandshakeConfirmed();
@@ -446,20 +415,55 @@ TEST_P(EndToEndTest, LargePostNoPacketLoss) {
}
TEST_P(EndToEndTest, LargePostWithPacketLoss) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
+ // Connect with lower fake packet loss than we'd like to test. Until
+ // b/10126687 is fixed, losing handshake packets is pretty brutal.
+ SetPacketLossPercentage(5);
+ ASSERT_TRUE(Initialize());
+
+ // Wait for the server SHLO before upping the packet loss.
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+ SetPacketLossPercentage(30);
+
+ // 10 Kb body.
+ string body;
+ GenerateBody(&body, 1024 * 10);
+
+ HTTPMessage request(HttpConstants::HTTP_1_1,
+ HttpConstants::POST, "/foo");
+ request.AddBody(body, true);
+
+ EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
+}
+
+TEST_P(EndToEndTest, LargePostNoPacketLossWithDelayAndReordering) {
+ ASSERT_TRUE(Initialize());
+
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+ // Both of these must be called when the writer is not actively used.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // 1 Mb body.
+ string body;
+ GenerateBody(&body, 1024 * 1024);
+ HTTPMessage request(HttpConstants::HTTP_1_1,
+ HttpConstants::POST, "/foo");
+ request.AddBody(body, true);
+
+ EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
+}
+
+TEST_P(EndToEndTest, LargePostWithPacketLossAndBlocketSocket) {
// Connect with lower fake packet loss than we'd like to test. Until
// b/10126687 is fixed, losing handshake packets is pretty brutal.
- // FLAGS_fake_packet_loss_percentage = 5;
+ SetPacketLossPercentage(5);
ASSERT_TRUE(Initialize());
// Wait for the server SHLO before upping the packet loss.
client_->client()->WaitForCryptoHandshakeConfirmed();
- // FLAGS_fake_packet_loss_percentage = 30;
+ SetPacketLossPercentage(30);
+ client_writer_->set_fake_blocked_socket_percentage(10);
// 10 Kb body.
string body;
@@ -472,7 +476,9 @@ TEST_P(EndToEndTest, LargePostWithPacketLoss) {
EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
}
-TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
+// TODO(rtenneti): rch is investigating the root cause. Will enable after we
+// find the bug.
+TEST_P(EndToEndTest, DISABLED_LargePostZeroRTTFailure) {
// Have the server accept 0-RTT without waiting a startup period.
strike_register_no_startup_period_ = true;
@@ -494,6 +500,7 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
// The 0-RTT handshake should succeed.
client_->Connect();
+ client_->WaitForResponseForMs(-1);
ASSERT_TRUE(client_->client()->connected());
EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
EXPECT_EQ(1, client_->client()->session()->GetNumSentClientHellos());
@@ -502,6 +509,7 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
// Restart the server so that the 0-RTT handshake will take 1 RTT.
StopServer();
+ server_writer_ = new PacketDroppingTestWriter();
StartServer();
client_->Connect();
@@ -512,17 +520,7 @@ TEST_P(EndToEndTest, LargePostZeroRTTFailure) {
// TODO(ianswett): Enable once b/9295090 is fixed.
TEST_P(EndToEndTest, DISABLED_LargePostFEC) {
- // FLAGS_fake_packet_loss_percentage = 30;
- ASSERT_TRUE(Initialize());
- client_->options()->max_packets_per_fec_group = 6;
-
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
- // FLAGS_fake_packet_loss_percentage = 30;
+ SetPacketLossPercentage(30);
ASSERT_TRUE(Initialize());
client_->options()->max_packets_per_fec_group = 6;
@@ -536,31 +534,30 @@ TEST_P(EndToEndTest, DISABLED_LargePostFEC) {
EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
}
-/*TEST_P(EndToEndTest, PacketTooLarge) {
- FLAGS_quic_allow_oversized_packets_for_test = true;
+TEST_P(EndToEndTest, LargePostLargeBuffer) {
ASSERT_TRUE(Initialize());
+ SetPacketSendDelay(QuicTime::Delta::FromMicroseconds(1));
+ // 1Mbit per second with a 128k buffer from server to client. Wireless
+ // clients commonly have larger buffers, but our max CWND is 200.
+ server_writer_->set_max_bandwidth_and_buffer_size(
+ QuicBandwidth::FromBytesPerSecond(256 * 1024), 128 * 1024);
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // 1 Mb body.
string body;
- GenerateBody(&body, kMaxPacketSize);
+ GenerateBody(&body, 1024 * 1024);
HTTPMessage request(HttpConstants::HTTP_1_1,
HttpConstants::POST, "/foo");
request.AddBody(body, true);
- client_->options()->max_packet_length = 20480;
- EXPECT_EQ("", client_->SendCustomSynchronousRequest(request));
- EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
- EXPECT_EQ(QUIC_PACKET_TOO_LARGE, client_->connection_error());
-}*/
+ EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
+}
TEST_P(EndToEndTest, InvalidStream) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
string body;
GenerateBody(&body, kMaxPacketSize);
@@ -579,12 +576,6 @@ TEST_P(EndToEndTest, InvalidStream) {
// TODO(rch): this test seems to cause net_unittests timeouts :|
TEST_P(EndToEndTest, DISABLED_MultipleTermination) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
HTTPMessage request(HttpConstants::HTTP_1_1,
@@ -595,11 +586,12 @@ TEST_P(EndToEndTest, DISABLED_MultipleTermination) {
// Set the offset so we won't frame. Otherwise when we pick up termination
// before HTTP framing is complete, we send an error and close the stream,
// and the second write is picked up as writing on a closed stream.
- QuicReliableClientStream* stream = client_->GetOrCreateStream();
+ QuicSpdyClientStream* stream = client_->GetOrCreateStream();
ASSERT_TRUE(stream != NULL);
ReliableQuicStreamPeer::SetStreamBytesWritten(3, stream);
client_->SendData("bar", true);
+ client_->WaitForWriteToFlush();
// By default the stream protects itself from writes after terminte is set.
// Override this to test the server handling buggy clients.
@@ -649,14 +641,105 @@ TEST_P(EndToEndTest, LimitMaxOpenStreams) {
EXPECT_EQ(2u, client_negotiated_config->max_streams_per_connection());
}
-TEST_P(EndToEndTest, ResetConnection) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
+// TODO(rtenneti): DISABLED_LimitCongestionWindowAndRTT seems to be flaky.
+// http://crbug.com/321870.
+TEST_P(EndToEndTest, DISABLED_LimitCongestionWindowAndRTT) {
+ server_config_.set_server_initial_congestion_window(kMaxInitialWindow,
+ kDefaultInitialWindow);
+ // Client tries to negotiate twice the server's max and negotiation settles
+ // on the max.
+ client_config_.set_server_initial_congestion_window(2 * kMaxInitialWindow,
+ kDefaultInitialWindow);
+ client_config_.set_initial_round_trip_time_us(1, 1);
+
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+ server_thread_->WaitForCryptoHandshakeConfirmed();
+
+ // Pause the server so we can access the server's internals without races.
+ server_thread_->Pause();
+ QuicDispatcher* dispatcher =
+ QuicServerPeer::GetDispatcher(server_thread_->server());
+ ASSERT_EQ(1u, dispatcher->session_map().size());
+ QuicSession* session = dispatcher->session_map().begin()->second;
+ QuicConfig* client_negotiated_config = client_->client()->session()->config();
+ QuicConfig* server_negotiated_config = session->config();
+ const QuicSentPacketManager& client_sent_packet_manager =
+ client_->client()->session()->connection()->sent_packet_manager();
+ const QuicSentPacketManager& server_sent_packet_manager =
+ session->connection()->sent_packet_manager();
+
+ EXPECT_EQ(kMaxInitialWindow,
+ client_negotiated_config->server_initial_congestion_window());
+ EXPECT_EQ(kMaxInitialWindow,
+ server_negotiated_config->server_initial_congestion_window());
+ // The client shouldn't set it's initial window based on the negotiated value.
+ EXPECT_EQ(kDefaultInitialWindow * kDefaultTCPMSS,
+ client_sent_packet_manager.GetCongestionWindow());
+ EXPECT_EQ(kMaxInitialWindow * kDefaultTCPMSS,
+ server_sent_packet_manager.GetCongestionWindow());
+
+ EXPECT_EQ(FLAGS_enable_quic_pacing,
+ server_sent_packet_manager.using_pacing());
+ EXPECT_EQ(FLAGS_enable_quic_pacing,
+ client_sent_packet_manager.using_pacing());
+
+ EXPECT_EQ(1u, client_negotiated_config->initial_round_trip_time_us());
+ EXPECT_EQ(1u, server_negotiated_config->initial_round_trip_time_us());
+
+ // Now use the negotiated limits with packet loss.
+ SetPacketLossPercentage(30);
+
+ // 10 Kb body.
+ string body;
+ GenerateBody(&body, 1024 * 10);
+
+ HTTPMessage request(HttpConstants::HTTP_1_1,
+ HttpConstants::POST, "/foo");
+ request.AddBody(body, true);
+
+ server_thread_->Resume();
+ EXPECT_EQ(kFooResponseBody, client_->SendCustomSynchronousRequest(request));
+}
+
+TEST_P(EndToEndTest, InitialRTT) {
+ // Client tries to negotiate twice the server's max and negotiation settles
+ // on the max.
+ client_config_.set_initial_round_trip_time_us(2 * kMaxInitialRoundTripTimeUs,
+ 0);
+
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+ server_thread_->WaitForCryptoHandshakeConfirmed();
+
+ // Pause the server so we can access the server's internals without races.
+ server_thread_->Pause();
+ QuicDispatcher* dispatcher =
+ QuicServerPeer::GetDispatcher(server_thread_->server());
+ ASSERT_EQ(1u, dispatcher->session_map().size());
+ QuicSession* session = dispatcher->session_map().begin()->second;
+ QuicConfig* client_negotiated_config = client_->client()->session()->config();
+ QuicConfig* server_negotiated_config = session->config();
+ const QuicSentPacketManager& client_sent_packet_manager =
+ client_->client()->session()->connection()->sent_packet_manager();
+ const QuicSentPacketManager& server_sent_packet_manager =
+ session->connection()->sent_packet_manager();
+
+ EXPECT_EQ(kMaxInitialRoundTripTimeUs,
+ client_negotiated_config->initial_round_trip_time_us());
+ EXPECT_EQ(kMaxInitialRoundTripTimeUs,
+ server_negotiated_config->initial_round_trip_time_us());
+ // Now that acks have been exchanged, the RTT estimate has decreased on the
+ // server and is not infinite on the client.
+ EXPECT_FALSE(client_sent_packet_manager.SmoothedRtt().IsInfinite());
+ EXPECT_GE(static_cast<int64>(kMaxInitialRoundTripTimeUs),
+ server_sent_packet_manager.SmoothedRtt().ToMicroseconds());
+}
+
+TEST_P(EndToEndTest, ResetConnection) {
ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
@@ -666,7 +749,7 @@ TEST_P(EndToEndTest, ResetConnection) {
}
TEST_P(EndToEndTest, MaxStreamsUberTest) {
- // FLAGS_fake_packet_loss_percentage = 1;
+ SetPacketLossPercentage(1);
ASSERT_TRUE(Initialize());
string large_body;
GenerateBody(&large_body, 10240);
@@ -675,7 +758,7 @@ TEST_P(EndToEndTest, MaxStreamsUberTest) {
AddToCache("GET", "/large_response", "HTTP/1.1", "200", "OK", large_body);;
client_->client()->WaitForCryptoHandshakeConfirmed();
- // FLAGS_fake_packet_loss_percentage = 10;
+ SetPacketLossPercentage(10);
for (int i = 0; i < max_streams; ++i) {
EXPECT_LT(0, client_->SendRequest("/large_response"));
@@ -687,49 +770,44 @@ TEST_P(EndToEndTest, MaxStreamsUberTest) {
}
}
-class WrongAddressWriter : public QuicPacketWriter {
+class WrongAddressWriter : public QuicTestWriter {
public:
- explicit WrongAddressWriter(int fd) : fd_(fd) {
+ WrongAddressWriter() {
IPAddressNumber ip;
CHECK(net::ParseIPLiteralToNumber("127.0.0.2", &ip));
self_address_ = IPEndPoint(ip, 0);
}
- virtual int WritePacket(const char* buffer, size_t buf_len,
- const IPAddressNumber& real_self_address,
- const IPEndPoint& peer_address,
- QuicBlockedWriterInterface* blocked_writer,
- int* error) OVERRIDE {
- return QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
- self_address_.address(), peer_address,
- error);
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const IPAddressNumber& real_self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE {
+ return writer()->WritePacket(buffer, buf_len, self_address_.address(),
+ peer_address, blocked_writer);
+ }
+
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE {
+ return false;
}
IPEndPoint self_address_;
- int fd_;
};
TEST_P(EndToEndTest, ConnectionMigration) {
- // TODO(rtenneti): Delete this when NSS is supported.
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
ASSERT_TRUE(Initialize());
EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
EXPECT_EQ(200u, client_->response_headers()->parsed_response_code());
- WrongAddressWriter writer(QuicClientPeer::GetFd(client_->client()));
- QuicEpollConnectionHelper* helper =
- reinterpret_cast<QuicEpollConnectionHelper*>(
- QuicConnectionPeer::GetHelper(
- client_->client()->session()->connection()));
- QuicEpollConnectionHelperPeer::SetWriter(helper, &writer);
+ scoped_ptr<WrongAddressWriter> writer(new WrongAddressWriter());
+
+ writer->set_writer(new QuicDefaultPacketWriter(
+ QuicClientPeer::GetFd(client_->client())));
+ QuicConnectionPeer::SetWriter(client_->client()->session()->connection(),
+ writer.get());
client_->SendSynchronousRequest("/bar");
- QuicEpollConnectionHelperPeer::SetWriter(helper, NULL);
EXPECT_EQ(QUIC_STREAM_CONNECTION_ERROR, client_->stream_error());
EXPECT_EQ(QUIC_ERROR_MIGRATING_ADDRESS, client_->connection_error());
diff --git a/chromium/net/tools/quic/quic_client.cc b/chromium/net/tools/quic/quic_client.cc
index 86fa6c48b75..dcf9612a38f 100644
--- a/chromium/net/tools/quic/quic_client.cc
+++ b/chromium/net/tools/quic/quic_client.cc
@@ -16,10 +16,10 @@
#include "net/quic/quic_connection.h"
#include "net/quic/quic_data_reader.h"
#include "net/quic/quic_protocol.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
-#include "net/tools/quic/quic_reliable_client_stream.h"
#include "net/tools/quic/quic_socket_utils.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
@@ -32,31 +32,36 @@ const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
QuicClient::QuicClient(IPEndPoint server_address,
const string& server_hostname,
- const QuicVersion version)
+ const QuicVersionVector& supported_versions,
+ bool print_response)
: server_address_(server_address),
server_hostname_(server_hostname),
local_port_(0),
fd_(-1),
+ helper_(CreateQuicConnectionHelper()),
initialized_(false),
packets_dropped_(0),
overflow_supported_(false),
- version_(version) {
+ supported_versions_(supported_versions),
+ print_response_(print_response) {
config_.SetDefaults();
}
QuicClient::QuicClient(IPEndPoint server_address,
const string& server_hostname,
const QuicConfig& config,
- const QuicVersion version)
+ const QuicVersionVector& supported_versions)
: server_address_(server_address),
server_hostname_(server_hostname),
config_(config),
local_port_(0),
fd_(-1),
+ helper_(CreateQuicConnectionHelper()),
initialized_(false),
packets_dropped_(0),
overflow_supported_(false),
- version_(version) {
+ supported_versions_(supported_versions),
+ print_response_(false) {
}
QuicClient::~QuicClient() {
@@ -150,13 +155,16 @@ bool QuicClient::Connect() {
bool QuicClient::StartConnect() {
DCHECK(!connected() && initialized_);
- QuicGuid guid = QuicRandom::GetInstance()->RandUint64();
+ QuicPacketWriter* writer = CreateQuicPacketWriter();
+ if (writer_.get() != writer) {
+ writer_.reset(writer);
+ }
+
session_.reset(new QuicClientSession(
server_hostname_,
config_,
- new QuicConnection(guid, server_address_,
- CreateQuicConnectionHelper(), false,
- version_),
+ new QuicConnection(GenerateGuid(), server_address_, helper_.get(),
+ writer_.get(), false, supported_versions_),
&crypto_config_));
return session_->CryptoConnect();
}
@@ -167,9 +175,11 @@ bool QuicClient::EncryptionBeingEstablished() {
}
void QuicClient::Disconnect() {
- DCHECK(connected());
+ DCHECK(initialized_);
- session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
+ if (connected()) {
+ session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
+ }
epoll_server_.UnregisterFD(fd_);
close(fd_);
fd_ = -1;
@@ -178,21 +188,23 @@ void QuicClient::Disconnect() {
void QuicClient::SendRequestsAndWaitForResponse(
const CommandLine::StringVector& args) {
- for (uint32_t i = 0; i < args.size(); i++) {
+ for (size_t i = 0; i < args.size(); ++i) {
BalsaHeaders headers;
headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1");
- CreateReliableClientStream()->SendRequest(headers, "", true);
+ QuicSpdyClientStream* stream = CreateReliableClientStream();
+ stream->SendRequest(headers, "", true);
+ stream->set_visitor(this);
}
while (WaitForEvents()) { }
}
-QuicReliableClientStream* QuicClient::CreateReliableClientStream() {
+QuicSpdyClientStream* QuicClient::CreateReliableClientStream() {
if (!connected()) {
return NULL;
}
- return session_->CreateOutgoingReliableStream();
+ return session_->CreateOutgoingDataStream();
}
void QuicClient::WaitForStreamToClose(QuicStreamId id) {
@@ -233,6 +245,24 @@ void QuicClient::OnEvent(int fd, EpollEvent* event) {
}
}
+void QuicClient::OnClose(QuicDataStream* stream) {
+ if (!print_response_) {
+ return;
+ }
+
+ QuicSpdyClientStream* client_stream =
+ static_cast<QuicSpdyClientStream*>(stream);
+ const BalsaHeaders& headers = client_stream->headers();
+ printf("%s\n", headers.first_line().as_string().c_str());
+ for (BalsaHeaders::const_header_lines_iterator i =
+ headers.header_lines_begin();
+ i != headers.header_lines_end(); ++i) {
+ printf("%s: %s\n", i->first.as_string().c_str(),
+ i->second.as_string().c_str());
+ }
+ printf("%s\n", client_stream->data().c_str());
+}
+
QuicPacketCreator::Options* QuicClient::options() {
if (session() == NULL) {
return NULL;
@@ -245,8 +275,16 @@ bool QuicClient::connected() const {
session_->connection()->connected();
}
+QuicGuid QuicClient::GenerateGuid() {
+ return QuicRandom::GetInstance()->RandUint64();
+}
+
QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() {
- return new QuicEpollConnectionHelper(fd_, &epoll_server_);
+ return new QuicEpollConnectionHelper(&epoll_server_);
+}
+
+QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
+ return new QuicDefaultPacketWriter(fd_);
}
bool QuicClient::ReadAndProcessPacket() {
diff --git a/chromium/net/tools/quic/quic_client.h b/chromium/net/tools/quic/quic_client.h
index 5e8960124d1..02f45e6c56a 100644
--- a/chromium/net/tools/quic/quic_client.h
+++ b/chromium/net/tools/quic/quic_client.h
@@ -11,16 +11,15 @@
#include <string>
#include "base/command_line.h"
-#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/crypto_handshake.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client_session.h"
-#include "net/tools/quic/quic_reliable_client_stream.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
namespace net {
@@ -34,14 +33,17 @@ namespace test {
class QuicClientPeer;
} // namespace test
-class QuicClient : public EpollCallbackInterface {
+class QuicClient : public EpollCallbackInterface,
+ public QuicDataStream::Visitor {
public:
- QuicClient(IPEndPoint server_address, const std::string& server_hostname,
- const QuicVersion version);
+ QuicClient(IPEndPoint server_address,
+ const string& server_hostname,
+ const QuicVersionVector& supported_versions,
+ bool print_response);
QuicClient(IPEndPoint server_address,
const std::string& server_hostname,
const QuicConfig& config,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
virtual ~QuicClient();
@@ -73,7 +75,7 @@ class QuicClient : public EpollCallbackInterface {
// Returns a newly created CreateReliableClientStream, owned by the
// QuicClient.
- QuicReliableClientStream* CreateReliableClientStream();
+ QuicSpdyClientStream* CreateReliableClientStream();
// Wait for events until the stream with the given ID is closed.
void WaitForStreamToClose(QuicStreamId id);
@@ -96,6 +98,9 @@ class QuicClient : public EpollCallbackInterface {
virtual void OnUnregistration(int fd, bool replaced) OVERRIDE {}
virtual void OnShutdown(EpollServer* eps, int fd) OVERRIDE {}
+ // QuicDataStream::Visitor
+ virtual void OnClose(QuicDataStream* stream) OVERRIDE;
+
QuicPacketCreator::Options* options();
QuicClientSession* session() { return session_.get(); }
@@ -138,7 +143,9 @@ class QuicClient : public EpollCallbackInterface {
}
protected:
+ virtual QuicGuid GenerateGuid();
virtual QuicEpollConnectionHelper* CreateQuicConnectionHelper();
+ virtual QuicPacketWriter* CreateQuicPacketWriter();
private:
friend class net::tools::test::QuicClientPeer;
@@ -146,9 +153,6 @@ class QuicClient : public EpollCallbackInterface {
// Read a UDP packet and hand it to the framer.
bool ReadAndProcessPacket();
- // Set of streams created (and owned) by this client
- base::hash_set<QuicReliableClientStream*> streams_;
-
// Address of the server.
const IPEndPoint server_address_;
@@ -175,6 +179,12 @@ class QuicClient : public EpollCallbackInterface {
// UDP socket.
int fd_;
+ // Helper to be used by created connections.
+ scoped_ptr<QuicEpollConnectionHelper> helper_;
+
+ // Writer used to actually send packets to the wire.
+ scoped_ptr<QuicPacketWriter> writer_;
+
// Tracks if the client is initialized to connect.
bool initialized_;
@@ -187,8 +197,16 @@ class QuicClient : public EpollCallbackInterface {
// because the socket would otherwise overflow.
bool overflow_supported_;
- // Which QUIC version does this client talk?
- QuicVersion version_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary). We will always pick supported_versions_[0] as the
+ // initial version to use.
+ QuicVersionVector supported_versions_;
+
+ // If true, then the contents of each response will be printed to stdout
+ // when the stream is closed (in OnClose).
+ bool print_response_;
DISALLOW_COPY_AND_ASSIGN(QuicClient);
};
diff --git a/chromium/net/tools/quic/quic_client_bin.cc b/chromium/net/tools/quic/quic_client_bin.cc
index e13bea5e8c1..2f8cfac1736 100644
--- a/chromium/net/tools/quic/quic_client_bin.cc
+++ b/chromium/net/tools/quic/quic_client_bin.cc
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// A binary wrapper for QuicClient. Connects to --hostname or --address on
-// --port and requests URLs specified on the command line.
+// A binary wrapper for QuicClient. Connects to --hostname via --address
+// on --port and requests URLs specified on the command line.
//
// For example:
-// quic_client --port=6122 /index.html /favicon.ico
+// quic_client --address=127.0.0.1 --port=6122 --hostname=www.google.com
+// http://www.google.com/index.html http://www.google.com/favicon.ico
+
+#include <iostream>
#include "base/at_exit.h"
#include "base/command_line.h"
@@ -23,6 +26,18 @@ std::string FLAGS_hostname = "localhost";
int main(int argc, char *argv[]) {
CommandLine::Init(argc, argv);
CommandLine* line = CommandLine::ForCurrentProcess();
+ if (line->HasSwitch("h") || line->HasSwitch("help")) {
+ const char* help_str =
+ "Usage: quic_client [options]\n"
+ "\n"
+ "Options:\n"
+ "-h, --help show this help message and exit\n"
+ "--port=<port> specify the port to connect to\n"
+ "--address=<address> specify the IP address to connect to\n"
+ "--host=<host> specify the SNI hostname to use\n";
+ std::cout << help_str;
+ exit(0);
+ }
if (line->HasSwitch("port")) {
int port;
if (base::StringToInt(line->GetSwitchValueASCII("port"), &port)) {
@@ -45,7 +60,8 @@ int main(int argc, char *argv[]) {
CHECK(net::ParseIPLiteralToNumber(FLAGS_address, &addr));
// TODO(rjshade): Set version on command line.
net::tools::QuicClient client(
- net::IPEndPoint(addr, FLAGS_port), FLAGS_hostname, net::QuicVersionMax());
+ net::IPEndPoint(addr, FLAGS_port), FLAGS_hostname,
+ net::QuicSupportedVersions(), true);
client.Initialize();
diff --git a/chromium/net/tools/quic/quic_client_session.cc b/chromium/net/tools/quic/quic_client_session.cc
index f993908b624..5bcf6f201f4 100644
--- a/chromium/net/tools/quic/quic_client_session.cc
+++ b/chromium/net/tools/quic/quic_client_session.cc
@@ -6,7 +6,6 @@
#include "base/logging.h"
#include "net/quic/crypto/crypto_protocol.h"
-#include "net/tools/quic/quic_reliable_client_stream.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
using std::string;
@@ -19,14 +18,14 @@ QuicClientSession::QuicClientSession(
const QuicConfig& config,
QuicConnection* connection,
QuicCryptoClientConfig* crypto_config)
- : QuicSession(connection, config, false),
+ : QuicSession(connection, config),
crypto_stream_(server_hostname, this, crypto_config) {
}
QuicClientSession::~QuicClientSession() {
}
-QuicReliableClientStream* QuicClientSession::CreateOutgoingReliableStream() {
+QuicSpdyClientStream* QuicClientSession::CreateOutgoingDataStream() {
if (!crypto_stream_.encryption_established()) {
DLOG(INFO) << "Encryption not active so no outgoing stream created.";
return NULL;
@@ -41,7 +40,7 @@ QuicReliableClientStream* QuicClientSession::CreateOutgoingReliableStream() {
<< "Already received goaway.";
return NULL;
}
- QuicReliableClientStream* stream
+ QuicSpdyClientStream* stream
= new QuicSpdyClientStream(GetNextStreamId(), this);
ActivateStream(stream);
return stream;
@@ -59,7 +58,7 @@ int QuicClientSession::GetNumSentClientHellos() const {
return crypto_stream_.num_sent_client_hellos();
}
-ReliableQuicStream* QuicClientSession::CreateIncomingReliableStream(
+QuicDataStream* QuicClientSession::CreateIncomingDataStream(
QuicStreamId id) {
DLOG(ERROR) << "Server push not supported";
return NULL;
diff --git a/chromium/net/tools/quic/quic_client_session.h b/chromium/net/tools/quic/quic_client_session.h
index a73d721fef6..dcee15e4275 100644
--- a/chromium/net/tools/quic/quic_client_session.h
+++ b/chromium/net/tools/quic/quic_client_session.h
@@ -12,7 +12,7 @@
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_session.h"
-#include "net/tools/quic/quic_reliable_client_stream.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
namespace net {
@@ -21,8 +21,6 @@ class ReliableQuicStream;
namespace tools {
-class QuicReliableClientStream;
-
class QuicClientSession : public QuicSession {
public:
QuicClientSession(const std::string& server_hostname,
@@ -32,7 +30,7 @@ class QuicClientSession : public QuicSession {
virtual ~QuicClientSession();
// QuicSession methods:
- virtual QuicReliableClientStream* CreateOutgoingReliableStream() OVERRIDE;
+ virtual QuicSpdyClientStream* CreateOutgoingDataStream() OVERRIDE;
virtual QuicCryptoClientStream* GetCryptoStream() OVERRIDE;
// Performs a crypto handshake with the server. Returns true if the crypto
@@ -46,8 +44,7 @@ class QuicClientSession : public QuicSession {
protected:
// QuicSession methods:
- virtual ReliableQuicStream* CreateIncomingReliableStream(
- QuicStreamId id) OVERRIDE;
+ virtual QuicDataStream* CreateIncomingDataStream(QuicStreamId id) OVERRIDE;
private:
QuicCryptoClientStream crypto_stream_;
diff --git a/chromium/net/tools/quic/quic_client_session_test.cc b/chromium/net/tools/quic/quic_client_session_test.cc
index 1b1ece6597e..c893c20b5e3 100644
--- a/chromium/net/tools/quic/quic_client_session_test.cc
+++ b/chromium/net/tools/quic/quic_client_session_test.cc
@@ -10,12 +10,13 @@
#include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/tools/quic/quic_reliable_client_stream.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
-using testing::_;
using net::test::CryptoTestUtils;
+using net::test::DefaultQuicConfig;
using net::test::PacketSavingConnection;
+using testing::_;
namespace net {
namespace tools {
@@ -27,10 +28,9 @@ const char kServerHostname[] = "www.example.com";
class ToolsQuicClientSessionTest : public ::testing::Test {
protected:
ToolsQuicClientSessionTest()
- : guid_(1),
- connection_(new PacketSavingConnection(guid_, IPEndPoint(), false)) {
+ : connection_(new PacketSavingConnection(false)) {
crypto_config_.SetDefaults();
- session_.reset(new QuicClientSession(kServerHostname, QuicConfig(),
+ session_.reset(new QuicClientSession(kServerHostname, DefaultQuicConfig(),
connection_, &crypto_config_));
session_->config()->SetDefaults();
}
@@ -41,53 +41,39 @@ class ToolsQuicClientSessionTest : public ::testing::Test {
connection_, session_->GetCryptoStream());
}
- QuicGuid guid_;
PacketSavingConnection* connection_;
scoped_ptr<QuicClientSession> session_;
QuicCryptoClientConfig crypto_config_;
};
TEST_F(ToolsQuicClientSessionTest, CryptoConnect) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
CompleteCryptoHandshake();
}
TEST_F(ToolsQuicClientSessionTest, MaxNumStreams) {
session_->config()->set_max_streams_per_connection(1, 1);
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
// FLAGS_max_streams_per_connection = 1;
// Initialize crypto before the client session will create a stream.
CompleteCryptoHandshake();
- QuicReliableClientStream* stream =
- session_->CreateOutgoingReliableStream();
+ QuicSpdyClientStream* stream =
+ session_->CreateOutgoingDataStream();
ASSERT_TRUE(stream);
- EXPECT_FALSE(session_->CreateOutgoingReliableStream());
+ EXPECT_FALSE(session_->CreateOutgoingDataStream());
// Close a stream and ensure I can now open a new one.
session_->CloseStream(stream->id());
- stream = session_->CreateOutgoingReliableStream();
+ stream = session_->CreateOutgoingDataStream();
EXPECT_TRUE(stream);
}
TEST_F(ToolsQuicClientSessionTest, GoAwayReceived) {
- if (!Aes128Gcm12Encrypter::IsSupported()) {
- LOG(INFO) << "AES GCM not supported. Test skipped.";
- return;
- }
-
CompleteCryptoHandshake();
// After receiving a GoAway, I should no longer be able to create outgoing
// streams.
session_->OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away."));
- EXPECT_EQ(NULL, session_->CreateOutgoingReliableStream());
+ EXPECT_EQ(NULL, session_->CreateOutgoingDataStream());
}
} // namespace
diff --git a/chromium/net/tools/quic/quic_default_packet_writer.cc b/chromium/net/tools/quic/quic_default_packet_writer.cc
new file mode 100644
index 00000000000..9d3e30831c1
--- /dev/null
+++ b/chromium/net/tools/quic/quic_default_packet_writer.cc
@@ -0,0 +1,30 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/quic_default_packet_writer.h"
+
+#include "net/tools/quic/quic_socket_utils.h"
+
+namespace net {
+namespace tools {
+
+QuicDefaultPacketWriter::QuicDefaultPacketWriter(int fd) : fd_(fd) {}
+
+QuicDefaultPacketWriter::~QuicDefaultPacketWriter() {}
+
+WriteResult QuicDefaultPacketWriter::WritePacket(
+ const char* buffer, size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) {
+ return QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
+ self_address, peer_address);
+}
+
+bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
+ return false;
+}
+
+} // 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
new file mode 100644
index 00000000000..20f5fb0db61
--- /dev/null
+++ b/chromium/net/tools/quic/quic_default_packet_writer.h
@@ -0,0 +1,40 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_
+#define NET_TOOLS_QUIC_QUIC_DEFAULT_PACKET_WRITER_H_
+
+#include "base/basictypes.h"
+#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_packet_writer.h"
+
+namespace net {
+
+class QuicBlockedWriterInterface;
+struct WriteResult;
+
+namespace tools {
+
+// Default packet writer which wraps QuicSocketUtils WritePacket.
+class QuicDefaultPacketWriter : public QuicPacketWriter {
+ public:
+ explicit QuicDefaultPacketWriter(int fd);
+ virtual ~QuicDefaultPacketWriter();
+
+ // QuicPacketWriter
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE;
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE;
+
+ private:
+ int fd_;
+};
+
+} // 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 5253764fb20..297234d9755 100644
--- a/chromium/net/tools/quic/quic_dispatcher.cc
+++ b/chromium/net/tools/quic/quic_dispatcher.cc
@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_utils.h"
+#include "net/tools/quic/quic_default_packet_writer.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_socket_utils.h"
@@ -36,16 +37,20 @@ class DeleteSessionsAlarm : public EpollAlarm {
QuicDispatcher::QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
+ const QuicVersionVector& supported_versions,
int fd,
EpollServer* epoll_server)
: config_(config),
crypto_config_(crypto_config),
time_wait_list_manager_(
- new QuicTimeWaitListManager(this, epoll_server)),
+ new QuicTimeWaitListManager(this, epoll_server, supported_versions)),
delete_sessions_alarm_(new DeleteSessionsAlarm(this)),
epoll_server_(epoll_server),
fd_(fd),
- write_blocked_(false) {
+ write_blocked_(false),
+ helper_(new QuicEpollConnectionHelper(epoll_server_)),
+ writer_(new QuicDefaultPacketWriter(fd)),
+ supported_versions_(supported_versions) {
}
QuicDispatcher::~QuicDispatcher() {
@@ -53,32 +58,39 @@ QuicDispatcher::~QuicDispatcher() {
STLDeleteElements(&closed_session_list_);
}
-int QuicDispatcher::WritePacket(const char* buffer, size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address,
- QuicBlockedWriterInterface* writer,
- int* error) {
+void QuicDispatcher::set_fd(int fd) {
+ fd_ = fd;
+ writer_.reset(new QuicDefaultPacketWriter(fd));
+}
+
+WriteResult QuicDispatcher::WritePacket(const char* buffer, size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* writer) {
if (write_blocked_) {
write_blocked_list_.insert(make_pair(writer, true));
- *error = EAGAIN;
- return -1;
+ return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
}
- int rc = QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
- self_address, peer_address,
- error);
- if (rc == -1 && (*error == EWOULDBLOCK || *error == EAGAIN)) {
+ WriteResult result =
+ writer_->WritePacket(buffer, buf_len, self_address, peer_address, writer);
+ if (result.status == WRITE_STATUS_BLOCKED) {
write_blocked_list_.insert(make_pair(writer, true));
write_blocked_ = true;
}
- return rc;
+ return result;
+}
+
+bool QuicDispatcher::IsWriteBlockedDataBuffered() const {
+ return writer_->IsWriteBlockedDataBuffered();
}
void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
QuicGuid guid,
+ bool has_version_flag,
const QuicEncryptedPacket& packet) {
- QuicSession* session;
+ QuicSession* session = NULL;
SessionMap::iterator it = session_map_.find(guid);
if (it == session_map_.end()) {
@@ -89,13 +101,22 @@ void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
packet);
return;
}
- session = CreateQuicSession(guid, client_address, fd_, epoll_server_);
+
+ // Ensure the packet has a version negotiation bit set before creating a new
+ // session for it. All initial packets for a new connection are required to
+ // have the flag set. Otherwise it may be a stray packet.
+ if (has_version_flag) {
+ session = CreateQuicSession(guid, server_address, client_address);
+ }
if (session == NULL) {
DLOG(INFO) << "Failed to create session for " << guid;
- // Add this guid fo the time-wait state, to safely nack future packets.
+ // Add this guid fo the time-wait state, to safely reject future packets.
// We don't know the version here, so assume latest.
- time_wait_list_manager_->AddGuidToTimeWait(guid, QuicVersionMax());
+ // TODO(ianswett): Produce a no-version version negotiation packet.
+ time_wait_list_manager_->AddGuidToTimeWait(guid,
+ supported_versions_.front(),
+ NULL);
time_wait_list_manager_->ProcessPacket(server_address,
client_address,
guid,
@@ -113,10 +134,13 @@ void QuicDispatcher::ProcessPacket(const IPEndPoint& server_address,
}
void QuicDispatcher::CleanUpSession(SessionMap::iterator it) {
- QuicSession* session = it->second;
- write_blocked_list_.erase(session->connection());
+ QuicConnection* connection = it->second->connection();
+ QuicEncryptedPacket* connection_close_packet =
+ connection->ReleaseConnectionClosePacket();
+ write_blocked_list_.erase(connection);
time_wait_list_manager_->AddGuidToTimeWait(it->first,
- session->connection()->version());
+ connection->version(),
+ connection_close_packet);
session_map_.erase(it);
}
@@ -124,6 +148,10 @@ void QuicDispatcher::DeleteSessions() {
STLDeleteElements(&closed_session_list_);
}
+void QuicDispatcher::UseWriter(QuicPacketWriter* writer) {
+ writer_.reset(writer);
+}
+
bool QuicDispatcher::OnCanWrite() {
// We got an EPOLLOUT: the socket should not be blocked.
write_blocked_ = false;
@@ -164,7 +192,7 @@ void QuicDispatcher::Shutdown() {
DeleteSessions();
}
-void QuicDispatcher::OnConnectionClose(QuicGuid guid, QuicErrorCode error) {
+void QuicDispatcher::OnConnectionClosed(QuicGuid guid, QuicErrorCode error) {
SessionMap::iterator it = session_map_.find(guid);
if (it == session_map_.end()) {
LOG(DFATAL) << "GUID " << guid << " does not exist in the session map. "
@@ -172,7 +200,8 @@ void QuicDispatcher::OnConnectionClose(QuicGuid guid, QuicErrorCode error) {
return;
}
- DLOG_IF(INFO, error != QUIC_NO_ERROR) << "Closing connection due to error: "
+ DLOG_IF(INFO, error != QUIC_NO_ERROR) << "Closing connection (" << guid
+ << ") due to error: "
<< QuicUtils::ErrorToString(error);
if (closed_session_list_.empty()) {
@@ -185,19 +214,14 @@ void QuicDispatcher::OnConnectionClose(QuicGuid guid, QuicErrorCode error) {
QuicSession* QuicDispatcher::CreateQuicSession(
QuicGuid guid,
- const IPEndPoint& client_address,
- int fd,
- EpollServer* epoll_server) {
- QuicConnectionHelperInterface* helper =
- new QuicEpollConnectionHelper(this, epoll_server);
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address) {
QuicServerSession* session = new QuicServerSession(
- config_, new QuicConnection(guid, client_address, helper, true,
- QuicVersionMax()), this);
+ config_, new QuicConnection(guid, client_address, helper_.get(), this,
+ true, supported_versions_), this);
session->InitializeSession(crypto_config_);
return session;
}
} // namespace tools
} // namespace net
-
-
diff --git a/chromium/net/tools/quic/quic_dispatcher.h b/chromium/net/tools/quic/quic_dispatcher.h
index aea76cba7c2..58a4c0c1423 100644
--- a/chromium/net/tools/quic/quic_dispatcher.h
+++ b/chromium/net/tools/quic/quic_dispatcher.h
@@ -11,12 +11,13 @@
#include <list>
#include "base/containers/hash_tables.h"
+#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
#include "net/base/linked_hash_map.h"
#include "net/quic/quic_blocked_writer_interface.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
-#include "net/tools/flip_server/epoll_server.h"
-#include "net/tools/quic/quic_packet_writer.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_server_session.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
@@ -46,29 +47,37 @@ class QuicDispatcherPeer;
} // namespace test
class DeleteSessionsAlarm;
+class QuicEpollConnectionHelper;
+
class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
public:
// Ideally we'd have a linked_hash_set: the boolean is unused.
typedef linked_hash_map<QuicBlockedWriterInterface*, bool> WriteBlockedList;
// Due to the way delete_sessions_closure_ is registered, the Dispatcher
- // must live until epoll_server Shutdown.
+ // must live until epoll_server Shutdown. |supported_versions| specifies the
+ // list of supported QUIC versions.
QuicDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
+ const QuicVersionVector& supported_versions,
int fd,
EpollServer* epoll_server);
virtual ~QuicDispatcher();
// QuicPacketWriter
- virtual int WritePacket(const char* buffer, size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address,
- QuicBlockedWriterInterface* writer,
- int* error) OVERRIDE;
-
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* writer) OVERRIDE;
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE;
+
+ // Process the incoming packet by creating a new session, passing it to
+ // an existing session, or passing it to the TimeWaitListManager.
virtual void ProcessPacket(const IPEndPoint& server_address,
const IPEndPoint& client_address,
QuicGuid guid,
+ bool has_version_flag,
const QuicEncryptedPacket& packet);
// Called when the underyling connection becomes writable to allow
@@ -81,23 +90,27 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
void Shutdown();
// Ensure that the closed connection is cleaned up asynchronously.
- virtual void OnConnectionClose(QuicGuid guid, QuicErrorCode error) OVERRIDE;
+ virtual void OnConnectionClosed(QuicGuid guid, QuicErrorCode error) OVERRIDE;
- void set_fd(int fd) { fd_ = fd; }
+ // Sets the fd and creates a default packet writer with that fd.
+ void set_fd(int fd);
typedef base::hash_map<QuicGuid, QuicSession*> SessionMap;
virtual QuicSession* CreateQuicSession(
QuicGuid guid,
- const IPEndPoint& client_address,
- int fd,
- EpollServer* epoll_server);
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address);
// Deletes all sessions on the closed session list and clears the list.
void DeleteSessions();
const SessionMap& session_map() const { return session_map_; }
+ // Uses the specified |writer| instead of QuicSocketUtils and takes ownership
+ // of writer.
+ void UseWriter(QuicPacketWriter* writer);
+
WriteBlockedList* write_blocked_list() { return &write_blocked_list_; }
protected:
@@ -108,6 +121,13 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
return time_wait_list_manager_.get();
}
+ QuicEpollConnectionHelper* helper() { return helper_.get(); }
+ EpollServer* epoll_server() { return epoll_server_; }
+
+ const QuicVersionVector& supported_versions() const {
+ return supported_versions_;
+ }
+
private:
friend class net::tools::test::QuicDispatcherPeer;
@@ -138,6 +158,18 @@ class QuicDispatcher : public QuicPacketWriter, public QuicSessionOwner {
// False if we have gotten a call to OnCanWrite after the last failed write.
bool write_blocked_;
+ // The helper used for all connections.
+ scoped_ptr<QuicEpollConnectionHelper> helper_;
+
+ // The writer to write to the socket with.
+ scoped_ptr<QuicPacketWriter> 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
+ // skipped as necessary).
+ const QuicVersionVector supported_versions_;
+
DISALLOW_COPY_AND_ASSIGN(QuicDispatcher);
};
diff --git a/chromium/net/tools/quic/quic_dispatcher_test.cc b/chromium/net/tools/quic/quic_dispatcher_test.cc
index 2e2c3097802..74cab69e6a7 100644
--- a/chromium/net/tools/quic/quic_dispatcher_test.cc
+++ b/chromium/net/tools/quic/quic_dispatcher_test.cc
@@ -8,12 +8,13 @@
#include "base/strings/string_piece.h"
#include "net/quic/crypto/crypto_handshake.h"
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_time_wait_list_manager.h"
+#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,19 +34,6 @@ using testing::WithoutArgs;
namespace net {
namespace tools {
namespace test {
-class QuicDispatcherPeer {
- public:
- static void SetTimeWaitListManager(
- QuicDispatcher* dispatcher,
- QuicTimeWaitListManager* time_wait_list_manager) {
- dispatcher->time_wait_list_manager_.reset(time_wait_list_manager);
- }
-
- static void SetWriteBlocked(QuicDispatcher* dispatcher) {
- dispatcher->write_blocked_ = true;
- }
-};
-
namespace {
class TestDispatcher : public QuicDispatcher {
@@ -53,13 +41,13 @@ class TestDispatcher : public QuicDispatcher {
explicit TestDispatcher(const QuicConfig& config,
const QuicCryptoServerConfig& crypto_config,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, 1, eps) {}
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), 1, eps) {
+ }
- MOCK_METHOD4(CreateQuicSession, QuicSession*(
+ MOCK_METHOD3(CreateQuicSession, QuicSession*(
QuicGuid guid,
- const IPEndPoint& client_address,
- int fd,
- EpollServer* eps));
+ const IPEndPoint& server_address,
+ const IPEndPoint& client_address));
using QuicDispatcher::write_blocked_list;
};
@@ -70,16 +58,13 @@ class TestDispatcher : public QuicDispatcher {
class MockServerConnection : public MockConnection {
public:
MockServerConnection(QuicGuid guid,
- IPEndPoint address,
- int fd,
- EpollServer* eps,
QuicDispatcher* dispatcher)
- : MockConnection(guid, address, fd, eps, true),
+ : MockConnection(guid, true),
dispatcher_(dispatcher) {
}
- void UnregisterOnConnectionClose() {
+ void UnregisterOnConnectionClosed() {
LOG(ERROR) << "Unregistering " << guid();
- dispatcher_->OnConnectionClose(guid(), QUIC_NO_ERROR);
+ dispatcher_->OnConnectionClosed(guid(), QUIC_NO_ERROR);
}
private:
QuicDispatcher* dispatcher_;
@@ -88,14 +73,12 @@ class MockServerConnection : public MockConnection {
QuicSession* CreateSession(QuicDispatcher* dispatcher,
QuicGuid guid,
const IPEndPoint& addr,
- MockSession** session,
- EpollServer* eps) {
- MockServerConnection* connection =
- new MockServerConnection(guid, addr, 0, eps, dispatcher);
- *session = new MockSession(connection, true);
+ MockSession** session) {
+ MockServerConnection* connection = new MockServerConnection(guid, dispatcher);
+ *session = new MockSession(connection);
ON_CALL(*connection, SendConnectionClose(_)).WillByDefault(
WithoutArgs(Invoke(
- connection, &MockServerConnection::UnregisterOnConnectionClose)));
+ connection, &MockServerConnection::UnregisterOnConnectionClosed)));
EXPECT_CALL(*reinterpret_cast<MockConnection*>((*session)->connection()),
ProcessUdpPacket(_, addr, _));
@@ -124,21 +107,17 @@ class QuicDispatcherTest : public ::testing::Test {
void ProcessPacket(IPEndPoint addr,
QuicGuid guid,
+ bool has_version_flag,
const string& data) {
- QuicEncryptedPacket packet(data.data(), data.length());
- dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, packet);
+ dispatcher_.ProcessPacket(
+ IPEndPoint(), addr, guid, has_version_flag,
+ QuicEncryptedPacket(data.data(), data.length()));
}
void ValidatePacket(const QuicEncryptedPacket& packet) {
EXPECT_TRUE(packet.AsStringPiece().find(data_) != StringPiece::npos);
}
- IPAddressNumber Loopback4() {
- net::IPAddressNumber addr;
- CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &addr));
- return addr;
- }
-
EpollServer eps_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
@@ -149,34 +128,34 @@ class QuicDispatcherTest : public ::testing::Test {
};
TEST_F(QuicDispatcherTest, ProcessPackets) {
- IPEndPoint addr(Loopback4(), 1);
+ IPEndPoint addr(net::test::Loopback4(), 1);
- EXPECT_CALL(dispatcher_, CreateQuicSession(1, addr, _, &eps_))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(1, _, addr))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 1, addr, &session1_, &eps_)));
- ProcessPacket(addr, 1, "foo");
+ &dispatcher_, 1, addr, &session1_)));
+ ProcessPacket(addr, 1, true, "foo");
- EXPECT_CALL(dispatcher_, CreateQuicSession(2, addr, _, &eps_))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(2, _, addr))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 2, addr, &session2_, &eps_)));
- ProcessPacket(addr, 2, "bar");
+ &dispatcher_, 2, addr, &session2_)));
+ ProcessPacket(addr, 2, true, "bar");
data_ = "eep";
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _)).Times(1).
WillOnce(testing::WithArgs<2>(Invoke(
this, &QuicDispatcherTest::ValidatePacket)));
- ProcessPacket(addr, 1, "eep");
+ ProcessPacket(addr, 1, false, "eep");
}
TEST_F(QuicDispatcherTest, Shutdown) {
- IPEndPoint addr(Loopback4(), 1);
+ IPEndPoint addr(net::test::Loopback4(), 1);
- EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 1, addr, &session1_, &eps_)));
+ &dispatcher_, 1, addr, &session1_)));
- ProcessPacket(addr, 1, "foo");
+ ProcessPacket(addr, 1, true, "foo");
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
SendConnectionClose(QUIC_PEER_GOING_AWAY));
@@ -188,7 +167,7 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
public:
MockTimeWaitListManager(QuicPacketWriter* writer,
EpollServer* eps)
- : QuicTimeWaitListManager(writer, eps) {
+ : QuicTimeWaitListManager(writer, eps, QuicSupportedVersions()) {
}
MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
@@ -199,17 +178,18 @@ class MockTimeWaitListManager : public QuicTimeWaitListManager {
TEST_F(QuicDispatcherTest, TimeWaitListManager) {
MockTimeWaitListManager* time_wait_list_manager =
- new MockTimeWaitListManager(&dispatcher_, &eps_);
+ new MockTimeWaitListManager(
+ QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
// dispatcher takes the ownership of time_wait_list_manager.
QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
time_wait_list_manager);
// Create a new session.
- IPEndPoint addr(Loopback4(), 1);
+ IPEndPoint addr(net::test::Loopback4(), 1);
QuicGuid guid = 1;
- EXPECT_CALL(dispatcher_, CreateQuicSession(guid, addr, _, &eps_))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(guid, _, addr))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, guid, addr, &session1_, &eps_)));
- ProcessPacket(addr, guid, "foo");
+ &dispatcher_, guid, addr, &session1_)));
+ ProcessPacket(addr, guid, true, "foo");
// Close the connection by sending public reset packet.
QuicPublicResetPacket packet;
@@ -220,38 +200,56 @@ TEST_F(QuicDispatcherTest, TimeWaitListManager) {
packet.nonce_proof = 132232;
scoped_ptr<QuicEncryptedPacket> encrypted(
QuicFramer::BuildPublicResetPacket(packet));
- EXPECT_CALL(*session1_, ConnectionClose(QUIC_PUBLIC_RESET, true)).Times(1)
+ EXPECT_CALL(*session1_, OnConnectionClosed(QUIC_PUBLIC_RESET, true)).Times(1)
.WillOnce(WithoutArgs(Invoke(
reinterpret_cast<MockServerConnection*>(session1_->connection()),
- &MockServerConnection::UnregisterOnConnectionClose)));
+ &MockServerConnection::UnregisterOnConnectionClosed)));
EXPECT_CALL(*reinterpret_cast<MockConnection*>(session1_->connection()),
ProcessUdpPacket(_, _, _))
.WillOnce(Invoke(
reinterpret_cast<MockConnection*>(session1_->connection()),
&MockConnection::ReallyProcessUdpPacket));
- dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, *encrypted);
+ dispatcher_.ProcessPacket(IPEndPoint(), addr, guid, true, *encrypted);
EXPECT_TRUE(time_wait_list_manager->IsGuidInTimeWait(guid));
// Dispatcher forwards subsequent packets for this guid to the time wait list
// manager.
EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
- ProcessPacket(addr, guid, "foo");
+ ProcessPacket(addr, guid, true, "foo");
+}
+
+TEST_F(QuicDispatcherTest, StrayPacketToTimeWaitListManager) {
+ MockTimeWaitListManager* time_wait_list_manager =
+ new MockTimeWaitListManager(
+ QuicDispatcherPeer::GetWriter(&dispatcher_), &eps_);
+ // dispatcher takes the ownership of time_wait_list_manager.
+ QuicDispatcherPeer::SetTimeWaitListManager(&dispatcher_,
+ time_wait_list_manager);
+
+ IPEndPoint addr(net::test::Loopback4(), 1);
+ QuicGuid guid = 1;
+ // Dispatcher forwards all packets for this guid to the time wait list
+ // manager.
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, _)).Times(0);
+ EXPECT_CALL(*time_wait_list_manager, ProcessPacket(_, _, guid, _)).Times(1);
+ string data = "foo";
+ ProcessPacket(addr, guid, false, "foo");
}
class QuicWriteBlockedListTest : public QuicDispatcherTest {
public:
virtual void SetUp() {
- IPEndPoint addr(Loopback4(), 1);
+ IPEndPoint addr(net::test::Loopback4(), 1);
- EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 1, addr, &session1_, &eps_)));
- ProcessPacket(addr, 1, "foo");
+ &dispatcher_, 1, addr, &session1_)));
+ ProcessPacket(addr, 1, true, "foo");
- EXPECT_CALL(dispatcher_, CreateQuicSession(_, addr, _, &eps_))
+ EXPECT_CALL(dispatcher_, CreateQuicSession(_, _, addr))
.WillOnce(testing::Return(CreateSession(
- &dispatcher_, 2, addr, &session2_, &eps_)));
- ProcessPacket(addr, 2, "bar");
+ &dispatcher_, 2, addr, &session2_)));
+ ProcessPacket(addr, 2, true, "bar");
blocked_list_ = dispatcher_.write_blocked_list();
}
@@ -384,7 +382,6 @@ TEST_F(QuicWriteBlockedListTest, TestWriteLimits) {
dispatcher_.OnCanWrite();
}
-
} // namespace
} // namespace test
} // namespace tools
diff --git a/chromium/net/tools/quic/quic_epoll_clock.cc b/chromium/net/tools/quic/quic_epoll_clock.cc
index 2a3abf1f1f5..450afb8c524 100644
--- a/chromium/net/tools/quic/quic_epoll_clock.cc
+++ b/chromium/net/tools/quic/quic_epoll_clock.cc
@@ -4,7 +4,7 @@
#include "net/tools/quic/quic_epoll_clock.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
namespace net {
namespace tools {
diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.cc b/chromium/net/tools/quic/quic_epoll_connection_helper.cc
index 4db1d4cd426..78bfe979405 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper.cc
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper.cc
@@ -11,7 +11,7 @@
#include "base/stl_util.h"
#include "net/base/ip_endpoint.h"
#include "net/quic/crypto/quic_random.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_socket_utils.h"
namespace net {
@@ -62,22 +62,8 @@ class QuicEpollAlarm : public QuicAlarm {
} // namespace
-QuicEpollConnectionHelper::QuicEpollConnectionHelper(
- int fd, EpollServer* epoll_server)
- : writer_(NULL),
- epoll_server_(epoll_server),
- fd_(fd),
- connection_(NULL),
- clock_(epoll_server),
- random_generator_(QuicRandom::GetInstance()) {
-}
-
-QuicEpollConnectionHelper::QuicEpollConnectionHelper(QuicPacketWriter* writer,
- EpollServer* epoll_server)
- : writer_(writer),
- epoll_server_(epoll_server),
- fd_(-1),
- connection_(NULL),
+QuicEpollConnectionHelper::QuicEpollConnectionHelper(EpollServer* epoll_server)
+ : epoll_server_(epoll_server),
clock_(epoll_server),
random_generator_(QuicRandom::GetInstance()) {
}
@@ -85,11 +71,6 @@ QuicEpollConnectionHelper::QuicEpollConnectionHelper(QuicPacketWriter* writer,
QuicEpollConnectionHelper::~QuicEpollConnectionHelper() {
}
-void QuicEpollConnectionHelper::SetConnection(QuicConnection* connection) {
- DCHECK(!connection_);
- connection_ = connection;
-}
-
const QuicClock* QuicEpollConnectionHelper::GetClock() const {
return &clock_;
}
@@ -98,39 +79,6 @@ QuicRandom* QuicEpollConnectionHelper::GetRandomGenerator() {
return random_generator_;
}
-int QuicEpollConnectionHelper::WritePacketToWire(
- const QuicEncryptedPacket& packet,
- int* error) {
- if (connection_->ShouldSimulateLostPacket()) {
- DLOG(INFO) << "Dropping packet due to fake packet loss.";
- *error = 0;
- return packet.length();
- }
-
- // If we have a writer, delgate the write to it.
- if (writer_) {
- return writer_->WritePacket(packet.data(), packet.length(),
- connection_->self_address().address(),
- connection_->peer_address(),
- connection_,
- error);
- } else {
- return QuicSocketUtils::WritePacket(
- fd_, packet.data(), packet.length(),
- connection_->self_address().address(),
- connection_->peer_address(),
- error);
- }
-}
-
-bool QuicEpollConnectionHelper::IsWriteBlockedDataBuffered() {
- return false;
-}
-
-bool QuicEpollConnectionHelper::IsWriteBlocked(int error) {
- return error == EAGAIN || error == EWOULDBLOCK;
-}
-
QuicAlarm* QuicEpollConnectionHelper::CreateAlarm(
QuicAlarm::Delegate* delegate) {
return new QuicEpollAlarm(epoll_server_, delegate);
diff --git a/chromium/net/tools/quic/quic_epoll_connection_helper.h b/chromium/net/tools/quic/quic_epoll_connection_helper.h
index 5bd526f8469..3198a144b59 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper.h
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper.h
@@ -12,10 +12,11 @@
#include <set>
#include "net/quic/quic_connection.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_time.h"
+#include "net/tools/quic/quic_default_packet_writer.h"
#include "net/tools/quic/quic_epoll_clock.h"
-#include "net/tools/quic/quic_packet_writer.h"
namespace net {
@@ -29,37 +30,23 @@ class RetransmissionAlarm;
class SendAlarm;
class TimeoutAlarm;
-namespace test {
-class QuicEpollConnectionHelperPeer;
-} // namespace test
-
class QuicEpollConnectionHelper : public QuicConnectionHelperInterface {
public:
- QuicEpollConnectionHelper(int fd, EpollServer* eps);
- QuicEpollConnectionHelper(QuicPacketWriter* writer, EpollServer* eps);
+ explicit QuicEpollConnectionHelper(EpollServer* eps);
virtual ~QuicEpollConnectionHelper();
// QuicEpollConnectionHelperInterface
- virtual void SetConnection(QuicConnection* connection) OVERRIDE;
virtual const QuicClock* GetClock() const OVERRIDE;
virtual QuicRandom* GetRandomGenerator() OVERRIDE;
- virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
- int* error) OVERRIDE;
- virtual bool IsWriteBlockedDataBuffered() OVERRIDE;
- virtual bool IsWriteBlocked(int error) OVERRIDE;
virtual QuicAlarm* CreateAlarm(QuicAlarm::Delegate* delegate) OVERRIDE;
EpollServer* epoll_server() { return epoll_server_; }
private:
friend class QuicConnectionPeer;
- friend class net::tools::test::QuicEpollConnectionHelperPeer;
- QuicPacketWriter* writer_; // Not owned
EpollServer* epoll_server_; // Not owned.
- int fd_;
- QuicConnection* connection_;
const QuicEpollClock clock_;
QuicRandom* random_generator_;
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 636d98f7ee5..0f977f4fb30 100644
--- a/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
+++ b/chromium/net/tools/quic/quic_epoll_connection_helper_test.cc
@@ -4,223 +4,103 @@
#include "net/tools/quic/quic_epoll_connection_helper.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_random.h"
-#include "net/quic/quic_connection.h"
-#include "net/quic/quic_framer.h"
-#include "net/quic/test_tools/quic_connection_peer.h"
-#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/quic/test_tools/mock_epoll_server.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using net::test::FramerVisitorCapturingFrames;
-using net::test::MockSendAlgorithm;
-using net::test::QuicConnectionPeer;
-using net::test::MockConnectionVisitor;
using net::tools::test::MockEpollServer;
-using testing::_;
-using testing::AnyNumber;
-using testing::Return;
namespace net {
namespace tools {
namespace test {
namespace {
-const char data1[] = "foo";
-const bool kFromPeer = true;
-
-class TestConnectionHelper : public QuicEpollConnectionHelper {
+class TestDelegate : public QuicAlarm::Delegate {
public:
- TestConnectionHelper(int fd, EpollServer* eps)
- : QuicEpollConnectionHelper(fd, eps) {
- }
+ TestDelegate() : fired_(false) {}
- virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
- int* error) OVERRIDE {
- QuicFramer framer(QuicVersionMax(), QuicTime::Zero(), true);
- FramerVisitorCapturingFrames visitor;
- framer.set_visitor(&visitor);
- EXPECT_TRUE(framer.ProcessPacket(packet));
- header_ = *visitor.header();
- *error = 0;
- return packet.length();
+ virtual QuicTime OnAlarm() OVERRIDE {
+ fired_ = true;
+ return QuicTime::Zero();
}
- QuicPacketHeader* header() { return &header_; }
+ bool fired() const { return fired_; }
private:
- QuicPacketHeader header_;
-};
-
-class TestConnection : public QuicConnection {
- public:
- TestConnection(QuicGuid guid,
- IPEndPoint address,
- TestConnectionHelper* helper)
- : QuicConnection(guid, address, helper, false, QuicVersionMax()) {
- }
-
- void SendAck() {
- QuicConnectionPeer::SendAck(this);
- }
-
- void SetSendAlgorithm(SendAlgorithmInterface* send_algorithm) {
- QuicConnectionPeer::SetSendAlgorithm(this, send_algorithm);
- }
-
- using QuicConnection::SendOrQueuePacket;
+ bool fired_;
};
class QuicEpollConnectionHelperTest : public ::testing::Test {
protected:
- QuicEpollConnectionHelperTest()
- : guid_(42),
- framer_(QuicVersionMax(), QuicTime::Zero(), false),
- send_algorithm_(new testing::StrictMock<MockSendAlgorithm>),
- helper_(new TestConnectionHelper(0, &epoll_server_)),
- connection_(guid_, IPEndPoint(), helper_),
- frame1_(1, false, 0, data1) {
- connection_.set_visitor(&visitor_);
- connection_.SetSendAlgorithm(send_algorithm_);
- epoll_server_.set_timeout_in_us(-1);
- EXPECT_CALL(*send_algorithm_, TimeUntilSend(_, _, _, _)).
- WillRepeatedly(Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(*send_algorithm_, BandwidthEstimate()).WillRepeatedly(Return(
- QuicBandwidth::FromKBitsPerSecond(100)));
- EXPECT_CALL(*send_algorithm_, SmoothedRtt()).WillRepeatedly(Return(
- QuicTime::Delta::FromMilliseconds(100)));
- ON_CALL(*send_algorithm_, SentPacket(_, _, _, _, _))
- .WillByDefault(Return(true));
- }
+ QuicEpollConnectionHelperTest() : helper_(&epoll_server_) {}
- QuicPacket* ConstructDataPacket(QuicPacketSequenceNumber number,
- QuicFecGroupNumber fec_group) {
- header_.public_header.version_flag = false;
- header_.public_header.reset_flag = false;
- header_.fec_flag = false;
- header_.entropy_flag = false;
- header_.packet_sequence_number = number;
- header_.is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
- header_.fec_group = fec_group;
-
- QuicFrames frames;
- QuicFrame frame(&frame1_);
- frames.push_back(frame);
- return framer_.BuildUnsizedDataPacket(header_, frames).packet;
- }
+ MockEpollServer epoll_server_;
+ QuicEpollConnectionHelper helper_;
+};
- QuicGuid guid_;
- QuicFramer framer_;
+TEST_F(QuicEpollConnectionHelperTest, GetClock) {
+ const QuicClock* clock = helper_.GetClock();
+ QuicTime start = clock->Now();
- MockEpollServer epoll_server_;
- testing::StrictMock<MockSendAlgorithm>* send_algorithm_;
- TestConnectionHelper* helper_;
- TestConnection connection_;
- testing::StrictMock<MockConnectionVisitor> visitor_;
+ QuicTime::Delta delta = QuicTime::Delta::FromMilliseconds(5);
+ epoll_server_.AdvanceBy(delta.ToMicroseconds());
- QuicPacketHeader header_;
- QuicStreamFrame frame1_;
-};
+ EXPECT_EQ(start.Add(delta), clock->Now());
+}
-TEST_F(QuicEpollConnectionHelperTest, DISABLED_TestRetransmission) {
- //FLAGS_fake_packet_loss_percentage = 100;
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
- const int64 kDefaultRetransmissionTimeMs = 500;
-
- const char buffer[] = "foo";
- const size_t packet_size =
- QuicPacketCreator::StreamFramePacketOverhead(
- framer_.version(), PACKET_8BYTE_GUID, kIncludeVersion,
- PACKET_1BYTE_SEQUENCE_NUMBER, NOT_IN_FEC_GROUP) +
- arraysize(buffer) - 1;
-
- EXPECT_CALL(*send_algorithm_,
- SentPacket(_, 1, packet_size, NOT_RETRANSMISSION, _));
- EXPECT_CALL(*send_algorithm_, AbandoningPacket(1, packet_size));
- struct iovec iov = {const_cast<char*>(buffer),
- static_cast<size_t>(3)};
- connection_.SendvStreamData(1, &iov, 1, 0, false);
- EXPECT_EQ(1u, helper_->header()->packet_sequence_number);
- EXPECT_CALL(*send_algorithm_,
- SentPacket(_, 2, packet_size, IS_RETRANSMISSION, _));
- epoll_server_.AdvanceByAndCallCallbacks(kDefaultRetransmissionTimeMs * 1000);
-
- EXPECT_EQ(2u, helper_->header()->packet_sequence_number);
+TEST_F(QuicEpollConnectionHelperTest, GetRandomGenerator) {
+ QuicRandom* random = helper_.GetRandomGenerator();
+ EXPECT_EQ(QuicRandom::GetInstance(), random);
}
-TEST_F(QuicEpollConnectionHelperTest, InitialTimeout) {
- EXPECT_TRUE(connection_.connected());
-
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA));
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillOnce(
- Return(QuicTime::Delta::FromMicroseconds(1)));
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, !kFromPeer));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
- EXPECT_FALSE(connection_.connected());
- EXPECT_EQ(kDefaultInitialTimeoutSecs * 1000000, epoll_server_.NowInUsec());
+TEST_F(QuicEpollConnectionHelperTest, CreateAlarm) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+
+ const QuicClock* clock = helper_.GetClock();
+ QuicTime start = clock->Now();
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(start.Add(delta));
+
+ epoll_server_.AdvanceByAndCallCallbacks(delta.ToMicroseconds());
+ EXPECT_EQ(start.Add(delta), clock->Now());
}
-TEST_F(QuicEpollConnectionHelperTest, TimeoutAfterSend) {
- EXPECT_TRUE(connection_.connected());
- EXPECT_EQ(0, epoll_server_.NowInUsec());
-
- // When we send a packet, the timeout will change to 5000 +
- // kDefaultInitialTimeoutSecs.
- epoll_server_.AdvanceBy(5000);
- EXPECT_EQ(5000, epoll_server_.NowInUsec());
-
- // Send an ack so we don't set the retransmission alarm.
- EXPECT_CALL(*send_algorithm_,
- SentPacket(_, 1, _, NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA));
- connection_.SendAck();
-
- // The original alarm will fire. We should not time out because we had a
- // network event at t=5000. The alarm will reregister.
- epoll_server_.WaitForEventsAndExecuteCallbacks();
- EXPECT_EQ(kDefaultInitialTimeoutSecs * 1000000, epoll_server_.NowInUsec());
-
- // This time, we should time out.
- EXPECT_CALL(visitor_, ConnectionClose(QUIC_CONNECTION_TIMED_OUT, !kFromPeer));
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 2, _, NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA));
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillOnce(
- Return(QuicTime::Delta::FromMicroseconds(1)));
- epoll_server_.WaitForEventsAndExecuteCallbacks();
- EXPECT_EQ(kDefaultInitialTimeoutSecs * 1000000 + 5000,
- epoll_server_.NowInUsec());
- EXPECT_FALSE(connection_.connected());
+TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndCancel) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+
+ const QuicClock* clock = helper_.GetClock();
+ QuicTime start = clock->Now();
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(start.Add(delta));
+ alarm->Cancel();
+
+ epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
+ EXPECT_EQ(start.Add(delta), clock->Now());
+ EXPECT_FALSE(delegate->fired());
}
-TEST_F(QuicEpollConnectionHelperTest, SendSchedulerDelayThenSend) {
- // Test that if we send a packet with a delay, it ends up queued.
- EXPECT_CALL(*send_algorithm_, RetransmissionDelay()).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
- QuicPacket* packet = ConstructDataPacket(1, 0);
- EXPECT_CALL(
- *send_algorithm_, TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillOnce(
- Return(QuicTime::Delta::FromMicroseconds(1)));
- connection_.SendOrQueuePacket(ENCRYPTION_NONE, 1, packet, 0,
- HAS_RETRANSMITTABLE_DATA,
- QuicConnection::NO_FORCE);
- EXPECT_CALL(*send_algorithm_, SentPacket(_, 1, _, NOT_RETRANSMISSION,
- _));
- EXPECT_EQ(1u, connection_.NumQueuedPackets());
-
- // Advance the clock to fire the alarm, and configure the scheduler
- // to permit the packet to be sent.
- EXPECT_CALL(*send_algorithm_,
- TimeUntilSend(_, NOT_RETRANSMISSION, _, _)).WillRepeatedly(
- Return(QuicTime::Delta::Zero()));
- EXPECT_CALL(visitor_, OnCanWrite()).WillOnce(Return(true));
- EXPECT_CALL(visitor_, HasPendingHandshake()).Times(AnyNumber());
- epoll_server_.AdvanceByAndCallCallbacks(1);
- EXPECT_EQ(0u, connection_.NumQueuedPackets());
+TEST_F(QuicEpollConnectionHelperTest, CreateAlarmAndReset) {
+ TestDelegate* delegate = new TestDelegate();
+ scoped_ptr<QuicAlarm> alarm(helper_.CreateAlarm(delegate));
+
+ const QuicClock* clock = helper_.GetClock();
+ QuicTime start = clock->Now();
+ QuicTime::Delta delta = QuicTime::Delta::FromMicroseconds(1);
+ alarm->Set(clock->Now().Add(delta));
+ alarm->Cancel();
+ QuicTime::Delta new_delta = QuicTime::Delta::FromMicroseconds(3);
+ alarm->Set(clock->Now().Add(new_delta));
+
+ epoll_server_.AdvanceByExactlyAndCallCallbacks(delta.ToMicroseconds());
+ EXPECT_EQ(start.Add(delta), clock->Now());
+ EXPECT_FALSE(delegate->fired());
+
+ epoll_server_.AdvanceByExactlyAndCallCallbacks(
+ new_delta.Subtract(delta).ToMicroseconds());
+ EXPECT_EQ(start.Add(new_delta), clock->Now());
+ EXPECT_TRUE(delegate->fired());
}
} // namespace
diff --git a/chromium/net/tools/quic/quic_in_memory_cache.cc b/chromium/net/tools/quic/quic_in_memory_cache.cc
index 6ed7dd5f832..c7c7cd04ebf 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache.cc
+++ b/chromium/net/tools/quic/quic_in_memory_cache.cc
@@ -7,6 +7,8 @@
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "net/tools/balsa/balsa_headers.h"
using base::FilePath;
using base::StringPiece;
@@ -19,20 +21,17 @@ using std::string;
namespace net {
namespace tools {
-std::string FLAGS_quic_in_memory_cache_dir = "/tmp/quic-data";
+std::string FLAGS_quic_in_memory_cache_dir = "";
namespace {
// BalsaVisitor implementation (glue) which caches response bodies.
-class CachingBalsaVisitor : public BalsaVisitorInterface {
+class CachingBalsaVisitor : public NoOpBalsaVisitor {
public:
CachingBalsaVisitor() : done_framing_(false) {}
virtual void ProcessBodyData(const char* input, size_t size) OVERRIDE {
AppendToBody(input, size);
}
- virtual void ProcessTrailers(const BalsaHeaders& trailer) {
- LOG(DFATAL) << "Trailers not supported.";
- }
virtual void MessageDone() OVERRIDE {
done_framing_ = true;
}
@@ -42,8 +41,6 @@ class CachingBalsaVisitor : public BalsaVisitorInterface {
virtual void HandleHeaderWarning(BalsaFrame* framer) OVERRIDE {
UnhandledError();
}
- virtual void HandleTrailerError(BalsaFrame* framer) { UnhandledError(); }
- virtual void HandleTrailerWarning(BalsaFrame* framer) { UnhandledError(); }
virtual void HandleChunkingError(BalsaFrame* framer) OVERRIDE {
UnhandledError();
}
@@ -53,20 +50,6 @@ class CachingBalsaVisitor : public BalsaVisitorInterface {
void UnhandledError() {
LOG(DFATAL) << "Unhandled error framing HTTP.";
}
- virtual void ProcessBodyInput(const char*, size_t) OVERRIDE {}
- virtual void ProcessHeaderInput(const char*, size_t) OVERRIDE {}
- virtual void ProcessTrailerInput(const char*, size_t) OVERRIDE {}
- virtual void ProcessHeaders(const net::BalsaHeaders&) OVERRIDE {}
- virtual void ProcessRequestFirstLine(
- const char*, size_t, const char*, size_t,
- const char*, size_t, const char*, size_t) OVERRIDE {}
- virtual void ProcessResponseFirstLine(
- const char*, size_t, const char*,
- size_t, const char*, size_t, const char*, size_t) OVERRIDE {}
- virtual void ProcessChunkLength(size_t) OVERRIDE {}
- virtual void ProcessChunkExtensions(const char*, size_t) OVERRIDE {}
- virtual void HeaderDone() OVERRIDE {}
-
void AppendToBody(const char* input, size_t size) {
body_.append(input, size);
}
@@ -80,6 +63,7 @@ class CachingBalsaVisitor : public BalsaVisitorInterface {
} // namespace
+// static
QuicInMemoryCache* QuicInMemoryCache::GetInstance() {
return Singleton<QuicInMemoryCache>::get();
}
@@ -93,12 +77,32 @@ const QuicInMemoryCache::Response* QuicInMemoryCache::GetResponse(
return it->second;
}
+void QuicInMemoryCache::AddSimpleResponse(StringPiece method,
+ StringPiece path,
+ StringPiece version,
+ StringPiece response_code,
+ StringPiece response_detail,
+ StringPiece body) {
+ BalsaHeaders request_headers, response_headers;
+ request_headers.SetRequestFirstlineFromStringPieces(method,
+ path,
+ version);
+ response_headers.SetRequestFirstlineFromStringPieces(version,
+ response_code,
+ response_detail);
+ response_headers.AppendHeader("content-length",
+ base::IntToString(body.length()));
+
+ AddResponse(request_headers, response_headers, body);
+}
+
void QuicInMemoryCache::AddResponse(const BalsaHeaders& request_headers,
const BalsaHeaders& response_headers,
StringPiece response_body) {
LOG(INFO) << "Adding response for: " << GetKey(request_headers);
if (ContainsKey(responses_, GetKey(request_headers))) {
LOG(DFATAL) << "Response for given request already exists!";
+ return;
}
Response* new_response = new Response();
new_response->set_headers(response_headers);
@@ -106,12 +110,12 @@ void QuicInMemoryCache::AddResponse(const BalsaHeaders& request_headers,
responses_[GetKey(request_headers)] = new_response;
}
-void QuicInMemoryCache::ResetForTests() {
- STLDeleteValues(&responses_);
+QuicInMemoryCache::QuicInMemoryCache() {
Initialize();
}
-QuicInMemoryCache::QuicInMemoryCache() {
+void QuicInMemoryCache::ResetForTests() {
+ STLDeleteValues(&responses_);
Initialize();
}
diff --git a/chromium/net/tools/quic/quic_in_memory_cache.h b/chromium/net/tools/quic/quic_in_memory_cache.h
index 6322e2da49d..3be25a6cac1 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache.h
+++ b/chromium/net/tools/quic/quic_in_memory_cache.h
@@ -10,14 +10,19 @@
#include "base/containers/hash_tables.h"
#include "base/memory/singleton.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_frame.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_frame.h"
+#include "net/tools/balsa/balsa_headers.h"
+#include "net/tools/balsa/noop_balsa_visitor.h"
template <typename T> struct DefaultSingletonTraits;
namespace net {
namespace tools {
+namespace test {
+class QuicInMemoryCachePeer;
+} // namespace
+
extern std::string FLAGS_quic_in_memory_cache_dir;
class QuicServer;
@@ -51,6 +56,8 @@ class QuicInMemoryCache {
DISALLOW_COPY_AND_ASSIGN(Response);
};
+
+ // Returns the singleton instance of the cache.
static QuicInMemoryCache* GetInstance();
// Retrieve a response from this cache for a given request.
@@ -58,22 +65,32 @@ class QuicInMemoryCache {
// Currently, responses are selected based on request URI only.
const Response* GetResponse(const BalsaHeaders& request_headers) const;
+ // Adds a simple response to the cache. The response headers will
+ // only contain the "content-length" header with the lenght of |body|.
+ void AddSimpleResponse(base::StringPiece method,
+ base::StringPiece path,
+ base::StringPiece version,
+ base::StringPiece response_code,
+ base::StringPiece response_detail,
+ base::StringPiece body);
+
// Add a response to the cache.
void AddResponse(const BalsaHeaders& request_headers,
const BalsaHeaders& response_headers,
base::StringPiece response_body);
- void ResetForTests();
-
private:
typedef base::hash_map<std::string, Response*> ResponseMap;
-
+ friend struct DefaultSingletonTraits<QuicInMemoryCache>;
+ friend class test::QuicInMemoryCachePeer;
QuicInMemoryCache();
- friend struct DefaultSingletonTraits<QuicInMemoryCache>;
~QuicInMemoryCache();
+ void ResetForTests();
+
void Initialize();
+
std::string GetKey(const BalsaHeaders& response_headers) const;
// Cached responses.
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 065ecc3b437..adcb59917c5 100644
--- a/chromium/net/tools/quic/quic_in_memory_cache_test.cc
+++ b/chromium/net/tools/quic/quic_in_memory_cache_test.cc
@@ -9,8 +9,9 @@
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::IntToString;
@@ -39,7 +40,7 @@ class QuicInMemoryCacheTest : public ::testing::Test {
}
virtual void SetUp() {
- QuicInMemoryCache::GetInstance()->ResetForTests();
+ QuicInMemoryCachePeer::ResetForTests();
}
// This method was copied from end_to_end_test.cc in this directory.
diff --git a/chromium/net/tools/quic/quic_packet_writer.h b/chromium/net/tools/quic/quic_packet_writer.h
deleted file mode 100644
index b10e852d299..00000000000
--- a/chromium/net/tools/quic/quic_packet_writer.h
+++ /dev/null
@@ -1,33 +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_TOOLS_QUIC_QUIC_PACKET_WRITER_H_
-#define NET_TOOLS_QUIC_QUIC_PACKET_WRITER_H_
-
-#include "net/base/ip_endpoint.h"
-
-namespace net {
-
-class QuicBlockedWriterInterface;
-
-namespace tools {
-
-// An interface between writers and the entity managing the
-// socket (in our case the QuicDispatcher). This allows the Dispatcher to
-// control writes, and manage any writers who end up write blocked.
-class QuicPacketWriter {
- public:
- virtual ~QuicPacketWriter() {}
-
- virtual int WritePacket(const char* buffer, size_t buf_len,
- const net::IPAddressNumber& self_address,
- const net::IPEndPoint& peer_address,
- QuicBlockedWriterInterface* blocked_writer,
- int* error) = 0;
-};
-
-} // namespace tools
-} // namespace net
-
-#endif // NET_TOOLS_QUIC_QUIC_PACKET_WRITER_H_
diff --git a/chromium/net/tools/quic/quic_reliable_client_stream.cc b/chromium/net/tools/quic/quic_reliable_client_stream.cc
deleted file mode 100644
index 359fec4dd90..00000000000
--- a/chromium/net/tools/quic/quic_reliable_client_stream.cc
+++ /dev/null
@@ -1,27 +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/tools/quic/quic_reliable_client_stream.h"
-
-using std::string;
-
-namespace net {
-namespace tools {
-
-// Sends body data to the server and returns the number of bytes sent.
-ssize_t QuicReliableClientStream::SendBody(const string& data, bool fin) {
- return WriteData(data, fin).bytes_consumed;
-}
-
-bool QuicReliableClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
- if (!write_side_closed()) {
- DLOG(INFO) << "Got a response before the request was complete. "
- << "Aborting request.";
- CloseWriteSide();
- }
- return ReliableQuicStream::OnStreamFrame(frame);
-}
-
-} // namespace tools
-} // namespace net
diff --git a/chromium/net/tools/quic/quic_reliable_client_stream.h b/chromium/net/tools/quic/quic_reliable_client_stream.h
deleted file mode 100644
index 10b60c2f696..00000000000
--- a/chromium/net/tools/quic/quic_reliable_client_stream.h
+++ /dev/null
@@ -1,66 +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_TOOLS_QUIC_QUIC_RELIABLE_CLIENT_STREAM_H_
-#define NET_TOOLS_QUIC_QUIC_RELIABLE_CLIENT_STREAM_H_
-
-#include <sys/types.h>
-#include <string>
-
-#include "base/strings/string_piece.h"
-#include "net/quic/quic_protocol.h"
-#include "net/quic/reliable_quic_stream.h"
-#include "net/tools/flip_server/balsa_frame.h"
-#include "net/tools/flip_server/balsa_headers.h"
-
-namespace net {
-
-class QuicSession;
-
-namespace tools {
-
-class QuicClientSession;
-
-// A base class for spdy/http client streams which handles the concept
-// of sending and receiving headers and bodies.
-class QuicReliableClientStream : public ReliableQuicStream {
- public:
- QuicReliableClientStream(QuicStreamId id, QuicSession* session)
- : ReliableQuicStream(id, session) {
- }
-
- // Serializes the headers and body, sends it to the server, and
- // returns the number of bytes sent.
- virtual ssize_t SendRequest(const BalsaHeaders& headers,
- base::StringPiece body,
- bool fin) = 0;
- // Sends body data to the server and returns the number of bytes sent.
- virtual ssize_t SendBody(const std::string& data, bool fin);
-
- // Override the base class to close the Write side as soon as we get a
- // response.
- // SPDY/HTTP do not support bidirectional streaming.
- virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
-
- // Returns the response data.
- const std::string& data() { return data_; }
-
- // Returns whatever headers have been received for this stream.
- const BalsaHeaders& headers() { return headers_; }
-
- protected:
- std::string* mutable_data() { return &data_; }
- BalsaHeaders* mutable_headers() { return &headers_; }
-
- private:
- BalsaHeaders headers_;
- std::string data_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicReliableClientStream);
-};
-
-} // namespace tools
-} // namespace net
-
-#endif // NET_TOOLS_QUIC_QUIC_RELIABLE_CLIENT_STREAM_H_
diff --git a/chromium/net/tools/quic/quic_reliable_server_stream.cc b/chromium/net/tools/quic/quic_reliable_server_stream.cc
deleted file mode 100644
index 58b884a1082..00000000000
--- a/chromium/net/tools/quic/quic_reliable_server_stream.cc
+++ /dev/null
@@ -1,56 +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/tools/quic/quic_reliable_server_stream.h"
-
-#include "base/logging.h"
-#include "base/memory/singleton.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
-
-using base::StringPiece;
-
-namespace net {
-namespace tools {
-
-QuicReliableServerStream::QuicReliableServerStream(QuicStreamId id,
- QuicSession* session)
- : ReliableQuicStream(id, session) {
-}
-
-
-void QuicReliableServerStream::SendResponse() {
- // Find response in cache. If not found, send error response.
- const QuicInMemoryCache::Response* response =
- QuicInMemoryCache::GetInstance()->GetResponse(headers_);
- if (response == NULL) {
- SendErrorResponse();
- return;
- }
-
- DLOG(INFO) << "Sending response for stream " << id();
- SendHeaders(response->headers());
- WriteData(response->body(), true);
-}
-
-void QuicReliableServerStream::SendErrorResponse() {
- DLOG(INFO) << "Sending error response for stream " << id();
- BalsaHeaders headers;
- headers.SetResponseFirstlineFromStringPieces(
- "HTTP/1.1", "500", "Server Error");
- headers.ReplaceOrAppendHeader("content-length", "3");
- SendHeaders(headers);
- WriteData("bad", true);
-}
-
-QuicConsumedData QuicReliableServerStream::WriteData(StringPiece data,
- bool fin) {
- // We only support SPDY and HTTP, and neither handles bidirectional streaming.
- if (!read_side_closed()) {
- CloseReadSide();
- }
- return ReliableQuicStream::WriteData(data, fin);
-}
-
-} // namespace tools
-} // namespace net
diff --git a/chromium/net/tools/quic/quic_reliable_server_stream.h b/chromium/net/tools/quic/quic_reliable_server_stream.h
deleted file mode 100644
index 2669f42649c..00000000000
--- a/chromium/net/tools/quic/quic_reliable_server_stream.h
+++ /dev/null
@@ -1,65 +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_TOOLS_QUIC_QUIC_RELIABLE_SERVER_STREAM_H_
-#define NET_TOOLS_QUIC_QUIC_RELIABLE_SERVER_STREAM_H_
-
-#include <string>
-
-#include "net/quic/quic_protocol.h"
-#include "net/quic/reliable_quic_stream.h"
-#include "net/tools/flip_server/balsa_headers.h"
-
-namespace net {
-
-class QuicSession;
-
-namespace tools {
-
-namespace test {
-class QuicReliableServerStreamPeer;
-} // namespace test
-
-// A base class for spdy/http server streams which handles the concept
-// of sending and receiving headers and bodies.
-class QuicReliableServerStream : public ReliableQuicStream {
- public:
- QuicReliableServerStream(QuicStreamId id, QuicSession* session);
- virtual ~QuicReliableServerStream() {}
-
- // Subclasses should process and frame data when this is called, returning
- // how many bytes are processed.
- virtual uint32 ProcessData(const char* data, uint32 data_len) = 0;
- // Subclasses should implement this to serialize headers in a
- // protocol-specific manner, and send it out to the client.
- virtual void SendHeaders(const BalsaHeaders& response_headers) = 0;
-
- // Sends a basic 200 response using SendHeaders for the headers and WriteData
- // for the body.
- void SendResponse();
- // Sends a basic 500 response using SendHeaders for the headers and WriteData
- // for the body
- void SendErrorResponse();
- // Make sure that as soon as we start writing data, we stop reading.
- virtual QuicConsumedData WriteData(base::StringPiece data, bool fin) OVERRIDE;
-
- // Returns whatever headers have been received for this stream.
- const BalsaHeaders& headers() { return headers_; }
-
- const string& body() { return body_; }
- protected:
- BalsaHeaders* mutable_headers() { return &headers_; }
- string* mutable_body() { return &body_; }
-
- private:
- friend class test::QuicReliableServerStreamPeer;
-
- BalsaHeaders headers_;
- string body_;
-};
-
-} // namespace tools
-} // namespace net
-
-#endif // NET_TOOLS_QUIC_QUIC_RELIABLE_SERVER_STREAM_H_
diff --git a/chromium/net/tools/quic/quic_reliable_server_stream_test.cc b/chromium/net/tools/quic/quic_reliable_server_stream_test.cc
deleted file mode 100644
index 53533a35cb1..00000000000
--- a/chromium/net/tools/quic/quic_reliable_server_stream_test.cc
+++ /dev/null
@@ -1,228 +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/tools/quic/quic_reliable_server_stream.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "net/quic/quic_spdy_compressor.h"
-#include "net/quic/quic_utils.h"
-#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/tools/flip_server/epoll_server.h"
-#include "net/tools/quic/quic_in_memory_cache.h"
-#include "net/tools/quic/quic_spdy_server_stream.h"
-#include "net/tools/quic/spdy_utils.h"
-#include "net/tools/quic/test_tools/quic_test_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::StringPiece;
-using net::tools::test::MockConnection;
-using net::test::MockSession;
-using std::string;
-using testing::_;
-using testing::AnyNumber;
-using testing::Invoke;
-using testing::InvokeArgument;
-using testing::InSequence;
-using testing::Return;
-using testing::StrEq;
-using testing::StrictMock;
-using testing::WithArgs;
-
-namespace net {
-namespace tools {
-namespace test {
-
-class QuicReliableServerStreamPeer {
- public:
- static BalsaHeaders* GetMutableHeaders(
- QuicReliableServerStream* stream) {
- return &(stream->headers_);
- }
-};
-
-namespace {
-
-class QuicReliableServerStreamTest : public ::testing::Test {
- public:
- QuicReliableServerStreamTest()
- : session_(new MockConnection(1, IPEndPoint(), 0, &eps_, true), true),
- body_("hello world") {
- BalsaHeaders request_headers;
- request_headers.SetRequestFirstlineFromStringPieces(
- "POST", "https://www.google.com/", "HTTP/1.1");
- request_headers.ReplaceOrAppendHeader("content-length", "11");
-
- headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers);
- stream_.reset(new QuicSpdyServerStream(3, &session_));
- }
-
- QuicConsumedData ValidateHeaders(const struct iovec* iov) {
- StringPiece headers =
- StringPiece(static_cast<const char*>(iov[0].iov_base), iov[0].iov_len);
- headers_string_ = SpdyUtils::SerializeResponseHeaders(
- response_headers_);
- QuicSpdyDecompressor decompressor;
- TestDecompressorVisitor visitor;
-
- // First the header id, then the compressed data.
- EXPECT_EQ(1, headers[0]);
- EXPECT_EQ(0, headers[1]);
- EXPECT_EQ(0, headers[2]);
- EXPECT_EQ(0, headers[3]);
- EXPECT_EQ(static_cast<size_t>(headers.length() - 4),
- decompressor.DecompressData(headers.substr(4), &visitor));
-
- EXPECT_EQ(headers_string_, visitor.data());
-
- return QuicConsumedData(headers.size(), false);
- }
-
- static void SetUpTestCase() {
- QuicInMemoryCache::GetInstance()->ResetForTests();
- }
-
- virtual void SetUp() {
- QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
-
- BalsaHeaders request_headers, response_headers;
- StringPiece body("Yum");
- request_headers.SetRequestFirstlineFromStringPieces(
- "GET",
- "https://www.google.com/foo",
- "HTTP/1.1");
- response_headers.SetRequestFirstlineFromStringPieces("HTTP/1.1",
- "200",
- "OK");
- response_headers.AppendHeader("content-length",
- base::IntToString(body.length()));
-
- // Check if response already exists and matches.
- const QuicInMemoryCache::Response* cached_response =
- cache->GetResponse(request_headers);
- if (cached_response != NULL) {
- string cached_response_headers_str, response_headers_str;
- cached_response->headers().DumpToString(&cached_response_headers_str);
- response_headers.DumpToString(&response_headers_str);
- CHECK_EQ(cached_response_headers_str, response_headers_str);
- CHECK_EQ(cached_response->body(), body);
- return;
- }
-
- cache->AddResponse(request_headers, response_headers, body);
- }
-
- BalsaHeaders response_headers_;
- EpollServer eps_;
- StrictMock<MockSession> session_;
- scoped_ptr<QuicReliableServerStream> stream_;
- string headers_string_;
- string body_;
-};
-
-QuicConsumedData ConsumeAllData(QuicStreamId id,
- const struct iovec* iov,
- int iov_count,
- QuicStreamOffset offset,
- bool fin) {
- ssize_t consumed_length = 0;
- for (int i = 0; i < iov_count; ++i) {
- consumed_length += iov[i].iov_len;
- }
- return QuicConsumedData(consumed_length, fin);
-}
-
-TEST_F(QuicReliableServerStreamTest, TestFraming) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(AnyNumber()).
- WillRepeatedly(Invoke(ConsumeAllData));
-
- EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
- headers_string_.c_str(), headers_string_.size()));
- EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size()));
- EXPECT_EQ(11u, stream_->headers().content_length());
- EXPECT_EQ("https://www.google.com/", stream_->headers().request_uri());
- EXPECT_EQ("POST", stream_->headers().request_method());
- EXPECT_EQ(body_, stream_->body());
-}
-
-TEST_F(QuicReliableServerStreamTest, TestFramingOnePacket) {
- EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(AnyNumber()).
- WillRepeatedly(Invoke(ConsumeAllData));
-
- string message = headers_string_ + body_;
-
- EXPECT_EQ(message.size(), stream_->ProcessData(
- message.c_str(), message.size()));
- EXPECT_EQ(11u, stream_->headers().content_length());
- EXPECT_EQ("https://www.google.com/",
- stream_->headers().request_uri());
- EXPECT_EQ("POST", stream_->headers().request_method());
- EXPECT_EQ(body_, stream_->body());
-}
-
-TEST_F(QuicReliableServerStreamTest, TestFramingExtraData) {
- string large_body = "hello world!!!!!!";
-
- // We'll automatically write out an error (headers + body)
- EXPECT_CALL(session_, WritevData(_, _, _, _, _)).Times(2).
- WillRepeatedly(Invoke(ConsumeAllData));
-
- EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
- headers_string_.c_str(), headers_string_.size()));
- // Content length is still 11. This will register as an error and we won't
- // accept the bytes.
- stream_->ProcessData(large_body.c_str(), large_body.size());
- stream_->TerminateFromPeer(true);
- EXPECT_EQ(11u, stream_->headers().content_length());
- EXPECT_EQ("https://www.google.com/", stream_->headers().request_uri());
- EXPECT_EQ("POST", stream_->headers().request_method());
-}
-
-TEST_F(QuicReliableServerStreamTest, TestSendResponse) {
- BalsaHeaders* request_headers =
- QuicReliableServerStreamPeer::GetMutableHeaders(stream_.get());
- request_headers->SetRequestFirstlineFromStringPieces(
- "GET",
- "https://www.google.com/foo",
- "HTTP/1.1");
-
- response_headers_.SetResponseFirstlineFromStringPieces(
- "HTTP/1.1", "200", "OK");
- response_headers_.ReplaceOrAppendHeader("content-length", "3");
-
- InSequence s;
- EXPECT_CALL(session_, WritevData(_, _, 1, _, _)).Times(1)
- .WillOnce(WithArgs<1>(Invoke(
- this, &QuicReliableServerStreamTest::ValidateHeaders)));
-
- EXPECT_CALL(session_, WritevData(_, _, 1, _, _)).Times(1).
- WillOnce(Return(QuicConsumedData(3, true)));
-
- stream_->SendResponse();
- EXPECT_TRUE(stream_->read_side_closed());
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-TEST_F(QuicReliableServerStreamTest, TestSendErrorResponse) {
- response_headers_.SetResponseFirstlineFromStringPieces(
- "HTTP/1.1", "500", "Server Error");
- response_headers_.ReplaceOrAppendHeader("content-length", "3");
-
- InSequence s;
- EXPECT_CALL(session_, WritevData(_, _, 1, _, _)).Times(1)
- .WillOnce(WithArgs<1>(Invoke(
- this, &QuicReliableServerStreamTest::ValidateHeaders)));
-
- EXPECT_CALL(session_, WritevData(_, _, 1, _, _)).Times(1).
- WillOnce(Return(QuicConsumedData(3, true)));
-
- stream_->SendErrorResponse();
- EXPECT_TRUE(stream_->read_side_closed());
- EXPECT_TRUE(stream_->write_side_closed());
-}
-
-} // namespace
-} // namespace test
-} // namespace tools
-} // namespace net
diff --git a/chromium/net/tools/quic/quic_server.cc b/chromium/net/tools/quic/quic_server.cc
index 9eae4ab7566..a62cfbbdf15 100644
--- a/chromium/net/tools/quic/quic_server.cc
+++ b/chromium/net/tools/quic/quic_server.cc
@@ -28,7 +28,6 @@
#endif
const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
-const int kNumPacketsPerReadCall = 5; // Arbitrary
static const char kSourceAddressTokenSecret[] = "secret";
namespace net {
@@ -40,20 +39,26 @@ QuicServer::QuicServer()
packets_dropped_(0),
overflow_supported_(false),
use_recvmmsg_(false),
- crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()) {
+ crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
+ supported_versions_(QuicSupportedVersions()) {
// Use hardcoded crypto parameters for now.
config_.SetDefaults();
+ config_.set_initial_round_trip_time_us(kMaxInitialRoundTripTimeUs, 0);
+ config_.set_server_initial_congestion_window(kMaxInitialWindow,
+ kDefaultInitialWindow);
Initialize();
}
-QuicServer::QuicServer(const QuicConfig& config)
+QuicServer::QuicServer(const QuicConfig& config,
+ const QuicVersionVector& supported_versions)
: port_(0),
fd_(-1),
packets_dropped_(0),
overflow_supported_(false),
use_recvmmsg_(false),
config_(config),
- crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()) {
+ crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
+ supported_versions_(supported_versions) {
Initialize();
}
@@ -142,8 +147,9 @@ bool QuicServer::Listen(const IPEndPoint& address) {
}
epoll_server_.RegisterFD(fd_, this, kEpollFlags);
- dispatcher_.reset(new QuicDispatcher(config_, crypto_config_, fd_,
- &epoll_server_));
+ dispatcher_.reset(new QuicDispatcher(config_, crypto_config_,
+ supported_versions_,
+ fd_, &epoll_server_));
return true;
}
@@ -194,7 +200,10 @@ void QuicServer::MaybeDispatchPacket(QuicDispatcher* dispatcher,
return;
}
- dispatcher->ProcessPacket(server_address, client_address, guid, packet);
+ bool has_version_flag = QuicFramer::HasVersionFlag(packet);
+
+ dispatcher->ProcessPacket(
+ server_address, client_address, guid, has_version_flag, packet);
}
bool QuicServer::ReadAndDispatchSinglePacket(int fd,
diff --git a/chromium/net/tools/quic/quic_server.h b/chromium/net/tools/quic/quic_server.h
index 90863ce6400..7c8e4054f53 100644
--- a/chromium/net/tools/quic/quic_server.h
+++ b/chromium/net/tools/quic/quic_server.h
@@ -10,22 +10,27 @@
#include "base/memory/scoped_ptr.h"
#include "net/base/ip_endpoint.h"
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_framer.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_dispatcher.h"
namespace net {
namespace tools {
+namespace test {
+class QuicServerPeer;
+} // namespace test
+
class QuicDispatcher;
class QuicServer : public EpollCallbackInterface {
public:
QuicServer();
- explicit QuicServer(const QuicConfig& config);
+ QuicServer(const QuicConfig& config,
+ const QuicVersionVector& supported_versions);
virtual ~QuicServer();
@@ -76,6 +81,8 @@ class QuicServer : public EpollCallbackInterface {
int port() { return port_; }
private:
+ friend class net::tools::test::QuicServerPeer;
+
// Initialize the internal state of the server.
void Initialize();
@@ -108,6 +115,12 @@ class QuicServer : public EpollCallbackInterface {
// crypto_config_ contains crypto parameters for the handshake.
QuicCryptoServerConfig crypto_config_;
+ // This vector contains QUIC versions which we currently support.
+ // This should be ordered such that the highest supported version is the first
+ // element, with subsequent elements in descending order (versions can be
+ // skipped as necessary).
+ QuicVersionVector supported_versions_;
+
DISALLOW_COPY_AND_ASSIGN(QuicServer);
};
diff --git a/chromium/net/tools/quic/quic_server_bin.cc b/chromium/net/tools/quic/quic_server_bin.cc
index cccf57819f5..a71cbcf6218 100644
--- a/chromium/net/tools/quic/quic_server_bin.cc
+++ b/chromium/net/tools/quic/quic_server_bin.cc
@@ -5,6 +5,8 @@
// A binary wrapper for QuicServer. It listens forever on --port
// (default 6121) until it's killed or ctrl-cd to death.
+#include <iostream>
+
#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/command_line.h"
@@ -20,6 +22,19 @@ int32 FLAGS_port = 6121;
int main(int argc, char *argv[]) {
CommandLine::Init(argc, argv);
CommandLine* line = CommandLine::ForCurrentProcess();
+ if (line->HasSwitch("h") || line->HasSwitch("help")) {
+ const char* help_str =
+ "Usage: quic_server [options]\n"
+ "\n"
+ "Options:\n"
+ "-h, --help show this help message and exit\n"
+ "--port=<port> specify the port to listen on\n"
+ "--quic_in_memory_cache_dir directory containing response data\n"
+ " to load\n";
+ std::cout << help_str;
+ exit(0);
+ }
+
if (line->HasSwitch("quic_in_memory_cache_dir")) {
net::tools::FLAGS_quic_in_memory_cache_dir =
line->GetSwitchValueASCII("quic_in_memory_cache_dir");
diff --git a/chromium/net/tools/quic/quic_server_session.cc b/chromium/net/tools/quic/quic_server_session.cc
index 7ec991c4aa9..dcb112e0204 100644
--- a/chromium/net/tools/quic/quic_server_session.cc
+++ b/chromium/net/tools/quic/quic_server_session.cc
@@ -5,6 +5,7 @@
#include "net/tools/quic/quic_server_session.h"
#include "base/logging.h"
+#include "net/quic/quic_connection.h"
#include "net/quic/reliable_quic_stream.h"
#include "net/tools/quic/quic_spdy_server_stream.h"
@@ -15,7 +16,7 @@ QuicServerSession::QuicServerSession(
const QuicConfig& config,
QuicConnection* connection,
QuicSessionOwner* owner)
- : QuicSession(connection, config, true),
+ : QuicSession(connection, config),
owner_(owner) {
}
@@ -32,12 +33,13 @@ QuicCryptoServerStream* QuicServerSession::CreateQuicCryptoServerStream(
return new QuicCryptoServerStream(crypto_config, this);
}
-void QuicServerSession::ConnectionClose(QuicErrorCode error, bool from_peer) {
- QuicSession::ConnectionClose(error, from_peer);
- owner_->OnConnectionClose(connection()->guid(), error);
+void QuicServerSession::OnConnectionClosed(QuicErrorCode error,
+ bool from_peer) {
+ QuicSession::OnConnectionClosed(error, from_peer);
+ owner_->OnConnectionClosed(connection()->guid(), error);
}
-bool QuicServerSession::ShouldCreateIncomingReliableStream(QuicStreamId id) {
+bool QuicServerSession::ShouldCreateIncomingDataStream(QuicStreamId id) {
if (id % 2 == 0) {
DLOG(INFO) << "Invalid incoming even stream_id:" << id;
connection()->SendConnectionClose(QUIC_INVALID_STREAM_ID);
@@ -52,16 +54,16 @@ bool QuicServerSession::ShouldCreateIncomingReliableStream(QuicStreamId id) {
return true;
}
-ReliableQuicStream* QuicServerSession::CreateIncomingReliableStream(
+QuicDataStream* QuicServerSession::CreateIncomingDataStream(
QuicStreamId id) {
- if (!ShouldCreateIncomingReliableStream(id)) {
+ if (!ShouldCreateIncomingDataStream(id)) {
return NULL;
}
return new QuicSpdyServerStream(id, this);
}
-ReliableQuicStream* QuicServerSession::CreateOutgoingReliableStream() {
+QuicDataStream* QuicServerSession::CreateOutgoingDataStream() {
DLOG(ERROR) << "Server push not yet supported";
return NULL;
}
diff --git a/chromium/net/tools/quic/quic_server_session.h b/chromium/net/tools/quic/quic_server_session.h
index 2f031373bda..f4705519791 100644
--- a/chromium/net/tools/quic/quic_server_session.h
+++ b/chromium/net/tools/quic/quic_server_session.h
@@ -36,7 +36,7 @@ class QuicSessionOwner {
public:
virtual ~QuicSessionOwner() {}
- virtual void OnConnectionClose(QuicGuid guid, QuicErrorCode error) = 0;
+ virtual void OnConnectionClosed(QuicGuid guid, QuicErrorCode error) = 0;
};
class QuicServerSession : public QuicSession {
@@ -46,7 +46,7 @@ class QuicServerSession : public QuicSession {
QuicSessionOwner* owner);
// Override the base class to notify the owner of the connection close.
- virtual void ConnectionClose(QuicErrorCode error, bool from_peer) OVERRIDE;
+ virtual void OnConnectionClosed(QuicErrorCode error, bool from_peer) OVERRIDE;
virtual ~QuicServerSession();
@@ -56,15 +56,14 @@ class QuicServerSession : public QuicSession {
protected:
// QuicSession methods:
- virtual ReliableQuicStream* CreateIncomingReliableStream(
- QuicStreamId id) OVERRIDE;
- virtual ReliableQuicStream* CreateOutgoingReliableStream() OVERRIDE;
+ virtual QuicDataStream* CreateIncomingDataStream(QuicStreamId id) OVERRIDE;
+ virtual QuicDataStream* CreateOutgoingDataStream() OVERRIDE;
virtual QuicCryptoServerStream* GetCryptoStream() 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 ShouldCreateIncomingReliableStream(QuicStreamId id);
+ virtual bool ShouldCreateIncomingDataStream(QuicStreamId id);
virtual QuicCryptoServerStream* CreateQuicCryptoServerStream(
const QuicCryptoServerConfig& crypto_config);
diff --git a/chromium/net/tools/quic/quic_server_session_test.cc b/chromium/net/tools/quic/quic_server_session_test.cc
index a6f94abd7ba..a3dd9968285 100644
--- a/chromium/net/tools/quic/quic_server_session_test.cc
+++ b/chromium/net/tools/quic/quic_server_session_test.cc
@@ -4,14 +4,13 @@
#include "net/tools/quic/quic_server_session.h"
-
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_connection.h"
#include "net/quic/test_tools/quic_connection_peer.h"
+#include "net/quic/test_tools/quic_data_stream_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/quic/test_tools/reliable_quic_stream_peer.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_spdy_server_stream.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -20,7 +19,7 @@
using __gnu_cxx::vector;
using net::test::MockConnection;
using net::test::QuicConnectionPeer;
-using net::test::ReliableQuicStreamPeer;
+using net::test::QuicDataStreamPeer;
using testing::_;
using testing::StrictMock;
@@ -30,19 +29,19 @@ namespace test {
class QuicServerSessionPeer {
public:
- static ReliableQuicStream* GetIncomingReliableStream(
+ static QuicDataStream* GetIncomingReliableStream(
QuicServerSession* s, QuicStreamId id) {
return s->GetIncomingReliableStream(id);
}
- static ReliableQuicStream* GetStream(QuicServerSession* s, QuicStreamId id) {
- return s->GetStream(id);
+ static QuicDataStream* GetDataStream(QuicServerSession* s, QuicStreamId id) {
+ return s->GetDataStream(id);
}
};
-class CloseOnDataStream : public ReliableQuicStream {
+class CloseOnDataStream : public QuicDataStream {
public:
CloseOnDataStream(QuicStreamId id, QuicSession* session)
- : ReliableQuicStream(id, session) {
+ : QuicDataStream(id, session) {
}
virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE {
@@ -65,9 +64,9 @@ class TestQuicQuicServerSession : public QuicServerSession {
close_stream_on_data_(false) {
}
- virtual ReliableQuicStream* CreateIncomingReliableStream(
+ virtual QuicDataStream* CreateIncomingDataStream(
QuicStreamId id) OVERRIDE {
- if (!ShouldCreateIncomingReliableStream(id)) {
+ if (!ShouldCreateIncomingDataStream(id)) {
return NULL;
}
if (close_stream_on_data_) {
@@ -90,13 +89,12 @@ namespace {
class QuicServerSessionTest : public ::testing::Test {
protected:
QuicServerSessionTest()
- : guid_(1),
- crypto_config_(QuicCryptoServerConfig::TESTING,
+ : crypto_config_(QuicCryptoServerConfig::TESTING,
QuicRandom::GetInstance()) {
config_.SetDefaults();
config_.set_max_streams_per_connection(3, 3);
- connection_ = new MockConnection(guid_, IPEndPoint(), 0, &eps_, true);
+ connection_ = new MockConnection(true);
session_.reset(new TestQuicQuicServerSession(
config_, connection_, &owner_));
session_->InitializeSession(crypto_config_);
@@ -104,14 +102,12 @@ class QuicServerSessionTest : public ::testing::Test {
}
void MarkHeadersReadForStream(QuicStreamId id) {
- ReliableQuicStream* stream = QuicServerSessionPeer::GetStream(
+ QuicDataStream* stream = QuicServerSessionPeer::GetDataStream(
session_.get(), id);
ASSERT_TRUE(stream != NULL);
- ReliableQuicStreamPeer::SetHeadersDecompressed(stream, true);
+ QuicDataStreamPeer::SetHeadersDecompressed(stream, true);
}
- QuicGuid guid_;
- EpollServer eps_;
StrictMock<MockQuicSessionOwner> owner_;
MockConnection* connection_;
QuicConfig config_;
@@ -123,11 +119,7 @@ class QuicServerSessionTest : public ::testing::Test {
TEST_F(QuicServerSessionTest, CloseStreamDueToReset) {
// Open a stream, then reset it.
// Send two bytes of payload to open it.
- QuicPacketHeader header;
- header.public_header.guid = guid_;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- QuicStreamFrame data1(3, false, 0, "HT");
+ QuicStreamFrame data1(3, false, 0, MakeIOVector("HT"));
vector<QuicStreamFrame> frames;
frames.push_back(data1);
EXPECT_TRUE(visitor_->OnStreamFrames(frames));
@@ -156,11 +148,7 @@ TEST_F(QuicServerSessionTest, NeverOpenStreamDueToReset) {
EXPECT_EQ(0u, session_->GetNumOpenStreams());
// Send two bytes of payload.
- QuicPacketHeader header;
- header.public_header.guid = guid_;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- QuicStreamFrame data1(3, false, 0, "HT");
+ QuicStreamFrame data1(3, false, 0, MakeIOVector("HT"));
vector<QuicStreamFrame> frames;
frames.push_back(data1);
@@ -176,11 +164,7 @@ TEST_F(QuicServerSessionTest, NeverOpenStreamDueToReset) {
}
TEST_F(QuicServerSessionTest, GoOverPrematureClosedStreamLimit) {
- QuicPacketHeader header;
- header.public_header.guid = guid_;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
- QuicStreamFrame data1(3, false, 0, "H");
+ QuicStreamFrame data1(3, false, 0, MakeIOVector("H"));
vector<QuicStreamFrame> frames;
frames.push_back(data1);
@@ -194,14 +178,12 @@ TEST_F(QuicServerSessionTest, GoOverPrematureClosedStreamLimit) {
}
TEST_F(QuicServerSessionTest, AcceptClosedStream) {
- QuicPacketHeader header;
- header.public_header.guid = guid_;
- header.public_header.reset_flag = false;
- header.public_header.version_flag = false;
vector<QuicStreamFrame> frames;
// Send (empty) compressed headers followed by two bytes of data.
- frames.push_back(QuicStreamFrame(3, false, 0, "\1\0\0\0\0\0\0\0HT"));
- frames.push_back(QuicStreamFrame(5, false, 0, "\2\0\0\0\0\0\0\0HT"));
+ frames.push_back(
+ QuicStreamFrame(3, false, 0, MakeIOVector("\1\0\0\0\0\0\0\0HT")));
+ frames.push_back(
+ QuicStreamFrame(5, false, 0, MakeIOVector("\2\0\0\0\0\0\0\0HT")));
EXPECT_TRUE(visitor_->OnStreamFrames(frames));
// Pretend we got full headers, so we won't trigger the 'unercoverable
@@ -216,8 +198,8 @@ TEST_F(QuicServerSessionTest, AcceptClosedStream) {
// past the reset point of stream 3. As it's a closed stream we just drop the
// data on the floor, but accept the packet because it has data for stream 5.
frames.clear();
- frames.push_back(QuicStreamFrame(3, false, 2, "TP"));
- frames.push_back(QuicStreamFrame(5, false, 2, "TP"));
+ frames.push_back(QuicStreamFrame(3, false, 2, MakeIOVector("TP")));
+ frames.push_back(QuicStreamFrame(5, false, 2, MakeIOVector("TP")));
EXPECT_TRUE(visitor_->OnStreamFrames(frames));
}
diff --git a/chromium/net/tools/quic/quic_server_test.cc b/chromium/net/tools/quic/quic_server_test.cc
index 7d1d66939c0..7d24edc28bb 100644
--- a/chromium/net/tools/quic/quic_server_test.cc
+++ b/chromium/net/tools/quic/quic_server_test.cc
@@ -45,7 +45,7 @@ TEST_F(QuicServerDispatchPacketTest, DoNotDispatchPacketWithoutGUID) {
// We expect the invalid packet to be dropped, and ProcessPacket should never
// be called.
- EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _)).Times(0);
+ EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _, _)).Times(0);
MaybeDispatchPacket(encrypted_invalid_packet);
}
@@ -64,7 +64,7 @@ TEST_F(QuicServerDispatchPacketTest, DispatchValidPacket) {
QuicEncryptedPacket encrypted_valid_packet(QuicUtils::AsChars(valid_packet),
arraysize(valid_packet), false);
- EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _)).Times(1);
+ EXPECT_CALL(dispatcher_, ProcessPacket(_, _, _, _, _)).Times(1);
MaybeDispatchPacket(encrypted_valid_packet);
}
diff --git a/chromium/net/tools/quic/quic_socket_utils.cc b/chromium/net/tools/quic/quic_socket_utils.cc
index 4d7d3600760..87071a681ae 100644
--- a/chromium/net/tools/quic/quic_socket_utils.cc
+++ b/chromium/net/tools/quic/quic_socket_utils.cc
@@ -12,6 +12,7 @@
#include <string>
#include "base/logging.h"
+#include "net/quic/quic_protocol.h"
#ifndef SO_RXQ_OVFL
#define SO_RXQ_OVFL 40
@@ -22,28 +23,35 @@ namespace tools {
// static
IPAddressNumber QuicSocketUtils::GetAddressFromMsghdr(struct msghdr *hdr) {
- IPAddressNumber ret;
if (hdr->msg_controllen > 0) {
for (cmsghdr* cmsg = CMSG_FIRSTHDR(hdr);
cmsg != NULL;
cmsg = CMSG_NXTHDR(hdr, cmsg)) {
- const uint8* addr_data = reinterpret_cast<const uint8*>CMSG_DATA(cmsg);
+ const uint8* addr_data = NULL;
int len = 0;
if (cmsg->cmsg_type == IPV6_PKTINFO) {
- len = sizeof(in6_pktinfo);
+ in6_pktinfo* info = reinterpret_cast<in6_pktinfo*>CMSG_DATA(cmsg);
+ in6_addr addr = info->ipi6_addr;
+ addr_data = reinterpret_cast<const uint8*>(&addr);
+ len = sizeof(addr);
} else if (cmsg->cmsg_type == IP_PKTINFO) {
- len = sizeof(in_pktinfo);
+ in_pktinfo* info = reinterpret_cast<in_pktinfo*>CMSG_DATA(cmsg);
+ in_addr addr = info->ipi_addr;
+ addr_data = reinterpret_cast<const uint8*>(&addr);
+ len = sizeof(addr);
+ } else {
+ continue;
}
- ret.assign(addr_data, addr_data + len);
- break;
+ return IPAddressNumber(addr_data, addr_data + len);
}
}
- return ret;
+ DCHECK(false) << "Unable to get address from msghdr";
+ return IPAddressNumber();
}
// static
bool QuicSocketUtils::GetOverflowFromMsghdr(struct msghdr *hdr,
- int *dropped_packets) {
+ int *dropped_packets) {
if (hdr->msg_controllen > 0) {
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(hdr);
@@ -72,9 +80,9 @@ int QuicSocketUtils::SetGetAddressInfo(int fd, int address_family) {
// static
int QuicSocketUtils::ReadPacket(int fd, char* buffer, size_t buf_len,
- int* dropped_packets,
- IPAddressNumber* self_address,
- IPEndPoint* peer_address) {
+ int* dropped_packets,
+ IPAddressNumber* self_address,
+ IPEndPoint* peer_address) {
CHECK(peer_address != NULL);
const int kSpaceForOverflowAndIp =
CMSG_SPACE(sizeof(int)) + CMSG_SPACE(sizeof(in6_pktinfo));
@@ -128,10 +136,11 @@ int QuicSocketUtils::ReadPacket(int fd, char* buffer, size_t buf_len,
}
// static
-int QuicSocketUtils::WritePacket(int fd, const char* buffer, size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address,
- int* error) {
+WriteResult QuicSocketUtils::WritePacket(int fd,
+ const char* buffer,
+ size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address) {
sockaddr_storage raw_address;
socklen_t address_len = sizeof(raw_address);
CHECK(peer_address.ToSockAddr(
@@ -183,8 +192,11 @@ int QuicSocketUtils::WritePacket(int fd, const char* buffer, size_t buf_len,
}
int rc = sendmsg(fd, &hdr, 0);
- *error = (rc >= 0) ? 0 : errno;
- return rc;
+ if (rc >= 0) {
+ return WriteResult(WRITE_STATUS_OK, rc);
+ }
+ return WriteResult((errno == EAGAIN || errno == EWOULDBLOCK) ?
+ WRITE_STATUS_BLOCKED : WRITE_STATUS_ERROR, errno);
}
} // namespace tools
diff --git a/chromium/net/tools/quic/quic_socket_utils.h b/chromium/net/tools/quic/quic_socket_utils.h
index bfacc6c4719..8f0feffced2 100644
--- a/chromium/net/tools/quic/quic_socket_utils.h
+++ b/chromium/net/tools/quic/quic_socket_utils.h
@@ -12,6 +12,7 @@
#include <string>
#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_protocol.h"
namespace net {
namespace tools {
@@ -45,12 +46,13 @@ class QuicSocketUtils {
IPAddressNumber* self_address,
IPEndPoint* peer_address);
- // Writes buf_len to the socket. If writing is successful returns the number
- // of bytes written otherwise returns -1 and sets error to errno.
- static int WritePacket(int fd, const char* buffer, size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address,
- int* error);
+ // Writes buf_len to the socket. If writing is successful, sets the result's
+ // status to WRITE_STATUS_OK and sets bytes_written. Otherwise sets the
+ // result's status to WRITE_STATUS_BLOCKED or WRITE_STATUS_ERROR and sets
+ // error_code to errno.
+ static WriteResult WritePacket(int fd, const char* buffer, size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address);
};
} // namespace tools
diff --git a/chromium/net/tools/quic/quic_spdy_client_stream.cc b/chromium/net/tools/quic/quic_spdy_client_stream.cc
index 368f93eb855..1956c7940db 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream.cc
+++ b/chromium/net/tools/quic/quic_spdy_client_stream.cc
@@ -18,7 +18,7 @@ static const size_t kHeaderBufInitialSize = 4096;
QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
QuicClientSession* session)
- : QuicReliableClientStream(id, session),
+ : QuicDataStream(id, session),
read_buf_(new GrowableIOBuffer()),
response_headers_received_(false) {
}
@@ -26,6 +26,15 @@ QuicSpdyClientStream::QuicSpdyClientStream(QuicStreamId id,
QuicSpdyClientStream::~QuicSpdyClientStream() {
}
+bool QuicSpdyClientStream::OnStreamFrame(const QuicStreamFrame& frame) {
+ if (!write_side_closed()) {
+ DLOG(INFO) << "Got a response before the request was complete. "
+ << "Aborting request.";
+ CloseWriteSide();
+ }
+ return QuicDataStream::OnStreamFrame(frame);
+}
+
uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 length) {
uint32 total_bytes_processed = 0;
@@ -39,20 +48,19 @@ uint32 QuicSpdyClientStream::ProcessData(const char* data, uint32 length) {
read_buf_->set_offset(read_buf_->offset() + length);
ParseResponseHeaders();
} else {
- mutable_data()->append(data + total_bytes_processed,
- length - total_bytes_processed);
+ data_.append(data + total_bytes_processed, length - total_bytes_processed);
}
return length;
}
-void QuicSpdyClientStream::TerminateFromPeer(bool half_close) {
- ReliableQuicStream::TerminateFromPeer(half_close);
+void QuicSpdyClientStream::OnFinRead() {
+ ReliableQuicStream::OnFinRead();
if (!response_headers_received_) {
- Close(QUIC_BAD_APPLICATION_PAYLOAD);
+ Reset(QUIC_BAD_APPLICATION_PAYLOAD);
} else if ((headers().content_length_status() ==
BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
- mutable_data()->size() != headers().content_length()) {
- Close(QUIC_BAD_APPLICATION_PAYLOAD);
+ data_.size() != headers().content_length()) {
+ Reset(QUIC_BAD_APPLICATION_PAYLOAD);
}
}
@@ -62,20 +70,13 @@ ssize_t QuicSpdyClientStream::SendRequest(const BalsaHeaders& headers,
SpdyHeaderBlock header_block =
SpdyUtils::RequestHeadersToSpdyHeaders(headers);
- string headers_string;
- if (session()->connection()->version() >= QUIC_VERSION_9) {
- headers_string = session()->compressor()->CompressHeadersWithPriority(
- priority(), header_block);
- } else {
- headers_string = session()->compressor()->CompressHeaders(header_block);
- }
+ bool send_fin_with_headers = fin && body.empty();
+ string headers_string = session()->compressor()->CompressHeadersWithPriority(
+ priority(), header_block);
+ WriteOrBufferData(headers_string, send_fin_with_headers);
- bool has_body = !body.empty();
-
- WriteData(headers_string, fin && !has_body); // last_data
-
- if (has_body) {
- WriteData(body, fin);
+ if (!body.empty()) {
+ WriteOrBufferData(body, fin);
}
return headers_string.size() + body.size();
@@ -92,18 +93,24 @@ int QuicSpdyClientStream::ParseResponseHeaders() {
return -1;
}
- if (!SpdyUtils::FillBalsaResponseHeaders(headers, mutable_headers())) {
- Close(QUIC_BAD_APPLICATION_PAYLOAD);
+ if (!SpdyUtils::FillBalsaResponseHeaders(headers, &headers_)) {
+ Reset(QUIC_BAD_APPLICATION_PAYLOAD);
return -1;
}
+ response_headers_received_ = true;
size_t delta = read_buf_len - len;
if (delta > 0) {
- mutable_data()->append(data + len, delta);
+ data_.append(data + len, delta);
}
return len;
}
+// Sends body data to the server and returns the number of bytes sent.
+void QuicSpdyClientStream::SendBody(const string& data, bool fin) {
+ return WriteOrBufferData(data, fin);
+}
+
} // 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 5d32b30d3cb..2b17205f53e 100644
--- a/chromium/net/tools/quic/quic_spdy_client_stream.h
+++ b/chromium/net/tools/quic/quic_spdy_client_stream.h
@@ -5,42 +5,65 @@
#ifndef NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_STREAM_H_
#define NET_TOOLS_QUIC_QUIC_SPDY_CLIENT_STREAM_H_
+#include <sys/types.h>
+#include <string>
+
#include "base/strings/string_piece.h"
#include "net/base/io_buffer.h"
-#include "net/tools/quic/quic_reliable_client_stream.h"
+#include "net/quic/quic_data_stream.h"
+#include "net/quic/quic_protocol.h"
+#include "net/tools/balsa/balsa_frame.h"
+#include "net/tools/balsa/balsa_headers.h"
namespace net {
-class BalsaHeaders;
-
namespace tools {
class QuicClientSession;
// All this does right now is send an SPDY request, and aggregate the
// SPDY response.
-class QuicSpdyClientStream : public QuicReliableClientStream {
+class QuicSpdyClientStream : public QuicDataStream {
public:
QuicSpdyClientStream(QuicStreamId id, QuicClientSession* session);
virtual ~QuicSpdyClientStream();
+ // Override the base class to close the write side as soon as we get a
+ // response.
+ // SPDY/HTTP does not support bidirectional streaming.
+ virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
+
// ReliableQuicStream implementation called by the session when there's
// data for us.
virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE;
- virtual void TerminateFromPeer(bool half_close) OVERRIDE;
+ virtual void OnFinRead() OVERRIDE;
+
+ // Serializes the headers and body, sends it to the server, and
+ // returns the number of bytes sent.
+ ssize_t SendRequest(const BalsaHeaders& headers,
+ base::StringPiece body,
+ bool fin);
- virtual ssize_t SendRequest(const BalsaHeaders& headers,
- base::StringPiece body,
- bool fin) OVERRIDE;
+ // Sends body data to the server, or buffers if it can't be sent immediately.
+ void SendBody(const std::string& data, bool fin);
+
+ // Returns the response data.
+ const std::string& data() { return data_; }
+
+ // Returns whatever headers have been received for this stream.
+ const BalsaHeaders& headers() { return headers_; }
// While the server's set_priority shouldn't be called externally, the creator
// of client-side streams should be able to set the priority.
- using QuicReliableClientStream::set_priority;
+ using QuicDataStream::set_priority;
private:
int ParseResponseHeaders();
+ BalsaHeaders headers_;
+ std::string data_;
+
scoped_refptr<GrowableIOBuffer> read_buf_;
bool response_headers_received_;
};
diff --git a/chromium/net/tools/quic/quic_reliable_client_stream_test.cc b/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
index af0ffd58f81..44c640cbdea 100644
--- a/chromium/net/tools/quic/quic_reliable_client_stream_test.cc
+++ b/chromium/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -1,13 +1,13 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/tools/quic/quic_reliable_client_stream.h"
+#include "net/tools/quic/quic_spdy_client_stream.h"
#include "base/strings/string_number_conversions.h"
#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_client_session.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/spdy_utils.h"
@@ -15,6 +15,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+using net::test::DefaultQuicConfig;
using testing::TestWithParam;
namespace net {
@@ -22,11 +23,11 @@ namespace tools {
namespace test {
namespace {
-class QuicClientStreamTest : public ::testing::Test {
+class QuicSpdyClientStreamTest : public ::testing::Test {
public:
- QuicClientStreamTest()
- : session_("example.com", QuicConfig(),
- new MockConnection(1, IPEndPoint(), 0, &eps_, false),
+ QuicSpdyClientStreamTest()
+ : session_("example.com", DefaultQuicConfig(),
+ new MockConnection(false),
&crypto_config_),
body_("hello world") {
session_.config()->SetDefaults();
@@ -39,16 +40,15 @@ class QuicClientStreamTest : public ::testing::Test {
stream_.reset(new QuicSpdyClientStream(3, &session_));
}
- EpollServer eps_;
QuicClientSession session_;
- scoped_ptr<QuicReliableClientStream> stream_;
+ scoped_ptr<QuicSpdyClientStream> stream_;
BalsaHeaders headers_;
string headers_string_;
string body_;
QuicCryptoClientConfig crypto_config_;
};
-TEST_F(QuicClientStreamTest, TestFraming) {
+TEST_F(QuicSpdyClientStreamTest, TestFraming) {
EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
headers_string_.c_str(), headers_string_.size()));
EXPECT_EQ(body_.size(),
@@ -57,7 +57,7 @@ TEST_F(QuicClientStreamTest, TestFraming) {
EXPECT_EQ(body_, stream_->data());
}
-TEST_F(QuicClientStreamTest, TestFramingOnePacket) {
+TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) {
string message = headers_string_ + body_;
EXPECT_EQ(message.size(), stream_->ProcessData(
@@ -66,7 +66,7 @@ TEST_F(QuicClientStreamTest, TestFramingOnePacket) {
EXPECT_EQ(body_, stream_->data());
}
-TEST_F(QuicClientStreamTest, TestFramingExtraData) {
+TEST_F(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) {
string large_body = "hello world!!!!!!";
EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
@@ -76,13 +76,12 @@ TEST_F(QuicClientStreamTest, TestFramingExtraData) {
EXPECT_EQ(200u, stream_->headers().parsed_response_code());
stream_->ProcessData(large_body.c_str(), large_body.size());
- stream_->TerminateFromPeer(true);
EXPECT_NE(QUIC_STREAM_NO_ERROR, stream_->stream_error());
}
-TEST_F(QuicClientStreamTest, TestNoBidirectionalStreaming) {
- QuicStreamFrame frame(3, false, 3, "asd");
+TEST_F(QuicSpdyClientStreamTest, TestNoBidirectionalStreaming) {
+ QuicStreamFrame frame(3, false, 3, MakeIOVector("asd"));
EXPECT_FALSE(stream_->write_side_closed());
EXPECT_TRUE(stream_->OnStreamFrame(frame));
@@ -93,4 +92,3 @@ TEST_F(QuicClientStreamTest, TestNoBidirectionalStreaming) {
} // namespace test
} // namespace tools
} // namespace net
-
diff --git a/chromium/net/tools/quic/quic_spdy_server_stream.cc b/chromium/net/tools/quic/quic_spdy_server_stream.cc
index 2ebe1dc64c6..c1a9cf15e18 100644
--- a/chromium/net/tools/quic/quic_spdy_server_stream.cc
+++ b/chromium/net/tools/quic/quic_spdy_server_stream.cc
@@ -4,10 +4,13 @@
#include "net/tools/quic/quic_spdy_server_stream.h"
+#include "base/memory/singleton.h"
#include "net/quic/quic_session.h"
#include "net/spdy/spdy_framer.h"
+#include "net/tools/quic/quic_in_memory_cache.h"
#include "net/tools/quic/spdy_utils.h"
+using base::StringPiece;
using std::string;
namespace net {
@@ -17,7 +20,7 @@ static const size_t kHeaderBufInitialSize = 4096;
QuicSpdyServerStream::QuicSpdyServerStream(QuicStreamId id,
QuicSession* session)
- : QuicReliableServerStream(id, session),
+ : QuicDataStream(id, session),
read_buf_(new GrowableIOBuffer()),
request_headers_received_(false) {
}
@@ -38,44 +41,28 @@ uint32 QuicSpdyServerStream::ProcessData(const char* data, uint32 length) {
read_buf_->set_offset(read_buf_->offset() + length);
ParseRequestHeaders();
} else {
- mutable_body()->append(data + total_bytes_processed,
- length - total_bytes_processed);
+ body_.append(data + total_bytes_processed, length - total_bytes_processed);
}
return length;
}
-void QuicSpdyServerStream::TerminateFromPeer(bool half_close) {
- ReliableQuicStream::TerminateFromPeer(half_close);
- // This is a full close: do not send a response.
- if (!half_close) {
- return;
- }
+void QuicSpdyServerStream::OnFinRead() {
+ ReliableQuicStream::OnFinRead();
if (write_side_closed() || fin_buffered()) {
return;
}
if (!request_headers_received_) {
- SendErrorResponse(); // We're not done writing headers.
- } else if ((headers().content_length_status() ==
+ SendErrorResponse(); // We're not done reading headers.
+ } else if ((headers_.content_length_status() ==
BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
- mutable_body()->size() != headers().content_length()) {
+ body_.size() != headers_.content_length()) {
SendErrorResponse(); // Invalid content length
} else {
SendResponse();
}
}
-void QuicSpdyServerStream::SendHeaders(
- const BalsaHeaders& response_headers) {
- SpdyHeaderBlock header_block =
- SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers);
-
- string headers_string;
- headers_string = session()->compressor()->CompressHeaders(header_block);
-
- WriteData(headers_string, false);
-}
-
int QuicSpdyServerStream::ParseRequestHeaders() {
size_t read_buf_len = static_cast<size_t>(read_buf_->offset());
SpdyFramer framer(SPDY3);
@@ -87,19 +74,61 @@ int QuicSpdyServerStream::ParseRequestHeaders() {
return -1;
}
- if (!SpdyUtils::FillBalsaRequestHeaders(headers, mutable_headers())) {
+ if (!SpdyUtils::FillBalsaRequestHeaders(headers, &headers_)) {
SendErrorResponse();
return -1;
}
size_t delta = read_buf_len - len;
if (delta > 0) {
- mutable_body()->append(data + len, delta);
+ body_.append(data + len, delta);
}
request_headers_received_ = true;
return len;
}
+void QuicSpdyServerStream::SendResponse() {
+ // Find response in cache. If not found, send error response.
+ const QuicInMemoryCache::Response* response =
+ QuicInMemoryCache::GetInstance()->GetResponse(headers_);
+ if (response == NULL) {
+ SendErrorResponse();
+ return;
+ }
+
+ DLOG(INFO) << "Sending response for stream " << id();
+ SendHeadersAndBody(response->headers(), response->body());
+}
+
+void QuicSpdyServerStream::SendErrorResponse() {
+ DLOG(INFO) << "Sending error response for stream " << id();
+ BalsaHeaders headers;
+ headers.SetResponseFirstlineFromStringPieces(
+ "HTTP/1.1", "500", "Server Error");
+ headers.ReplaceOrAppendHeader("content-length", "3");
+ SendHeadersAndBody(headers, "bad");
+}
+
+void QuicSpdyServerStream:: SendHeadersAndBody(
+ const BalsaHeaders& response_headers,
+ StringPiece body) {
+ // We only support SPDY and HTTP, and neither handles bidirectional streaming.
+ if (!read_side_closed()) {
+ CloseReadSide();
+ }
+
+ SpdyHeaderBlock header_block =
+ SpdyUtils::ResponseHeadersToSpdyHeaders(response_headers);
+
+ string headers_string =
+ session()->compressor()->CompressHeaders(header_block);
+ WriteOrBufferData(headers_string, body.empty());
+
+ if (!body.empty()) {
+ WriteOrBufferData(body, true);
+ }
+}
+
} // namespace tools
} // namespace net
diff --git a/chromium/net/tools/quic/quic_spdy_server_stream.h b/chromium/net/tools/quic/quic_spdy_server_stream.h
index 8ed2a8f3d65..574ef76f33d 100644
--- a/chromium/net/tools/quic/quic_spdy_server_stream.h
+++ b/chromium/net/tools/quic/quic_spdy_server_stream.h
@@ -8,7 +8,9 @@
#include <string>
#include "net/base/io_buffer.h"
-#include "net/tools/quic/quic_reliable_server_stream.h"
+#include "net/quic/quic_data_stream.h"
+#include "net/quic/quic_protocol.h"
+#include "net/tools/balsa/balsa_headers.h"
namespace net {
@@ -16,9 +18,13 @@ class QuicSession;
namespace tools {
-// All this does right now is aggregate data, and on fin, send a cached
+namespace test {
+class QuicSpdyServerStreamPeer;
+} // namespace test
+
+// All this does right now is aggregate data, and on fin, send an HTTP
// response.
-class QuicSpdyServerStream : public QuicReliableServerStream {
+class QuicSpdyServerStream : public QuicDataStream {
public:
QuicSpdyServerStream(QuicStreamId id, QuicSession* session);
virtual ~QuicSpdyServerStream();
@@ -26,13 +32,26 @@ class QuicSpdyServerStream : public QuicReliableServerStream {
// ReliableQuicStream implementation called by the session when there's
// data for us.
virtual uint32 ProcessData(const char* data, uint32 data_len) OVERRIDE;
-
- virtual void SendHeaders(const BalsaHeaders& response_headers) OVERRIDE;
+ virtual void OnFinRead() OVERRIDE;
int ParseRequestHeaders();
- protected:
- virtual void TerminateFromPeer(bool half_close) OVERRIDE;
+ private:
+ friend class test::QuicSpdyServerStreamPeer;
+
+ // Sends a basic 200 response using SendHeaders for the headers and WriteData
+ // for the body.
+ void SendResponse();
+
+ // Sends a basic 500 response using SendHeaders for the headers and WriteData
+ // for the body
+ void SendErrorResponse();
+
+ void SendHeadersAndBody(const BalsaHeaders& response_headers,
+ base::StringPiece body);
+
+ BalsaHeaders headers_;
+ string body_;
// Buffer into which response header data is read.
scoped_refptr<GrowableIOBuffer> read_buf_;
diff --git a/chromium/net/tools/quic/quic_spdy_server_stream_test.cc b/chromium/net/tools/quic/quic_spdy_server_stream_test.cc
index 8168fcbd4c1..c0ec9449707 100644
--- a/chromium/net/tools/quic/quic_spdy_server_stream_test.cc
+++ b/chromium/net/tools/quic/quic_spdy_server_stream_test.cc
@@ -4,35 +4,241 @@
#include "net/tools/quic/quic_spdy_server_stream.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "net/quic/quic_connection.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_spdy_compressor.h"
+#include "net/quic/quic_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
+#include "net/tools/epoll_server/epoll_server.h"
+#include "net/tools/quic/quic_in_memory_cache.h"
+#include "net/tools/quic/spdy_utils.h"
+#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
using net::tools::test::MockConnection;
using net::test::MockSession;
+using std::string;
+using testing::_;
+using testing::AnyNumber;
+using testing::Invoke;
+using testing::InvokeArgument;
+using testing::InSequence;
+using testing::Return;
+using testing::StrEq;
+using testing::StrictMock;
+using testing::WithArgs;
namespace net {
namespace tools {
namespace test {
+
+class QuicSpdyServerStreamPeer : public QuicSpdyServerStream {
+ public:
+ QuicSpdyServerStreamPeer(QuicStreamId stream_id, QuicSession* session)
+ : QuicSpdyServerStream(stream_id, session) {
+ }
+
+ using QuicSpdyServerStream::SendResponse;
+ using QuicSpdyServerStream::SendErrorResponse;
+
+ const string& body() {
+ return body_;
+ }
+
+ const BalsaHeaders& headers() {
+ return headers_;
+ }
+
+ BalsaHeaders* mutable_headers() {
+ return &headers_;
+ }
+};
+
namespace {
class QuicSpdyServerStreamTest : public ::testing::Test {
public:
QuicSpdyServerStreamTest()
- : connection_(new MockConnection(1, IPEndPoint(), false)),
- session_(connection_, true),
- stream_(1, &session_) {
+ : session_(new MockConnection(true)),
+ body_("hello world") {
+ BalsaHeaders request_headers;
+ request_headers.SetRequestFirstlineFromStringPieces(
+ "POST", "https://www.google.com/", "HTTP/1.1");
+ request_headers.ReplaceOrAppendHeader("content-length", "11");
+
+ headers_string_ = SpdyUtils::SerializeRequestHeaders(request_headers);
+ stream_.reset(new QuicSpdyServerStreamPeer(3, &session_));
+ }
+
+ QuicConsumedData ValidateHeaders(const struct iovec* iov) {
+ StringPiece headers =
+ StringPiece(static_cast<const char*>(iov[0].iov_base), iov[0].iov_len);
+ headers_string_ = SpdyUtils::SerializeResponseHeaders(
+ response_headers_);
+ QuicSpdyDecompressor decompressor;
+ TestDecompressorVisitor visitor;
+
+ // First the header id, then the compressed data.
+ EXPECT_EQ(1, headers[0]);
+ EXPECT_EQ(0, headers[1]);
+ EXPECT_EQ(0, headers[2]);
+ EXPECT_EQ(0, headers[3]);
+ EXPECT_EQ(static_cast<size_t>(headers.length() - 4),
+ decompressor.DecompressData(headers.substr(4), &visitor));
+
+ EXPECT_EQ(headers_string_, visitor.data());
+
+ return QuicConsumedData(headers.size(), false);
+ }
+
+ static void SetUpTestCase() {
+ QuicInMemoryCachePeer::ResetForTests();
+ }
+
+ virtual void SetUp() {
+ QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
+
+ BalsaHeaders request_headers, response_headers;
+ StringPiece body("Yum");
+ request_headers.SetRequestFirstlineFromStringPieces(
+ "GET",
+ "https://www.google.com/foo",
+ "HTTP/1.1");
+ response_headers.SetRequestFirstlineFromStringPieces("HTTP/1.1",
+ "200",
+ "OK");
+ response_headers.AppendHeader("content-length",
+ base::IntToString(body.length()));
+
+ // Check if response already exists and matches.
+ const QuicInMemoryCache::Response* cached_response =
+ cache->GetResponse(request_headers);
+ if (cached_response != NULL) {
+ string cached_response_headers_str, response_headers_str;
+ cached_response->headers().DumpToString(&cached_response_headers_str);
+ response_headers.DumpToString(&response_headers_str);
+ CHECK_EQ(cached_response_headers_str, response_headers_str);
+ CHECK_EQ(cached_response->body(), body);
+ return;
+ }
+
+ cache->AddResponse(request_headers, response_headers, body);
}
- MockConnection* connection_;
- MockSession session_;
- QuicSpdyServerStream stream_;
+ BalsaHeaders response_headers_;
+ EpollServer eps_;
+ StrictMock<MockSession> session_;
+ scoped_ptr<QuicSpdyServerStreamPeer> stream_;
+ string headers_string_;
+ string body_;
};
+QuicConsumedData ConsumeAllData(
+ QuicStreamId id,
+ const struct iovec* iov,
+ int iov_count,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicAckNotifier::DelegateInterface* /*ack_notifier_delegate*/) {
+ ssize_t consumed_length = 0;
+ for (int i = 0; i < iov_count; ++i) {
+ consumed_length += iov[i].iov_len;
+ }
+ return QuicConsumedData(consumed_length, fin);
+}
+
+TEST_F(QuicSpdyServerStreamTest, TestFraming) {
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()).
+ WillRepeatedly(Invoke(ConsumeAllData));
+
+ EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
+ headers_string_.c_str(), headers_string_.size()));
+ EXPECT_EQ(body_.size(), stream_->ProcessData(body_.c_str(), body_.size()));
+ EXPECT_EQ(11u, stream_->headers().content_length());
+ EXPECT_EQ("https://www.google.com/", stream_->headers().request_uri());
+ EXPECT_EQ("POST", stream_->headers().request_method());
+ EXPECT_EQ(body_, stream_->body());
+}
+
+TEST_F(QuicSpdyServerStreamTest, TestFramingOnePacket) {
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()).
+ WillRepeatedly(Invoke(ConsumeAllData));
+
+ string message = headers_string_ + body_;
+
+ EXPECT_EQ(message.size(), stream_->ProcessData(
+ message.c_str(), message.size()));
+ EXPECT_EQ(11u, stream_->headers().content_length());
+ EXPECT_EQ("https://www.google.com/",
+ stream_->headers().request_uri());
+ EXPECT_EQ("POST", stream_->headers().request_method());
+ EXPECT_EQ(body_, stream_->body());
+}
+
+TEST_F(QuicSpdyServerStreamTest, TestFramingExtraData) {
+ string large_body = "hello world!!!!!!";
+
+ // We'll automatically write out an error (headers + body)
+ EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()).
+ WillRepeatedly(Invoke(ConsumeAllData));
+
+ EXPECT_EQ(headers_string_.size(), stream_->ProcessData(
+ headers_string_.c_str(), headers_string_.size()));
+ // Content length is still 11. This will register as an error and we won't
+ // accept the bytes.
+ stream_->ProcessData(large_body.c_str(), large_body.size());
+ EXPECT_EQ(11u, stream_->headers().content_length());
+ EXPECT_EQ("https://www.google.com/", stream_->headers().request_uri());
+ EXPECT_EQ("POST", stream_->headers().request_method());
+}
+
+TEST_F(QuicSpdyServerStreamTest, TestSendResponse) {
+ BalsaHeaders* request_headers = stream_->mutable_headers();
+ request_headers->SetRequestFirstlineFromStringPieces(
+ "GET",
+ "https://www.google.com/foo",
+ "HTTP/1.1");
+
+ response_headers_.SetResponseFirstlineFromStringPieces(
+ "HTTP/1.1", "200", "OK");
+ response_headers_.ReplaceOrAppendHeader("content-length", "3");
+
+ InSequence s;
+ EXPECT_CALL(session_, WritevData(_, _, 1, _, _, _)).Times(1)
+ .WillOnce(WithArgs<1>(Invoke(
+ this, &QuicSpdyServerStreamTest::ValidateHeaders)));
+
+ EXPECT_CALL(session_, WritevData(_, _, 1, _, _, _)).Times(1).
+ WillOnce(Return(QuicConsumedData(3, true)));
+
+ stream_->SendResponse();
+ EXPECT_TRUE(stream_->read_side_closed());
+ EXPECT_TRUE(stream_->write_side_closed());
+}
+
+TEST_F(QuicSpdyServerStreamTest, TestSendErrorResponse) {
+ response_headers_.SetResponseFirstlineFromStringPieces(
+ "HTTP/1.1", "500", "Server Error");
+ response_headers_.ReplaceOrAppendHeader("content-length", "3");
+
+ InSequence s;
+ EXPECT_CALL(session_, WritevData(_, _, 1, _, _, _)).Times(1)
+ .WillOnce(WithArgs<1>(Invoke(
+ this, &QuicSpdyServerStreamTest::ValidateHeaders)));
+
+ EXPECT_CALL(session_, WritevData(_, _, 1, _, _, _)).Times(1).
+ WillOnce(Return(QuicConsumedData(3, true)));
+
+ stream_->SendErrorResponse();
+ EXPECT_TRUE(stream_->read_side_closed());
+ EXPECT_TRUE(stream_->write_side_closed());
+}
+
TEST_F(QuicSpdyServerStreamTest, InvalidHeadersWithFin) {
char arr[] = {
0x00, 0x00, 0x00, 0x05, // ....
@@ -59,9 +265,10 @@ TEST_F(QuicSpdyServerStreamTest, InvalidHeadersWithFin) {
0x54, 0x54, 0x50, 0x2f, // TTP/
0x31, 0x2e, 0x31, // 1.1
};
- QuicStreamFrame frame(1, true, 0, StringPiece(arr, arraysize(arr)));
+ QuicStreamFrame frame(
+ stream_->id(), true, 0, MakeIOVector(StringPiece(arr, arraysize(arr))));
// Verify that we don't crash when we get a invalid headers in stream frame.
- stream_.OnStreamFrame(frame);
+ stream_->OnStreamFrame(frame);
}
} // namespace
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 a2fc4f84cb6..df9e378e722 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager.cc
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager.cc
@@ -18,6 +18,7 @@
#include "net/quic/quic_protocol.h"
#include "net/quic/quic_utils.h"
+using base::StringPiece;
using std::make_pair;
namespace net {
@@ -92,8 +93,9 @@ class QuicTimeWaitListManager::QueuedPacket {
QuicTimeWaitListManager::QuicTimeWaitListManager(
QuicPacketWriter* writer,
- EpollServer* epoll_server)
- : framer_(QuicVersionMax(),
+ EpollServer* epoll_server,
+ const QuicVersionVector& supported_versions)
+ : framer_(supported_versions,
QuicTime::Zero(), // unused
true),
epoll_server_(epoll_server),
@@ -110,13 +112,18 @@ QuicTimeWaitListManager::~QuicTimeWaitListManager() {
guid_clean_up_alarm_->UnregisterIfRegistered();
STLDeleteElements(&time_ordered_guid_list_);
STLDeleteElements(&pending_packets_queue_);
+ for (GuidMapIterator it = guid_map_.begin(); it != guid_map_.end(); ++it) {
+ delete it->second.close_packet;
+ }
}
-void QuicTimeWaitListManager::AddGuidToTimeWait(QuicGuid guid,
- QuicVersion version) {
+void QuicTimeWaitListManager::AddGuidToTimeWait(
+ QuicGuid guid,
+ QuicVersion version,
+ QuicEncryptedPacket* close_packet) {
DCHECK(!IsGuidInTimeWait(guid));
// Initialize the guid with 0 packets received.
- GuidData data(0, version);
+ GuidData data(0, version, close_packet);
guid_map_.insert(make_pair(guid, data));
time_ordered_guid_list_.push_back(new GuidAddTime(guid,
clock_.ApproximateNow()));
@@ -172,55 +179,89 @@ bool QuicTimeWaitListManager::OnProtocolVersionMismatch(
return false;
}
-bool QuicTimeWaitListManager::OnStreamFrame(const QuicStreamFrame& frame) {
+bool QuicTimeWaitListManager::OnUnauthenticatedHeader(
+ const QuicPacketHeader& header) {
+ // TODO(satyamshekhar): Think about handling packets from different client
+ // addresses.
+ GuidMapIterator it = guid_map_.find(header.public_header.guid);
+ DCHECK(it != guid_map_.end());
+ // Increment the received packet count.
+ ++((it->second).num_packets);
+ if (!ShouldSendResponse((it->second).num_packets)) {
+ return false;
+ }
+ if (it->second.close_packet) {
+ QueuedPacket* queued_packet =
+ new QueuedPacket(server_address_,
+ client_address_,
+ it->second.close_packet->Clone());
+ // Takes ownership of the packet.
+ SendOrQueuePacket(queued_packet);
+ } else {
+ // We don't need the packet anymore. Just tell the client what sequence
+ // number we rejected.
+ SendPublicReset(server_address_,
+ client_address_,
+ header.public_header.guid,
+ header.packet_sequence_number);
+ }
+ // Never process the body of the packet in time wait state.
+ return false;
+}
+
+bool QuicTimeWaitListManager::OnPacketHeader(const QuicPacketHeader& header) {
+ DCHECK(false);
+ return false;
+}
+
+void QuicTimeWaitListManager::OnRevivedPacket() {
+ DCHECK(false);
+}
+
+void QuicTimeWaitListManager::OnFecProtectedPayload(StringPiece /*payload*/) {
+ DCHECK(false);
+}
+
+bool QuicTimeWaitListManager::OnStreamFrame(const QuicStreamFrame& /*frame*/) {
+ DCHECK(false);
return false;
}
-bool QuicTimeWaitListManager::OnAckFrame(const QuicAckFrame& frame) {
+bool QuicTimeWaitListManager::OnAckFrame(const QuicAckFrame& /*frame*/) {
+ DCHECK(false);
return false;
}
bool QuicTimeWaitListManager::OnCongestionFeedbackFrame(
- const QuicCongestionFeedbackFrame& frame) {
+ const QuicCongestionFeedbackFrame& /*frame*/) {
+ DCHECK(false);
return false;
}
bool QuicTimeWaitListManager::OnRstStreamFrame(
- const QuicRstStreamFrame& frame) {
+ const QuicRstStreamFrame& /*frame*/) {
+ DCHECK(false);
return false;
}
bool QuicTimeWaitListManager::OnConnectionCloseFrame(
- const QuicConnectionCloseFrame & frame) {
+ const QuicConnectionCloseFrame & /*frame*/) {
+ DCHECK(false);
return false;
}
-bool QuicTimeWaitListManager::OnGoAwayFrame(const QuicGoAwayFrame& frame) {
+bool QuicTimeWaitListManager::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
+ DCHECK(false);
return false;
}
-bool QuicTimeWaitListManager::OnPacketHeader(const QuicPacketHeader& header) {
- // TODO(satyamshekhar): Think about handling packets from different client
- // addresses.
- GuidMapIterator it = guid_map_.find(header.public_header.guid);
- DCHECK(it != guid_map_.end());
- // Increment the received packet count.
- ++((it->second).num_packets);
- if (ShouldSendPublicReset((it->second).num_packets)) {
- // We don't need the packet anymore. Just tell the client what sequence
- // number we rejected.
- SendPublicReset(server_address_,
- client_address_,
- header.public_header.guid,
- header.packet_sequence_number);
- }
- // Never process the body of the packet in time wait state.
- return false;
+void QuicTimeWaitListManager::OnFecData(const QuicFecData& /*fec*/) {
+ DCHECK(false);
}
// Returns true if the number of packets received for this guid is a power of 2
// to throttle the number of public reset packets we send to a client.
-bool QuicTimeWaitListManager::ShouldSendPublicReset(int received_packet_count) {
+bool QuicTimeWaitListManager::ShouldSendResponse(int received_packet_count) {
return (received_packet_count & (received_packet_count - 1)) == 0;
}
@@ -239,7 +280,7 @@ void QuicTimeWaitListManager::SendPublicReset(
QueuedPacket* queued_packet = new QueuedPacket(
server_address,
client_address,
- framer_.BuildPublicResetPacket(packet));
+ QuicFramer::BuildPublicResetPacket(packet));
// Takes ownership of the packet.
SendOrQueuePacket(queued_packet);
}
@@ -263,22 +304,19 @@ void QuicTimeWaitListManager::SendOrQueuePacket(QueuedPacket* packet) {
void QuicTimeWaitListManager::WriteToWire(QueuedPacket* queued_packet) {
DCHECK(!is_write_blocked_);
- int error;
- int rc = writer_->WritePacket(queued_packet->packet()->data(),
- queued_packet->packet()->length(),
- queued_packet->server_address().address(),
- queued_packet->client_address(),
- this,
- &error);
-
- if (rc == -1) {
- if (error == EAGAIN || error == EWOULDBLOCK) {
- is_write_blocked_ = true;
- } else {
- LOG(WARNING) << "Received unknown error while sending reset packet to "
- << queued_packet->client_address().ToString() << ": "
- << strerror(error);
- }
+ WriteResult result = writer_->WritePacket(
+ queued_packet->packet()->data(),
+ queued_packet->packet()->length(),
+ queued_packet->server_address().address(),
+ queued_packet->client_address(),
+ this);
+
+ if (result.status == WRITE_STATUS_BLOCKED) {
+ is_write_blocked_ = true;
+ } else if (result.status == WRITE_STATUS_ERROR) {
+ LOG(WARNING) << "Received unknown error while sending reset packet to "
+ << queued_packet->client_address().ToString() << ": "
+ << strerror(result.error_code);
}
}
@@ -311,6 +349,9 @@ void QuicTimeWaitListManager::CleanUpOldGuids() {
break;
}
// This guid has lived its age, retire it now.
+ GuidMapIterator it = guid_map_.find(oldest_guid->guid);
+ DCHECK(it != guid_map_.end());
+ delete it->second.close_packet;
guid_map_.erase(oldest_guid->guid);
time_ordered_guid_list_.pop_front();
delete oldest_guid;
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 815b9d913bf..bb24f144a02 100644
--- a/chromium/net/tools/quic/quic_time_wait_list_manager.h
+++ b/chromium/net/tools/quic/quic_time_wait_list_manager.h
@@ -14,39 +14,47 @@
#include "base/strings/string_piece.h"
#include "net/quic/quic_blocked_writer_interface.h"
#include "net/quic/quic_framer.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_epoll_clock.h"
-#include "net/tools/quic/quic_packet_writer.h"
namespace net {
namespace tools {
class GuidCleanUpAlarm;
+namespace test {
+class QuicTimeWaitListManagerPeer;
+} // namespace test
+
// Maintains a list of all guids that have been recently closed. A guid lives in
// this state for kTimeWaitPeriod. All packets received for guids in this state
-// are handed over to the QuicTimeWaitListManager by the QuicDispatcher. It also
-// decides whether we should send a public reset packet to the client which sent
-// a packet with the guid in time wait state and sends it when appropriate.
-// After the guid expires its time wait period, a new connection/session will be
-// created if a packet is received for this guid.
+// are handed over to the QuicTimeWaitListManager by the QuicDispatcher.
+// Decides whether to send a public reset packet, a copy of the previously sent
+// connection close packet, or nothing to the client which sent a packet
+// with the guid in time wait state. After the guid expires its time wait
+// period, a new connection/session will be created if a packet is received
+// for this guid.
class QuicTimeWaitListManager : public QuicBlockedWriterInterface,
public QuicFramerVisitorInterface {
public:
// writer - the entity that writes to the socket. (Owned by the dispatcher)
// epoll_server - used to run clean up alarms. (Owned by the dispatcher)
QuicTimeWaitListManager(QuicPacketWriter* writer,
- EpollServer* epoll_server);
+ EpollServer* epoll_server,
+ const QuicVersionVector& supported_versions);
virtual ~QuicTimeWaitListManager();
// Adds the given guid to time wait state for kTimeWaitPeriod. Henceforth,
// any packet bearing this guid should not be processed while the guid remains
- // in this list. Public reset packets are sent to the clients by the time wait
- // list manager that send packets to guids in this state. DCHECKs that guid is
- // not already on the list. Pass in the version as well so that if a public
- // reset packet needs to be sent the framer version can be set first.
- void AddGuidToTimeWait(QuicGuid guid, QuicVersion version);
+ // in this list. If a non-NULL |close_packet| is provided, it is sent again
+ // when packets are received for added guids. If NULL, a public reset packet
+ // is sent with the specified |version|. DCHECKs that guid is not already on
+ // the list.
+ void AddGuidToTimeWait(QuicGuid guid,
+ QuicVersion version,
+ QuicEncryptedPacket* close_packet); // Owned.
// Returns true if the guid is in time wait state, false otherwise. Packets
// received for this guid should not lead to creation of new QuicSessions.
@@ -70,55 +78,49 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface,
// Used to delete guid entries that have outlived their time wait period.
void CleanUpOldGuids();
- // FramerVisitorInterface
+ // QuicFramerVisitorInterface
virtual void OnError(QuicFramer* framer) OVERRIDE;
virtual bool OnProtocolVersionMismatch(QuicVersion received_version) OVERRIDE;
- virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
+ virtual bool OnUnauthenticatedHeader(const QuicPacketHeader& header) OVERRIDE;
virtual void OnPacket() OVERRIDE {}
virtual void OnPublicResetPacket(
- const QuicPublicResetPacket& packet) OVERRIDE {}
+ const QuicPublicResetPacket& /*packet*/) OVERRIDE {}
virtual void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& /*packet*/) OVERRIDE {}
virtual void OnPacketComplete() OVERRIDE {}
// The following methods should never get called because we always return
- // false from OnPacketHeader(). We never need to process body of a packet.
- virtual void OnRevivedPacket() OVERRIDE {}
- virtual void OnFecProtectedPayload(base::StringPiece payload) OVERRIDE {}
- virtual bool OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE;
- virtual bool OnAckFrame(const QuicAckFrame& frame) OVERRIDE;
+ // false from OnUnauthenticatedHeader(). We never process the encrypted bytes.
+ virtual bool OnPacketHeader(const QuicPacketHeader& header) OVERRIDE;
+ virtual void OnRevivedPacket() OVERRIDE;
+ virtual void OnFecProtectedPayload(base::StringPiece /*payload*/) OVERRIDE;
+ virtual bool OnStreamFrame(const QuicStreamFrame& /*frame*/) OVERRIDE;
+ virtual bool OnAckFrame(const QuicAckFrame& /*frame*/) OVERRIDE;
virtual bool OnCongestionFeedbackFrame(
- const QuicCongestionFeedbackFrame& frame) OVERRIDE;
- virtual bool OnRstStreamFrame(const QuicRstStreamFrame& frame) OVERRIDE;
+ const QuicCongestionFeedbackFrame& /*frame*/) OVERRIDE;
+ virtual bool OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) OVERRIDE;
virtual bool OnConnectionCloseFrame(
- const QuicConnectionCloseFrame & frame) OVERRIDE;
- virtual bool OnGoAwayFrame(const QuicGoAwayFrame& frame) OVERRIDE;
- virtual void OnFecData(const QuicFecData& fec) OVERRIDE {}
-
- QuicVersion version() const { return framer_.version(); }
+ const QuicConnectionCloseFrame & /*frame*/) OVERRIDE;
+ virtual bool OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) OVERRIDE;
+ virtual void OnFecData(const QuicFecData& /*fec*/) OVERRIDE;
- protected:
- // Exposed for tests.
- bool is_write_blocked() const { return is_write_blocked_; }
+ private:
+ friend class test::QuicTimeWaitListManagerPeer;
- // Decides if public reset packet should be sent for this guid based on the
- // number of received pacekts.
- bool ShouldSendPublicReset(int received_packet_count);
+ // Stores the guid and the time it was added to time wait state.
+ struct GuidAddTime;
+ // Internal structure to store pending public reset packets.
+ class QueuedPacket;
- // Exposed for tests.
- const QuicTime::Delta time_wait_period() const { return kTimeWaitPeriod_; }
+ // Decides if a packet should be sent for this guid based on the number of
+ // received packets.
+ bool ShouldSendResponse(int received_packet_count);
// Given a GUID that exists in the time wait list, returns the QuicVersion
// associated with it. Used internally to set the framer version before
// writing the public reset packet.
QuicVersion GetQuicVersionFromGuid(QuicGuid guid);
- private:
- // Stores the guid and the time it was added to time wait state.
- struct GuidAddTime;
- // Internal structure to store pending public reset packets.
- class QueuedPacket;
-
// Creates a public reset packet and sends it or queues it to be sent later.
void SendPublicReset(const IPEndPoint& server_address,
const IPEndPoint& client_address,
@@ -141,10 +143,15 @@ class QuicTimeWaitListManager : public QuicBlockedWriterInterface,
// A map from a recently closed guid to the number of packets received after
// the termination of the connection bound to the guid.
struct GuidData {
- GuidData(int num_packets_, QuicVersion version_)
- : num_packets(num_packets_), version(version_) {}
+ GuidData(int num_packets_,
+ QuicVersion version_,
+ QuicEncryptedPacket* close_packet)
+ : num_packets(num_packets_),
+ version(version_),
+ close_packet(close_packet) {}
int num_packets;
QuicVersion version;
+ QuicEncryptedPacket* close_packet;
};
base::hash_map<QuicGuid, GuidData> guid_map_;
typedef base::hash_map<QuicGuid, GuidData>::iterator GuidMapIterator;
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 8f596874370..22fd8ef4d06 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
@@ -12,9 +12,9 @@
#include "net/quic/crypto/quic_encrypter.h"
#include "net/quic/quic_data_reader.h"
#include "net/quic/quic_framer.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_protocol.h"
#include "net/quic/test_tools/quic_test_utils.h"
-#include "net/tools/quic/quic_packet_writer.h"
#include "net/tools/quic/test_tools/mock_epoll_server.h"
#include "net/tools/quic/test_tools/quic_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -32,19 +32,40 @@ using testing::Truly;
namespace net {
namespace tools {
namespace test {
+
+class QuicTimeWaitListManagerPeer {
+ public:
+ static QuicVersion version(QuicTimeWaitListManager* manager) {
+ return manager->framer_.version();
+ }
+
+ static bool is_write_blocked(QuicTimeWaitListManager* manager) {
+ return manager->is_write_blocked_;
+ }
+
+ static bool ShouldSendResponse(QuicTimeWaitListManager* manager,
+ int received_packet_count) {
+ return manager->ShouldSendResponse(received_packet_count);
+ }
+
+ static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager) {
+ return manager->kTimeWaitPeriod_;
+ }
+
+ static QuicVersion GetQuicVersionFromGuid(QuicTimeWaitListManager* manager,
+ QuicGuid guid) {
+ return manager->GetQuicVersionFromGuid(guid);
+ }
+};
+
namespace {
class TestTimeWaitListManager : public QuicTimeWaitListManager {
public:
TestTimeWaitListManager(QuicPacketWriter* writer,
EpollServer* epoll_server)
- : QuicTimeWaitListManager(writer, epoll_server) {
+ : QuicTimeWaitListManager(writer, epoll_server, QuicSupportedVersions()) {
}
-
- using QuicTimeWaitListManager::is_write_blocked;
- using QuicTimeWaitListManager::time_wait_period;
- using QuicTimeWaitListManager::ShouldSendPublicReset;
- using QuicTimeWaitListManager::GetQuicVersionFromGuid;
};
class MockFakeTimeEpollServer : public FakeTimeEpollServer {
@@ -56,19 +77,22 @@ class MockFakeTimeEpollServer : public FakeTimeEpollServer {
class QuicTimeWaitListManagerTest : public testing::Test {
protected:
QuicTimeWaitListManagerTest()
- : time_wait_list_manager_(&writer_, &epoll_server_),
- framer_(QuicVersionMax(),
- QuicTime::Zero(),
- true),
+ : time_wait_list_manager_(
+ &writer_, &epoll_server_, QuicSupportedVersions()),
+ framer_(QuicSupportedVersions(), QuicTime::Zero(), true),
guid_(45) {
}
+ virtual ~QuicTimeWaitListManagerTest() {}
+
void AddGuid(QuicGuid guid) {
- time_wait_list_manager_.AddGuidToTimeWait(guid, QuicVersionMax());
+ AddGuid(guid, net::test::QuicVersionMax(), NULL);
}
- void AddGuid(QuicGuid guid, QuicVersion version) {
- time_wait_list_manager_.AddGuidToTimeWait(guid, version);
+ void AddGuid(QuicGuid guid,
+ QuicVersion version,
+ QuicEncryptedPacket* packet) {
+ time_wait_list_manager_.AddGuidToTimeWait(guid, version, packet);
}
bool IsGuidInTimeWait(QuicGuid guid) {
@@ -83,6 +107,7 @@ class QuicTimeWaitListManagerTest : public testing::Test {
}
QuicEncryptedPacket* ConstructEncryptedPacket(
+ EncryptionLevel level,
QuicGuid guid,
QuicPacketSequenceNumber sequence_number) {
QuicPacketHeader header;
@@ -97,7 +122,7 @@ class QuicTimeWaitListManagerTest : public testing::Test {
header.fec_flag = false;
header.is_in_fec_group = NOT_IN_FEC_GROUP;
header.fec_group = 0;
- QuicStreamFrame stream_frame(1, false, 0, "data");
+ QuicStreamFrame stream_frame(1, false, 0, MakeIOVector("data"));
QuicFrame frame(&stream_frame);
QuicFrames frames;
frames.push_back(frame);
@@ -113,7 +138,7 @@ class QuicTimeWaitListManagerTest : public testing::Test {
MockFakeTimeEpollServer epoll_server_;
MockPacketWriter writer_;
- TestTimeWaitListManager time_wait_list_manager_;
+ QuicTimeWaitListManager time_wait_list_manager_;
QuicFramer framer_;
QuicGuid guid_;
IPEndPoint server_address_;
@@ -132,7 +157,7 @@ class ValidatePublicResetPacketPredicate
const std::tr1::tuple<const char*, int> packet_buffer,
testing::MatchResultListener* /* listener */) const {
FramerVisitorCapturingPublicReset visitor;
- QuicFramer framer(QuicVersionMax(),
+ QuicFramer framer(QuicSupportedVersions(),
QuicTime::Zero(),
false);
framer.set_visitor(&visitor);
@@ -154,25 +179,6 @@ class ValidatePublicResetPacketPredicate
QuicPacketSequenceNumber sequence_number_;
};
-void ValidPublicResetPacketPredicate(
- QuicGuid expected_guid,
- QuicPacketSequenceNumber expected_sequence_number,
- const std::tr1::tuple<const char*, int>& packet_buffer) {
- FramerVisitorCapturingPublicReset visitor;
- QuicFramer framer(QuicVersionMax(),
- QuicTime::Zero(),
- false);
- framer.set_visitor(&visitor);
- QuicEncryptedPacket encrypted(std::tr1::get<0>(packet_buffer),
- std::tr1::get<1>(packet_buffer));
- framer.ProcessPacket(encrypted);
- QuicPublicResetPacket packet = visitor.public_reset_packet();
- EXPECT_EQ(expected_guid, packet.public_header.guid);
- EXPECT_TRUE(packet.public_header.reset_flag);
- EXPECT_FALSE(packet.public_header.version_flag);
- EXPECT_EQ(expected_sequence_number, packet.rejected_sequence_number);
-}
-
Matcher<const std::tr1::tuple<const char*, int> > PublicResetPacketEq(
QuicGuid guid,
@@ -187,19 +193,53 @@ TEST_F(QuicTimeWaitListManagerTest, CheckGuidInTimeWait) {
EXPECT_TRUE(IsGuidInTimeWait(guid_));
}
+TEST_F(QuicTimeWaitListManagerTest, SendConnectionClose) {
+ size_t kConnectionCloseLength = 100;
+ AddGuid(guid_,
+ net::test::QuicVersionMax(),
+ new QuicEncryptedPacket(
+ new char[kConnectionCloseLength], kConnectionCloseLength, true));
+ const int kRandomSequenceNumber = 1;
+ scoped_ptr<QuicEncryptedPacket> packet(
+ ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber));
+ EXPECT_CALL(writer_, WritePacket(_, kConnectionCloseLength,
+ server_address_.address(),
+ client_address_,
+ &time_wait_list_manager_))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
+
+ ProcessPacket(guid_, *packet);
+}
+
TEST_F(QuicTimeWaitListManagerTest, SendPublicReset) {
AddGuid(guid_);
const int kRandomSequenceNumber = 1;
scoped_ptr<QuicEncryptedPacket> packet(
- ConstructEncryptedPacket(guid_, kRandomSequenceNumber));
+ ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber));
EXPECT_CALL(writer_, WritePacket(_, _,
server_address_.address(),
client_address_,
- &time_wait_list_manager_,
- _))
+ &time_wait_list_manager_))
.With(Args<0, 1>(PublicResetPacketEq(guid_,
kRandomSequenceNumber)))
- .WillOnce(Return(packet->length()));
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
+
+ ProcessPacket(guid_, *packet);
+}
+
+TEST_F(QuicTimeWaitListManagerTest, SendPublicResetUndecryptable) {
+ AddGuid(guid_);
+ const int kRandomSequenceNumber = 1;
+ scoped_ptr<QuicEncryptedPacket> packet(
+ ConstructEncryptedPacket(
+ ENCRYPTION_INITIAL, guid_, kRandomSequenceNumber));
+ EXPECT_CALL(writer_, WritePacket(_, _,
+ server_address_.address(),
+ client_address_,
+ &time_wait_list_manager_))
+ .With(Args<0, 1>(PublicResetPacketEq(guid_,
+ kRandomSequenceNumber)))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
ProcessPacket(guid_, *packet);
}
@@ -208,9 +248,9 @@ TEST_F(QuicTimeWaitListManagerTest, DropInvalidPacket) {
AddGuid(guid_);
const char buffer[] = "invalid";
QuicEncryptedPacket packet(buffer, arraysize(buffer));
- ProcessPacket(guid_, packet);
// Will get called for a valid packet since received packet count = 1 (2 ^ 0).
- EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _)).Times(0);
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0);
+ ProcessPacket(guid_, packet);
}
TEST_F(QuicTimeWaitListManagerTest, DropPublicResetPacket) {
@@ -223,29 +263,28 @@ TEST_F(QuicTimeWaitListManagerTest, DropPublicResetPacket) {
packet.nonce_proof = 1010101;
scoped_ptr<QuicEncryptedPacket> public_reset_packet(
QuicFramer::BuildPublicResetPacket(packet));
- ProcessPacket(guid_, *public_reset_packet);
// Will get called for a data packet since received packet count = 1 (2 ^ 0).
- EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _))
- .Times(0);
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0);
+ ProcessPacket(guid_, *public_reset_packet);
}
TEST_F(QuicTimeWaitListManagerTest, SendPublicResetWithExponentialBackOff) {
AddGuid(guid_);
for (int sequence_number = 1; sequence_number < 101; ++sequence_number) {
scoped_ptr<QuicEncryptedPacket> packet(
- ConstructEncryptedPacket(guid_, sequence_number));
+ ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, sequence_number));
if ((sequence_number & (sequence_number - 1)) == 0) {
- EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _))
- .WillOnce(Return(1));
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _))
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 1)));
}
ProcessPacket(guid_, *packet);
// Send public reset with exponential back off.
if ((sequence_number & (sequence_number - 1)) == 0) {
- EXPECT_TRUE(
- time_wait_list_manager_.ShouldSendPublicReset(sequence_number));
+ EXPECT_TRUE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
+ &time_wait_list_manager_, sequence_number));
} else {
- EXPECT_FALSE(
- time_wait_list_manager_.ShouldSendPublicReset(sequence_number));
+ EXPECT_FALSE(QuicTimeWaitListManagerPeer::ShouldSendResponse(
+ &time_wait_list_manager_, sequence_number));
}
}
}
@@ -262,7 +301,7 @@ TEST_F(QuicTimeWaitListManagerTest, CleanUpOldGuids) {
// Add remaining guids such that their add time is 2 * kTimeWaitPeriod.
const QuicTime::Delta time_wait_period =
- time_wait_list_manager_.time_wait_period();
+ QuicTimeWaitListManagerPeer::time_wait_period(&time_wait_list_manager_);
epoll_server_.set_now_in_usec(time_wait_period.ToMicroseconds());
for (int guid = kOldGuidCount + 1; guid <= kGuidCount; ++guid) {
AddGuid(guid);
@@ -289,32 +328,32 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
AddGuid(guid);
QuicPacketSequenceNumber sequence_number = 234;
scoped_ptr<QuicEncryptedPacket> packet(
- ConstructEncryptedPacket(guid, sequence_number));
+ ConstructEncryptedPacket(ENCRYPTION_NONE, guid, sequence_number));
// Let first write through.
EXPECT_CALL(writer_, WritePacket(_, _,
server_address_.address(),
client_address_,
- &time_wait_list_manager_,
- _))
+ &time_wait_list_manager_))
.With(Args<0, 1>(PublicResetPacketEq(guid,
sequence_number)))
- .WillOnce(Return(packet->length()));
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
ProcessPacket(guid, *packet);
- EXPECT_FALSE(time_wait_list_manager_.is_write_blocked());
+ EXPECT_FALSE(
+ QuicTimeWaitListManagerPeer::is_write_blocked(&time_wait_list_manager_));
// write block for the next packet.
EXPECT_CALL(writer_, WritePacket(_, _,
server_address_.address(),
client_address_,
- &time_wait_list_manager_,
- _))
+ &time_wait_list_manager_))
.With(Args<0, 1>(PublicResetPacketEq(guid,
sequence_number)))
- .WillOnce(DoAll(SetArgPointee<5>(EAGAIN), Return(-1)));
+ .WillOnce(Return(WriteResult(WRITE_STATUS_BLOCKED, EAGAIN)));
ProcessPacket(guid, *packet);
// 3rd packet. No public reset should be sent;
ProcessPacket(guid, *packet);
- EXPECT_TRUE(time_wait_list_manager_.is_write_blocked());
+ EXPECT_TRUE(
+ QuicTimeWaitListManagerPeer::is_write_blocked(&time_wait_list_manager_));
// write packet should not be called since already write blocked but the
// should be queued.
@@ -322,8 +361,9 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
AddGuid(other_guid);
QuicPacketSequenceNumber other_sequence_number = 23423;
scoped_ptr<QuicEncryptedPacket> other_packet(
- ConstructEncryptedPacket(other_guid, other_sequence_number));
- EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _))
+ ConstructEncryptedPacket(
+ ENCRYPTION_NONE, other_guid, other_sequence_number));
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _))
.Times(0);
ProcessPacket(other_guid, *other_packet);
@@ -331,47 +371,53 @@ TEST_F(QuicTimeWaitListManagerTest, SendQueuedPackets) {
EXPECT_CALL(writer_, WritePacket(_, _,
server_address_.address(),
client_address_,
- &time_wait_list_manager_,
- _))
+ &time_wait_list_manager_))
.With(Args<0, 1>(PublicResetPacketEq(guid,
sequence_number)))
- .WillOnce(Return(packet->length()));
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, packet->length())));
EXPECT_CALL(writer_, WritePacket(_, _,
server_address_.address(),
client_address_,
- &time_wait_list_manager_,
- _))
+ &time_wait_list_manager_))
.With(Args<0, 1>(PublicResetPacketEq(other_guid,
other_sequence_number)))
- .WillOnce(Return(other_packet->length()));
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK,
+ other_packet->length())));
time_wait_list_manager_.OnCanWrite();
- EXPECT_FALSE(time_wait_list_manager_.is_write_blocked());
+ EXPECT_FALSE(
+ QuicTimeWaitListManagerPeer::is_write_blocked(&time_wait_list_manager_));
}
TEST_F(QuicTimeWaitListManagerTest, MakeSureFramerUsesCorrectVersion) {
const int kRandomSequenceNumber = 1;
scoped_ptr<QuicEncryptedPacket> packet;
- AddGuid(guid_, QuicVersionMin());
- framer_.set_version(QuicVersionMin());
- packet.reset(ConstructEncryptedPacket(guid_, kRandomSequenceNumber));
+ AddGuid(guid_, net::test::QuicVersionMin(), NULL);
+ framer_.set_version(net::test::QuicVersionMin());
+ packet.reset(
+ ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber));
// Reset packet should be written, using the minimum quic version.
- EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _)).Times(1);
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(1)
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
ProcessPacket(guid_, *packet);
- EXPECT_EQ(time_wait_list_manager_.version(), QuicVersionMin());
+ EXPECT_EQ(QuicTimeWaitListManagerPeer::version(&time_wait_list_manager_),
+ net::test::QuicVersionMin());
// New guid
++guid_;
- AddGuid(guid_, QuicVersionMax());
- framer_.set_version(QuicVersionMax());
- packet.reset(ConstructEncryptedPacket(guid_, kRandomSequenceNumber));
+ AddGuid(guid_, net::test::QuicVersionMax(), NULL);
+ framer_.set_version(net::test::QuicVersionMax());
+ packet.reset(
+ ConstructEncryptedPacket(ENCRYPTION_NONE, guid_, kRandomSequenceNumber));
// Reset packet should be written, using the maximum quic version.
- EXPECT_CALL(writer_, WritePacket(_, _, _, _, _, _)).Times(1);
+ EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(1)
+ .WillOnce(Return(WriteResult(WRITE_STATUS_OK, 0)));
ProcessPacket(guid_, *packet);
- EXPECT_EQ(time_wait_list_manager_.version(), QuicVersionMax());
+ EXPECT_EQ(QuicTimeWaitListManagerPeer::version(&time_wait_list_manager_),
+ net::test::QuicVersionMax());
}
TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
@@ -379,16 +425,19 @@ TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
const int kGuid2 = 456;
const int kGuid3 = 789;
- AddGuid(kGuid1, QuicVersionMin());
- AddGuid(kGuid2, QuicVersionMax());
- AddGuid(kGuid3, QuicVersionMax());
-
- EXPECT_EQ(QuicVersionMin(),
- time_wait_list_manager_.GetQuicVersionFromGuid(kGuid1));
- EXPECT_EQ(QuicVersionMax(),
- time_wait_list_manager_.GetQuicVersionFromGuid(kGuid2));
- EXPECT_EQ(QuicVersionMax(),
- time_wait_list_manager_.GetQuicVersionFromGuid(kGuid3));
+ AddGuid(kGuid1, net::test::QuicVersionMin(), NULL);
+ AddGuid(kGuid2, net::test::QuicVersionMax(), NULL);
+ AddGuid(kGuid3, net::test::QuicVersionMax(), NULL);
+
+ EXPECT_EQ(net::test::QuicVersionMin(),
+ QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
+ &time_wait_list_manager_, kGuid1));
+ EXPECT_EQ(net::test::QuicVersionMax(),
+ QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
+ &time_wait_list_manager_, kGuid2));
+ EXPECT_EQ(net::test::QuicVersionMax(),
+ QuicTimeWaitListManagerPeer::GetQuicVersionFromGuid(
+ &time_wait_list_manager_, kGuid3));
}
} // namespace
diff --git a/chromium/net/tools/quic/spdy_utils.cc b/chromium/net/tools/quic/spdy_utils.cc
index 13d05e5e706..c350a96f9e2 100644
--- a/chromium/net/tools/quic/spdy_utils.cc
+++ b/chromium/net/tools/quic/spdy_utils.cc
@@ -13,7 +13,7 @@
#include "net/spdy/spdy_frame_builder.h"
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_protocol.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "url/gurl.h"
using base::StringPiece;
@@ -250,10 +250,10 @@ bool SpdyUtils::FillBalsaResponseHeaders(
return false;
}
- request_headers->SetRequestVersion(version_it->second);
if (!ParseReasonAndStatus(status_it->second, request_headers)) {
return false;
}
+ request_headers->SetResponseVersion(version_it->second);
for (BlockIt it = header_block.begin(); it != header_block.end(); ++it) {
if (!IsSpecialSpdyHeader(it, request_headers)) {
request_headers->AppendHeader(it->first, it->second);
diff --git a/chromium/net/tools/quic/spdy_utils.h b/chromium/net/tools/quic/spdy_utils.h
index 44782744526..cfad5f1918b 100644
--- a/chromium/net/tools/quic/spdy_utils.h
+++ b/chromium/net/tools/quic/spdy_utils.h
@@ -10,7 +10,7 @@
#include "net/spdy/spdy_framer.h"
#include "net/spdy/spdy_header_block.h"
#include "net/spdy/spdy_protocol.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_headers.h"
namespace net {
namespace tools {
diff --git a/chromium/net/tools/quic/test_tools/http_message_test_utils.h b/chromium/net/tools/quic/test_tools/http_message_test_utils.h
index d389e21c8f2..fefdb4909cd 100644
--- a/chromium/net/tools/quic/test_tools/http_message_test_utils.h
+++ b/chromium/net/tools/quic/test_tools/http_message_test_utils.h
@@ -9,8 +9,8 @@
#include <vector>
#include "base/strings/string_piece.h"
-#include "net/tools/flip_server/balsa_enums.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/tools/balsa/balsa_enums.h"
+#include "net/tools/balsa/balsa_headers.h"
namespace net {
namespace tools {
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 710d5fdf772..fbc16956d72 100644
--- a/chromium/net/tools/quic/test_tools/mock_epoll_server.h
+++ b/chromium/net/tools/quic/test_tools/mock_epoll_server.h
@@ -6,7 +6,7 @@
#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_EPOLL_SERVER_H_
#include "base/logging.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
diff --git a/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.cc b/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.cc
index 3a2b1d98252..2d9c1ec184f 100644
--- a/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.cc
+++ b/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.cc
@@ -13,7 +13,9 @@ MockQuicDispatcher::MockQuicDispatcher(
const QuicCryptoServerConfig& crypto_config,
QuicGuid guid,
EpollServer* eps)
- : QuicDispatcher(config, crypto_config, guid, eps) { }
+ : QuicDispatcher(config, crypto_config, QuicSupportedVersions(), guid,
+ eps) {
+}
MockQuicDispatcher::~MockQuicDispatcher() {}
} // namespace test
diff --git a/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.h b/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.h
index 563ab0de5fd..5f885e875b6 100644
--- a/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.h
+++ b/chromium/net/tools/quic/test_tools/mock_quic_dispatcher.h
@@ -6,10 +6,10 @@
#define NET_TOOLS_QUIC_TEST_TOOLS_MOCK_QUIC_DISPATCHER_H_
#include "net/base/ip_endpoint.h"
-#include "net/quic/crypto/crypto_server_config.h"
+#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/quic_config.h"
#include "net/quic/quic_protocol.h"
-#include "net/tools/flip_server/epoll_server.h"
+#include "net/tools/epoll_server/epoll_server.h"
#include "net/tools/quic/quic_dispatcher.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -25,9 +25,10 @@ class MockQuicDispatcher : public QuicDispatcher {
EpollServer* eps);
virtual ~MockQuicDispatcher();
- MOCK_METHOD4(ProcessPacket, void(const IPEndPoint& server_address,
+ MOCK_METHOD5(ProcessPacket, void(const IPEndPoint& server_address,
const IPEndPoint& client_address,
QuicGuid guid,
+ bool has_version_flag,
const QuicEncryptedPacket& packet));
};
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
new file mode 100644
index 00000000000..11aafb69495
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.cc
@@ -0,0 +1,203 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/test_tools/packet_dropping_test_writer.h"
+
+#include <limits>
+
+#include "base/rand_util.h"
+#include "net/tools/quic/quic_epoll_connection_helper.h"
+#include "net/tools/quic/quic_socket_utils.h"
+
+using net::test::QuicTestWriter;
+
+namespace net {
+namespace tools {
+namespace test {
+
+// An alarm that is scheduled if a blocked socket is simulated to indicate
+// it's writable again.
+class WriteUnblockedAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer)
+ : writer_(writer) { }
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ DCHECK(writer_->blocked_writer());
+ writer_->blocked_writer()->OnCanWrite();
+ return QuicTime::Zero();
+ }
+
+ private:
+ PacketDroppingTestWriter* writer_;
+};
+
+// An alarm that is scheduled every time a new packet is to be written at a
+// later point.
+class DelayAlarm : public QuicAlarm::Delegate {
+ public:
+ explicit DelayAlarm(PacketDroppingTestWriter* writer)
+ : writer_(writer) { }
+
+ virtual QuicTime OnAlarm() OVERRIDE {
+ return writer_->ReleaseOldPackets();
+ }
+
+ private:
+ PacketDroppingTestWriter* writer_;
+};
+
+PacketDroppingTestWriter::PacketDroppingTestWriter()
+ : clock_(NULL),
+ blocked_writer_(NULL),
+ cur_buffer_size_(0),
+ config_mutex_(),
+ fake_packet_loss_percentage_(0),
+ fake_blocked_socket_percentage_(0),
+ fake_packet_reorder_percentage_(0),
+ fake_packet_delay_(QuicTime::Delta::Zero()),
+ fake_bandwidth_(QuicBandwidth::Zero()),
+ buffer_size_(0) {
+ uint32 seed = base::RandInt(0, std::numeric_limits<int32>::max());
+ LOG(INFO) << "Seeding packet loss with " << seed;
+ simple_random_.set_seed(seed);
+}
+
+PacketDroppingTestWriter::~PacketDroppingTestWriter() { }
+
+void PacketDroppingTestWriter::SetConnectionHelper(
+ QuicEpollConnectionHelper* helper) {
+ clock_ = helper->GetClock();
+ write_unblocked_alarm_.reset(
+ helper->CreateAlarm(new WriteUnblockedAlarm(this)));
+ delay_alarm_.reset(
+ helper->CreateAlarm(new DelayAlarm(this)));
+}
+
+WriteResult PacketDroppingTestWriter::WritePacket(
+ const char* buffer, size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) {
+ ReleaseOldPackets();
+
+ base::AutoLock locked(config_mutex_);
+ if (fake_packet_loss_percentage_ > 0 &&
+ simple_random_.RandUint64() % 100 <
+ static_cast<uint64>(fake_packet_loss_percentage_)) {
+ DLOG(INFO) << "Dropping packet.";
+ return WriteResult(WRITE_STATUS_OK, buf_len);
+ }
+ if (fake_blocked_socket_percentage_ > 0 &&
+ simple_random_.RandUint64() % 100 <
+ static_cast<uint64>(fake_blocked_socket_percentage_)) {
+ DLOG(INFO) << "Blocking socket.";
+ if (!write_unblocked_alarm_->IsSet()) {
+ blocked_writer_ = blocked_writer;
+ // Set the alarm for 1ms in the future.
+ write_unblocked_alarm_->Set(
+ clock_->ApproximateNow().Add(
+ QuicTime::Delta::FromMilliseconds(1)));
+ }
+ return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
+ }
+
+ if (!fake_packet_delay_.IsZero() || !fake_bandwidth_.IsZero()) {
+ if (buffer_size_ > 0 && buf_len + cur_buffer_size_ > buffer_size_) {
+ // Drop packets which do not fit into the buffer.
+ DLOG(INFO) << "Dropping packet because the buffer is full.";
+ return WriteResult(WRITE_STATUS_OK, buf_len);
+ }
+
+ // Queue it to be sent.
+ QuicTime send_time = clock_->ApproximateNow().Add(fake_packet_delay_);
+ if (!fake_bandwidth_.IsZero()) {
+ // Calculate a time the bandwidth limit would impose.
+ QuicTime::Delta bandwidth_delay = QuicTime::Delta::FromMicroseconds(
+ (buf_len * kNumMicrosPerSecond) /
+ fake_bandwidth_.ToBytesPerSecond());
+ send_time = delayed_packets_.empty() ?
+ send_time.Add(bandwidth_delay) :
+ delayed_packets_.back().send_time.Add(bandwidth_delay);
+ }
+ delayed_packets_.push_back(DelayedWrite(buffer, buf_len, self_address,
+ peer_address, send_time));
+ cur_buffer_size_ += buf_len;
+
+ // Set the alarm if it's not yet set.
+ if (!delay_alarm_->IsSet()) {
+ delay_alarm_->Set(send_time);
+ }
+
+ return WriteResult(WRITE_STATUS_OK, buf_len);
+ }
+
+ return writer()->WritePacket(buffer, buf_len, self_address, peer_address,
+ blocked_writer);
+}
+
+bool PacketDroppingTestWriter::IsWriteBlockedDataBuffered() const {
+ return false;
+}
+
+QuicTime PacketDroppingTestWriter::ReleaseNextPacket() {
+ if (delayed_packets_.empty()) {
+ return QuicTime::Zero();
+ }
+ base::AutoLock locked(config_mutex_);
+ DelayedPacketList::iterator iter = delayed_packets_.begin();
+ // Determine if we should re-order.
+ if (delayed_packets_.size() > 1 && fake_packet_reorder_percentage_ > 0 &&
+ simple_random_.RandUint64() % 100 <
+ static_cast<uint64>(fake_packet_reorder_percentage_)) {
+ DLOG(INFO) << "Reordering packets.";
+ ++iter;
+ // Swap the send times when re-ordering packets.
+ delayed_packets_.begin()->send_time = iter->send_time;
+ }
+
+ DLOG(INFO) << "Releasing packet. " << (delayed_packets_.size() - 1)
+ << " remaining.";
+ // Grab the next one off the queue and send it.
+ writer()->WritePacket(iter->buffer.data(), iter->buffer.length(),
+ iter->self_address, iter->peer_address, NULL);
+ DCHECK_GE(cur_buffer_size_, iter->buffer.length());
+ cur_buffer_size_ -= iter->buffer.length();
+ delayed_packets_.erase(iter);
+
+ // If there are others, find the time for the next to be sent.
+ if (delayed_packets_.empty()) {
+ return QuicTime::Zero();
+ }
+ return delayed_packets_.begin()->send_time;
+}
+
+QuicTime PacketDroppingTestWriter::ReleaseOldPackets() {
+ while (!delayed_packets_.empty()) {
+ QuicTime next_send_time = delayed_packets_.front().send_time;
+ if (next_send_time > clock_->Now()) {
+ return next_send_time;
+ }
+ ReleaseNextPacket();
+ }
+ return QuicTime::Zero();
+}
+
+PacketDroppingTestWriter::DelayedWrite::DelayedWrite(
+ const char* buffer,
+ size_t buf_len,
+ const net::IPAddressNumber& self_address,
+ const net::IPEndPoint& peer_address,
+ QuicTime send_time)
+ : buffer(buffer, buf_len),
+ self_address(self_address),
+ peer_address(peer_address),
+ send_time(send_time) {
+}
+
+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
new file mode 100644
index 00000000000..2a736e0cfe2
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/packet_dropping_test_writer.h
@@ -0,0 +1,146 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
+#define NET_TOOLS_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
+
+#include <list>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "net/quic/quic_alarm.h"
+#include "net/quic/quic_blocked_writer_interface.h"
+#include "net/quic/quic_packet_writer.h"
+#include "net/quic/test_tools/quic_test_writer.h"
+#include "net/tools/quic/quic_epoll_clock.h"
+#include "net/tools/quic/test_tools/quic_test_client.h"
+#include "net/tools/quic/test_tools/quic_test_utils.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+// Simulates a connection that drops packets a configured percentage of the time
+// and has a blocked socket a configured percentage of the time. Also provides
+// the options to delay packets and reorder packets if delay is enabled.
+class PacketDroppingTestWriter : public net::test::QuicTestWriter {
+ public:
+ PacketDroppingTestWriter();
+
+ virtual ~PacketDroppingTestWriter();
+
+ void SetConnectionHelper(QuicEpollConnectionHelper* helper);
+
+ // QuicPacketWriter methods:
+ virtual WriteResult WritePacket(
+ const char* buffer, size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer) OVERRIDE;
+
+ virtual bool IsWriteBlockedDataBuffered() const OVERRIDE;
+
+ // Writes out any packet which should have been sent by now
+ // to the contained writer and returns the time
+ // for the next delayed packet to be written.
+ QuicTime ReleaseOldPackets();
+
+ QuicBlockedWriterInterface* blocked_writer() { return blocked_writer_; }
+
+ // The percent of time a packet is simulated as being lost.
+ void set_fake_packet_loss_percentage(int32 fake_packet_loss_percentage) {
+ base::AutoLock locked(config_mutex_);
+ fake_packet_loss_percentage_ = fake_packet_loss_percentage;
+ }
+
+ // The percent of time WritePacket will block and set WriteResult's status
+ // to WRITE_STATUS_BLOCKED.
+ void set_fake_blocked_socket_percentage(
+ int32 fake_blocked_socket_percentage) {
+ DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
+ fake_blocked_socket_percentage_ = fake_blocked_socket_percentage;
+ }
+
+ // The percent of time a packet is simulated as being reordered.
+ void set_fake_reorder_percentage(int32 fake_packet_reorder_percentage) {
+ DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
+ DCHECK(!fake_packet_delay_.IsZero());
+ fake_packet_reorder_percentage_ = fake_packet_reorder_percentage;
+ }
+
+ // The percent of time WritePacket will block and set WriteResult's status
+ // to WRITE_STATUS_BLOCKED.
+ void set_fake_packet_delay(QuicTime::Delta fake_packet_delay) {
+ DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
+ fake_packet_delay_ = fake_packet_delay;
+ }
+
+ // The maximum bandwidth and buffer size of the connection. When these are
+ // set, packets will be delayed until a connection with that bandwidth would
+ // transmit it. Once the |buffer_size| is reached, all new packets are
+ // dropped.
+ void set_max_bandwidth_and_buffer_size(QuicBandwidth fake_bandwidth,
+ QuicByteCount buffer_size) {
+ DCHECK(clock_);
+ base::AutoLock locked(config_mutex_);
+ fake_bandwidth_ = fake_bandwidth;
+ buffer_size_ = buffer_size;
+ }
+
+ void set_seed(uint64 seed) {
+ simple_random_.set_seed(seed);
+ }
+
+ private:
+ // Writes out the next packet to the contained writer and returns the time
+ // for the next delayed packet to be written.
+ QuicTime ReleaseNextPacket();
+
+ // A single packet which will be sent at the supplied send_time.
+ class DelayedWrite {
+ public:
+ DelayedWrite(const char* buffer,
+ size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicTime send_time);
+ ~DelayedWrite();
+
+ string buffer;
+ const IPAddressNumber self_address;
+ const IPEndPoint peer_address;
+ QuicTime send_time;
+ };
+
+ typedef std::list<DelayedWrite> DelayedPacketList;
+
+ const QuicClock* clock_;
+ scoped_ptr<QuicAlarm> write_unblocked_alarm_;
+ scoped_ptr<QuicAlarm> delay_alarm_;
+ QuicBlockedWriterInterface* blocked_writer_;
+ SimpleRandom simple_random_;
+ // Stored packets delayed by fake packet delay or bandwidth restrictions.
+ DelayedPacketList delayed_packets_;
+ QuicByteCount cur_buffer_size_;
+
+ base::Lock config_mutex_;
+ int32 fake_packet_loss_percentage_;
+ int32 fake_blocked_socket_percentage_;
+ int32 fake_packet_reorder_percentage_;
+ QuicTime::Delta fake_packet_delay_;
+ QuicBandwidth fake_bandwidth_;
+ QuicByteCount buffer_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PacketDroppingTestWriter);
+};
+
+} // 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_dispatcher_peer.cc b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
new file mode 100644
index 00000000000..c96eafd57e5
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/test_tools/quic_dispatcher_peer.h"
+
+#include "net/tools/quic/quic_dispatcher.h"
+
+using net::test::QuicTestWriter;
+
+namespace net {
+namespace tools {
+namespace test {
+
+// static
+void QuicDispatcherPeer::SetTimeWaitListManager(
+ QuicDispatcher* dispatcher,
+ QuicTimeWaitListManager* time_wait_list_manager) {
+ dispatcher->time_wait_list_manager_.reset(time_wait_list_manager);
+}
+
+// static
+void QuicDispatcherPeer::SetWriteBlocked(QuicDispatcher* dispatcher) {
+ dispatcher->write_blocked_ = true;
+}
+
+// static
+void QuicDispatcherPeer::UseWriter(QuicDispatcher* dispatcher,
+ QuicTestWriter* writer) {
+ writer->set_writer(dispatcher->writer_.release());
+ dispatcher->writer_.reset(writer);
+}
+
+// static
+QuicPacketWriter* QuicDispatcherPeer::GetWriter(QuicDispatcher* dispatcher) {
+ return dispatcher->writer_.get();
+}
+
+// static
+QuicEpollConnectionHelper* QuicDispatcherPeer::GetHelper(
+ QuicDispatcher* dispatcher) {
+ return dispatcher->helper_.get();
+}
+
+} // 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
new file mode 100644
index 00000000000..f463453f17a
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/quic_dispatcher_peer.h
@@ -0,0 +1,35 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_
+#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_DISPATCHER_PEER_H_
+
+#include "net/quic/test_tools/quic_test_writer.h"
+#include "net/tools/quic/quic_dispatcher.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+class QuicDispatcherPeer {
+ public:
+ static void SetTimeWaitListManager(
+ QuicDispatcher* dispatcher,
+ QuicTimeWaitListManager* time_wait_list_manager);
+
+ static void SetWriteBlocked(QuicDispatcher* dispatcher);
+
+ static void UseWriter(QuicDispatcher* dispatcher,
+ net::test::QuicTestWriter* writer);
+
+ static QuicPacketWriter* GetWriter(QuicDispatcher* dispatcher);
+
+ static QuicEpollConnectionHelper* GetHelper(QuicDispatcher* dispatcher);
+};
+
+} // 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_epoll_connection_helper_peer.cc b/chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.cc
deleted file mode 100644
index e358273d0a2..00000000000
--- a/chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.cc
+++ /dev/null
@@ -1,21 +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.
-
-#include "net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h"
-
-#include "net/tools/quic/quic_epoll_connection_helper.h"
-
-namespace net {
-namespace tools {
-namespace test {
-
-// static
-void QuicEpollConnectionHelperPeer::SetWriter(QuicEpollConnectionHelper* helper,
- QuicPacketWriter* writer) {
- helper->writer_ = writer;
-}
-
-} // namespace test
-} // namespace tools
-} // namespace net
diff --git a/chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h b/chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h
deleted file mode 100644
index 72085dfde1c..00000000000
--- a/chromium/net/tools/quic/test_tools/quic_epoll_connection_helper_peer.h
+++ /dev/null
@@ -1,31 +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.
-
-#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_EPOLL_CONNECTION_HELPER_PEER_H_
-#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_EPOLL_CONNECTION_HELPER_PEER_H_
-
-#include "base/basictypes.h"
-
-namespace net {
-namespace tools {
-
-class QuicPacketWriter;
-class QuicEpollConnectionHelper;
-
-namespace test {
-
-class QuicEpollConnectionHelperPeer {
- public:
- static void SetWriter(QuicEpollConnectionHelper* helper,
- QuicPacketWriter* writer);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(QuicEpollConnectionHelperPeer);
-};
-
-} // namespace test
-} // namespace tools
-} // namespace net
-
-#endif // NET_TOOLS_QUIC_TEST_TOOLS_QUIC_EPOLL_CONNECTION_HELPER_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
new file mode 100644
index 00000000000..feb506e49c8
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.cc
@@ -0,0 +1,20 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
+
+#include "net/tools/quic/quic_in_memory_cache.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+// static
+void QuicInMemoryCachePeer::ResetForTests() {
+ QuicInMemoryCache::GetInstance()->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
new file mode 100644
index 00000000000..b5996bd7505
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/quic_in_memory_cache_peer.h
@@ -0,0 +1,27 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_IN_MEMORY_CACHE_PEER_H_
+#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_IN_MEMORY_CACHE_PEER_H_
+
+#include "net/tools/quic/quic_in_memory_cache.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+class QuicInMemoryCachePeer {
+ public:
+ // Resets the singleton QuicInMemoryCache to a fresh state.
+ static void ResetForTests();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCachePeer);
+};
+
+} // namespace test
+} // namespace 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
new file mode 100644
index 00000000000..15f31297d17
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/quic_server_peer.cc
@@ -0,0 +1,38 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/test_tools/quic_server_peer.h"
+
+#include "net/tools/quic/quic_dispatcher.h"
+#include "net/tools/quic/quic_server.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+// static
+bool QuicServerPeer::SetSmallSocket(QuicServer* server) {
+ int size = 1024 * 10;
+ return setsockopt(
+ server->fd_, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) != -1;
+}
+
+// static
+void QuicServerPeer::DisableRecvmmsg(QuicServer* server) {
+ server->use_recvmmsg_ = false;
+}
+
+// static
+QuicDispatcher* QuicServerPeer::GetDispatcher(QuicServer* server) {
+ return server->dispatcher_.get();
+}
+
+// static
+int QuicServerPeer::GetFD(QuicServer* server) {
+ return server->fd_;
+}
+
+} // 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
new file mode 100644
index 00000000000..65e2c5e96b2
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/quic_server_peer.h
@@ -0,0 +1,29 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_TEST_TOOLS_QUIC_SERVER_PEER_H_
+#define NET_TOOLS_QUIC_TEST_TOOLS_QUIC_SERVER_PEER_H_
+
+namespace net {
+
+namespace tools {
+
+class QuicDispatcher;
+class QuicServer;
+
+namespace test {
+
+class QuicServerPeer {
+ public:
+ static bool SetSmallSocket(QuicServer* server);
+ static void DisableRecvmmsg(QuicServer* server);
+ static QuicDispatcher* GetDispatcher(QuicServer* server);
+ static int GetFD(QuicServer* server);
+};
+
+} // 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 272786ebf45..57edadeec70 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_client.cc
+++ b/chromium/net/tools/quic/test_tools/quic_test_client.cc
@@ -4,20 +4,24 @@
#include "net/tools/quic/test_tools/quic_test_client.h"
+#include "base/time/time.h"
#include "net/base/completion_callback.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/quic/crypto/proof_verifier.h"
-#include "net/tools/flip_server/balsa_headers.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
+#include "net/tools/balsa/balsa_headers.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
#include "net/tools/quic/quic_spdy_client_stream.h"
#include "net/tools/quic/test_tools/http_message_test_utils.h"
#include "url/gurl.h"
+using base::StringPiece;
+using net::test::QuicConnectionPeer;
+using net::test::QuicTestWriter;
using std::string;
using std::vector;
-using base::StringPiece;
namespace {
@@ -97,15 +101,17 @@ class QuicEpollClient : public QuicClient {
QuicEpollClient(IPEndPoint server_address,
const string& server_hostname,
- const QuicVersion version)
- : Super(server_address, server_hostname, version) {
+ const QuicVersionVector& supported_versions)
+ : Super(server_address, server_hostname, supported_versions, false),
+ override_guid_(0), test_writer_(NULL) {
}
QuicEpollClient(IPEndPoint server_address,
const string& server_hostname,
const QuicConfig& config,
- const QuicVersion version)
- : Super(server_address, server_hostname, config, version) {
+ const QuicVersionVector& supported_versions)
+ : Super(server_address, server_hostname, config, supported_versions),
+ override_guid_(0), test_writer_(NULL) {
}
virtual ~QuicEpollClient() {
@@ -114,32 +120,42 @@ class QuicEpollClient : public QuicClient {
}
}
- virtual QuicEpollConnectionHelper* CreateQuicConnectionHelper() OVERRIDE {
- if (writer_.get() != NULL) {
- writer_->set_fd(fd());
- return new QuicEpollConnectionHelper(writer_.get(), epoll_server());
- } else {
- return Super::CreateQuicConnectionHelper();
+ virtual QuicPacketWriter* CreateQuicPacketWriter() OVERRIDE {
+ QuicPacketWriter* writer = Super::CreateQuicPacketWriter();
+ if (!test_writer_) {
+ return writer;
}
+ test_writer_->set_writer(writer);
+ return test_writer_;
}
- void UseWriter(QuicTestWriter* writer) { writer_.reset(writer); }
+ virtual QuicGuid GenerateGuid() OVERRIDE {
+ return override_guid_ ? override_guid_ : Super::GenerateGuid();
+ }
+
+ // Takes ownership of writer.
+ void UseWriter(QuicTestWriter* writer) { test_writer_ = writer; }
+
+ void UseGuid(QuicGuid guid) {
+ override_guid_ = guid;
+ }
private:
- scoped_ptr<QuicTestWriter> writer_;
+ QuicGuid override_guid_; // GUID to use, if nonzero
+ QuicTestWriter* test_writer_;
};
QuicTestClient::QuicTestClient(IPEndPoint address, const string& hostname,
- const QuicVersion version)
- : client_(new QuicEpollClient(address, hostname, version)) {
+ const QuicVersionVector& supported_versions)
+ : client_(new QuicEpollClient(address, hostname, supported_versions)) {
Initialize(address, hostname, true);
}
QuicTestClient::QuicTestClient(IPEndPoint address,
const string& hostname,
bool secure,
- const QuicVersion version)
- : client_(new QuicEpollClient(address, hostname, version)) {
+ const QuicVersionVector& supported_versions)
+ : client_(new QuicEpollClient(address, hostname, supported_versions)) {
Initialize(address, hostname, secure);
}
@@ -147,8 +163,9 @@ QuicTestClient::QuicTestClient(IPEndPoint address,
const string& hostname,
bool secure,
const QuicConfig& config,
- const QuicVersion version)
- : client_(new QuicEpollClient(address, hostname, config, version)) {
+ const QuicVersionVector& supported_versions)
+ : client_(new QuicEpollClient(address, hostname, config,
+ supported_versions)) {
Initialize(address, hostname, secure);
}
@@ -156,15 +173,13 @@ void QuicTestClient::Initialize(IPEndPoint address,
const string& hostname,
bool secure) {
server_address_ = address;
- stream_ = NULL;
- stream_error_ = QUIC_STREAM_NO_ERROR;
priority_ = 3;
- bytes_read_ = 0;
- bytes_written_= 0;
- never_connected_ = true;
+ connect_attempted_ = false;
secure_ = secure;
auto_reconnect_ = false;
+ buffer_body_ = true;
proof_verifier_ = NULL;
+ ClearPerRequestState();
ExpectCertificates(secure_);
}
@@ -200,21 +215,24 @@ ssize_t QuicTestClient::SendMessage(const HTTPMessage& message) {
}
}
- QuicReliableClientStream* stream = GetOrCreateStream();
+ QuicSpdyClientStream* stream = GetOrCreateStream();
if (!stream) { return 0; }
scoped_ptr<BalsaHeaders> munged_headers(MungeHeaders(message.headers(),
secure_));
- return GetOrCreateStream()->SendRequest(
+ ssize_t ret = GetOrCreateStream()->SendRequest(
munged_headers.get() ? *munged_headers.get() : *message.headers(),
message.body(),
message.has_complete_message());
+ WaitForWriteToFlush();
+ return ret;
}
ssize_t QuicTestClient::SendData(string data, bool last_data) {
- QuicReliableClientStream* stream = GetOrCreateStream();
+ QuicSpdyClientStream* stream = GetOrCreateStream();
if (!stream) { return 0; }
GetOrCreateStream()->SendBody(data, last_data);
+ WaitForWriteToFlush();
return data.length();
}
@@ -234,8 +252,8 @@ string QuicTestClient::SendSynchronousRequest(const string& uri) {
return response_;
}
-QuicReliableClientStream* QuicTestClient::GetOrCreateStream() {
- if (never_connected_ == true || auto_reconnect_) {
+QuicSpdyClientStream* QuicTestClient::GetOrCreateStream() {
+ if (!connect_attempted_ || auto_reconnect_) {
if (!connected()) {
Connect();
}
@@ -274,9 +292,11 @@ void QuicTestClient::WaitForResponse() {
void QuicTestClient::Connect() {
DCHECK(!connected());
- client_->Initialize();
+ if (!connect_attempted_) {
+ client_->Initialize();
+ }
client_->Connect();
- never_connected_ = false;
+ connect_attempted_ = true;
}
void QuicTestClient::ResetConnection() {
@@ -286,6 +306,7 @@ void QuicTestClient::ResetConnection() {
void QuicTestClient::Disconnect() {
client_->Disconnect();
+ connect_attempted_ = false;
}
IPEndPoint QuicTestClient::LocalSocketAddress() const {
@@ -296,22 +317,78 @@ void QuicTestClient::ClearPerRequestState() {
stream_error_ = QUIC_STREAM_NO_ERROR;
stream_ = NULL;
response_ = "";
+ response_complete_ = false;
+ response_headers_complete_ = false;
headers_.Clear();
bytes_read_ = 0;
bytes_written_ = 0;
+ response_header_size_ = 0;
+ response_body_size_ = 0;
}
-void QuicTestClient::WaitForInitialResponse() {
- DCHECK(stream_ != NULL);
- while (stream_ && stream_->stream_bytes_read() == 0) {
+void QuicTestClient::WaitForResponseForMs(int timeout_ms) {
+ int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
+ int64 old_timeout_us = client()->epoll_server()->timeout_in_us();
+ if (timeout_us > 0) {
+ client()->epoll_server()->set_timeout_in_us(timeout_us);
+ }
+ const QuicClock* clock =
+ QuicConnectionPeer::GetHelper(client()->session()->connection())->
+ GetClock();
+ QuicTime end_waiting_time = clock->Now().Add(
+ QuicTime::Delta::FromMicroseconds(timeout_us));
+ while (stream_ != NULL &&
+ !client_->session()->IsClosedStream(stream_->id()) &&
+ (timeout_us < 0 || clock->Now() < end_waiting_time)) {
client_->WaitForEvents();
}
+ if (timeout_us > 0) {
+ client()->epoll_server()->set_timeout_in_us(old_timeout_us);
+ }
+}
+
+void QuicTestClient::WaitForInitialResponseForMs(int timeout_ms) {
+ int64 timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
+ int64 old_timeout_us = client()->epoll_server()->timeout_in_us();
+ if (timeout_us > 0) {
+ client()->epoll_server()->set_timeout_in_us(timeout_us);
+ }
+ const QuicClock* clock =
+ QuicConnectionPeer::GetHelper(client()->session()->connection())->
+ GetClock();
+ QuicTime end_waiting_time = clock->Now().Add(
+ QuicTime::Delta::FromMicroseconds(timeout_us));
+ while (stream_ != NULL &&
+ !client_->session()->IsClosedStream(stream_->id()) &&
+ stream_->stream_bytes_read() == 0 &&
+ (timeout_us < 0 || clock->Now() < end_waiting_time)) {
+ client_->WaitForEvents();
+ }
+ if (timeout_us > 0) {
+ client()->epoll_server()->set_timeout_in_us(old_timeout_us);
+ }
}
ssize_t QuicTestClient::Send(const void *buffer, size_t size) {
return SendData(string(static_cast<const char*>(buffer), size), false);
}
+bool QuicTestClient::response_headers_complete() const {
+ if (stream_ != NULL) {
+ return stream_->headers_decompressed();
+ } else {
+ return response_headers_complete_;
+ }
+}
+
+const BalsaHeaders* QuicTestClient::response_headers() const {
+ if (stream_ != NULL) {
+ return &stream_->headers();
+ } else {
+ return &headers_;
+ }
+}
+
int QuicTestClient::response_size() const {
return bytes_read_;
}
@@ -324,23 +401,40 @@ size_t QuicTestClient::bytes_written() const {
return bytes_written_;
}
-void QuicTestClient::OnClose(ReliableQuicStream* stream) {
+void QuicTestClient::OnClose(QuicDataStream* stream) {
if (stream_ != stream) {
return;
}
- response_ = stream_->data();
+ if (buffer_body()) {
+ // TODO(fnk): The stream still buffers the whole thing. Fix that.
+ response_ = stream_->data();
+ }
+ response_complete_ = true;
+ response_headers_complete_ = stream_->headers_decompressed();
headers_.CopyFrom(stream_->headers());
stream_error_ = stream_->stream_error();
bytes_read_ = stream_->stream_bytes_read();
bytes_written_ = stream_->stream_bytes_written();
+ response_header_size_ = headers_.GetSizeForWriteBuffer();
+ response_body_size_ = stream_->data().size();
stream_ = NULL;
}
void QuicTestClient::UseWriter(QuicTestWriter* writer) {
- DCHECK(!connected());
reinterpret_cast<QuicEpollClient*>(client_.get())->UseWriter(writer);
}
+void QuicTestClient::UseGuid(QuicGuid guid) {
+ DCHECK(!connected());
+ reinterpret_cast<QuicEpollClient*>(client_.get())->UseGuid(guid);
+}
+
+void QuicTestClient::WaitForWriteToFlush() {
+ while (connected() && client()->session()->HasQueuedData()) {
+ client_->WaitForEvents();
+ }
+}
+
} // 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 3cd71d59f81..e67a2a159bb 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_client.h
+++ b/chromium/net/tools/quic/test_tools/quic_test_client.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUIC_TEST_TOOLS_QUIC_CLIENT_H_
-#define NET_QUIC_TEST_TOOLS_QUIC_CLIENT_H_
+#ifndef NET_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_
+#define NET_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_
#include <string>
@@ -12,8 +12,8 @@
#include "net/quic/quic_framer.h"
#include "net/quic/quic_packet_creator.h"
#include "net/quic/quic_protocol.h"
+#include "net/quic/test_tools/quic_test_writer.h"
#include "net/tools/quic/quic_client.h"
-#include "net/tools/quic/quic_packet_writer.h"
namespace net {
@@ -23,30 +23,22 @@ namespace tools {
namespace test {
-// Allows setting a writer for the client's QuicConnectionHelper, to allow
-// fine-grained control of writes.
-class QuicTestWriter : public QuicPacketWriter {
- public:
- virtual ~QuicTestWriter() {}
- virtual void set_fd(int fd) = 0;
-};
-
class HTTPMessage;
// A toy QUIC client used for testing.
-class QuicTestClient : public ReliableQuicStream::Visitor {
+class QuicTestClient : public QuicDataStream::Visitor {
public:
QuicTestClient(IPEndPoint server_address, const string& server_hostname,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
QuicTestClient(IPEndPoint server_address,
const string& server_hostname,
bool secure,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
QuicTestClient(IPEndPoint server_address,
const string& server_hostname,
bool secure,
const QuicConfig& config,
- const QuicVersion version);
+ const QuicVersionVector& supported_versions);
virtual ~QuicTestClient();
@@ -68,8 +60,6 @@ class QuicTestClient : public ReliableQuicStream::Visitor {
QuicPacketCreator::Options* options() { return client_->options(); }
- const BalsaHeaders *response_headers() const {return &headers_;}
-
void WaitForResponse();
void Connect();
@@ -77,21 +67,32 @@ class QuicTestClient : public ReliableQuicStream::Visitor {
void Disconnect();
IPEndPoint LocalSocketAddress() const;
void ClearPerRequestState();
- void WaitForInitialResponse();
+ void WaitForResponseForMs(int timeout_ms);
+ void WaitForInitialResponseForMs(int timeout_ms);
ssize_t Send(const void *buffer, size_t size);
+ bool response_complete() const { return response_complete_; }
+ bool response_headers_complete() const;
+ const BalsaHeaders* response_headers() const;
int response_size() const;
+ int response_header_size() const { return response_header_size_; }
+ int response_body_size() const { return response_body_size_; }
size_t bytes_read() const;
size_t bytes_written() const;
+ bool buffer_body() const { return buffer_body_; }
+ void set_buffer_body(bool buffer_body) { buffer_body_ = buffer_body; }
- // From ReliableQuicStream::Visitor
- virtual void OnClose(ReliableQuicStream* stream) OVERRIDE;
+ // From QuicDataStream::Visitor
+ virtual void OnClose(QuicDataStream* stream) OVERRIDE;
// Configures client_ to take ownership of and use the writer.
// Must be called before initial connect.
- void UseWriter(QuicTestWriter* writer);
+ void UseWriter(net::test::QuicTestWriter* writer);
+ // If the given GUID is nonzero, configures client_ to use a specific GUID
+ // instead of a random one.
+ void UseGuid(QuicGuid guid);
// Returns NULL if the maximum number of streams have already been created.
- QuicReliableClientStream* GetOrCreateStream();
+ QuicSpdyClientStream* GetOrCreateStream();
QuicRstStreamErrorCode stream_error() { return stream_error_; }
QuicErrorCode connection_error() { return client()->session()->error(); }
@@ -109,30 +110,38 @@ class QuicTestClient : public ReliableQuicStream::Visitor {
void set_priority(QuicPriority priority) { priority_ = priority; }
+ void WaitForWriteToFlush();
+
private:
void Initialize(IPEndPoint address, const string& hostname, bool secure);
IPEndPoint server_address_;
IPEndPoint client_address_;
scoped_ptr<QuicClient> client_; // The actual client
- QuicReliableClientStream* stream_;
+ QuicSpdyClientStream* stream_;
QuicRstStreamErrorCode stream_error_;
+ bool response_complete_;
+ bool response_headers_complete_;
BalsaHeaders headers_;
QuicPriority priority_;
-
string response_;
uint64 bytes_read_;
uint64 bytes_written_;
- // True if the client has never connected before. The client will
- // auto-connect exactly once before sending data. If something causes a
- // connection reset, it will not automatically reconnect.
- bool never_connected_;
+ // The number of uncompressed HTTP header bytes received.
+ int response_header_size_;
+ // The number of HTTP body bytes received.
+ int response_body_size_;
+ // True if we tried to connect already since the last call to Disconnect().
+ bool connect_attempted_;
bool secure_;
- // If true, the client will always reconnect if necessary before creating a
- // stream.
+ // The client will auto-connect exactly once before sending data. If
+ // something causes a connection reset, it will not automatically reconnect
+ // unless auto_reconnect_ is true.
bool auto_reconnect_;
+ // Should we buffer the response body? Defaults to true.
+ bool buffer_body_;
// proof_verifier_ points to a RecordingProofVerifier that is owned by
// client_.
@@ -144,4 +153,4 @@ class QuicTestClient : public ReliableQuicStream::Visitor {
} // namespace tools
} // namespace net
-#endif // NET_QUIC_TEST_TOOLS_QUIC_CLIENT_H_
+#endif // NET_QUIC_TEST_TOOLS_QUIC_TEST_CLIENT_H_
diff --git a/chromium/net/tools/quic/test_tools/quic_test_utils.cc b/chromium/net/tools/quic/test_tools/quic_test_utils.cc
index fa3627ba74f..1aad3273832 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/tools/quic/test_tools/quic_test_utils.cc
@@ -4,6 +4,9 @@
#include "net/tools/quic/test_tools/quic_test_utils.h"
+#include "base/sha1.h"
+#include "net/quic/quic_connection.h"
+#include "net/quic/test_tools/quic_connection_peer.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/tools/quic/quic_epoll_connection_helper.h"
@@ -14,62 +17,55 @@ namespace net {
namespace tools {
namespace test {
-MockConnection::MockConnection(QuicGuid guid,
- IPEndPoint address,
- int fd,
- EpollServer* eps,
- bool is_server)
- : QuicConnection(guid, address,
- new QuicEpollConnectionHelper(fd, eps), is_server,
- QuicVersionMax()),
- has_mock_helper_(false) {
+MockConnection::MockConnection(bool is_server)
+ : QuicConnection(kTestGuid,
+ IPEndPoint(net::test::Loopback4(), kTestPort),
+ new testing::NiceMock<MockHelper>(),
+ new testing::NiceMock<MockPacketWriter>(),
+ is_server, QuicSupportedVersions()),
+ writer_(net::test::QuicConnectionPeer::GetWriter(this)),
+ helper_(helper()) {
}
-MockConnection::MockConnection(QuicGuid guid,
- IPEndPoint address,
+MockConnection::MockConnection(IPEndPoint address,
bool is_server)
- : QuicConnection(guid, address, new testing::NiceMock<MockHelper>(),
- is_server, QuicVersionMax()),
- has_mock_helper_(true) {
+ : QuicConnection(kTestGuid, address,
+ new testing::NiceMock<MockHelper>(),
+ new testing::NiceMock<MockPacketWriter>(),
+ is_server, QuicSupportedVersions()),
+ writer_(net::test::QuicConnectionPeer::GetWriter(this)),
+ helper_(helper()) {
}
MockConnection::MockConnection(QuicGuid guid,
- IPEndPoint address,
- QuicConnectionHelperInterface* helper,
bool is_server)
- : QuicConnection(guid, address, helper, is_server, QuicVersionMax()),
- has_mock_helper_(false) {
+ : QuicConnection(guid,
+ IPEndPoint(net::test::Loopback4(), kTestPort),
+ new testing::NiceMock<MockHelper>(),
+ new testing::NiceMock<MockPacketWriter>(),
+ is_server, QuicSupportedVersions()),
+ writer_(net::test::QuicConnectionPeer::GetWriter(this)),
+ helper_(helper()) {
}
MockConnection::~MockConnection() {
}
void MockConnection::AdvanceTime(QuicTime::Delta delta) {
- CHECK(has_mock_helper_) << "Cannot advance time unless a MockClock is being"
- " used";
static_cast<MockHelper*>(helper())->AdvanceTime(delta);
}
-
-MockQuicSessionOwner::MockQuicSessionOwner() {
-}
-
-MockQuicSessionOwner::~MockQuicSessionOwner() {
-}
-
-bool TestDecompressorVisitor::OnDecompressedData(StringPiece data) {
- data.AppendToString(&data_);
- return true;
-}
-
-void TestDecompressorVisitor::OnDecompressionError() {
- error_ = true;
+uint64 SimpleRandom::RandUint64() {
+ unsigned char hash[base::kSHA1Length];
+ base::SHA1HashBytes(reinterpret_cast<unsigned char*>(&seed_), sizeof(seed_),
+ hash);
+ memcpy(&seed_, hash, sizeof(seed_));
+ return seed_;
}
TestSession::TestSession(QuicConnection* connection,
- const QuicConfig& config,
- bool is_server)
- : QuicSession(connection, config, is_server),
+ const QuicConfig& config)
+ : QuicSession(connection, config),
crypto_stream_(NULL) {
}
@@ -83,16 +79,31 @@ QuicCryptoStream* TestSession::GetCryptoStream() {
return crypto_stream_;
}
-MockAckNotifierDelegate::MockAckNotifierDelegate() {
+MockPacketWriter::MockPacketWriter() {
}
-MockAckNotifierDelegate::~MockAckNotifierDelegate() {
+MockPacketWriter::~MockPacketWriter() {
}
-MockPacketWriter::MockPacketWriter() {
+MockQuicSessionOwner::MockQuicSessionOwner() {
}
-MockPacketWriter::~MockPacketWriter() {
+MockQuicSessionOwner::~MockQuicSessionOwner() {
+}
+
+bool TestDecompressorVisitor::OnDecompressedData(StringPiece data) {
+ data.AppendToString(&data_);
+ return true;
+}
+
+void TestDecompressorVisitor::OnDecompressionError() {
+ error_ = true;
+}
+
+MockAckNotifierDelegate::MockAckNotifierDelegate() {
+}
+
+MockAckNotifierDelegate::~MockAckNotifierDelegate() {
}
} // namespace test
diff --git a/chromium/net/tools/quic/test_tools/quic_test_utils.h b/chromium/net/tools/quic/test_tools/quic_test_utils.h
index dffa2558af3..986665bd1ed 100644
--- a/chromium/net/tools/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/tools/quic/test_tools/quic_test_utils.h
@@ -9,10 +9,10 @@
#include "base/strings/string_piece.h"
#include "net/quic/quic_connection.h"
+#include "net/quic/quic_packet_writer.h"
#include "net/quic/quic_session.h"
#include "net/quic/quic_spdy_decompressor.h"
#include "net/spdy/spdy_framer.h"
-#include "net/tools/quic/quic_packet_writer.h"
#include "net/tools/quic/quic_server_session.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -24,19 +24,39 @@ class IPEndPoint;
namespace tools {
namespace test {
+static const QuicGuid kTestGuid = 42;
+static const int kTestPort = 123;
+
+// Simple random number generator used to compute random numbers suitable
+// for pseudo-randomly dropping packets in tests. It works by computing
+// the sha1 hash of the current seed, and using the first 64 bits as
+// the next random number, and the next seed.
+class SimpleRandom {
+ public:
+ SimpleRandom() : seed_(0) {}
+
+ // Returns a random number in the range [0, kuint64max].
+ uint64 RandUint64();
+
+ void set_seed(uint64 seed) { seed_ = seed; }
+
+ private:
+ uint64 seed_;
+};
+
class MockConnection : public QuicConnection {
public:
- // Uses a QuicConnectionHelper created with fd and eps.
- MockConnection(QuicGuid guid,
- IPEndPoint address,
- int fd,
- EpollServer* eps,
+ // Uses a MockHelper, GUID of 42, and 127.0.0.1:123.
+ explicit MockConnection(bool is_server);
+
+ // Uses a MockHelper, GUID of 42.
+ MockConnection(IPEndPoint address,
bool is_server);
- // Uses a MockHelper.
- MockConnection(QuicGuid guid, IPEndPoint address, bool is_server);
+
+ // Uses a MockHelper, and 127.0.0.1:123
MockConnection(QuicGuid guid,
- IPEndPoint address,
- QuicConnectionHelperInterface* helper, bool is_server);
+ bool is_server);
+
virtual ~MockConnection();
// If the constructor that uses a MockHelper has been used then this method
@@ -66,16 +86,48 @@ class MockConnection : public QuicConnection {
virtual bool OnProtocolVersionMismatch(QuicVersion version) { return false; }
private:
- const bool has_mock_helper_;
+ scoped_ptr<QuicPacketWriter> writer_;
+ scoped_ptr<QuicConnectionHelperInterface> helper_;
DISALLOW_COPY_AND_ASSIGN(MockConnection);
};
+class TestSession : public QuicSession {
+ public:
+ TestSession(QuicConnection* connection, const QuicConfig& config);
+ virtual ~TestSession();
+
+ MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
+ MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
+
+ void SetCryptoStream(QuicCryptoStream* stream);
+
+ virtual QuicCryptoStream* GetCryptoStream();
+
+ private:
+ QuicCryptoStream* crypto_stream_;
+ DISALLOW_COPY_AND_ASSIGN(TestSession);
+};
+
+class MockPacketWriter : public QuicPacketWriter {
+ public:
+ MockPacketWriter();
+ virtual ~MockPacketWriter();
+
+ MOCK_METHOD5(WritePacket,
+ WriteResult(const char* buffer,
+ size_t buf_len,
+ const IPAddressNumber& self_address,
+ const IPEndPoint& peer_address,
+ QuicBlockedWriterInterface* blocked_writer));
+ MOCK_CONST_METHOD0(IsWriteBlockedDataBuffered, bool());
+};
+
class MockQuicSessionOwner : public QuicSessionOwner {
public:
MockQuicSessionOwner();
~MockQuicSessionOwner();
- MOCK_METHOD2(OnConnectionClose, void(QuicGuid guid, QuicErrorCode error));
+ MOCK_METHOD2(OnConnectionClosed, void(QuicGuid guid, QuicErrorCode error));
};
class TestDecompressorVisitor : public QuicSpdyDecompressor::Visitor {
@@ -92,26 +144,6 @@ class TestDecompressorVisitor : public QuicSpdyDecompressor::Visitor {
bool error_;
};
-class TestSession : public QuicSession {
- public:
- TestSession(QuicConnection* connection,
- const QuicConfig& config,
- bool is_server);
- virtual ~TestSession();
-
- MOCK_METHOD1(CreateIncomingReliableStream,
- ReliableQuicStream*(QuicStreamId id));
- MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
-
- void SetCryptoStream(QuicCryptoStream* stream);
-
- virtual QuicCryptoStream* GetCryptoStream();
-
- private:
- QuicCryptoStream* crypto_stream_;
- DISALLOW_COPY_AND_ASSIGN(TestSession);
-};
-
class MockAckNotifierDelegate : public QuicAckNotifier::DelegateInterface {
public:
MockAckNotifierDelegate();
@@ -120,19 +152,6 @@ class MockAckNotifierDelegate : public QuicAckNotifier::DelegateInterface {
MOCK_METHOD0(OnAckNotification, void());
};
-class MockPacketWriter : public QuicPacketWriter {
- public:
- MockPacketWriter();
- virtual ~MockPacketWriter();
-
- MOCK_METHOD6(WritePacket, int(const char* buffer,
- size_t buf_len,
- const IPAddressNumber& self_address,
- const IPEndPoint& peer_address,
- QuicBlockedWriterInterface* blocked_writer,
- int* error));
-};
-
} // 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
new file mode 100644
index 00000000000..a1bebc760d5
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/server_thread.cc
@@ -0,0 +1,107 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/tools/quic/test_tools/server_thread.h"
+
+#include "net/tools/quic/test_tools/quic_server_peer.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+ServerThread::ServerThread(IPEndPoint address,
+ const QuicConfig& config,
+ const QuicVersionVector& supported_versions,
+ bool strike_register_no_startup_period)
+ : SimpleThread("server_thread"),
+ listening_(true, false),
+ confirmed_(true, false),
+ pause_(true, false),
+ paused_(true, false),
+ resume_(true, false),
+ quit_(true, false),
+ server_(config, supported_versions),
+ address_(address),
+ port_(0) {
+ if (strike_register_no_startup_period) {
+ server_.SetStrikeRegisterNoStartupPeriod();
+ }
+}
+
+ServerThread::~ServerThread() {
+}
+
+void ServerThread::Run() {
+ server_.Listen(address_);
+
+ port_lock_.Acquire();
+ port_ = server_.port();
+ port_lock_.Release();
+
+ listening_.Signal();
+ while (!quit_.IsSignaled()) {
+ if (pause_.IsSignaled() && !resume_.IsSignaled()) {
+ paused_.Signal();
+ resume_.Wait();
+ }
+ server_.WaitForEvents();
+ MaybeNotifyOfHandshakeConfirmation();
+ }
+
+ server_.Shutdown();
+}
+
+int ServerThread::GetPort() {
+ port_lock_.Acquire();
+ int rc = port_;
+ port_lock_.Release();
+ return rc;
+}
+
+void ServerThread::WaitForServerStartup() {
+ listening_.Wait();
+}
+
+void ServerThread::WaitForCryptoHandshakeConfirmed() {
+ confirmed_.Wait();
+}
+
+void ServerThread::Pause() {
+ DCHECK(!pause_.IsSignaled());
+ pause_.Signal();
+ paused_.Wait();
+}
+
+void ServerThread::Resume() {
+ DCHECK(!resume_.IsSignaled());
+ DCHECK(pause_.IsSignaled());
+ resume_.Signal();
+}
+
+void ServerThread::Quit() {
+ if (pause_.IsSignaled() && !resume_.IsSignaled()) {
+ resume_.Signal();
+ }
+ quit_.Signal();
+}
+
+void ServerThread::MaybeNotifyOfHandshakeConfirmation() {
+ if (confirmed_.IsSignaled()) {
+ // Only notify once.
+ return;
+ }
+ QuicDispatcher* dispatcher = QuicServerPeer::GetDispatcher(server());
+ if (dispatcher->session_map().empty()) {
+ // Wait for a session to be created.
+ return;
+ }
+ QuicSession* session = dispatcher->session_map().begin()->second;
+ if (session->IsCryptoHandshakeConfirmed()) {
+ confirmed_.Signal();
+ }
+}
+
+} // 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
new file mode 100644
index 00000000000..ed36c37b349
--- /dev/null
+++ b/chromium/net/tools/quic/test_tools/server_thread.h
@@ -0,0 +1,79 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_TOOLS_QUIC_SERVER_THREAD_H_
+#define NET_TOOLS_QUIC_SERVER_THREAD_H_
+
+#include "base/threading/simple_thread.h"
+#include "net/base/ip_endpoint.h"
+#include "net/quic/quic_config.h"
+#include "net/tools/quic/quic_server.h"
+
+namespace net {
+namespace tools {
+namespace test {
+
+// Simple wrapper class to run server in a thread.
+class ServerThread : public base::SimpleThread {
+ public:
+ ServerThread(IPEndPoint address,
+ const QuicConfig& config,
+ const QuicVersionVector& supported_versions,
+ bool strike_register_no_startup_period);
+
+ virtual ~ServerThread();
+
+ // SimpleThread implementation.
+ virtual void Run() OVERRIDE;
+
+ // Waits until the server has started and is listening for requests.
+ void WaitForServerStartup();
+
+ // Waits for the handshake to be confirmed for the first session created.
+ void WaitForCryptoHandshakeConfirmed();
+
+ // Pauses execution of the server until Resume() is called. May only be
+ // called once.
+ void Pause();
+
+ // Resumes execution of the server after Pause() has been called. May only
+ // be called once.
+ void Resume();
+
+ // Stops the server from executing and shuts it down, destroying all
+ // server objects.
+ void Quit();
+
+ // Returns the underlying server. Care must be taken to avoid data races
+ // when accessing the server. It is always safe to access the server
+ // after calling Pause() and before calling Resume().
+ QuicServer* server() { return &server_; }
+
+ // Returns the port that the server is listening on.
+ int GetPort();
+
+ private:
+ void MaybeNotifyOfHandshakeConfirmation();
+
+ base::WaitableEvent listening_; // Notified when the server is listening.
+ base::WaitableEvent confirmed_; // Notified when the first handshake is
+ // confirmed.
+ base::WaitableEvent pause_; // Notified when the server should pause.
+ base::WaitableEvent paused_; // Notitied when the server has paused
+ base::WaitableEvent resume_; // Notified when the server should resume.
+ base::WaitableEvent quit_; // Notified when the server should quit.
+
+ tools::QuicServer server_;
+ IPEndPoint address_;
+ base::Lock port_lock_;
+ int port_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServerThread);
+};
+
+} // namespace test
+} // namespace tools
+} // namespace net
+
+#endif // NET_TOOLS_QUIC_SERVER_THREAD_H_
diff --git a/chromium/net/tools/spdyshark/AUTHORS b/chromium/net/tools/spdyshark/AUTHORS
deleted file mode 100644
index 5643b2000b9..00000000000
--- a/chromium/net/tools/spdyshark/AUTHORS
+++ /dev/null
@@ -1,2 +0,0 @@
-Author:
-Eric Shienbrood <ers@google.com>
diff --git a/chromium/net/tools/spdyshark/COPYING b/chromium/net/tools/spdyshark/COPYING
deleted file mode 100644
index d60c31a97a5..00000000000
--- a/chromium/net/tools/spdyshark/COPYING
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/chromium/net/tools/spdyshark/ChangeLog b/chromium/net/tools/spdyshark/ChangeLog
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/net/tools/spdyshark/ChangeLog
+++ /dev/null
diff --git a/chromium/net/tools/spdyshark/INSTALL b/chromium/net/tools/spdyshark/INSTALL
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/net/tools/spdyshark/INSTALL
+++ /dev/null
diff --git a/chromium/net/tools/spdyshark/Makefile.am b/chromium/net/tools/spdyshark/Makefile.am
deleted file mode 100644
index b707baea732..00000000000
--- a/chromium/net/tools/spdyshark/Makefile.am
+++ /dev/null
@@ -1,126 +0,0 @@
-# Makefile.am
-# Automake file for SPDY plugin
-#
-# $Id$
-#
-# Wireshark - Network traffic analyzer
-# By Gerald Combs <gerald@wireshark.org>
-# Copyright 1998 Gerald Combs
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-
-INCLUDES = -I$(top_srcdir) -I$(includedir)
-
-include Makefile.common
-
-if HAVE_WARNINGS_AS_ERRORS
-AM_CFLAGS = -Werror
-endif
-
-plugin_LTLIBRARIES = spdy.la
-spdy_la_SOURCES = \
- plugin.c \
- moduleinfo.h \
- $(DISSECTOR_SRC) \
- $(DISSECTOR_SUPPORT_SRC) \
- $(DISSECTOR_INCLUDES)
-spdy_la_LDFLAGS = -module -avoid-version
-spdy_la_LIBADD = @PLUGIN_LIBS@
-
-# Libs must be cleared, or else libtool won't create a shared module.
-# If your module needs to be linked against any particular libraries,
-# add them here.
-LIBS =
-
-#
-# Build plugin.c, which contains the plugin version[] string, a
-# function plugin_register() that calls the register routines for all
-# protocols, and a function plugin_reg_handoff() that calls the handoff
-# registration routines for all protocols.
-#
-# We do this by scanning sources. If that turns out to be too slow,
-# maybe we could just require every .o file to have an register routine
-# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
-#
-# Formatting conventions: The name of the proto_register_* routines an
-# proto_reg_handoff_* routines must start in column zero, or must be
-# preceded only by "void " starting in column zero, and must not be
-# inside #if.
-#
-# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
-#
-# For some unknown reason, having a big "for" loop in the Makefile
-# to scan all the files doesn't work with some "make"s; they seem to
-# pass only the first few names in the list to the shell, for some
-# reason.
-#
-# Therefore, we have a script to generate the plugin.c file.
-# The shell script runs slowly, as multiple greps and seds are run
-# for each input file; this is especially slow on Windows. Therefore,
-# if Python is present (as indicated by PYTHON being defined), we run
-# a faster Python script to do that work instead.
-#
-# The first argument is the directory in which the source files live.
-# The second argument is "plugin", to indicate that we should build
-# a plugin.c file for a plugin.
-# All subsequent arguments are the files to scan.
-#
-plugin.c: $(DISSECTOR_SRC) $(top_srcdir)/tools/make-dissector-reg \
- $(top_srcdir)/tools/make-dissector-reg.py
- @if test -n "$(PYTHON)"; then \
- echo Making plugin.c with python ; \
- $(PYTHON) $(top_srcdir)/tools/make-dissector-reg.py $(srcdir) \
- plugin $(DISSECTOR_SRC) ; \
- else \
- echo Making plugin.c with shell script ; \
- $(top_srcdir)/tools/make-dissector-reg $(srcdir) \
- $(plugin_src) plugin $(DISSECTOR_SRC) ; \
- fi
-
-#
-# Currently plugin.c can be included in the distribution because
-# we always build all protocol dissectors. We used to have to check
-# whether or not to build the snmp dissector. If we again need to
-# variably build something, making plugin.c non-portable, uncomment
-# the dist-hook line below.
-#
-# Oh, yuk. We don't want to include "plugin.c" in the distribution, as
-# its contents depend on the configuration, and therefore we want it
-# to be built when the first "make" is done; however, Automake insists
-# on putting *all* source into the distribution.
-#
-# We work around this by having a "dist-hook" rule that deletes
-# "plugin.c", so that "dist" won't pick it up.
-#
-#dist-hook:
-# @rm -f $(distdir)/plugin.c
-
-CLEANFILES = \
- spdy \
- *~
-
-MAINTAINERCLEANFILES = \
- Makefile.in \
- plugin.c
-
-EXTRA_DIST = \
- Makefile.common \
- Makefile.nmake \
- moduleinfo.nmake \
- plugin.rc.in
-
-checkapi:
- $(PERL) $(top_srcdir)/tools/checkAPIs.pl -g abort -g termoutput $(DISSECTOR_SRC)
diff --git a/chromium/net/tools/spdyshark/Makefile.common b/chromium/net/tools/spdyshark/Makefile.common
deleted file mode 100644
index 9386f46f125..00000000000
--- a/chromium/net/tools/spdyshark/Makefile.common
+++ /dev/null
@@ -1,40 +0,0 @@
-# Makefile.common for SPDY plugin
-# Contains the stuff from Makefile.am and Makefile.nmake that is
-# a) common to both files and
-# b) portable between both files
-#
-# $Id$
-#
-# Wireshark - Network traffic analyzer
-# By Gerald Combs <gerald@wireshark.org>
-# Copyright 1998 Gerald Combs
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-# the name of the plugin
-PLUGIN_NAME = spdy
-
-# the dissector sources (without any helpers)
-DISSECTOR_SRC = \
- packet-spdy.c
-
-# corresponding headers
-DISSECTOR_INCLUDES = \
- packet-spdy.h
-
-# Dissector helpers. They're included in the source files in this
-# directory, but they're not dissectors themselves, i.e. they're not
-# used to generate "register.c").
-#DISSECTOR_SUPPORT_SRC =
diff --git a/chromium/net/tools/spdyshark/Makefile.nmake b/chromium/net/tools/spdyshark/Makefile.nmake
deleted file mode 100644
index d554918cef4..00000000000
--- a/chromium/net/tools/spdyshark/Makefile.nmake
+++ /dev/null
@@ -1,104 +0,0 @@
-# Makefile.nmake
-# nmake file for Wireshark plugin
-#
-# $Id: Makefile.nmake 27579 2009-03-02 18:57:35Z gerald $
-#
-
-include ..\..\config.nmake
-include moduleinfo.nmake
-
-include Makefile.common
-
-CFLAGS=/WX /Zi /DHAVE_CONFIG_H /I../.. $(GLIB_CFLAGS) $(ZLIB_CFLAGS) \
- /I$(PCAP_DIR)\include -D_U_="" $(LOCAL_CFLAGS)
-
-.c.obj::
- $(CC) $(CFLAGS) -Fd.\ -c $<
-
-LDFLAGS = $(PLUGIN_LDFLAGS)
-
-!IFDEF ENABLE_LIBWIRESHARK
-LINK_PLUGIN_WITH=..\..\epan\libwireshark.lib $(ZLIB_LIBS)
-CFLAGS=/DHAVE_WIN32_LIBWIRESHARK_LIB /D_NEED_VAR_IMPORT_ $(CFLAGS)
-
-DISSECTOR_OBJECTS = $(DISSECTOR_SRC:.c=.obj)
-
-DISSECTOR_SUPPORT_OBJECTS = $(DISSECTOR_SUPPORT_SRC:.c=.obj)
-
-OBJECTS = $(DISSECTOR_OBJECTS) $(DISSECTOR_SUPPORT_OBJECTS) plugin.obj
-
-RESOURCE=$(PLUGIN_NAME).res
-
-all: $(PLUGIN_NAME).dll
-
-$(PLUGIN_NAME).rc : moduleinfo.nmake
- sed -e s/@PLUGIN_NAME@/$(PLUGIN_NAME)/ \
- -e s/@RC_MODULE_VERSION@/$(RC_MODULE_VERSION)/ \
- -e s/@RC_VERSION@/$(RC_VERSION)/ \
- -e s/@MODULE_VERSION@/$(MODULE_VERSION)/ \
- -e s/@PACKAGE@/$(PACKAGE)/ \
- -e s/@VERSION@/$(VERSION)/ \
- -e s/@MSVC_VARIANT@/$(MSVC_VARIANT)/ \
- < plugin.rc.in > $@
-
-$(PLUGIN_NAME).dll $(PLUGIN_NAME).exp $(PLUGIN_NAME).lib : $(OBJECTS) $(LINK_PLUGIN_WITH) $(RESOURCE)
- link -dll /out:$(PLUGIN_NAME).dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \
- $(GLIB_LIBS) $(RESOURCE)
-
-#
-# Build plugin.c, which contains the plugin version[] string, a
-# function plugin_register() that calls the register routines for all
-# protocols, and a function plugin_reg_handoff() that calls the handoff
-# registration routines for all protocols.
-#
-# We do this by scanning sources. If that turns out to be too slow,
-# maybe we could just require every .o file to have an register routine
-# of a given name (packet-aarp.o -> proto_register_aarp, etc.).
-#
-# Formatting conventions: The name of the proto_register_* routines an
-# proto_reg_handoff_* routines must start in column zero, or must be
-# preceded only by "void " starting in column zero, and must not be
-# inside #if.
-#
-# DISSECTOR_SRC is assumed to have all the files that need to be scanned.
-#
-# For some unknown reason, having a big "for" loop in the Makefile
-# to scan all the files doesn't work with some "make"s; they seem to
-# pass only the first few names in the list to the shell, for some
-# reason.
-#
-# Therefore, we have a script to generate the plugin.c file.
-# The shell script runs slowly, as multiple greps and seds are run
-# for each input file; this is especially slow on Windows. Therefore,
-# if Python is present (as indicated by PYTHON being defined), we run
-# a faster Python script to do that work instead.
-#
-# The first argument is the directory in which the source files live.
-# The second argument is "plugin", to indicate that we should build
-# a plugin.c file for a plugin.
-# All subsequent arguments are the files to scan.
-#
-!IFDEF PYTHON
-plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg.py
- @echo Making plugin.c (using python)
- @$(PYTHON) "../../tools/make-dissector-reg.py" . plugin $(DISSECTOR_SRC)
-!ELSE
-plugin.c: $(DISSECTOR_SRC) moduleinfo.h ../../tools/make-dissector-reg
- @echo Making plugin.c (using sh)
- @$(SH) ../../tools/make-dissector-reg . plugin $(DISSECTOR_SRC)
-!ENDIF
-
-!ENDIF
-
-clean:
- rm -f $(OBJECTS) $(RESOURCE) plugin.c *.pdb \
- $(PLUGIN_NAME).dll $(PLUGIN_NAME).dll.manifest $(PLUGIN_NAME).lib \
- $(PLUGIN_NAME).exp $(PLUGIN_NAME).rc
-
-distclean: clean
-
-maintainer-clean: distclean
-
-checkapi:
-# TODO: Fix api's :)
-# $(PERL) ../../tools/checkAPIs.pl -g abort -g termoutput $(DISSECTOR_SRC)
diff --git a/chromium/net/tools/spdyshark/NEWS b/chromium/net/tools/spdyshark/NEWS
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/net/tools/spdyshark/NEWS
+++ /dev/null
diff --git a/chromium/net/tools/spdyshark/README b/chromium/net/tools/spdyshark/README
deleted file mode 100644
index e06515e78a5..00000000000
--- a/chromium/net/tools/spdyshark/README
+++ /dev/null
@@ -1,49 +0,0 @@
-How to build SPDY dissector for Wireshark (Windows directions).
-
-1) Retrieve wireshark source code.
-
-> mkdir D:\src\wireshark
-> cd D:\src\wireshark
-> svn co http://anonsvn.wireshark.org/wireshark/trunk/ trunk
-
-2) Retrieve the spdyshark source code.
-
-> cd D:\src
-> svn co http://src.chromium.org/svn/trunk/src/net/tools/spdyshark
-
-3) Follow directions to build Wireshark from
-
-http://www.wireshark.org/docs/wsdg_html_chunked/ChSetupWin32.html
-
- - Read all the directions, there are a number of preliminary steps.
-
- - You may need to explicitly make C:\wireshark-win32-libs [or
- C:\wireshark-win64-libs]
-
- - Make sure PYTHON environment variable is set (this may not be the
- case if using the one from depot_tools). Although wireshark seems
- to require it, it tries to workaround missing PYTHON environment
- variables unsuccessfully.
-
-4) Make a symbolic link for spdyshark to Wireshark
-
-> mklink /D D:\src\wireshark\trunk\plugins\spdyshark D:\src\spdyshark
-
-5) Build the plugin.
-
-> cd D:\src\wireshark\trunk\plugins\spdyshark
-> nmake -f Makefile.nmake all
-
-6) Move the plugin into the wireshark-gtk directory [should automate]
-
-> copy D:\src\wireshark\trunk\plugins\spdyshark.dll
- D:\src\wireshark\trunk\wireshark-gtk2\plugins
-
-7) Start wireshark, and confirm that SPDY plugin is loaded.
-
-> D:\src\wireshark\trunk\wireshark-gtk2\wireshark.exe
-
-Choose Edit > Preferences to bring up the Preferences dialog.
-
-Exand "Protocols" in the left pane of the preferences dialog and
-confirm that spdyshark is there.
diff --git a/chromium/net/tools/spdyshark/README.chromium b/chromium/net/tools/spdyshark/README.chromium
deleted file mode 100644
index d8dbcf16bb7..00000000000
--- a/chromium/net/tools/spdyshark/README.chromium
+++ /dev/null
@@ -1,4 +0,0 @@
-Name: Spdyshark
-URL: http://anonsvn.wireshark.org/wireshark/trunk
-License: GPL v2
-Security Critical: no
diff --git a/chromium/net/tools/spdyshark/moduleinfo.h b/chromium/net/tools/spdyshark/moduleinfo.h
deleted file mode 100644
index 9e5f7c816f8..00000000000
--- a/chromium/net/tools/spdyshark/moduleinfo.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* Included *after* config.h, in order to re-define these macros */
-
-#ifdef PACKAGE
-#undef PACKAGE
-#endif
-
-/* Name of package */
-#define PACKAGE "spdy"
-
-
-#ifdef VERSION
-#undef VERSION
-#endif
-
-/* Version number of package */
-#define VERSION "0.1.0"
diff --git a/chromium/net/tools/spdyshark/moduleinfo.nmake b/chromium/net/tools/spdyshark/moduleinfo.nmake
deleted file mode 100644
index bbdf7660970..00000000000
--- a/chromium/net/tools/spdyshark/moduleinfo.nmake
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# $Id$
-#
-
-# The name
-PACKAGE=spdy
-
-# The version
-MODULE_VERSION_MAJOR=0
-MODULE_VERSION_MINOR=1
-MODULE_VERSION_MICRO=0
-MODULE_VERSION_EXTRA=0
-
-#
-# The RC_VERSION should be comma-separated, not dot-separated,
-# as per Graham Bloice's message in
-#
-# http://www.ethereal.com/lists/ethereal-dev/200303/msg00283.html
-#
-# "The RC_VERSION variable in config.nmake should be comma separated.
-# This allows the resources to be built correctly and the version
-# number to be correctly displayed in the explorer properties dialog
-# for the executables, and XP's tooltip, rather than 0.0.0.0."
-#
-
-MODULE_VERSION=$(MODULE_VERSION_MAJOR).$(MODULE_VERSION_MINOR).$(MODULE_VERSION_MICRO).$(MODULE_VERSION_EXTRA)
-RC_MODULE_VERSION=$(MODULE_VERSION_MAJOR),$(MODULE_VERSION_MINOR),$(MODULE_VERSION_MICRO),$(MODULE_VERSION_EXTRA)
-
diff --git a/chromium/net/tools/spdyshark/packet-spdy.c b/chromium/net/tools/spdyshark/packet-spdy.c
deleted file mode 100644
index becc585c0cb..00000000000
--- a/chromium/net/tools/spdyshark/packet-spdy.c
+++ /dev/null
@@ -1,1532 +0,0 @@
-/* packet-spdy.c
- * Routines for SPDY packet disassembly
- * For now, the protocol spec can be found at
- * http://dev.chromium.org/spdy/spdy-protocol
- *
- * Copyright 2010, Google Inc.
- * Eric Shienbrood <ers@google.com>
- *
- * $Id$
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * Originally based on packet-http.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <ctype.h>
-
-#include <glib.h>
-#include <epan/conversation.h>
-#include <epan/packet.h>
-#include <epan/strutil.h>
-#include <epan/base64.h>
-#include <epan/emem.h>
-#include <epan/stats_tree.h>
-
-#include <epan/req_resp_hdrs.h>
-#include "packet-spdy.h"
-#include <epan/dissectors/packet-tcp.h>
-#include <epan/dissectors/packet-ssl.h>
-#include <epan/prefs.h>
-#include <epan/expert.h>
-#include <epan/uat.h>
-
-#define SPDY_FIN 0x01
-
-/* The types of SPDY control frames */
-typedef enum _spdy_type {
- SPDY_DATA,
- SPDY_SYN_STREAM,
- SPDY_SYN_REPLY,
- SPDY_FIN_STREAM,
- SPDY_HELLO,
- SPDY_NOOP,
- SPDY_PING,
- SPDY_INVALID
-} spdy_frame_type_t;
-
-static const char *frame_type_names[] = {
- "DATA", "SYN_STREAM", "SYN_REPLY", "FIN_STREAM", "HELLO", "NOOP",
- "PING", "INVALID"
-};
-
-/*
- * This structure will be tied to each SPDY frame.
- * Note that there may be multiple SPDY frames
- * in one packet.
- */
-typedef struct _spdy_frame_info_t {
- guint32 stream_id;
- guint8 *header_block;
- guint header_block_len;
- guint16 frame_type;
-} spdy_frame_info_t;
-
-/*
- * This structures keeps track of all the data frames
- * associated with a stream, so that they can be
- * reassembled into a single chunk.
- */
-typedef struct _spdy_data_frame_t {
- guint8 *data;
- guint32 length;
- guint32 framenum;
-} spdy_data_frame_t;
-
-typedef struct _spdy_stream_info_t {
- gchar *content_type;
- gchar *content_type_parameters;
- gchar *content_encoding;
- GSList *data_frames;
- tvbuff_t *assembled_data;
- guint num_data_frames;
-} spdy_stream_info_t;
-
-#include <epan/tap.h>
-
-
-static int spdy_tap = -1;
-static int spdy_eo_tap = -1;
-
-static int proto_spdy = -1;
-static int hf_spdy_syn_stream = -1;
-static int hf_spdy_syn_reply = -1;
-static int hf_spdy_control_bit = -1;
-static int hf_spdy_version = -1;
-static int hf_spdy_type = -1;
-static int hf_spdy_flags = -1;
-static int hf_spdy_flags_fin = -1;
-static int hf_spdy_length = -1;
-static int hf_spdy_header = -1;
-static int hf_spdy_header_name = -1;
-static int hf_spdy_header_name_text = -1;
-static int hf_spdy_header_value = -1;
-static int hf_spdy_header_value_text = -1;
-static int hf_spdy_streamid = -1;
-static int hf_spdy_associated_streamid = -1;
-static int hf_spdy_priority = -1;
-static int hf_spdy_num_headers = -1;
-static int hf_spdy_num_headers_string = -1;
-
-static gint ett_spdy = -1;
-static gint ett_spdy_syn_stream = -1;
-static gint ett_spdy_syn_reply = -1;
-static gint ett_spdy_fin_stream = -1;
-static gint ett_spdy_flags = -1;
-static gint ett_spdy_header = -1;
-static gint ett_spdy_header_name = -1;
-static gint ett_spdy_header_value = -1;
-
-static gint ett_spdy_encoded_entity = -1;
-
-static dissector_handle_t data_handle;
-static dissector_handle_t media_handle;
-static dissector_handle_t spdy_handle;
-
-/* Stuff for generation/handling of fields for custom HTTP headers */
-typedef struct _header_field_t {
- gchar* header_name;
- gchar* header_desc;
-} header_field_t;
-
-/*
- * desegmentation of SPDY control frames
- * (when we are over TCP or another protocol providing the desegmentation API)
- */
-static gboolean spdy_desegment_control_frames = TRUE;
-
-/*
- * desegmentation of SPDY data frames bodies
- * (when we are over TCP or another protocol providing the desegmentation API)
- * TODO let the user filter on content-type the bodies he wants desegmented
- */
-static gboolean spdy_desegment_data_frames = TRUE;
-
-static gboolean spdy_assemble_entity_bodies = TRUE;
-
-/*
- * Decompression of zlib encoded entities.
- */
-#ifdef HAVE_LIBZ
-static gboolean spdy_decompress_body = TRUE;
-static gboolean spdy_decompress_headers = TRUE;
-#else
-static gboolean spdy_decompress_body = FALSE;
-static gboolean spdy_decompress_headers = FALSE;
-#endif
-static gboolean spdy_debug = FALSE;
-
-#define TCP_PORT_DAAP 3689
-
-/*
- * SSDP is implemented atop HTTP (yes, it really *does* run over UDP).
- */
-#define TCP_PORT_SSDP 1900
-#define UDP_PORT_SSDP 1900
-
-/*
- * tcp and ssl ports
- */
-
-#define TCP_DEFAULT_RANGE "80,8080"
-#define SSL_DEFAULT_RANGE "443"
-
-static range_t *global_spdy_tcp_range = NULL;
-static range_t *global_spdy_ssl_range = NULL;
-
-static range_t *spdy_tcp_range = NULL;
-static range_t *spdy_ssl_range = NULL;
-
-static const value_string vals_status_code[] = {
- { 100, "Continue" },
- { 101, "Switching Protocols" },
- { 102, "Processing" },
- { 199, "Informational - Others" },
-
- { 200, "OK"},
- { 201, "Created"},
- { 202, "Accepted"},
- { 203, "Non-authoritative Information"},
- { 204, "No Content"},
- { 205, "Reset Content"},
- { 206, "Partial Content"},
- { 207, "Multi-Status"},
- { 299, "Success - Others"},
-
- { 300, "Multiple Choices"},
- { 301, "Moved Permanently"},
- { 302, "Found"},
- { 303, "See Other"},
- { 304, "Not Modified"},
- { 305, "Use Proxy"},
- { 307, "Temporary Redirect"},
- { 399, "Redirection - Others"},
-
- { 400, "Bad Request"},
- { 401, "Unauthorized"},
- { 402, "Payment Required"},
- { 403, "Forbidden"},
- { 404, "Not Found"},
- { 405, "Method Not Allowed"},
- { 406, "Not Acceptable"},
- { 407, "Proxy Authentication Required"},
- { 408, "Request Time-out"},
- { 409, "Conflict"},
- { 410, "Gone"},
- { 411, "Length Required"},
- { 412, "Precondition Failed"},
- { 413, "Request Entity Too Large"},
- { 414, "Request-URI Too Long"},
- { 415, "Unsupported Media Type"},
- { 416, "Requested Range Not Satisfiable"},
- { 417, "Expectation Failed"},
- { 418, "I'm a teapot"}, /* RFC 2324 */
- { 422, "Unprocessable Entity"},
- { 423, "Locked"},
- { 424, "Failed Dependency"},
- { 499, "Client Error - Others"},
-
- { 500, "Internal Server Error"},
- { 501, "Not Implemented"},
- { 502, "Bad Gateway"},
- { 503, "Service Unavailable"},
- { 504, "Gateway Time-out"},
- { 505, "HTTP Version not supported"},
- { 507, "Insufficient Storage"},
- { 599, "Server Error - Others"},
-
- { 0, NULL}
-};
-
-static const char spdy_dictionary[] =
- "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
- "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
- "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
- "-agent10010120020120220320420520630030130230330430530630740040140240340440"
- "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
- "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
- "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
- "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
- "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
- "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
- "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
- "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
- ".1statusversionurl";
-
-static void reset_decompressors(void)
-{
- if (spdy_debug) printf("Should reset SPDY decompressors\n");
-}
-
-static spdy_conv_t *
-get_spdy_conversation_data(packet_info *pinfo)
-{
- conversation_t *conversation;
- spdy_conv_t *conv_data;
- int retcode;
-
- conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
- if (spdy_debug) {
- printf("\n===========================================\n\n");
- printf("Conversation for frame #%d is %p\n", pinfo->fd->num, conversation);
- if (conversation)
- printf(" conv_data=%p\n", conversation_get_proto_data(conversation, proto_spdy));
- }
-
- if(!conversation) /* Conversation does not exist yet - create it */
- conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
-
- /* Retrieve information from conversation
- */
- conv_data = conversation_get_proto_data(conversation, proto_spdy);
- if(!conv_data) {
- /* Setup the conversation structure itself */
- conv_data = se_alloc0(sizeof(spdy_conv_t));
-
- conv_data->streams = NULL;
- if (spdy_decompress_headers) {
- conv_data->rqst_decompressor = se_alloc0(sizeof(z_stream));
- conv_data->rply_decompressor = se_alloc0(sizeof(z_stream));
- retcode = inflateInit(conv_data->rqst_decompressor);
- if (retcode == Z_OK)
- retcode = inflateInit(conv_data->rply_decompressor);
- if (retcode != Z_OK)
- printf("frame #%d: inflateInit() failed: %d\n", pinfo->fd->num, retcode);
- else if (spdy_debug)
- printf("created decompressor\n");
- conv_data->dictionary_id = adler32(0L, Z_NULL, 0);
- conv_data->dictionary_id = adler32(conv_data->dictionary_id,
- spdy_dictionary,
- sizeof(spdy_dictionary));
- }
-
- conversation_add_proto_data(conversation, proto_spdy, conv_data);
- register_postseq_cleanup_routine(reset_decompressors);
- }
- return conv_data;
-}
-
-static void
-spdy_save_stream_info(spdy_conv_t *conv_data,
- guint32 stream_id,
- gchar *content_type,
- gchar *content_type_params,
- gchar *content_encoding)
-{
- spdy_stream_info_t *si;
-
- if (conv_data->streams == NULL)
- conv_data->streams = g_array_new(FALSE, TRUE, sizeof(spdy_stream_info_t *));
- if (stream_id < conv_data->streams->len)
- DISSECTOR_ASSERT(g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id) == NULL);
- else
- g_array_set_size(conv_data->streams, stream_id+1);
- si = se_alloc(sizeof(spdy_stream_info_t));
- si->content_type = content_type;
- si->content_type_parameters = content_type_params;
- si->content_encoding = content_encoding;
- si->data_frames = NULL;
- si->num_data_frames = 0;
- si->assembled_data = NULL;
- g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id) = si;
- if (spdy_debug)
- printf("Saved stream info for ID %u, content type %s\n", stream_id, content_type);
-}
-
-static spdy_stream_info_t *
-spdy_get_stream_info(spdy_conv_t *conv_data, guint32 stream_id)
-{
- if (conv_data->streams == NULL || stream_id >= conv_data->streams->len)
- return NULL;
- else
- return g_array_index(conv_data->streams, spdy_stream_info_t*, stream_id);
-}
-
-static void
-spdy_add_data_chunk(spdy_conv_t *conv_data, guint32 stream_id, guint32 frame,
- guint8 *data, guint32 length)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
-
- if (si == NULL) {
- if (spdy_debug) printf("No stream_info found for stream %d\n", stream_id);
- } else {
- spdy_data_frame_t *df = g_malloc(sizeof(spdy_data_frame_t));
- df->data = data;
- df->length = length;
- df->framenum = frame;
- si->data_frames = g_slist_append(si->data_frames, df);
- ++si->num_data_frames;
- if (spdy_debug)
- printf("Saved %u bytes of data for stream %u frame %u\n",
- length, stream_id, df->framenum);
- }
-}
-
-static void
-spdy_increment_data_chunk_count(spdy_conv_t *conv_data, guint32 stream_id)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
- if (si != NULL)
- ++si->num_data_frames;
-}
-
-/*
- * Return the number of data frames saved so far for the specified stream.
- */
-static guint
-spdy_get_num_data_frames(spdy_conv_t *conv_data, guint32 stream_id)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
-
- return si == NULL ? 0 : si->num_data_frames;
-}
-
-static spdy_stream_info_t *
-spdy_assemble_data_frames(spdy_conv_t *conv_data, guint32 stream_id)
-{
- spdy_stream_info_t *si = spdy_get_stream_info(conv_data, stream_id);
- tvbuff_t *tvb;
-
- if (si == NULL)
- return NULL;
-
- /*
- * Compute the total amount of data and concatenate the
- * data chunks, if it hasn't already been done.
- */
- if (si->assembled_data == NULL) {
- spdy_data_frame_t *df;
- guint8 *data;
- guint32 datalen;
- guint32 offset;
- guint32 framenum;
- GSList *dflist = si->data_frames;
- if (dflist == NULL)
- return si;
- dflist = si->data_frames;
- datalen = 0;
- /*
- * I'd like to use a composite tvbuff here, but since
- * only a real-data tvbuff can be the child of another
- * tvb, I can't. It would be nice if this limitation
- * could be fixed.
- */
- while (dflist != NULL) {
- df = dflist->data;
- datalen += df->length;
- dflist = g_slist_next(dflist);
- }
- if (datalen != 0) {
- data = se_alloc(datalen);
- dflist = si->data_frames;
- offset = 0;
- framenum = 0;
- while (dflist != NULL) {
- df = dflist->data;
- memcpy(data+offset, df->data, df->length);
- offset += df->length;
- dflist = g_slist_next(dflist);
- }
- tvb = tvb_new_real_data(data, datalen, datalen);
- si->assembled_data = tvb;
- }
- }
- return si;
-}
-
-static void
-spdy_discard_data_frames(spdy_stream_info_t *si)
-{
- GSList *dflist = si->data_frames;
- spdy_data_frame_t *df;
-
- if (dflist == NULL)
- return;
- while (dflist != NULL) {
- df = dflist->data;
- if (df->data != NULL) {
- g_free(df->data);
- df->data = NULL;
- }
- dflist = g_slist_next(dflist);
- }
- /*g_slist_free(si->data_frames);
- si->data_frames = NULL; */
-}
-
-// TODO(cbentzel): tvb_child_uncompress should be exported by wireshark.
-static tvbuff_t* spdy_tvb_child_uncompress(tvbuff_t *parent _U_, tvbuff_t *tvb,
- int offset, int comprlen)
-{
- tvbuff_t *new_tvb = tvb_uncompress(tvb, offset, comprlen);
- if (new_tvb)
- tvb_set_child_real_data_tvbuff (parent, new_tvb);
- return new_tvb;
-}
-
-static int
-dissect_spdy_data_frame(tvbuff_t *tvb, int offset,
- packet_info *pinfo,
- proto_tree *top_level_tree,
- proto_tree *spdy_tree,
- proto_item *spdy_proto,
- spdy_conv_t *conv_data)
-{
- guint32 stream_id;
- guint8 flags;
- guint32 frame_length;
- proto_item *ti;
- proto_tree *flags_tree;
- guint32 reported_datalen;
- guint32 datalen;
- dissector_table_t media_type_subdissector_table;
- dissector_table_t port_subdissector_table;
- dissector_handle_t handle;
- guint num_data_frames;
- gboolean dissected;
-
- stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- flags = tvb_get_guint8(tvb, offset+4);
- frame_length = tvb_get_ntoh24(tvb, offset+5);
-
- if (spdy_debug)
- printf("Data frame [stream_id=%u flags=0x%x length=%d]\n",
- stream_id, flags, frame_length);
- if (spdy_tree) proto_item_append_text(spdy_tree, ", data frame");
- col_add_fstr(pinfo->cinfo, COL_INFO, "DATA[%u] length=%d",
- stream_id, frame_length);
-
- proto_item_append_text(spdy_proto, ":%s stream=%d length=%d",
- flags & SPDY_FIN ? " [FIN]" : "",
- stream_id, frame_length);
-
- proto_tree_add_boolean(spdy_tree, hf_spdy_control_bit, tvb, offset, 1, 0);
- proto_tree_add_uint(spdy_tree, hf_spdy_streamid, tvb, offset, 4, stream_id);
- ti = proto_tree_add_uint_format(spdy_tree, hf_spdy_flags, tvb, offset+4, 1, flags,
- "Flags: 0x%02x%s", flags, flags&SPDY_FIN ? " (FIN)" : "");
-
- flags_tree = proto_item_add_subtree(ti, ett_spdy_flags);
- proto_tree_add_boolean(flags_tree, hf_spdy_flags_fin, tvb, offset+4, 1, flags);
- proto_tree_add_uint(spdy_tree, hf_spdy_length, tvb, offset+5, 3, frame_length);
-
- datalen = tvb_length_remaining(tvb, offset);
- if (datalen > frame_length)
- datalen = frame_length;
-
- reported_datalen = tvb_reported_length_remaining(tvb, offset);
- if (reported_datalen > frame_length)
- reported_datalen = frame_length;
-
- num_data_frames = spdy_get_num_data_frames(conv_data, stream_id);
- if (datalen != 0 || num_data_frames != 0) {
- /*
- * There's stuff left over; process it.
- */
- tvbuff_t *next_tvb = NULL;
- tvbuff_t *data_tvb = NULL;
- spdy_stream_info_t *si = NULL;
- void *save_private_data = NULL;
- guint8 *copied_data;
- gboolean private_data_changed = FALSE;
- gboolean is_single_chunk = FALSE;
- gboolean have_entire_body;
-
- /*
- * Create a tvbuff for the payload.
- */
- if (datalen != 0) {
- next_tvb = tvb_new_subset(tvb, offset+8, datalen,
- reported_datalen);
- is_single_chunk = num_data_frames == 0 && (flags & SPDY_FIN) != 0;
- if (!pinfo->fd->flags.visited) {
- if (!is_single_chunk) {
- if (spdy_assemble_entity_bodies) {
- copied_data = tvb_memdup(next_tvb, 0, datalen);
- spdy_add_data_chunk(conv_data, stream_id, pinfo->fd->num,
- copied_data, datalen);
- } else
- spdy_increment_data_chunk_count(conv_data, stream_id);
- }
- }
- } else
- is_single_chunk = (num_data_frames == 1);
-
- if (!(flags & SPDY_FIN)) {
- col_set_fence(pinfo->cinfo, COL_INFO);
- col_add_fstr(pinfo->cinfo, COL_INFO, " (partial entity)");
- proto_item_append_text(spdy_proto, " (partial entity body)");
- /* would like the proto item to say */
- /* " (entity body fragment N of M)" */
- goto body_dissected;
- }
- have_entire_body = is_single_chunk;
- /*
- * On seeing the last data frame in a stream, we can
- * reassemble the frames into one data block.
- */
- si = spdy_assemble_data_frames(conv_data, stream_id);
- if (si == NULL)
- goto body_dissected;
- data_tvb = si->assembled_data;
- if (spdy_assemble_entity_bodies)
- have_entire_body = TRUE;
-
- if (!have_entire_body)
- goto body_dissected;
-
- if (data_tvb == NULL)
- data_tvb = next_tvb;
- else
- add_new_data_source(pinfo, data_tvb, "Assembled entity body");
-
- if (have_entire_body && si->content_encoding != NULL &&
- g_ascii_strcasecmp(si->content_encoding, "identity") != 0) {
- /*
- * We currently can't handle, for example, "compress";
- * just handle them as data for now.
- *
- * After July 7, 2004 the LZW patent expires, so support
- * might be added then. However, I don't think that
- * anybody ever really implemented "compress", due to
- * the aforementioned patent.
- */
- tvbuff_t *uncomp_tvb = NULL;
- proto_item *e_ti = NULL;
- proto_item *ce_ti = NULL;
- proto_tree *e_tree = NULL;
-
- if (spdy_decompress_body &&
- (g_ascii_strcasecmp(si->content_encoding, "gzip") == 0 ||
- g_ascii_strcasecmp(si->content_encoding, "deflate")
- == 0)) {
- uncomp_tvb = spdy_tvb_child_uncompress(tvb, data_tvb, 0,
- tvb_length(data_tvb));
- }
- /*
- * Add the encoded entity to the protocol tree
- */
- e_ti = proto_tree_add_text(top_level_tree, data_tvb,
- 0, tvb_length(data_tvb),
- "Content-encoded entity body (%s): %u bytes",
- si->content_encoding,
- tvb_length(data_tvb));
- e_tree = proto_item_add_subtree(e_ti, ett_spdy_encoded_entity);
- if (si->num_data_frames > 1) {
- GSList *dflist;
- spdy_data_frame_t *df;
- guint32 framenum;
- ce_ti = proto_tree_add_text(e_tree, data_tvb, 0,
- tvb_length(data_tvb),
- "Assembled from %d frames in packet(s)", si->num_data_frames);
- dflist = si->data_frames;
- framenum = 0;
- while (dflist != NULL) {
- df = dflist->data;
- if (framenum != df->framenum) {
- proto_item_append_text(ce_ti, " #%u", df->framenum);
- framenum = df->framenum;
- }
- dflist = g_slist_next(dflist);
- }
- }
-
- if (uncomp_tvb != NULL) {
- /*
- * Decompression worked
- */
-
- /* XXX - Don't free this, since it's possible
- * that the data was only partially
- * decompressed, such as when desegmentation
- * isn't enabled.
- *
- tvb_free(next_tvb);
- */
- proto_item_append_text(e_ti, " -> %u bytes", tvb_length(uncomp_tvb));
- data_tvb = uncomp_tvb;
- add_new_data_source(pinfo, data_tvb, "Uncompressed entity body");
- } else {
- if (spdy_decompress_body)
- proto_item_append_text(e_ti, " [Error: Decompression failed]");
- call_dissector(data_handle, data_tvb, pinfo, e_tree);
-
- goto body_dissected;
- }
- }
- if (si != NULL)
- spdy_discard_data_frames(si);
- /*
- * Do subdissector checks.
- *
- * First, check whether some subdissector asked that they
- * be called if something was on some particular port.
- */
-
- port_subdissector_table = find_dissector_table("http.port");
- media_type_subdissector_table = find_dissector_table("media_type");
- if (have_entire_body && port_subdissector_table != NULL)
- handle = dissector_get_port_handle(port_subdissector_table,
- pinfo->match_port);
- else
- handle = NULL;
- if (handle == NULL && have_entire_body && si->content_type != NULL &&
- media_type_subdissector_table != NULL) {
- /*
- * We didn't find any subdissector that
- * registered for the port, and we have a
- * Content-Type value. Is there any subdissector
- * for that content type?
- */
- save_private_data = pinfo->private_data;
- private_data_changed = TRUE;
-
- if (si->content_type_parameters)
- pinfo->private_data = ep_strdup(si->content_type_parameters);
- else
- pinfo->private_data = NULL;
- /*
- * Calling the string handle for the media type
- * dissector table will set pinfo->match_string
- * to si->content_type for us.
- */
- pinfo->match_string = si->content_type;
- handle = dissector_get_string_handle(
- media_type_subdissector_table,
- si->content_type);
- }
- if (handle != NULL) {
- /*
- * We have a subdissector - call it.
- */
- dissected = call_dissector(handle, data_tvb, pinfo, top_level_tree);
- } else
- dissected = FALSE;
-
- if (dissected) {
- /*
- * The subdissector dissected the body.
- * Fix up the top-level item so that it doesn't
- * include the stuff for that protocol.
- */
- if (ti != NULL)
- proto_item_set_len(ti, offset);
- } else if (have_entire_body && si->content_type != NULL) {
- /*
- * Calling the default media handle if there is a content-type that
- * wasn't handled above.
- */
- call_dissector(media_handle, next_tvb, pinfo, top_level_tree);
- } else {
- /* Call the default data dissector */
- call_dissector(data_handle, next_tvb, pinfo, top_level_tree);
- }
-
-body_dissected:
- /*
- * Do *not* attempt at freeing the private data;
- * it may be in use by subdissectors.
- */
- if (private_data_changed) /*restore even NULL value*/
- pinfo->private_data = save_private_data;
- /*
- * We've processed "datalen" bytes worth of data
- * (which may be no data at all); advance the
- * offset past whatever data we've processed.
- */
- }
- return frame_length + 8;
-}
-
-static guint8 *
-spdy_decompress_header_block(tvbuff_t *tvb, z_streamp decomp,
- guint32 dictionary_id, int offset,
- guint32 length, guint *uncomp_length)
-{
- int retcode;
- size_t bufsize = 16384;
- const guint8 *hptr = tvb_get_ptr(tvb, offset, length);
- guint8 *uncomp_block = ep_alloc(bufsize);
- decomp->next_in = (Bytef *)hptr;
- decomp->avail_in = length;
- decomp->next_out = uncomp_block;
- decomp->avail_out = bufsize;
- retcode = inflate(decomp, Z_SYNC_FLUSH);
- if (retcode == Z_NEED_DICT) {
- if (decomp->adler != dictionary_id) {
- printf("decompressor wants dictionary %#x, but we have %#x\n",
- (guint)decomp->adler, dictionary_id);
- } else {
- retcode = inflateSetDictionary(decomp,
- spdy_dictionary,
- sizeof(spdy_dictionary));
- if (retcode == Z_OK)
- retcode = inflate(decomp, Z_SYNC_FLUSH);
- }
- }
-
- if (retcode != Z_OK) {
- return NULL;
- } else {
- *uncomp_length = bufsize - decomp->avail_out;
- if (spdy_debug)
- printf("Inflation SUCCEEDED. uncompressed size=%d\n", *uncomp_length);
- if (decomp->avail_in != 0)
- if (spdy_debug)
- printf(" but there were %d input bytes left over\n", decomp->avail_in);
- }
- return se_memdup(uncomp_block, *uncomp_length);
-}
-
-/*
- * Try to determine heuristically whether the header block is
- * compressed. For an uncompressed block, the first two bytes
- * gives the number of headers. Each header name and value is
- * a two-byte length followed by ASCII characters.
- */
-static gboolean
-spdy_check_header_compression(tvbuff_t *tvb,
- int offset,
- guint32 frame_length)
-{
- guint16 length;
- if (!tvb_bytes_exist(tvb, offset, 6))
- return 1;
- length = tvb_get_ntohs(tvb, offset);
- if (length > frame_length)
- return 1;
- length = tvb_get_ntohs(tvb, offset+2);
- if (length > frame_length)
- return 1;
- if (spdy_debug) printf("Looks like the header block is not compressed\n");
- return 0;
-}
-
-// TODO(cbentzel): Change wireshark to export p_remove_proto_data, rather
-// than duplicating code here.
-typedef struct _spdy_frame_proto_data {
- int proto;
- void *proto_data;
-} spdy_frame_proto_data;
-
-static gint spdy_p_compare(gconstpointer a, gconstpointer b)
-{
- const spdy_frame_proto_data *ap = (const spdy_frame_proto_data *)a;
- const spdy_frame_proto_data *bp = (const spdy_frame_proto_data *)b;
-
- if (ap -> proto > bp -> proto)
- return 1;
- else if (ap -> proto == bp -> proto)
- return 0;
- else
- return -1;
-
-}
-
-static void spdy_p_remove_proto_data(frame_data *fd, int proto)
-{
- spdy_frame_proto_data temp;
- GSList *item;
-
- temp.proto = proto;
- temp.proto_data = NULL;
-
- item = g_slist_find_custom(fd->pfd, (gpointer *)&temp, spdy_p_compare);
-
- if (item) {
- fd->pfd = g_slist_remove(fd->pfd, item->data);
- }
-}
-
-static spdy_frame_info_t *
-spdy_save_header_block(frame_data *fd,
- guint32 stream_id,
- guint frame_type,
- guint8 *header,
- guint length)
-{
- GSList *filist = p_get_proto_data(fd, proto_spdy);
- spdy_frame_info_t *frame_info = se_alloc(sizeof(spdy_frame_info_t));
- if (filist != NULL)
- spdy_p_remove_proto_data(fd, proto_spdy);
- frame_info->stream_id = stream_id;
- frame_info->header_block = header;
- frame_info->header_block_len = length;
- frame_info->frame_type = frame_type;
- filist = g_slist_append(filist, frame_info);
- p_add_proto_data(fd, proto_spdy, filist);
- return frame_info;
- /* TODO(ers) these need to get deleted when no longer needed */
-}
-
-static spdy_frame_info_t *
-spdy_find_saved_header_block(frame_data *fd,
- guint32 stream_id,
- guint16 frame_type)
-{
- GSList *filist = p_get_proto_data(fd, proto_spdy);
- while (filist != NULL) {
- spdy_frame_info_t *fi = filist->data;
- if (fi->stream_id == stream_id && fi->frame_type == frame_type)
- return fi;
- filist = g_slist_next(filist);
- }
- return NULL;
-}
-
-/*
- * Given a content type string that may contain optional parameters,
- * return the parameter string, if any, otherwise return NULL. This
- * also has the side effect of null terminating the content type
- * part of the original string.
- */
-static gchar *
-spdy_parse_content_type(gchar *content_type)
-{
- gchar *cp = content_type;
-
- while (*cp != '\0' && *cp != ';' && !isspace(*cp)) {
- *cp = tolower(*cp);
- ++cp;
- }
- if (*cp == '\0')
- cp = NULL;
-
- if (cp != NULL) {
- *cp++ = '\0';
- while (*cp == ';' || isspace(*cp))
- ++cp;
- if (*cp != '\0')
- return cp;
- }
- return NULL;
-}
-
-static int
-dissect_spdy_message(tvbuff_t *tvb, int offset, packet_info *pinfo,
- proto_tree *tree, spdy_conv_t *conv_data)
-{
- guint8 control_bit;
- guint16 version;
- guint16 frame_type;
- guint8 flags;
- guint32 frame_length;
- guint32 stream_id;
- guint32 associated_stream_id;
- gint priority;
- guint16 num_headers;
- guint32 fin_status;
- guint8 *frame_header;
- const char *proto_tag;
- const char *frame_type_name;
- proto_tree *spdy_tree = NULL;
- proto_item *ti = NULL;
- proto_item *spdy_proto = NULL;
- int orig_offset;
- int hoffset;
- int hdr_offset = 0;
- spdy_frame_type_t spdy_type;
- proto_tree *sub_tree;
- proto_tree *flags_tree;
- tvbuff_t *header_tvb = NULL;
- gboolean headers_compressed;
- gchar *hdr_verb = NULL;
- gchar *hdr_url = NULL;
- gchar *hdr_version = NULL;
- gchar *content_type = NULL;
- gchar *content_encoding = NULL;
-
- /*
- * Minimum size for a SPDY frame is 8 bytes.
- */
- if (tvb_reported_length_remaining(tvb, offset) < 8)
- return -1;
-
- proto_tag = "SPDY";
-
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_tag);
-
- /*
- * Is this a control frame or a data frame?
- */
- orig_offset = offset;
- control_bit = tvb_get_bits8(tvb, offset << 3, 1);
- if (control_bit) {
- version = tvb_get_bits16(tvb, (offset << 3) + 1, 15, FALSE);
- frame_type = tvb_get_ntohs(tvb, offset+2);
- if (frame_type >= SPDY_INVALID) {
- return -1;
- }
- frame_header = ep_tvb_memdup(tvb, offset, 16);
- } else {
- version = 1; /* avoid gcc warning */
- frame_type = SPDY_DATA;
- frame_header = NULL; /* avoid gcc warning */
- }
- frame_type_name = frame_type_names[frame_type];
- offset += 4;
- flags = tvb_get_guint8(tvb, offset);
- frame_length = tvb_get_ntoh24(tvb, offset+1);
- offset += 4;
- /*
- * Make sure there's as much data as the frame header says there is.
- */
- if ((guint)tvb_reported_length_remaining(tvb, offset) < frame_length) {
- if (spdy_debug)
- printf("Not enough header data: %d vs. %d\n",
- frame_length, tvb_reported_length_remaining(tvb, offset));
- return -1;
- }
- if (tree) {
- spdy_proto = proto_tree_add_item(tree, proto_spdy, tvb, orig_offset, frame_length+8, FALSE);
- spdy_tree = proto_item_add_subtree(spdy_proto, ett_spdy);
- }
-
- if (control_bit) {
- if (spdy_debug)
- printf("Control frame [version=%d type=%d flags=0x%x length=%d]\n",
- version, frame_type, flags, frame_length);
- if (tree) proto_item_append_text(spdy_tree, ", control frame");
- } else {
- return dissect_spdy_data_frame(tvb, orig_offset, pinfo, tree,
- spdy_tree, spdy_proto, conv_data);
- }
- num_headers = 0;
- sub_tree = NULL; /* avoid gcc warning */
- switch (frame_type) {
- case SPDY_SYN_STREAM:
- case SPDY_SYN_REPLY:
- if (tree) {
- int hf;
- hf = frame_type == SPDY_SYN_STREAM ? hf_spdy_syn_stream : hf_spdy_syn_reply;
- ti = proto_tree_add_bytes(spdy_tree, hf, tvb,
- orig_offset, 16, frame_header);
- sub_tree = proto_item_add_subtree(ti, ett_spdy_syn_stream);
- }
- stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- offset += 4;
- if (frame_type == SPDY_SYN_STREAM) {
- associated_stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- offset += 4;
- priority = tvb_get_bits8(tvb, offset << 3, 2);
- offset += 2;
- } else {
- // The next two bytes have no meaning in SYN_REPLY
- offset += 2;
- }
- if (tree) {
- proto_tree_add_boolean(sub_tree, hf_spdy_control_bit, tvb, orig_offset, 1, control_bit);
- proto_tree_add_uint(sub_tree, hf_spdy_version, tvb, orig_offset, 2, version);
- proto_tree_add_uint(sub_tree, hf_spdy_type, tvb, orig_offset+2, 2, frame_type);
- ti = proto_tree_add_uint_format(sub_tree, hf_spdy_flags, tvb, orig_offset+4, 1, flags,
- "Flags: 0x%02x%s", flags, flags&SPDY_FIN ? " (FIN)" : "");
- flags_tree = proto_item_add_subtree(ti, ett_spdy_flags);
- proto_tree_add_boolean(flags_tree, hf_spdy_flags_fin, tvb, orig_offset+4, 1, flags);
- proto_tree_add_uint(sub_tree, hf_spdy_length, tvb, orig_offset+5, 3, frame_length);
- proto_tree_add_uint(sub_tree, hf_spdy_streamid, tvb, orig_offset+8, 4, stream_id);
- if (frame_type == SPDY_SYN_STREAM) {
- proto_tree_add_uint(sub_tree, hf_spdy_associated_streamid, tvb, orig_offset+12, 4, associated_stream_id);
- proto_tree_add_uint(sub_tree, hf_spdy_priority, tvb, orig_offset+16, 1, priority);
- }
- proto_item_append_text(spdy_proto, ": %s%s stream=%d length=%d",
- frame_type_name,
- flags & SPDY_FIN ? " [FIN]" : "",
- stream_id, frame_length);
- if (spdy_debug)
- printf(" stream ID=%u priority=%d\n", stream_id, priority);
- }
- break;
-
- case SPDY_FIN_STREAM:
- stream_id = tvb_get_bits32(tvb, (offset << 3) + 1, 31, FALSE);
- fin_status = tvb_get_ntohl(tvb, offset);
- // TODO(ers) fill in tree and summary
- offset += 8;
- break;
-
- case SPDY_HELLO:
- // TODO(ers) fill in tree and summary
- stream_id = 0; /* avoid gcc warning */
- break;
-
- default:
- stream_id = 0; /* avoid gcc warning */
- return -1;
- break;
- }
-
- /*
- * Process the name-value pairs one at a time, after possibly
- * decompressing the header block.
- */
- if (frame_type == SPDY_SYN_STREAM || frame_type == SPDY_SYN_REPLY) {
- headers_compressed = spdy_check_header_compression(tvb, offset, frame_length);
- if (!spdy_decompress_headers || !headers_compressed) {
- header_tvb = tvb;
- hdr_offset = offset;
- } else {
- spdy_frame_info_t *per_frame_info =
- spdy_find_saved_header_block(pinfo->fd,
- stream_id,
- frame_type == SPDY_SYN_REPLY);
- if (per_frame_info == NULL) {
- guint uncomp_length;
- z_streamp decomp = frame_type == SPDY_SYN_STREAM ?
- conv_data->rqst_decompressor : conv_data->rply_decompressor;
- guint8 *uncomp_ptr =
- spdy_decompress_header_block(tvb, decomp,
- conv_data->dictionary_id,
- offset,
- frame_length + 8 - (offset - orig_offset),
- &uncomp_length);
- if (uncomp_ptr == NULL) { /* decompression failed */
- if (spdy_debug)
- printf("Frame #%d: Inflation failed\n", pinfo->fd->num);
- proto_item_append_text(spdy_proto, " [Error: Header decompression failed]");
- // Should we just bail here?
- } else {
- if (spdy_debug)
- printf("Saving %u bytes of uncomp hdr\n", uncomp_length);
- per_frame_info =
- spdy_save_header_block(pinfo->fd, stream_id, frame_type == SPDY_SYN_REPLY,
- uncomp_ptr, uncomp_length);
- }
- } else if (spdy_debug) {
- printf("Found uncompressed header block len %u for stream %u frame_type=%d\n",
- per_frame_info->header_block_len,
- per_frame_info->stream_id,
- per_frame_info->frame_type);
- }
- if (per_frame_info != NULL) {
- header_tvb = tvb_new_child_real_data(tvb,
- per_frame_info->header_block,
- per_frame_info->header_block_len,
- per_frame_info->header_block_len);
- add_new_data_source(pinfo, header_tvb, "Uncompressed headers");
- hdr_offset = 0;
- }
- }
- offset = orig_offset + 8 + frame_length;
- num_headers = tvb_get_ntohs(header_tvb, hdr_offset);
- hdr_offset += 2;
- if (header_tvb == NULL ||
- (headers_compressed && !spdy_decompress_headers)) {
- num_headers = 0;
- ti = proto_tree_add_string(sub_tree, hf_spdy_num_headers_string,
- tvb,
- frame_type == SPDY_SYN_STREAM ? orig_offset+18 : orig_offset + 14,
- 2,
- "Unknown (header block is compressed)");
- } else
- ti = proto_tree_add_uint(sub_tree, hf_spdy_num_headers,
- tvb,
- frame_type == SPDY_SYN_STREAM ? orig_offset+18 : orig_offset +14,
- 2, num_headers);
- }
- spdy_type = SPDY_INVALID; /* type not known yet */
- if (spdy_debug)
- printf(" %d Headers:\n", num_headers);
- if (num_headers > frame_length) {
- printf("Number of headers is greater than frame length!\n");
- proto_item_append_text(ti, " [Error: Number of headers is larger than frame length]");
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]", frame_type_name, stream_id);
- return frame_length+8;
- }
- hdr_verb = hdr_url = hdr_version = content_type = content_encoding = NULL;
- while (num_headers-- && tvb_reported_length_remaining(header_tvb, hdr_offset) != 0) {
- gchar *header_name;
- gchar *header_value;
- proto_tree *header_tree;
- proto_tree *name_tree;
- proto_tree *value_tree;
- proto_item *header;
- gint16 length;
- gint header_length = 0;
-
- hoffset = hdr_offset;
-
- header = proto_tree_add_item(spdy_tree, hf_spdy_header, header_tvb,
- hdr_offset, frame_length, FALSE);
- header_tree = proto_item_add_subtree(header, ett_spdy_header);
-
- length = tvb_get_ntohs(header_tvb, hdr_offset);
- hdr_offset += 2;
- header_name = (gchar *)tvb_get_ephemeral_string(header_tvb, hdr_offset, length);
- hdr_offset += length;
- header_length += hdr_offset - hoffset;
- if (tree) {
- ti = proto_tree_add_text(header_tree, header_tvb, hoffset, length+2, "Name: %s",
- header_name);
- name_tree = proto_item_add_subtree(ti, ett_spdy_header_name);
- proto_tree_add_uint(name_tree, hf_spdy_length, header_tvb, hoffset, 2, length);
- proto_tree_add_string_format(name_tree, hf_spdy_header_name_text, header_tvb, hoffset+2, length,
- header_name, "Text: %s", format_text(header_name, length));
- }
-
- hoffset = hdr_offset;
- length = tvb_get_ntohs(header_tvb, hdr_offset);
- hdr_offset += 2;
- header_value = (gchar *)tvb_get_ephemeral_string(header_tvb, hdr_offset, length);
- hdr_offset += length;
- header_length += hdr_offset - hoffset;
- if (tree) {
- ti = proto_tree_add_text(header_tree, header_tvb, hoffset, length+2, "Value: %s",
- header_value);
- value_tree = proto_item_add_subtree(ti, ett_spdy_header_value);
- proto_tree_add_uint(value_tree, hf_spdy_length, header_tvb, hoffset, 2, length);
- proto_tree_add_string_format(value_tree, hf_spdy_header_value_text, header_tvb, hoffset+2, length,
- header_value, "Text: %s", format_text(header_value, length));
- proto_item_append_text(header, ": %s: %s", header_name, header_value);
- proto_item_set_len(header, header_length);
- }
- if (spdy_debug) printf(" %s: %s\n", header_name, header_value);
- /*
- * TODO(ers) check that the header name contains only legal characters.
- */
- if (g_ascii_strcasecmp(header_name, "method") == 0 ||
- g_ascii_strcasecmp(header_name, "status") == 0) {
- hdr_verb = header_value;
- } else if (g_ascii_strcasecmp(header_name, "url") == 0) {
- hdr_url = header_value;
- } else if (g_ascii_strcasecmp(header_name, "version") == 0) {
- hdr_version = header_value;
- } else if (g_ascii_strcasecmp(header_name, "content-type") == 0) {
- content_type = se_strdup(header_value);
- } else if (g_ascii_strcasecmp(header_name, "content-encoding") == 0) {
- content_encoding = se_strdup(header_value);
- }
- }
- if (hdr_version != NULL) {
- if (hdr_url != NULL) {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: %s %s %s",
- frame_type_name, stream_id, hdr_verb, hdr_url, hdr_version);
- } else {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]: %s %s",
- frame_type_name, stream_id, hdr_verb, hdr_version);
- }
- } else {
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s[%d]", frame_type_name, stream_id);
- }
- /*
- * If we expect data on this stream, we need to remember the content
- * type and content encoding.
- */
- if (content_type != NULL && !pinfo->fd->flags.visited) {
- gchar *content_type_params = spdy_parse_content_type(content_type);
- spdy_save_stream_info(conv_data, stream_id, content_type,
- content_type_params, content_encoding);
- }
-
- return offset - orig_offset;
-}
-
-static int
-dissect_spdy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- spdy_conv_t *conv_data;
- int offset = 0;
- int len;
- int firstpkt = 1;
-
- /*
- * The first byte of a SPDY packet must be either 0 or
- * 0x80. If it's not, assume that this is not SPDY.
- * (In theory, a data frame could have a stream ID
- * >= 2^24, in which case it won't have 0 for a first
- * byte, but this is a pretty reliable heuristic for
- * now.)
- */
- guint8 first_byte = tvb_get_guint8(tvb, 0);
- if (first_byte != 0x80 && first_byte != 0x0)
- return 0;
-
- conv_data = get_spdy_conversation_data(pinfo);
-
- while (tvb_reported_length_remaining(tvb, offset) != 0) {
- if (!firstpkt) {
- col_add_fstr(pinfo->cinfo, COL_INFO, " >> ");
- col_set_fence(pinfo->cinfo, COL_INFO);
- }
- len = dissect_spdy_message(tvb, offset, pinfo, tree, conv_data);
- if (len <= 0)
- return 0;
- offset += len;
- /*
- * OK, we've set the Protocol and Info columns for the
- * first SPDY message; set a fence so that subsequent
- * SPDY messages don't overwrite the Info column.
- */
- col_set_fence(pinfo->cinfo, COL_INFO);
- firstpkt = 0;
- }
- return 1;
-}
-
-static gboolean
-dissect_spdy_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- if (!value_is_in_range(global_spdy_tcp_range, pinfo->destport) &&
- !value_is_in_range(global_spdy_tcp_range, pinfo->srcport))
- return FALSE;
- return dissect_spdy(tvb, pinfo, tree) != 0;
-}
-
-static void reinit_spdy(void)
-{
-}
-
-// NMAKE complains about flags_set_truth not being constant. Duplicate
-// the values inside of it.
-static const true_false_string tfs_spdy_set_notset = { "Set", "Not set" };
-
-void
-proto_register_spdy(void)
-{
- static hf_register_info hf[] = {
- { &hf_spdy_syn_stream,
- { "Syn Stream", "spdy.syn_stream",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_syn_reply,
- { "Syn Reply", "spdy.syn_reply",
- FT_BYTES, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_control_bit,
- { "Control bit", "spdy.control_bit",
- FT_BOOLEAN, BASE_NONE, NULL, 0x0,
- "TRUE if SPDY control frame", HFILL }},
- { &hf_spdy_version,
- { "Version", "spdy.version",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_type,
- { "Type", "spdy.type",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_flags,
- { "Flags", "spdy.flags",
- FT_UINT8, BASE_HEX, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_flags_fin,
- { "Fin", "spdy.flags.fin",
- FT_BOOLEAN, 8, TFS(&tfs_spdy_set_notset),
- SPDY_FIN, "", HFILL }},
- { &hf_spdy_length,
- { "Length", "spdy.length",
- FT_UINT24, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header,
- { "Header", "spdy.header",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_name,
- { "Name", "spdy.header.name",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_name_text,
- { "Text", "spdy.header.name.text",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_value,
- { "Value", "spdy.header.value",
- FT_NONE, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_header_value_text,
- { "Text", "spdy.header.value.text",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_streamid,
- { "Stream ID", "spdy.streamid",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_associated_streamid,
- { "Associated Stream ID", "spdy.associated.streamid",
- FT_UINT32, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_priority,
- { "Priority", "spdy.priority",
- FT_UINT8, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_num_headers,
- { "Number of headers", "spdy.numheaders",
- FT_UINT16, BASE_DEC, NULL, 0x0,
- "", HFILL }},
- { &hf_spdy_num_headers_string,
- { "Number of headers", "spdy.numheaders",
- FT_STRING, BASE_NONE, NULL, 0x0,
- "", HFILL }},
- };
- static gint *ett[] = {
- &ett_spdy,
- &ett_spdy_syn_stream,
- &ett_spdy_syn_reply,
- &ett_spdy_fin_stream,
- &ett_spdy_flags,
- &ett_spdy_header,
- &ett_spdy_header_name,
- &ett_spdy_header_value,
- &ett_spdy_encoded_entity,
- };
-
- module_t *spdy_module;
-
- proto_spdy = proto_register_protocol("SPDY", "SPDY", "spdy");
- proto_register_field_array(proto_spdy, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
- new_register_dissector("spdy", dissect_spdy, proto_spdy);
- spdy_module = prefs_register_protocol(proto_spdy, reinit_spdy);
- prefs_register_bool_preference(spdy_module, "desegment_headers",
- "Reassemble SPDY control frames spanning multiple TCP segments",
- "Whether the SPDY dissector should reassemble control frames "
- "spanning multiple TCP segments. "
- "To use this option, you must also enable "
- "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
- &spdy_desegment_control_frames);
- prefs_register_bool_preference(spdy_module, "desegment_body",
- "Reassemble SPDY bodies spanning multiple TCP segments",
- "Whether the SPDY dissector should reassemble "
- "data frames spanning multiple TCP segments. "
- "To use this option, you must also enable "
- "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
- &spdy_desegment_data_frames);
- prefs_register_bool_preference(spdy_module, "assemble_data_frames",
- "Assemble SPDY bodies that consist of multiple DATA frames",
- "Whether the SPDY dissector should reassemble multiple "
- "data frames into an entity body.",
- &spdy_assemble_entity_bodies);
-#ifdef HAVE_LIBZ
- prefs_register_bool_preference(spdy_module, "decompress_headers",
- "Uncompress SPDY headers",
- "Whether to uncompress SPDY headers.",
- &spdy_decompress_headers);
- prefs_register_bool_preference(spdy_module, "decompress_body",
- "Uncompress entity bodies",
- "Whether to uncompress entity bodies that are compressed "
- "using \"Content-Encoding: \"",
- &spdy_decompress_body);
-#endif
- prefs_register_bool_preference(spdy_module, "debug_output",
- "Print debug info on stdout",
- "Print debug info on stdout",
- &spdy_debug);
-#if 0
- prefs_register_string_preference(ssl_module, "debug_file", "SPDY debug file",
- "Redirect SPDY debug to file name; "
- "leave empty to disable debugging, "
- "or use \"" SPDY_DEBUG_USE_STDOUT "\""
- " to redirect output to stdout\n",
- (const gchar **)&sdpy_debug_file_name);
-#endif
- prefs_register_obsolete_preference(spdy_module, "tcp_alternate_port");
-
- range_convert_str(&global_spdy_tcp_range, TCP_DEFAULT_RANGE, 65535);
- spdy_tcp_range = range_empty();
- prefs_register_range_preference(spdy_module, "tcp.port", "TCP Ports",
- "TCP Ports range",
- &global_spdy_tcp_range, 65535);
-
- range_convert_str(&global_spdy_ssl_range, SSL_DEFAULT_RANGE, 65535);
- spdy_ssl_range = range_empty();
- prefs_register_range_preference(spdy_module, "ssl.port", "SSL/TLS Ports",
- "SSL/TLS Ports range",
- &global_spdy_ssl_range, 65535);
-
- spdy_handle = new_create_dissector_handle(dissect_spdy, proto_spdy);
- /*
- * Register for tapping
- */
- spdy_tap = register_tap("spdy"); /* SPDY statistics tap */
- spdy_eo_tap = register_tap("spdy_eo"); /* SPDY Export Object tap */
-}
-
-void
-proto_reg_handoff_spdy(void)
-{
- data_handle = find_dissector("data");
- media_handle = find_dissector("media");
- heur_dissector_add("tcp", dissect_spdy_heur, proto_spdy);
-}
-
-/*
- * Content-Type: message/http
- */
-
-static gint proto_message_spdy = -1;
-static gint ett_message_spdy = -1;
-
-static void
-dissect_message_spdy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- proto_tree *subtree;
- proto_item *ti;
- gint offset = 0, next_offset;
- gint len;
-
- if (check_col(pinfo->cinfo, COL_INFO))
- col_append_str(pinfo->cinfo, COL_INFO, " (message/spdy)");
- if (tree) {
- ti = proto_tree_add_item(tree, proto_message_spdy,
- tvb, 0, -1, FALSE);
- subtree = proto_item_add_subtree(ti, ett_message_spdy);
- while (tvb_reported_length_remaining(tvb, offset) != 0) {
- len = tvb_find_line_end(tvb, offset,
- tvb_ensure_length_remaining(tvb, offset),
- &next_offset, FALSE);
- if (len == -1)
- break;
- proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
- "%s", tvb_format_text(tvb, offset, len));
- offset = next_offset;
- }
- }
-}
-
-void
-proto_register_message_spdy(void)
-{
- static gint *ett[] = {
- &ett_message_spdy,
- };
-
- proto_message_spdy = proto_register_protocol(
- "Media Type: message/spdy",
- "message/spdy",
- "message-spdy"
- );
- proto_register_subtree_array(ett, array_length(ett));
-}
-
-void
-proto_reg_handoff_message_spdy(void)
-{
- dissector_handle_t message_spdy_handle;
-
- message_spdy_handle = create_dissector_handle(dissect_message_spdy,
- proto_message_spdy);
-
- dissector_add_string("media_type", "message/spdy", message_spdy_handle);
-
- reinit_spdy();
-}
diff --git a/chromium/net/tools/spdyshark/packet-spdy.h b/chromium/net/tools/spdyshark/packet-spdy.h
deleted file mode 100644
index 02b586b9ab0..00000000000
--- a/chromium/net/tools/spdyshark/packet-spdy.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* packet-spdy.h
- *
- * Copyright 2010, Google Inc.
- * Eric Shienbrood <ers@google.com>
- *
- * $Id$
- *
- * Wireshark - Network traffic analyzer
- * By Gerald Combs <gerald@wireshark.org>
- * Copyright 1998 Gerald Combs
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __PACKET_SPDY_H__
-#define __PACKET_SPDY_H__
-
-#include <epan/packet.h>
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-/*
- * Conversation data - used for assembling multi-data-frame
- * entities and for decompressing request & reply header blocks.
- */
-typedef struct _spdy_conv_t {
- z_streamp rqst_decompressor;
- z_streamp rply_decompressor;
- guint32 dictionary_id;
- GArray *streams;
-} spdy_conv_t;
-
-#endif /* __PACKET_SPDY_H__ */
diff --git a/chromium/net/tools/spdyshark/plugin.rc.in b/chromium/net/tools/spdyshark/plugin.rc.in
deleted file mode 100644
index 568dc07b498..00000000000
--- a/chromium/net/tools/spdyshark/plugin.rc.in
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "winver.h"
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION @RC_MODULE_VERSION@
- PRODUCTVERSION @RC_VERSION@
- FILEFLAGSMASK 0x0L
-#ifdef _DEBUG
- FILEFLAGS VS_FF_DEBUG
-#else
- FILEFLAGS 0
-#endif
- FILEOS VOS_NT_WINDOWS32
- FILETYPE VFT_DLL
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "CompanyName", "The Wireshark developer community, http://www.wireshark.org/\0"
- VALUE "FileDescription", "@PACKAGE@ dissector\0"
- VALUE "FileVersion", "@MODULE_VERSION@\0"
- VALUE "InternalName", "@PACKAGE@ @MODULE_VERSION@\0"
- VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs <gerald@wireshark.org>, Gilbert Ramirez <gram@alumni.rice.edu> and others\0"
- VALUE "OriginalFilename", "@PLUGIN_NAME@.dll\0"
- VALUE "ProductName", "Wireshark\0"
- VALUE "ProductVersion", "@VERSION@\0"
- VALUE "Comments", "Build with @MSVC_VARIANT@\0"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
diff --git a/chromium/net/tools/testserver/testserver.py b/chromium/net/tools/testserver/testserver.py
index e0317e88685..0a1f59b0c59 100755
--- a/chromium/net/tools/testserver/testserver.py
+++ b/chromium/net/tools/testserver/testserver.py
@@ -35,15 +35,22 @@ import urllib
import urlparse
import zlib
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(BASE_DIR)))
+
import echo_message
-import pyftpdlib.ftpserver
import testserver_base
+
+# Append at the end of sys.path, it's fine to use the system library.
+sys.path.append(os.path.join(ROOT_DIR, 'third_party', 'pyftpdlib', 'src'))
+sys.path.append(os.path.join(ROOT_DIR, 'third_party', 'tlslite'))
+import pyftpdlib.ftpserver
import tlslite
import tlslite.api
-BASE_DIR = os.path.dirname(os.path.abspath(__file__))
-sys.path.insert(
- 0, os.path.join(BASE_DIR, '..', '..', '..', 'third_party/pywebsocket/src'))
+# Insert at the beginning of the path, we want this to be used
+# unconditionally.
+sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party', 'pywebsocket', 'src'))
from mod_pywebsocket.standalone import WebSocketServer
SERVER_HTTP = 0
@@ -128,7 +135,8 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
def __init__(self, server_address, request_hander_class, pem_cert_and_key,
ssl_client_auth, ssl_client_cas, ssl_bulk_ciphers,
- record_resume_info, tls_intolerant):
+ record_resume_info, tls_intolerant, signed_cert_timestamps,
+ fallback_scsv_enabled, ocsp_response):
self.cert_chain = tlslite.api.X509CertChain().parseChain(pem_cert_and_key)
# Force using only python implementation - otherwise behavior is different
# depending on whether m2crypto Python module is present (error is thrown
@@ -140,6 +148,9 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
self.ssl_client_auth = ssl_client_auth
self.ssl_client_cas = []
self.tls_intolerant = tls_intolerant
+ self.signed_cert_timestamps = signed_cert_timestamps
+ self.fallback_scsv_enabled = fallback_scsv_enabled
+ self.ocsp_response = ocsp_response
for ca_file in ssl_client_cas:
s = open(ca_file).read()
@@ -171,7 +182,11 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
reqCert=self.ssl_client_auth,
settings=self.ssl_handshake_settings,
reqCAs=self.ssl_client_cas,
- tlsIntolerant=self.tls_intolerant)
+ tlsIntolerant=self.tls_intolerant,
+ signedCertTimestamps=
+ self.signed_cert_timestamps,
+ fallbackSCSV=self.fallback_scsv_enabled,
+ ocspResponse = self.ocsp_response)
tlsConnection.ignoreAbruptClose = True
return True
except tlslite.api.TLSAbruptCloseError:
@@ -1478,6 +1493,8 @@ class TestPageHandler(testserver_base.BasePageHandler):
if not self._ShouldHandleRequest('/rangereset'):
return False
+ # HTTP/1.1 is required for ETag and range support.
+ self.protocol_version = 'HTTP/1.1'
_, _, url_path, _, query, _ = urlparse.urlparse(self.path)
# Defaults
@@ -1558,7 +1575,10 @@ class TestPageHandler(testserver_base.BasePageHandler):
self.send_header('Content-Type', 'application/octet-stream')
self.send_header('Content-Length', last_byte - first_byte + 1)
if send_verifiers:
- self.send_header('Etag', '"XYZZY"')
+ # If fail_precondition is non-zero, then the ETag for each request will be
+ # different.
+ etag = "%s%d" % (token, fail_precondition)
+ self.send_header('ETag', etag)
self.send_header('Last-Modified', 'Tue, 19 Feb 2013 14:32 EST')
self.end_headers()
@@ -1928,12 +1948,21 @@ class ServerRunner(testserver_base.TestServerRunner):
raise testserver_base.OptionError(
'specified trusted client CA file not found: ' + ca_cert +
' exiting...')
+
+ stapled_ocsp_response = None
+ if self.__ocsp_server and self.options.staple_ocsp_response:
+ stapled_ocsp_response = self.__ocsp_server.ocsp_response
+
server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
self.options.ssl_client_auth,
self.options.ssl_client_ca,
self.options.ssl_bulk_cipher,
self.options.record_resume,
- self.options.tls_intolerant)
+ self.options.tls_intolerant,
+ self.options.signed_cert_timestamps_tls_ext.decode(
+ "base64"),
+ self.options.fallback_scsv,
+ stapled_ocsp_response)
print 'HTTPS server started on %s:%d...' % (host, server.server_port)
else:
server = HTTPServer((host, port), TestPageHandler)
@@ -2071,6 +2100,26 @@ class ServerRunner(testserver_base.TestServerRunner):
'aborted. 2 means TLS 1.1 or higher will be '
'aborted. 3 means TLS 1.2 or higher will be '
'aborted.')
+ self.option_parser.add_option('--signed-cert-timestamps-tls-ext',
+ dest='signed_cert_timestamps_tls_ext',
+ default='',
+ help='Base64 encoded SCT list. If set, '
+ 'server will respond with a '
+ 'signed_certificate_timestamp TLS extension '
+ 'whenever the client supports it.')
+ self.option_parser.add_option('--fallback-scsv', dest='fallback_scsv',
+ default=False, const=True,
+ action='store_const',
+ help='If given, TLS_FALLBACK_SCSV support '
+ 'will be enabled. This causes the server to '
+ 'reject fallback connections from compatible '
+ 'clients (e.g. Chrome).')
+ self.option_parser.add_option('--staple-ocsp-response',
+ dest='staple_ocsp_response',
+ default=False, action='store_true',
+ help='If set, server will staple the OCSP '
+ 'response whenever OCSP is on and the client '
+ 'supports OCSP stapling.')
self.option_parser.add_option('--https-record-resume',
dest='record_resume', const=True,
default=False, action='store_const',
diff --git a/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc b/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc
index 8e04b55bd1c..623403fed93 100644
--- a/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc
+++ b/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc
@@ -177,7 +177,8 @@ NormalizeResult NormalizeDataToRuleMap(const std::string data,
// wildcard for the same rule, or that the same domain is listed as both
// private and not private. If we did, we'd have to update our
// parsing code to handle this case.
- CHECK(rules->find(domain) == rules->end());
+ CHECK(rules->find(domain) == rules->end())
+ << "Duplicate rule found for " << domain;
(*rules)[domain] = rule;
// Add true TLD for multi-level rules. We don't add them right now, in
diff --git a/chromium/net/udp/datagram_server_socket.h b/chromium/net/udp/datagram_server_socket.h
index f2016c0e0d0..ed5ab7a7c4f 100644
--- a/chromium/net/udp/datagram_server_socket.h
+++ b/chromium/net/udp/datagram_server_socket.h
@@ -80,6 +80,12 @@ class NET_EXPORT DatagramServerSocket : public DatagramSocket {
// Returns a network error code.
virtual int LeaveGroup(const IPAddressNumber& group_address) const = 0;
+ // Set interface to use for multicast. If |interface_index| set to 0, default
+ // interface is used.
+ // Should be called before Bind().
+ // Returns a network error code.
+ virtual int SetMulticastInterface(uint32 interface_index) = 0;
+
// Set the time-to-live option for UDP packets sent to the multicast
// group address. The default value of this option is 1.
// Cannot be negative or more than 255.
@@ -93,6 +99,10 @@ class NET_EXPORT DatagramServerSocket : public DatagramSocket {
// Should be called before Bind().
// Returns a network error code.
virtual int SetMulticastLoopbackMode(bool loopback) = 0;
+
+ // Set the Differentiated Services Code Point. May do nothing on
+ // some platforms. Returns a network error code.
+ virtual int SetDiffServCodePoint(DiffServCodePoint dscp) = 0;
};
} // namespace net
diff --git a/chromium/net/udp/udp_server_socket.cc b/chromium/net/udp/udp_server_socket.cc
index 16e4061f09c..99d741b4700 100644
--- a/chromium/net/udp/udp_server_socket.cc
+++ b/chromium/net/udp/udp_server_socket.cc
@@ -77,6 +77,10 @@ int UDPServerSocket::LeaveGroup(const IPAddressNumber& group_address) const {
return socket_.LeaveGroup(group_address);
}
+int UDPServerSocket::SetMulticastInterface(uint32 interface_index) {
+ return socket_.SetMulticastInterface(interface_index);
+}
+
int UDPServerSocket::SetMulticastTimeToLive(int time_to_live) {
return socket_.SetMulticastTimeToLive(time_to_live);
}
@@ -85,4 +89,8 @@ int UDPServerSocket::SetMulticastLoopbackMode(bool loopback) {
return socket_.SetMulticastLoopbackMode(loopback);
}
+int UDPServerSocket::SetDiffServCodePoint(DiffServCodePoint dscp) {
+ return socket_.SetDiffServCodePoint(dscp);
+}
+
} // namespace net
diff --git a/chromium/net/udp/udp_server_socket.h b/chromium/net/udp/udp_server_socket.h
index cc475f4f6b1..c593413d628 100644
--- a/chromium/net/udp/udp_server_socket.h
+++ b/chromium/net/udp/udp_server_socket.h
@@ -18,8 +18,7 @@ class BoundNetLog;
// A client socket that uses UDP as the transport layer.
class NET_EXPORT UDPServerSocket : public DatagramServerSocket {
public:
- UDPServerSocket(net::NetLog* net_log,
- const net::NetLog::Source& source);
+ UDPServerSocket(net::NetLog* net_log, const net::NetLog::Source& source);
virtual ~UDPServerSocket();
// Implement DatagramServerSocket:
@@ -42,8 +41,10 @@ class NET_EXPORT UDPServerSocket : public DatagramServerSocket {
virtual void AllowBroadcast() OVERRIDE;
virtual int JoinGroup(const IPAddressNumber& group_address) const OVERRIDE;
virtual int LeaveGroup(const IPAddressNumber& group_address) const OVERRIDE;
+ virtual int SetMulticastInterface(uint32 interface_index) OVERRIDE;
virtual int SetMulticastTimeToLive(int time_to_live) OVERRIDE;
virtual int SetMulticastLoopbackMode(bool loopback) OVERRIDE;
+ virtual int SetDiffServCodePoint(DiffServCodePoint dscp) OVERRIDE;
private:
UDPSocket socket_;
diff --git a/chromium/net/udp/udp_socket_libevent.cc b/chromium/net/udp/udp_socket_libevent.cc
index 5ed52f57090..ef2bae06a06 100644
--- a/chromium/net/udp/udp_socket_libevent.cc
+++ b/chromium/net/udp/udp_socket_libevent.cc
@@ -7,12 +7,15 @@
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
-#include <sys/socket.h>
+#include <net/if.h>
#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
#include "base/callback.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/posix/eintr_wrapper.h"
#include "base/rand_util.h"
@@ -24,15 +27,37 @@
#include "net/socket/socket_descriptor.h"
#include "net/udp/udp_net_log_parameters.h"
+
+namespace net {
+
namespace {
const int kBindRetries = 10;
const int kPortStart = 1024;
const int kPortEnd = 65535;
-} // namespace
+#if defined(OS_MACOSX)
-namespace net {
+// Returns IPv4 address in network order.
+int GetIPv4AddressFromIndex(int socket, uint32 index, uint32* address){
+ if (!index) {
+ *address = htonl(INADDR_ANY);
+ return OK;
+ }
+ ifreq ifr;
+ ifr.ifr_addr.sa_family = AF_INET;
+ if (!if_indextoname(index, ifr.ifr_name))
+ return ERR_FAILED;
+ int rv = ioctl(socket, SIOCGIFADDR, &ifr);
+ if (!rv)
+ return MapSystemError(rv);
+ *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr;
+ return OK;
+}
+
+#endif // OS_MACOSX
+
+} // namespace
UDPSocketLibevent::UDPSocketLibevent(
DatagramSocket::BindType bind_type,
@@ -42,6 +67,7 @@ UDPSocketLibevent::UDPSocketLibevent(
: socket_(kInvalidSocket),
addr_family_(0),
socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
+ multicast_interface_(0),
multicast_time_to_live_(1),
bind_type_(bind_type),
rand_int_cb_(rand_int_cb),
@@ -83,7 +109,7 @@ void UDPSocketLibevent::Close() {
ok = write_socket_watcher_.StopWatchingFileDescriptor();
DCHECK(ok);
- if (HANDLE_EINTR(close(socket_)) < 0)
+ if (IGNORE_EINTR(close(socket_)) < 0)
PLOG(ERROR) << "close";
socket_ = kInvalidSocket;
@@ -229,15 +255,23 @@ int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) {
DCHECK(CalledOnValidThread());
DCHECK(!is_connected());
DCHECK(!remote_address_.get());
- int rv = CreateSocket(address);
+ int addr_family = address.GetSockAddrFamily();
+ int rv = CreateSocket(addr_family);
if (rv < 0)
return rv;
- if (bind_type_ == DatagramSocket::RANDOM_BIND)
- rv = RandomBind(address);
+ if (bind_type_ == DatagramSocket::RANDOM_BIND) {
+ // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
+ // representing INADDR_ANY or in6addr_any.
+ size_t addr_size =
+ addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize;
+ IPAddressNumber addr_any(addr_size);
+ rv = RandomBind(addr_any);
+ }
// else connect() does the DatagramSocket::DEFAULT_BIND
if (rv < 0) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", rv);
Close();
return rv;
}
@@ -263,7 +297,7 @@ int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) {
int UDPSocketLibevent::Bind(const IPEndPoint& address) {
DCHECK(CalledOnValidThread());
DCHECK(!is_connected());
- int rv = CreateSocket(address);
+ int rv = CreateSocket(address.GetSockAddrFamily());
if (rv < 0)
return rv;
@@ -380,8 +414,8 @@ void UDPSocketLibevent::LogRead(int result,
read_bytes.Add(result);
}
-int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) {
- addr_family_ = address.GetSockAddrFamily();
+int UDPSocketLibevent::CreateSocket(int addr_family) {
+ addr_family_ = addr_family;
socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
if (socket_ == kInvalidSocket)
return MapSystemError(errno);
@@ -524,7 +558,7 @@ int UDPSocketLibevent::SetSocketOptions() {
rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof(ttl));
} else {
- // Signed interger. -1 to use route default.
+ // Signed integer. -1 to use route default.
int ttl = multicast_time_to_live_;
rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
&ttl, sizeof(ttl));
@@ -532,6 +566,40 @@ int UDPSocketLibevent::SetSocketOptions() {
if (rv < 0)
return MapSystemError(errno);
}
+ if (multicast_interface_ != 0) {
+ switch (addr_family_) {
+ case AF_INET: {
+#if !defined(OS_MACOSX)
+ ip_mreqn mreq;
+ mreq.imr_ifindex = multicast_interface_;
+ mreq.imr_address.s_addr = htonl(INADDR_ANY);
+#else
+ ip_mreq mreq;
+ int error = GetIPv4AddressFromIndex(socket_, multicast_interface_,
+ &mreq.imr_interface.s_addr);
+ if (error != OK)
+ return error;
+#endif
+ int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
+ reinterpret_cast<const char*>(&mreq), sizeof(mreq));
+ if (rv)
+ return MapSystemError(errno);
+ break;
+ }
+ case AF_INET6: {
+ uint32 interface_index = multicast_interface_;
+ int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ reinterpret_cast<const char*>(&interface_index),
+ sizeof(interface_index));
+ if (rv)
+ return MapSystemError(errno);
+ break;
+ }
+ default:
+ NOTREACHED() << "Invalid address family";
+ return ERR_ADDRESS_INVALID;
+ }
+ }
return OK;
}
@@ -540,21 +608,23 @@ int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
if (!address.ToSockAddr(storage.addr, &storage.addr_len))
return ERR_ADDRESS_INVALID;
int rv = bind(socket_, storage.addr, storage.addr_len);
- return rv < 0 ? MapSystemError(errno) : rv;
+ if (rv == 0)
+ return OK;
+ int last_error = errno;
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromPosix", last_error);
+ return MapSystemError(last_error);
}
-int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
+int UDPSocketLibevent::RandomBind(const IPAddressNumber& address) {
DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
- // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
- IPAddressNumber ip(address.address().size());
-
for (int i = 0; i < kBindRetries; ++i) {
- int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
+ int rv = DoBind(IPEndPoint(address,
+ rand_int_cb_.Run(kPortStart, kPortEnd)));
if (rv == OK || rv != ERR_ADDRESS_IN_USE)
return rv;
}
- return DoBind(IPEndPoint(ip, 0));
+ return DoBind(IPEndPoint(address, 0));
}
int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const {
@@ -566,8 +636,18 @@ int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const {
case kIPv4AddressSize: {
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
+
+#if !defined(OS_MACOSX)
+ ip_mreqn mreq;
+ mreq.imr_ifindex = multicast_interface_;
+ mreq.imr_address.s_addr = htonl(INADDR_ANY);
+#else
ip_mreq mreq;
- mreq.imr_interface.s_addr = INADDR_ANY;
+ int error = GetIPv4AddressFromIndex(socket_, multicast_interface_,
+ &mreq.imr_interface.s_addr);
+ if (error != OK)
+ return error;
+#endif
memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&mreq, sizeof(mreq));
@@ -579,7 +659,7 @@ int UDPSocketLibevent::JoinGroup(const IPAddressNumber& group_address) const {
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
- mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
+ mreq.ipv6mr_interface = multicast_interface_;
memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
&mreq, sizeof(mreq));
@@ -630,6 +710,14 @@ int UDPSocketLibevent::LeaveGroup(const IPAddressNumber& group_address) const {
}
}
+int UDPSocketLibevent::SetMulticastInterface(uint32 interface_index) {
+ DCHECK(CalledOnValidThread());
+ if (is_connected())
+ return ERR_SOCKET_IS_CONNECTED;
+ multicast_interface_ = interface_index;
+ return OK;
+}
+
int UDPSocketLibevent::SetMulticastTimeToLive(int time_to_live) {
DCHECK(CalledOnValidThread());
if (is_connected())
@@ -652,4 +740,24 @@ int UDPSocketLibevent::SetMulticastLoopbackMode(bool loopback) {
socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
return OK;
}
+
+int UDPSocketLibevent::SetDiffServCodePoint(DiffServCodePoint dscp) {
+ if (dscp == DSCP_NO_CHANGE) {
+ return OK;
+ }
+ int rv;
+ int dscp_and_ecn = dscp << 2;
+ if (addr_family_ == AF_INET) {
+ rv = setsockopt(socket_, IPPROTO_IP, IP_TOS,
+ &dscp_and_ecn, sizeof(dscp_and_ecn));
+ } else {
+ rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS,
+ &dscp_and_ecn, sizeof(dscp_and_ecn));
+ }
+ if (rv < 0)
+ return MapSystemError(errno);
+
+ return OK;
+}
+
} // namespace net
diff --git a/chromium/net/udp/udp_socket_libevent.h b/chromium/net/udp/udp_socket_libevent.h
index 6c8bf61e0dd..2d1cefd3aa9 100644
--- a/chromium/net/udp/udp_socket_libevent.h
+++ b/chromium/net/udp/udp_socket_libevent.h
@@ -129,6 +129,12 @@ class NET_EXPORT UDPSocketLibevent : public base::NonThreadSafe {
// Return a network error code.
int LeaveGroup(const IPAddressNumber& group_address) const;
+ // Set interface to use for multicast. If |interface_index| set to 0, default
+ // interface is used.
+ // Should be called before Bind().
+ // Returns a network error code.
+ int SetMulticastInterface(uint32 interface_index);
+
// Set the time-to-live option for UDP packets sent to the multicast
// group address. The default value of this option is 1.
// Cannot be negative or more than 255.
@@ -152,6 +158,11 @@ class NET_EXPORT UDPSocketLibevent : public base::NonThreadSafe {
// other applications on the same host. See MSDN: http://goo.gl/6vqbj
int SetMulticastLoopbackMode(bool loopback);
+ // Set the differentiated services flags on outgoing packets. May not
+ // do anything on some platforms.
+ // Return a network error code.
+ int SetDiffServCodePoint(DiffServCodePoint dscp);
+
private:
enum SocketOptions {
SOCKET_OPTION_REUSE_ADDRESS = 1 << 0,
@@ -205,7 +216,7 @@ class NET_EXPORT UDPSocketLibevent : public base::NonThreadSafe {
void LogWrite(int result, const char* bytes, const IPEndPoint* address) const;
// Returns the OS error code (or 0 on success).
- int CreateSocket(const IPEndPoint& address);
+ int CreateSocket(int addr_family);
// Same as SendTo(), except that address is passed by pointer
// instead of by reference. It is called from Write() with |address|
@@ -223,7 +234,8 @@ class NET_EXPORT UDPSocketLibevent : public base::NonThreadSafe {
// Bind().
int SetSocketOptions();
int DoBind(const IPEndPoint& address);
- int RandomBind(const IPEndPoint& address);
+ // Binds to a random port on |address|.
+ int RandomBind(const IPAddressNumber& address);
int socket_;
int addr_family_;
@@ -232,6 +244,9 @@ class NET_EXPORT UDPSocketLibevent : public base::NonThreadSafe {
// options that should be applied to |socket_| before Bind().
int socket_options_;
+ // Multicast interface.
+ uint32 multicast_interface_;
+
// Multicast socket options cached for SetSocketOption.
// Cannot be used after Bind().
int multicast_time_to_live_;
diff --git a/chromium/net/udp/udp_socket_unittest.cc b/chromium/net/udp/udp_socket_unittest.cc
index ffb56d98141..20e38ee4c11 100644
--- a/chromium/net/udp/udp_socket_unittest.cc
+++ b/chromium/net/udp/udp_socket_unittest.cc
@@ -574,9 +574,14 @@ TEST_F(UDPSocketTest, MulticastOptions) {
EXPECT_EQ(OK, socket.SetMulticastTimeToLive(0));
EXPECT_EQ(OK, socket.SetMulticastTimeToLive(3));
EXPECT_NE(OK, socket.SetMulticastTimeToLive(-1));
+ EXPECT_EQ(OK, socket.SetMulticastInterface(0));
EXPECT_EQ(OK, socket.Bind(bind_address));
+ EXPECT_NE(OK, socket.SetMulticastLoopbackMode(false));
+ EXPECT_NE(OK, socket.SetMulticastTimeToLive(0));
+ EXPECT_NE(OK, socket.SetMulticastInterface(0));
+
socket.Close();
}
diff --git a/chromium/net/udp/udp_socket_win.cc b/chromium/net/udp/udp_socket_win.cc
index f9ce6799c4b..17fec44d7f0 100644
--- a/chromium/net/udp/udp_socket_win.cc
+++ b/chromium/net/udp/udp_socket_win.cc
@@ -10,8 +10,8 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
#include "base/metrics/stats_counters.h"
-#include "base/posix/eintr_wrapper.h"
#include "base/rand_util.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
@@ -166,6 +166,7 @@ UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type,
: socket_(INVALID_SOCKET),
addr_family_(0),
socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
+ multicast_interface_(0),
multicast_time_to_live_(1),
bind_type_(bind_type),
rand_int_cb_(rand_int_cb),
@@ -322,15 +323,23 @@ int UDPSocketWin::Connect(const IPEndPoint& address) {
int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
DCHECK(!is_connected());
DCHECK(!remote_address_.get());
- int rv = CreateSocket(address);
+ int addr_family = address.GetSockAddrFamily();
+ int rv = CreateSocket(addr_family);
if (rv < 0)
return rv;
- if (bind_type_ == DatagramSocket::RANDOM_BIND)
- rv = RandomBind(address);
+ if (bind_type_ == DatagramSocket::RANDOM_BIND) {
+ // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s,
+ // representing INADDR_ANY or in6addr_any.
+ size_t addr_size =
+ addr_family == AF_INET ? kIPv4AddressSize : kIPv6AddressSize;
+ IPAddressNumber addr_any(addr_size);
+ rv = RandomBind(addr_any);
+ }
// else connect() does the DatagramSocket::DEFAULT_BIND
if (rv < 0) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", rv);
Close();
return rv;
}
@@ -353,7 +362,7 @@ int UDPSocketWin::InternalConnect(const IPEndPoint& address) {
int UDPSocketWin::Bind(const IPEndPoint& address) {
DCHECK(!is_connected());
- int rv = CreateSocket(address);
+ int rv = CreateSocket(address.GetSockAddrFamily());
if (rv < 0)
return rv;
rv = SetSocketOptions();
@@ -370,8 +379,8 @@ int UDPSocketWin::Bind(const IPEndPoint& address) {
return rv;
}
-int UDPSocketWin::CreateSocket(const IPEndPoint& address) {
- addr_family_ = address.GetSockAddrFamily();
+int UDPSocketWin::CreateSocket(int addr_family) {
+ addr_family_ = addr_family;
socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, IPPROTO_UDP);
if (socket_ == INVALID_SOCKET)
return MapSystemError(WSAGetLastError());
@@ -622,6 +631,32 @@ int UDPSocketWin::SetSocketOptions() {
if (rv < 0)
return MapSystemError(WSAGetLastError());
}
+ if (multicast_interface_ != 0) {
+ switch (addr_family_) {
+ case AF_INET: {
+ in_addr address;
+ address.s_addr = htonl(multicast_interface_);
+ int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
+ reinterpret_cast<const char*>(&address),
+ sizeof(address));
+ if (rv)
+ return MapSystemError(WSAGetLastError());
+ break;
+ }
+ case AF_INET6: {
+ uint32 interface_index = multicast_interface_;
+ int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ reinterpret_cast<const char*>(&interface_index),
+ sizeof(interface_index));
+ if (rv)
+ return MapSystemError(WSAGetLastError());
+ break;
+ }
+ default:
+ NOTREACHED() << "Invalid address family";
+ return ERR_ADDRESS_INVALID;
+ }
+ }
return OK;
}
@@ -630,21 +665,26 @@ int UDPSocketWin::DoBind(const IPEndPoint& address) {
if (!address.ToSockAddr(storage.addr, &storage.addr_len))
return ERR_ADDRESS_INVALID;
int rv = bind(socket_, storage.addr, storage.addr_len);
- return rv < 0 ? MapSystemError(WSAGetLastError()) : rv;
+ if (rv == 0)
+ return OK;
+ int last_error = WSAGetLastError();
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromWinOS", last_error);
+ // Map some codes that are special to bind() separately.
+ if (last_error == WSAEACCES || last_error == WSAEINVAL)
+ return ERR_ADDRESS_IN_USE;
+ return MapSystemError(last_error);
}
-int UDPSocketWin::RandomBind(const IPEndPoint& address) {
+int UDPSocketWin::RandomBind(const IPAddressNumber& address) {
DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
- // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
- IPAddressNumber ip(address.address().size());
-
for (int i = 0; i < kBindRetries; ++i) {
- int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
+ int rv = DoBind(IPEndPoint(address,
+ rand_int_cb_.Run(kPortStart, kPortEnd)));
if (rv == OK || rv != ERR_ADDRESS_IN_USE)
return rv;
}
- return DoBind(IPEndPoint(ip, 0));
+ return DoBind(IPEndPoint(address, 0));
}
bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const {
@@ -663,7 +703,7 @@ int UDPSocketWin::JoinGroup(
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
ip_mreq mreq;
- mreq.imr_interface.s_addr = INADDR_ANY;
+ mreq.imr_interface.s_addr = htonl(multicast_interface_);
memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
reinterpret_cast<const char*>(&mreq),
@@ -676,7 +716,7 @@ int UDPSocketWin::JoinGroup(
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
- mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
+ mreq.ipv6mr_interface = multicast_interface_;
memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
reinterpret_cast<const char*>(&mreq),
@@ -702,11 +742,10 @@ int UDPSocketWin::LeaveGroup(
if (addr_family_ != AF_INET)
return ERR_ADDRESS_INVALID;
ip_mreq mreq;
- mreq.imr_interface.s_addr = INADDR_ANY;
+ mreq.imr_interface.s_addr = htonl(multicast_interface_);
memcpy(&mreq.imr_multiaddr, &group_address[0], kIPv4AddressSize);
int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
- reinterpret_cast<const char*>(&mreq),
- sizeof(mreq));
+ reinterpret_cast<const char*>(&mreq), sizeof(mreq));
if (rv)
return MapSystemError(WSAGetLastError());
return OK;
@@ -715,11 +754,10 @@ int UDPSocketWin::LeaveGroup(
if (addr_family_ != AF_INET6)
return ERR_ADDRESS_INVALID;
ipv6_mreq mreq;
- mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
+ mreq.ipv6mr_interface = multicast_interface_;
memcpy(&mreq.ipv6mr_multiaddr, &group_address[0], kIPv6AddressSize);
int rv = setsockopt(socket_, IPPROTO_IPV6, IP_DROP_MEMBERSHIP,
- reinterpret_cast<const char*>(&mreq),
- sizeof(mreq));
+ reinterpret_cast<const char*>(&mreq), sizeof(mreq));
if (rv)
return MapSystemError(WSAGetLastError());
return OK;
@@ -730,6 +768,14 @@ int UDPSocketWin::LeaveGroup(
}
}
+int UDPSocketWin::SetMulticastInterface(uint32 interface_index) {
+ DCHECK(CalledOnValidThread());
+ if (is_connected())
+ return ERR_SOCKET_IS_CONNECTED;
+ multicast_interface_ = interface_index;
+ return OK;
+}
+
int UDPSocketWin::SetMulticastTimeToLive(int time_to_live) {
DCHECK(CalledOnValidThread());
if (is_connected())
@@ -753,4 +799,10 @@ int UDPSocketWin::SetMulticastLoopbackMode(bool loopback) {
return OK;
}
+// TODO(hubbe): Implement differentiated services for windows.
+// Note: setsockopt(IP_TOS) does not work on windows XP and later.
+int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) {
+ return ERR_NOT_IMPLEMENTED;
+}
+
} // namespace net
diff --git a/chromium/net/udp/udp_socket_win.h b/chromium/net/udp/udp_socket_win.h
index 807b403034e..2f24877c1e0 100644
--- a/chromium/net/udp/udp_socket_win.h
+++ b/chromium/net/udp/udp_socket_win.h
@@ -130,6 +130,12 @@ class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
// Return a network error code.
int LeaveGroup(const IPAddressNumber& group_address) const;
+ // Set interface to use for multicast. If |interface_index| set to 0, default
+ // interface is used.
+ // Should be called before Bind().
+ // Returns a network error code.
+ int SetMulticastInterface(uint32 interface_index);
+
// Set the time-to-live option for UDP packets sent to the multicast
// group address. The default value of this option is 1.
// Cannot be negative or more than 255.
@@ -151,6 +157,10 @@ class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
// other applications on the same host. See MSDN: http://goo.gl/6vqbj
int SetMulticastLoopbackMode(bool loopback);
+ // Set the differentiated services flags on outgoing packets. May not
+ // do anything on some platforms.
+ int SetDiffServCodePoint(DiffServCodePoint dscp);
+
private:
enum SocketOptions {
SOCKET_OPTION_REUSE_ADDRESS = 1 << 0,
@@ -172,7 +182,7 @@ class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
void LogWrite(int result, const char* bytes, const IPEndPoint* address) const;
// Returns the OS error code (or 0 on success).
- int CreateSocket(const IPEndPoint& address);
+ int CreateSocket(int addr_family);
// Same as SendTo(), except that address is passed by pointer
// instead of by reference. It is called from Write() with |address|
@@ -190,7 +200,8 @@ class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
// Bind().
int SetSocketOptions();
int DoBind(const IPEndPoint& address);
- int RandomBind(const IPEndPoint& address);
+ // Binds to a random port on |address|.
+ int RandomBind(const IPAddressNumber& address);
// Attempts to convert the data in |recv_addr_storage_| and |recv_addr_len_|
// to an IPEndPoint and writes it to |address|. Returns true on success.
@@ -203,6 +214,9 @@ class NET_EXPORT UDPSocketWin : NON_EXPORTED_BASE(public base::NonThreadSafe) {
// options that should be applied to |socket_| before Bind().
int socket_options_;
+ // Multicast interface.
+ uint32 multicast_interface_;
+
// Multicast socket options cached for SetSocketOption.
// Cannot be used after Bind().
int multicast_time_to_live_;
diff --git a/chromium/net/url_request/test_url_fetcher_factory.cc b/chromium/net/url_request/test_url_fetcher_factory.cc
index 30380354b2d..5a72d71dfb2 100644
--- a/chromium/net/url_request/test_url_fetcher_factory.cc
+++ b/chromium/net/url_request/test_url_fetcher_factory.cc
@@ -11,9 +11,11 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "net/base/host_port_pair.h"
+#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_fetcher_impl.h"
+#include "net/url_request/url_fetcher_response_writer.h"
#include "net/url_request/url_request_status.h"
namespace net {
@@ -140,11 +142,15 @@ void TestURLFetcher::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
void TestURLFetcher::SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner) {
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
}
void TestURLFetcher::SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner) {
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
+}
+
+void TestURLFetcher::SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer) {
}
HttpResponseHeaders* TestURLFetcher::GetResponseHeaders() const {
@@ -186,11 +192,6 @@ const ResponseCookies& TestURLFetcher::GetCookies() const {
return fake_cookies_;
}
-bool TestURLFetcher::FileErrorOccurred(int* out_error_code) const {
- NOTIMPLEMENTED();
- return false;
-}
-
void TestURLFetcher::ReceivedContentWasMalformed() {
}
@@ -283,13 +284,27 @@ void TestURLFetcherFactory::SetDelegateForTests(
FakeURLFetcher::FakeURLFetcher(const GURL& url,
URLFetcherDelegate* d,
const std::string& response_data,
- bool success)
+ HttpStatusCode response_code,
+ URLRequestStatus::Status status)
: TestURLFetcher(0, url, d),
weak_factory_(this) {
- set_status(URLRequestStatus(
- success ? URLRequestStatus::SUCCESS : URLRequestStatus::FAILED,
- 0));
- set_response_code(success ? 200 : 500);
+ Error error = OK;
+ switch(status) {
+ case URLRequestStatus::SUCCESS:
+ // |error| is initialized to OK.
+ break;
+ case URLRequestStatus::IO_PENDING:
+ error = ERR_IO_PENDING;
+ break;
+ case URLRequestStatus::CANCELED:
+ error = ERR_ABORTED;
+ break;
+ case URLRequestStatus::FAILED:
+ error = ERR_FAILED;
+ break;
+ }
+ set_status(URLRequestStatus(status, error));
+ set_response_code(response_code);
SetResponseString(response_data);
}
@@ -327,10 +342,11 @@ FakeURLFetcherFactory::FakeURLFetcherFactory(
scoped_ptr<FakeURLFetcher> FakeURLFetcherFactory::DefaultFakeURLFetcherCreator(
const GURL& url,
URLFetcherDelegate* delegate,
- const std::string& response,
- bool success) {
- return scoped_ptr<FakeURLFetcher>(new FakeURLFetcher(url, delegate,
- response, success));
+ const std::string& response_data,
+ HttpStatusCode response_code,
+ URLRequestStatus::Status status) {
+ return scoped_ptr<FakeURLFetcher>(
+ new FakeURLFetcher(url, delegate, response_data, response_code, status));
}
FakeURLFetcherFactory::~FakeURLFetcherFactory() {}
@@ -352,23 +368,23 @@ URLFetcher* FakeURLFetcherFactory::CreateURLFetcher(
}
scoped_ptr<FakeURLFetcher> fake_fetcher =
- creator_.Run(url, d, it->second.first, it->second.second);
+ creator_.Run(url, d, it->second.response_data,
+ it->second.response_code, it->second.status);
// TODO: Make URLFetcherFactory::CreateURLFetcher return a scoped_ptr
return fake_fetcher.release();
}
-void FakeURLFetcherFactory::SetFakeResponseForURL(
+void FakeURLFetcherFactory::SetFakeResponse(
const GURL& url,
const std::string& response_data,
- bool success) {
+ HttpStatusCode response_code,
+ URLRequestStatus::Status status) {
// Overwrite existing URL if it already exists.
- fake_responses_[url] = std::make_pair(response_data, success);
-}
-
-void FakeURLFetcherFactory::SetFakeResponse(const std::string& url,
- const std::string& response_data,
- bool success) {
- SetFakeResponseForURL(GURL(url), response_data, success);
+ FakeURLResponse response;
+ response.response_data = response_data;
+ response.response_code = response_code;
+ response.status = status;
+ fake_responses_[url] = response;
}
void FakeURLFetcherFactory::ClearFakeResponses() {
diff --git a/chromium/net/url_request/test_url_fetcher_factory.h b/chromium/net/url_request/test_url_fetcher_factory.h
index 35b4607f995..75ffcade6ea 100644
--- a/chromium/net/url_request/test_url_fetcher_factory.h
+++ b/chromium/net/url_request/test_url_fetcher_factory.h
@@ -18,6 +18,7 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
#include "net/url_request/url_fetcher_factory.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
@@ -123,9 +124,11 @@ class TestURLFetcher : public URLFetcher {
virtual void SetAutomaticallyRetryOnNetworkChanges(int max_retries) OVERRIDE;
virtual void SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) OVERRIDE;
virtual void SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) OVERRIDE;
+ virtual void SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer) OVERRIDE;
virtual HttpResponseHeaders* GetResponseHeaders() const OVERRIDE;
virtual HostPortPair GetSocketAddress() const OVERRIDE;
virtual bool WasFetchedViaProxy() const OVERRIDE;
@@ -139,7 +142,6 @@ class TestURLFetcher : public URLFetcher {
virtual const URLRequestStatus& GetStatus() const OVERRIDE;
virtual int GetResponseCode() const OVERRIDE;
virtual const ResponseCookies& GetCookies() const OVERRIDE;
- virtual bool FileErrorOccurred(int* out_error_code) const OVERRIDE;
virtual void ReceivedContentWasMalformed() OVERRIDE;
// Override response access functions to return fake data.
virtual bool GetResponseAsString(
@@ -275,7 +277,7 @@ class TestURLFetcherFactory : public URLFetcherFactory,
// Example usage:
// FakeURLFetcher fake_fetcher("http://a.com", some_delegate,
// "<html><body>hello world</body></html>",
-// true);
+// HTTP_OK);
//
// // Will schedule a call to some_delegate->OnURLFetchComplete(&fake_fetcher).
// fake_fetcher.Start();
@@ -284,7 +286,9 @@ class FakeURLFetcher : public TestURLFetcher {
// Normal URL fetcher constructor but also takes in a pre-baked response.
FakeURLFetcher(const GURL& url,
URLFetcherDelegate* d,
- const std::string& response_data, bool success);
+ const std::string& response_data,
+ HttpStatusCode response_code,
+ URLRequestStatus::Status status);
// Start the request. This will call the given delegate asynchronously
// with the pre-baked response as parameter.
@@ -311,7 +315,7 @@ class FakeURLFetcher : public TestURLFetcher {
//
// This class is not thread-safe. You should not call SetFakeResponse or
// ClearFakeResponse at the same time you call CreateURLFetcher. However, it is
-// OK to start URLFetcher objects while setting or clearning fake responses
+// OK to start URLFetcher objects while setting or clearing fake responses
// since already created URLFetcher objects will not be affected by any changes
// made to the fake responses (once a URLFetcher object is created you cannot
// change its fake response).
@@ -319,32 +323,55 @@ class FakeURLFetcher : public TestURLFetcher {
// Example usage:
// FakeURLFetcherFactory factory;
//
-// // You know that class SomeService will request url http://a.com/ and you
-// // want to test the service class by returning an error.
-// factory.SetFakeResponse("http://a.com/", "", false);
-// // But if the service requests http://b.com/asdf you want to respond with
-// // a simple html page and an HTTP/200 code.
-// factory.SetFakeResponse("http://b.com/asdf",
+// // You know that class SomeService will request http://a.com/success and you
+// // want to respond with a simple html page and an HTTP/200 code.
+// factory.SetFakeResponse("http://a.com/success",
// "<html><body>hello world</body></html>",
-// true);
+// HTTP_OK,
+// URLRequestStatus::SUCCESS);
+// // You know that class SomeService will request url http://a.com/servererror
+// // and you want to test the service class by returning a server error.
+// factory.SetFakeResponse("http://a.com/servererror",
+// "",
+// HTTP_INTERNAL_SERVER_ERROR,
+// URLRequestStatus::SUCCESS);
+// // You know that class SomeService will request url http://a.com/autherror
+// // and you want to test the service class by returning a specific error
+// // code, say, a HTTP/401 error.
+// factory.SetFakeResponse("http://a.com/autherror",
+// "some_response",
+// HTTP_UNAUTHORIZED,
+// URLRequestStatus::SUCCESS);
+//
+// // You know that class SomeService will request url http://a.com/failure
+// // and you want to test the service class by returning a failure in the
+// // network layer.
+// factory.SetFakeResponse("http://a.com/failure",
+// "",
+// HTTP_INTERNAL_SERVER_ERROR,
+// URLRequestStatus::FAILURE);
//
// SomeService service;
-// service.Run(); // Will eventually request these two URLs.
+// service.Run(); // Will eventually request these three URLs.
class FakeURLFetcherFactory : public URLFetcherFactory,
public ScopedURLFetcherFactory {
public:
- // Parameters to FakeURLFetcherCreator: url, delegate, response_data, success
+ // Parameters to FakeURLFetcherCreator: url, delegate, response_data,
+ // response_code
// |url| URL for instantiated FakeURLFetcher
// |delegate| Delegate for FakeURLFetcher
// |response_data| response data for FakeURLFetcher
- // |success| bool indicating response code. true = 200 and false = 500.
- // These argument should by default be used in instantiating FakeURLFetcher
- // as follows: new FakeURLFetcher(url, delegate, response_data, success)
+ // |response_code| response code for FakeURLFetcher
+ // |status| URL fetch status for FakeURLFetcher
+ // These arguments should by default be used in instantiating FakeURLFetcher
+ // like so:
+ // new FakeURLFetcher(url, delegate, response_data, response_code, status)
typedef base::Callback<scoped_ptr<FakeURLFetcher>(
const GURL&,
URLFetcherDelegate*,
const std::string&,
- bool)> FakeURLFetcherCreator;
+ HttpStatusCode,
+ URLRequestStatus::Status)> FakeURLFetcherCreator;
// |default_factory|, which can be NULL, is a URLFetcherFactory that
// will be used to construct a URLFetcher in case the URL being created
@@ -375,33 +402,40 @@ class FakeURLFetcherFactory : public URLFetcherFactory,
URLFetcher::RequestType request_type,
URLFetcherDelegate* d) OVERRIDE;
- // Sets the fake response for a given URL. If success is true we will serve
- // an HTTP/200 and an HTTP/500 otherwise. The |response_data| may be empty.
- void SetFakeResponseForURL(const GURL& url,
- const std::string& response_data,
- bool success);
-
- // Convenience helper that calls SetFakeResponseForURL with GURL(url).
- // TODO(mnissler): Convert callers to SetFakeResponseForURL.
- void SetFakeResponse(const std::string& url,
+ // Sets the fake response for a given URL. The |response_data| may be empty.
+ // The |response_code| may be any HttpStatusCode. For instance, HTTP_OK will
+ // return an HTTP/200 and HTTP_INTERNAL_SERVER_ERROR will return an HTTP/500.
+ // The |status| argument may be any URLRequestStatus::Status value. Typically,
+ // requests that return a valid HttpStatusCode have the SUCCESS status, while
+ // requests that indicate a failure to connect to the server have the FAILED
+ // status.
+ void SetFakeResponse(const GURL& url,
const std::string& response_data,
- bool success);
+ HttpStatusCode response_code,
+ URLRequestStatus::Status status);
// Clear all the fake responses that were previously set via
// SetFakeResponse().
void ClearFakeResponses();
private:
+ struct FakeURLResponse {
+ std::string response_data;
+ HttpStatusCode response_code;
+ URLRequestStatus::Status status;
+ };
+ typedef std::map<GURL, FakeURLResponse> FakeResponseMap;
+
const FakeURLFetcherCreator creator_;
- typedef std::map<GURL, std::pair<std::string, bool> > FakeResponseMap;
FakeResponseMap fake_responses_;
URLFetcherFactory* const default_factory_;
static scoped_ptr<FakeURLFetcher> DefaultFakeURLFetcherCreator(
const GURL& url,
URLFetcherDelegate* delegate,
- const std::string& response,
- bool success);
+ const std::string& response_data,
+ HttpStatusCode response_code,
+ URLRequestStatus::Status status);
DISALLOW_COPY_AND_ASSIGN(FakeURLFetcherFactory);
};
diff --git a/chromium/net/url_request/url_fetcher.h b/chromium/net/url_request/url_fetcher.h
index c8a587dbc88..4cc6f5fa62e 100644
--- a/chromium/net/url_request/url_fetcher.h
+++ b/chromium/net/url_request/url_fetcher.h
@@ -10,8 +10,8 @@
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/supports_user_data.h"
-#include "base/task_runner.h"
#include "net/base/net_export.h"
class GURL;
@@ -19,6 +19,8 @@ class GURL;
namespace base {
class FilePath;
class MessageLoopProxy;
+class SequencedTaskRunner;
+class TaskRunner;
class TimeDelta;
}
@@ -27,6 +29,7 @@ class HostPortPair;
class HttpRequestHeaders;
class HttpResponseHeaders;
class URLFetcherDelegate;
+class URLFetcherResponseWriter;
class URLRequestContextGetter;
class URLRequestStatus;
typedef std::vector<std::string> ResponseCookies;
@@ -229,7 +232,7 @@ class NET_EXPORT URLFetcher {
// take ownership by calling GetResponseAsFilePath().
virtual void SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner) = 0;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) = 0;
// By default, the response is saved in a string. Call this method to save the
// response to a temporary file instead. Must be called before Start().
@@ -237,7 +240,12 @@ class NET_EXPORT URLFetcher {
// The created file is removed when the URLFetcher is deleted unless you
// take ownership by calling GetResponseAsFilePath().
virtual void SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner) = 0;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) = 0;
+
+ // By default, the response is saved in a string. Call this method to use the
+ // specified writer to save the response. Must be called before Start().
+ virtual void SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer) = 0;
// Retrieve the response headers from the request. Must only be called after
// the OnURLFetchComplete callback has run.
@@ -273,11 +281,6 @@ class NET_EXPORT URLFetcher {
// Cookies recieved.
virtual const ResponseCookies& GetCookies() const = 0;
- // Return true if any file system operation failed. If so, set |error_code|
- // to the net error code. File system errors are only possible if user called
- // SaveResponseToTemporaryFile().
- virtual bool FileErrorOccurred(int* out_error_code) const = 0;
-
// Reports that the received content was malformed.
virtual void ReceivedContentWasMalformed() = 0;
diff --git a/chromium/net/url_request/url_fetcher_core.cc b/chromium/net/url_request/url_fetcher_core.cc
index f8d3773b7d0..e2fcc450219 100644
--- a/chromium/net/url_request/url_fetcher_core.cc
+++ b/chromium/net/url_request/url_fetcher_core.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
+#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
@@ -14,6 +15,7 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_file_element_reader.h"
@@ -31,6 +33,8 @@ const int kUploadProgressTimerInterval = 100;
bool g_interception_enabled = false;
bool g_ignore_certificate_requests = false;
+void EmptyCompletionCallback(int result) {}
+
} // namespace
namespace net {
@@ -52,7 +56,7 @@ void URLFetcherCore::Registry::RemoveURLFetcherCore(URLFetcherCore* core) {
void URLFetcherCore::Registry::CancelAll() {
while (!fetchers_.empty())
- (*fetchers_.begin())->CancelURLRequest();
+ (*fetchers_.begin())->CancelURLRequest(ERR_ABORTED);
}
// URLFetcherCore -------------------------------------------------------------
@@ -80,8 +84,6 @@ URLFetcherCore::URLFetcherCore(URLFetcher* fetcher,
upload_range_length_(0),
is_chunked_upload_(false),
was_cancelled_(false),
- file_writer_(NULL),
- response_destination_(STRING),
stop_on_redirect_(false),
stopped_on_redirect_(false),
automatically_retry_on_5xx_(true),
@@ -119,10 +121,11 @@ void URLFetcherCore::Stop() {
if (!network_task_runner_.get())
return;
if (network_task_runner_->RunsTasksOnCurrentThread()) {
- CancelURLRequest();
+ CancelURLRequest(ERR_ABORTED);
} else {
network_task_runner_->PostTask(
- FROM_HERE, base::Bind(&URLFetcherCore::CancelURLRequest, this));
+ FROM_HERE,
+ base::Bind(&URLFetcherCore::CancelURLRequest, this, ERR_ABORTED));
}
}
@@ -264,18 +267,23 @@ void URLFetcherCore::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
void URLFetcherCore::SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner) {
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
- file_task_runner_ = file_task_runner;
- response_destination_ = URLFetcherCore::PERMANENT_FILE;
- response_destination_file_path_ = file_path;
+ SaveResponseWithWriter(scoped_ptr<URLFetcherResponseWriter>(
+ new URLFetcherFileWriter(file_task_runner, file_path)));
}
void URLFetcherCore::SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner) {
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
+ DCHECK(delegate_task_runner_->BelongsToCurrentThread());
+ SaveResponseWithWriter(scoped_ptr<URLFetcherResponseWriter>(
+ new URLFetcherFileWriter(file_task_runner, base::FilePath())));
+}
+
+void URLFetcherCore::SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
- file_task_runner_ = file_task_runner;
- response_destination_ = URLFetcherCore::TEMP_FILE;
+ response_writer_ = response_writer.Pass();
}
HttpResponseHeaders* URLFetcherCore::GetResponseHeaders() const {
@@ -313,19 +321,6 @@ const ResponseCookies& URLFetcherCore::GetCookies() const {
return cookies_;
}
-bool URLFetcherCore::FileErrorOccurred(int* out_error_code) const {
- // Can't have a file error if no file is being created or written to.
- if (!file_writer_)
- return false;
-
- int error_code = file_writer_->error_code();
- if (error_code == OK)
- return false;
-
- *out_error_code = error_code;
- return true;
-}
-
void URLFetcherCore::ReceivedContentWasMalformed() {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
if (network_task_runner_.get()) {
@@ -336,26 +331,27 @@ void URLFetcherCore::ReceivedContentWasMalformed() {
bool URLFetcherCore::GetResponseAsString(
std::string* out_response_string) const {
- if (response_destination_ != URLFetcherCore::STRING)
+ URLFetcherStringWriter* string_writer =
+ response_writer_ ? response_writer_->AsStringWriter() : NULL;
+ if (!string_writer)
return false;
- *out_response_string = data_;
+ *out_response_string = string_writer->data();
UMA_HISTOGRAM_MEMORY_KB("UrlFetcher.StringResponseSize",
- (data_.length() / 1024));
-
+ (string_writer->data().length() / 1024));
return true;
}
bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
base::FilePath* out_response_path) {
DCHECK(delegate_task_runner_->BelongsToCurrentThread());
- const bool destination_is_file =
- response_destination_ == URLFetcherCore::TEMP_FILE ||
- response_destination_ == URLFetcherCore::PERMANENT_FILE;
- if (!destination_is_file || !file_writer_)
+
+ URLFetcherFileWriter* file_writer =
+ response_writer_ ? response_writer_->AsFileWriter() : NULL;
+ if (!file_writer)
return false;
- *out_response_path = file_writer_->file_path();
+ *out_response_path = file_writer->file_path();
if (take_ownership) {
// Intentionally calling a file_writer_ method directly without posting
@@ -367,7 +363,7 @@ bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
//
// This direct call should be thread-safe, since DisownFile itself does no
// file operation. It just flips the state to be referred in destruction.
- file_writer_->DisownFile();
+ file_writer->DisownFile();
}
return true;
}
@@ -427,22 +423,18 @@ void URLFetcherCore::OnReadCompleted(URLRequest* request,
url_throttler_entry_ = throttler_manager->RegisterRequestUrl(url_);
}
- bool waiting_on_write = false;
do {
if (!request_->status().is_success() || bytes_read <= 0)
break;
current_response_bytes_ += bytes_read;
InformDelegateDownloadProgress();
- InformDelegateDownloadDataIfNecessary(bytes_read);
const int result =
WriteBuffer(new DrainableIOBuffer(buffer_.get(), bytes_read));
if (result < 0) {
// Write failed or waiting for write completion.
- if (result == ERR_IO_PENDING)
- waiting_on_write = true;
- break;
+ return;
}
} while (request_->Read(buffer_.get(), kBufferSize, &bytes_read));
@@ -452,8 +444,7 @@ void URLFetcherCore::OnReadCompleted(URLRequest* request,
request_->GetResponseCookies(&cookies_);
// See comments re: HEAD requests in ReadResponse().
- if ((!status.is_io_pending() && !waiting_on_write) ||
- (request_type_ == URLFetcher::HEAD)) {
+ if (!status.is_io_pending() || request_type_ == URLFetcher::HEAD) {
status_ = status;
ReleaseRequest();
@@ -490,31 +481,9 @@ URLFetcherCore::~URLFetcherCore() {
void URLFetcherCore::StartOnIOThread() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
- switch (response_destination_) {
- case STRING:
- response_writer_.reset(new URLFetcherStringWriter(&data_));
- break;
-
- case PERMANENT_FILE:
- case TEMP_FILE:
- DCHECK(file_task_runner_.get())
- << "Need to set the file task runner.";
+ if (!response_writer_)
+ response_writer_.reset(new URLFetcherStringWriter);
- file_writer_ = new URLFetcherFileWriter(file_task_runner_);
-
- // If the file is successfully created,
- // URLFetcherCore::StartURLRequestWhenAppropriate() will be called.
- if (response_destination_ == PERMANENT_FILE) {
- file_writer_->set_destination_file_path(
- response_destination_file_path_);
- }
- response_writer_.reset(file_writer_);
- break;
-
- default:
- NOTREACHED();
- }
- DCHECK(response_writer_);
const int result = response_writer_->Initialize(
base::Bind(&URLFetcherCore::DidInitializeWriter, this));
if (result != ERR_IO_PENDING)
@@ -535,8 +504,8 @@ void URLFetcherCore::StartURLRequest() {
g_registry.Get().AddURLFetcherCore(this);
current_response_bytes_ = 0;
- request_.reset(request_context_getter_->GetURLRequestContext()->CreateRequest(
- original_url_, this));
+ request_ = request_context_getter_->GetURLRequestContext()->CreateRequest(
+ original_url_, DEFAULT_PRIORITY, this);
request_->set_stack_trace(stack_trace_);
int flags = request_->load_flags() | load_flags_;
if (!g_interception_enabled)
@@ -544,7 +513,7 @@ void URLFetcherCore::StartURLRequest() {
if (is_chunked_upload_)
request_->EnableChunkedUpload();
- request_->set_load_flags(flags);
+ request_->SetLoadFlags(flags);
request_->SetReferrer(referrer_);
request_->set_first_party_for_cookies(first_party_for_cookies_.is_empty() ?
original_url_ : first_party_for_cookies_);
@@ -613,18 +582,12 @@ void URLFetcherCore::StartURLRequest() {
if (!extra_request_headers_.IsEmpty())
request_->SetExtraRequestHeaders(extra_request_headers_);
- // There might be data left over from a previous request attempt.
- data_.clear();
-
- // If we are writing the response to a file, the only caller
- // of this function should have created it and not written yet.
- DCHECK(!file_writer_ || file_writer_->total_bytes_written() == 0);
-
request_->Start();
}
void URLFetcherCore::DidInitializeWriter(int result) {
if (result != OK) {
+ CancelURLRequest(result);
delegate_task_runner_->PostTask(
FROM_HERE,
base::Bind(&URLFetcherCore::InformDelegateFetchIsComplete, this));
@@ -664,13 +627,23 @@ void URLFetcherCore::StartURLRequestWhenAppropriate() {
}
}
-void URLFetcherCore::CancelURLRequest() {
+void URLFetcherCore::CancelURLRequest(int error) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
if (request_.get()) {
- request_->Cancel();
+ request_->CancelWithError(error);
ReleaseRequest();
}
+
+ // Set the error manually.
+ // Normally, calling URLRequest::CancelWithError() results in calling
+ // OnReadCompleted() with bytes_read = -1 via an asynchronous task posted by
+ // URLRequestJob::NotifyDone(). But, because the request was released
+ // immediately after being canceled, the request could not call
+ // OnReadCompleted() which overwrites |status_| with the error status.
+ status_.set_status(URLRequestStatus::CANCELED);
+ status_.set_error(error);
+
// Release the reference to the request context. There could be multiple
// references to URLFetcher::Core at this point so it may take a while to
// delete the object, but we cannot delay the destruction of the request
@@ -680,8 +653,6 @@ void URLFetcherCore::CancelURLRequest() {
url_request_data_key_ = NULL;
url_request_create_data_callback_.Reset();
was_cancelled_ = true;
- response_writer_.reset();
- file_writer_ = NULL;
}
void URLFetcherCore::OnCompletedURLRequest(
@@ -719,6 +690,7 @@ void URLFetcherCore::NotifyMalformedContent() {
void URLFetcherCore::DidFinishWriting(int result) {
if (result != OK) {
+ CancelURLRequest(result);
delegate_task_runner_->PostTask(
FROM_HERE,
base::Bind(&URLFetcherCore::InformDelegateFetchIsComplete, this));
@@ -830,8 +802,11 @@ int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) {
data.get(),
data->BytesRemaining(),
base::Bind(&URLFetcherCore::DidWriteBuffer, this, data));
- if (result < 0)
+ if (result < 0) {
+ if (result != ERR_IO_PENDING)
+ DidWriteBuffer(data, result);
return result;
+ }
data->DidConsume(result);
}
return OK;
@@ -839,22 +814,25 @@ int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) {
void URLFetcherCore::DidWriteBuffer(scoped_refptr<DrainableIOBuffer> data,
int result) {
- if (result >= 0) { // Continue writing.
- data->DidConsume(result);
- result = WriteBuffer(data);
- if (result == ERR_IO_PENDING)
- return;
- }
-
if (result < 0) { // Handle errors.
+ CancelURLRequest(result);
+ response_writer_->Finish(base::Bind(&EmptyCompletionCallback));
delegate_task_runner_->PostTask(
FROM_HERE,
base::Bind(&URLFetcherCore::InformDelegateFetchIsComplete, this));
return;
}
- // Finished writing buffer_. Read some more.
+
+ // Continue writing.
+ data->DidConsume(result);
+ if (WriteBuffer(data) < 0)
+ return;
+
+ // Finished writing buffer_. Read some more, unless the request has been
+ // cancelled and deleted.
DCHECK_EQ(0, data->BytesRemaining());
- ReadResponse();
+ if (request_.get())
+ ReadResponse();
}
void URLFetcherCore::ReadResponse() {
@@ -915,24 +893,4 @@ void URLFetcherCore::InformDelegateDownloadProgressInDelegateThread(
delegate_->OnURLFetchDownloadProgress(fetcher_, current, total);
}
-void URLFetcherCore::InformDelegateDownloadDataIfNecessary(int bytes_read) {
- DCHECK(network_task_runner_->BelongsToCurrentThread());
- if (delegate_ && delegate_->ShouldSendDownloadData()) {
- scoped_ptr<std::string> download_data(
- new std::string(buffer_->data(), bytes_read));
- delegate_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &URLFetcherCore::InformDelegateDownloadDataInDelegateThread,
- this, base::Passed(&download_data)));
- }
-}
-
-void URLFetcherCore::InformDelegateDownloadDataInDelegateThread(
- scoped_ptr<std::string> download_data) {
- DCHECK(delegate_task_runner_->BelongsToCurrentThread());
- if (delegate_)
- delegate_->OnURLFetchDownloadData(fetcher_, download_data.Pass());
-}
-
} // namespace net
diff --git a/chromium/net/url_request/url_fetcher_core.h b/chromium/net/url_request/url_fetcher_core.h
index 27e253fbe54..c8864d4a64c 100644
--- a/chromium/net/url_request/url_fetcher_core.h
+++ b/chromium/net/url_request/url_fetcher_core.h
@@ -32,7 +32,6 @@ class DrainableIOBuffer;
class HttpResponseHeaders;
class IOBuffer;
class URLFetcherDelegate;
-class URLFetcherFileWriter;
class URLFetcherResponseWriter;
class URLRequestContextGetter;
class URLRequestThrottlerEntryInterface;
@@ -98,9 +97,11 @@ class URLFetcherCore
void SetAutomaticallyRetryOnNetworkChanges(int max_retries);
void SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner);
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner);
void SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner);
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner);
+ void SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer);
HttpResponseHeaders* GetResponseHeaders() const;
HostPortPair GetSocketAddress() const;
bool WasFetchedViaProxy() const;
@@ -109,7 +110,6 @@ class URLFetcherCore
const URLRequestStatus& GetStatus() const;
int GetResponseCode() const;
const ResponseCookies& GetCookies() const;
- bool FileErrorOccurred(int* out_error_code) const;
// Reports that the received content was malformed (i.e. failed parsing
// or validation). This makes the throttling logic that does exponential
// back-off when servers are having problems treat the current request as
@@ -141,13 +141,6 @@ class URLFetcherCore
private:
friend class base::RefCountedThreadSafe<URLFetcherCore>;
- // How should the response be stored?
- enum ResponseDestinationType {
- STRING, // Default: In a std::string
- PERMANENT_FILE, // Write to a permanent file.
- TEMP_FILE, // Write to a temporary file.
- };
-
class Registry {
public:
Registry();
@@ -176,7 +169,7 @@ class URLFetcherCore
void StartURLRequest();
void DidInitializeWriter(int result);
void StartURLRequestWhenAppropriate();
- void CancelURLRequest();
+ void CancelURLRequest(int error);
void OnCompletedURLRequest(base::TimeDelta backoff_delay);
void InformDelegateFetchIsComplete();
void NotifyMalformedContent();
@@ -211,9 +204,6 @@ class URLFetcherCore
void InformDelegateDownloadProgress();
void InformDelegateDownloadProgressInDelegateThread(int64 current,
int64 total);
- void InformDelegateDownloadDataIfNecessary(int bytes_read);
- void InformDelegateDownloadDataInDelegateThread(
- scoped_ptr<std::string> download_data);
URLFetcher* fetcher_; // Corresponding fetcher object
GURL original_url_; // The URL we were asked to fetch
@@ -221,18 +211,15 @@ class URLFetcherCore
URLFetcher::RequestType request_type_; // What type of request is this?
URLRequestStatus status_; // Status of the request
URLFetcherDelegate* delegate_; // Object to notify on completion
+ // Task runner for the creating thread. Used to interact with the delegate.
scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
- // Task runner for the creating thread.
+ // Task runner for network operations.
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
- // Task runner for download file access.
- scoped_refptr<base::TaskRunner> file_task_runner_;
- // Task runner for upload file access.
+ // Task runner for upload file access.
scoped_refptr<base::TaskRunner> upload_file_task_runner_;
scoped_ptr<URLRequest> request_; // The actual request this wraps
int load_flags_; // Flags for the load operation
int response_code_; // HTTP status code for the request
- std::string data_; // Results of the request, when we are
- // storing the response as a string.
scoped_refptr<IOBuffer> buffer_;
// Read buffer
scoped_refptr<URLRequestContextGetter> request_context_getter_;
@@ -283,18 +270,6 @@ class URLFetcherCore
// Writer object to write response to the destination like file and string.
scoped_ptr<URLFetcherResponseWriter> response_writer_;
- // If writing results to a file, |file_writer_| will manage creation,
- // writing, and destruction of that file.
- // |file_writer_| points to the same object as |response_writer_| when writing
- // response to a file, otherwise, |file_writer_| is NULL.
- URLFetcherFileWriter* file_writer_;
-
- // Where should responses be saved?
- ResponseDestinationType response_destination_;
-
- // Path to the file where the response is written.
- base::FilePath response_destination_file_path_;
-
// By default any server-initiated redirects are automatically followed. If
// this flag is set to true, however, a redirect will halt the fetch and call
// back to to the delegate immediately.
diff --git a/chromium/net/url_request/url_fetcher_delegate.cc b/chromium/net/url_request/url_fetcher_delegate.cc
index 1cc58e7f3e5..4f7cd653bff 100644
--- a/chromium/net/url_request/url_fetcher_delegate.cc
+++ b/chromium/net/url_request/url_fetcher_delegate.cc
@@ -9,16 +9,9 @@ namespace net {
void URLFetcherDelegate::OnURLFetchDownloadProgress(
const URLFetcher* source, int64 current, int64 total) {}
-void URLFetcherDelegate::OnURLFetchDownloadData(
- const URLFetcher* source, scoped_ptr<std::string> download_data) {}
-
void URLFetcherDelegate::OnURLFetchUploadProgress(
const URLFetcher* source, int64 current, int64 total) {}
-bool URLFetcherDelegate::ShouldSendDownloadData() {
- return false;
-}
-
URLFetcherDelegate::~URLFetcherDelegate() {}
} // namespace net
diff --git a/chromium/net/url_request/url_fetcher_delegate.h b/chromium/net/url_request/url_fetcher_delegate.h
index ac7b2a60ef7..e1b1352fb50 100644
--- a/chromium/net/url_request/url_fetcher_delegate.h
+++ b/chromium/net/url_request/url_fetcher_delegate.h
@@ -28,19 +28,6 @@ class NET_EXPORT URLFetcherDelegate {
virtual void OnURLFetchDownloadProgress(const URLFetcher* source,
int64 current, int64 total);
- // This will be called when some part of the response is read.
- // |download_data| contains the current bytes received since the last call.
- // This will be called after ShouldSendDownloadData() and only if the latter
- // returns true.
- virtual void OnURLFetchDownloadData(const URLFetcher* source,
- scoped_ptr<std::string> download_data);
-
- // This indicates if OnURLFetchDownloadData should be called.
- // This will be called before OnURLFetchDownloadData is called, and only if
- // this returns true.
- // Default implementation is false.
- virtual bool ShouldSendDownloadData();
-
// This will be called when uploading of POST or PUT requests proceeded.
// |current| denotes the number of bytes sent so far, and |total| is the
// total size of uploading data (or -1 if chunked upload is enabled).
diff --git a/chromium/net/url_request/url_fetcher_impl.cc b/chromium/net/url_request/url_fetcher_impl.cc
index e8f9d32f05a..32253c92145 100644
--- a/chromium/net/url_request/url_fetcher_impl.cc
+++ b/chromium/net/url_request/url_fetcher_impl.cc
@@ -6,8 +6,10 @@
#include "base/bind.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/sequenced_task_runner.h"
#include "net/url_request/url_fetcher_core.h"
#include "net/url_request/url_fetcher_factory.h"
+#include "net/url_request/url_fetcher_response_writer.h"
namespace net {
@@ -120,15 +122,20 @@ void URLFetcherImpl::SetAutomaticallyRetryOnNetworkChanges(int max_retries) {
void URLFetcherImpl::SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner) {
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
core_->SaveResponseToFileAtPath(file_path, file_task_runner);
}
void URLFetcherImpl::SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner) {
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
core_->SaveResponseToTemporaryFile(file_task_runner);
}
+void URLFetcherImpl::SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer) {
+ core_->SaveResponseWithWriter(response_writer.Pass());
+}
+
HttpResponseHeaders* URLFetcherImpl::GetResponseHeaders() const {
return core_->GetResponseHeaders();
}
@@ -165,10 +172,6 @@ const ResponseCookies& URLFetcherImpl::GetCookies() const {
return core_->GetCookies();
}
-bool URLFetcherImpl::FileErrorOccurred(int* out_error_code) const {
- return core_->FileErrorOccurred(out_error_code);
-}
-
void URLFetcherImpl::ReceivedContentWasMalformed() {
core_->ReceivedContentWasMalformed();
}
diff --git a/chromium/net/url_request/url_fetcher_impl.h b/chromium/net/url_request/url_fetcher_impl.h
index d643a94580f..fe0362b3aea 100644
--- a/chromium/net/url_request/url_fetcher_impl.h
+++ b/chromium/net/url_request/url_fetcher_impl.h
@@ -70,9 +70,11 @@ class NET_EXPORT_PRIVATE URLFetcherImpl : public URLFetcher {
virtual void SetAutomaticallyRetryOnNetworkChanges(int max_retries) OVERRIDE;
virtual void SaveResponseToFileAtPath(
const base::FilePath& file_path,
- scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) OVERRIDE;
virtual void SaveResponseToTemporaryFile(
- scoped_refptr<base::TaskRunner> file_task_runner) OVERRIDE;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner) OVERRIDE;
+ virtual void SaveResponseWithWriter(
+ scoped_ptr<URLFetcherResponseWriter> response_writer) OVERRIDE;
virtual HttpResponseHeaders* GetResponseHeaders() const OVERRIDE;
virtual HostPortPair GetSocketAddress() const OVERRIDE;
virtual bool WasFetchedViaProxy() const OVERRIDE;
@@ -82,7 +84,6 @@ class NET_EXPORT_PRIVATE URLFetcherImpl : public URLFetcher {
virtual const URLRequestStatus& GetStatus() const OVERRIDE;
virtual int GetResponseCode() const OVERRIDE;
virtual const ResponseCookies& GetCookies() const OVERRIDE;
- virtual bool FileErrorOccurred(int* out_error_code) const OVERRIDE;
virtual void ReceivedContentWasMalformed() OVERRIDE;
virtual bool GetResponseAsString(
std::string* out_response_string) const OVERRIDE;
diff --git a/chromium/net/url_request/url_fetcher_impl_unittest.cc b/chromium/net/url_request/url_fetcher_impl_unittest.cc
index 62f627258db..c96993f89a4 100644
--- a/chromium/net/url_request/url_fetcher_impl_unittest.cc
+++ b/chromium/net/url_request/url_fetcher_impl_unittest.cc
@@ -868,19 +868,16 @@ void URLFetcherFileTest::CreateFetcherForTempFile(const GURL& url) {
void URLFetcherFileTest::OnURLFetchComplete(const URLFetcher* source) {
if (expected_file_error_ == OK) {
EXPECT_TRUE(source->GetStatus().is_success());
- EXPECT_EQ(source->GetResponseCode(), 200);
-
- int error_code = OK;
- EXPECT_FALSE(fetcher_->FileErrorOccurred(&error_code));
+ EXPECT_EQ(OK, source->GetStatus().error());
+ EXPECT_EQ(200, source->GetResponseCode());
EXPECT_TRUE(source->GetResponseAsFilePath(
take_ownership_of_file_, &file_path_));
EXPECT_TRUE(base::ContentsEqual(expected_file_, file_path_));
} else {
- int error_code = OK;
- EXPECT_TRUE(fetcher_->FileErrorOccurred(&error_code));
- EXPECT_EQ(expected_file_error_, error_code);
+ EXPECT_FALSE(source->GetStatus().is_success());
+ EXPECT_EQ(expected_file_error_, source->GetStatus().error());
}
CleanupAfterFetchComplete();
}
@@ -1461,7 +1458,7 @@ TEST_F(URLFetcherFileTest, TryToOverwriteDirectory) {
// Create a directory before trying to fetch.
static const char kFileToFetch[] = "simple.html";
file_path_ = temp_dir.path().AppendASCII(kFileToFetch);
- ASSERT_TRUE(file_util::CreateDirectory(file_path_));
+ ASSERT_TRUE(base::CreateDirectory(file_path_));
ASSERT_TRUE(base::PathExists(file_path_));
// Get a small file.
diff --git a/chromium/net/url_request/url_fetcher_response_writer.cc b/chromium/net/url_request/url_fetcher_response_writer.cc
index a7d5b5a8a24..1a63d406c0a 100644
--- a/chromium/net/url_request/url_fetcher_response_writer.cc
+++ b/chromium/net/url_request/url_fetcher_response_writer.cc
@@ -6,7 +6,7 @@
#include "base/file_util.h"
#include "base/location.h"
-#include "base/task_runner.h"
+#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "net/base/file_stream.h"
#include "net/base/io_buffer.h"
@@ -14,22 +14,29 @@
namespace net {
-URLFetcherStringWriter::URLFetcherStringWriter(std::string* string)
- : string_(string) {
+URLFetcherStringWriter* URLFetcherResponseWriter::AsStringWriter() {
+ return NULL;
+}
+
+URLFetcherFileWriter* URLFetcherResponseWriter::AsFileWriter() {
+ return NULL;
+}
+
+URLFetcherStringWriter::URLFetcherStringWriter() {
}
URLFetcherStringWriter::~URLFetcherStringWriter() {
}
int URLFetcherStringWriter::Initialize(const CompletionCallback& callback) {
- // Do nothing.
+ data_.clear();
return OK;
}
int URLFetcherStringWriter::Write(IOBuffer* buffer,
int num_bytes,
const CompletionCallback& callback) {
- string_->append(buffer->data(), num_bytes);
+ data_.append(buffer->data(), num_bytes);
return num_bytes;
}
@@ -38,13 +45,17 @@ int URLFetcherStringWriter::Finish(const CompletionCallback& callback) {
return OK;
}
+URLFetcherStringWriter* URLFetcherStringWriter::AsStringWriter() {
+ return this;
+}
+
URLFetcherFileWriter::URLFetcherFileWriter(
- scoped_refptr<base::TaskRunner> file_task_runner)
- : error_code_(OK),
- weak_factory_(this),
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner,
+ const base::FilePath& file_path)
+ : weak_factory_(this),
file_task_runner_(file_task_runner),
- owns_file_(false),
- total_bytes_written_(0) {
+ file_path_(file_path),
+ owns_file_(false) {
DCHECK(file_task_runner_.get());
}
@@ -53,9 +64,6 @@ URLFetcherFileWriter::~URLFetcherFileWriter() {
}
int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
- DCHECK(!file_stream_);
- DCHECK(!owns_file_);
-
file_stream_.reset(new FileStream(NULL));
int result = ERR_IO_PENDING;
@@ -64,7 +72,7 @@ int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
base::PostTaskAndReplyWithResult(
file_task_runner_.get(),
FROM_HERE,
- base::Bind(&file_util::CreateTemporaryFile, temp_file_path),
+ base::Bind(&base::CreateTemporaryFile, temp_file_path),
base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
weak_factory_.GetWeakPtr(),
callback,
@@ -78,8 +86,6 @@ int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
weak_factory_.GetWeakPtr(),
callback));
DCHECK_NE(OK, result);
- if (result != ERR_IO_PENDING)
- error_code_ = result;
}
return result;
}
@@ -94,10 +100,9 @@ int URLFetcherFileWriter::Write(IOBuffer* buffer,
base::Bind(&URLFetcherFileWriter::DidWrite,
weak_factory_.GetWeakPtr(),
callback));
- if (result < 0 && result != ERR_IO_PENDING) {
- error_code_ = result;
+ if (result < 0 && result != ERR_IO_PENDING)
CloseAndDeleteFile();
- }
+
return result;
}
@@ -110,20 +115,8 @@ int URLFetcherFileWriter::Finish(const CompletionCallback& callback) {
return result;
}
-void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
- int result) {
- // Destroy |file_stream_| whether or not the close succeeded.
- file_stream_.reset();
- callback.Run(result);
-}
-
-void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
- int result) {
- if (result < 0) {
- error_code_ = result;
- CloseAndDeleteFile();
- }
- callback.Run(result);
+URLFetcherFileWriter* URLFetcherFileWriter::AsFileWriter() {
+ return this;
}
void URLFetcherFileWriter::DisownFile() {
@@ -134,6 +127,14 @@ void URLFetcherFileWriter::DisownFile() {
owns_file_ = false;
}
+void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
+ int result) {
+ if (result < 0)
+ CloseAndDeleteFile();
+
+ callback.Run(result);
+}
+
void URLFetcherFileWriter::CloseAndDeleteFile() {
if (!owns_file_)
return;
@@ -150,8 +151,7 @@ void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
base::FilePath* temp_file_path,
bool success) {
if (!success) {
- error_code_ = ERR_FILE_NOT_FOUND;
- callback.Run(error_code_);
+ callback.Run(ERR_FILE_NOT_FOUND);
return;
}
file_path_ = *temp_file_path;
@@ -169,13 +169,18 @@ void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback,
void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback,
int result) {
- if (result == OK) {
- total_bytes_written_ = 0;
+ if (result == OK)
owns_file_ = true;
- } else {
- error_code_ = result;
+ else
CloseAndDeleteFile();
- }
+
+ callback.Run(result);
+}
+
+void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback,
+ int result) {
+ // Destroy |file_stream_| whether or not the close succeeded.
+ file_stream_.reset();
callback.Run(result);
}
diff --git a/chromium/net/url_request/url_fetcher_response_writer.h b/chromium/net/url_request/url_fetcher_response_writer.h
index 2f15831873d..422a8a400ad 100644
--- a/chromium/net/url_request/url_fetcher_response_writer.h
+++ b/chromium/net/url_request/url_fetcher_response_writer.h
@@ -11,9 +11,10 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "net/base/completion_callback.h"
+#include "net/base/net_export.h"
namespace base {
-class TaskRunner;
+class SequencedTaskRunner;
} // namespace base
namespace net {
@@ -21,15 +22,18 @@ namespace net {
class DrainableIOBuffer;
class FileStream;
class IOBuffer;
+class URLFetcherFileWriter;
+class URLFetcherStringWriter;
// This class encapsulates all state involved in writing URLFetcher response
// bytes to the destination.
-class URLFetcherResponseWriter {
+class NET_EXPORT URLFetcherResponseWriter {
public:
virtual ~URLFetcherResponseWriter() {}
// Initializes this instance. If ERR_IO_PENDING is returned, |callback| will
- // be run later with the result.
+ // be run later with the result. Calling this method again after a
+ // Initialize() success results in discarding already written data.
virtual int Initialize(const CompletionCallback& callback) = 0;
// Writes |num_bytes| bytes in |buffer|, and returns the number of bytes
@@ -42,40 +46,47 @@ class URLFetcherResponseWriter {
// Finishes writing. If ERR_IO_PENDING is returned, |callback| will be run
// later with the result.
virtual int Finish(const CompletionCallback& callback) = 0;
+
+ // Returns this instance's pointer as URLFetcherStringWriter when possible.
+ virtual URLFetcherStringWriter* AsStringWriter();
+
+ // Returns this instance's pointer as URLFetcherFileWriter when possible.
+ virtual URLFetcherFileWriter* AsFileWriter();
};
// URLFetcherResponseWriter implementation for std::string.
-class URLFetcherStringWriter : public URLFetcherResponseWriter {
+class NET_EXPORT URLFetcherStringWriter : public URLFetcherResponseWriter {
public:
- URLFetcherStringWriter(std::string* string);
+ URLFetcherStringWriter();
virtual ~URLFetcherStringWriter();
+ const std::string& data() const { return data_; }
+
// URLFetcherResponseWriter overrides:
virtual int Initialize(const CompletionCallback& callback) OVERRIDE;
virtual int Write(IOBuffer* buffer,
int num_bytes,
const CompletionCallback& callback) OVERRIDE;
virtual int Finish(const CompletionCallback& callback) OVERRIDE;
+ virtual URLFetcherStringWriter* AsStringWriter() OVERRIDE;
private:
- std::string* const string_;
+ std::string data_;
DISALLOW_COPY_AND_ASSIGN(URLFetcherStringWriter);
};
// URLFetcherResponseWriter implementation for files.
-class URLFetcherFileWriter : public URLFetcherResponseWriter {
+class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter {
public:
- URLFetcherFileWriter(scoped_refptr<base::TaskRunner> file_task_runner);
+ // |file_path| is used as the destination path. If |file_path| is empty,
+ // Initialize() will create a temporary file.
+ URLFetcherFileWriter(
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner,
+ const base::FilePath& file_path);
virtual ~URLFetcherFileWriter();
- // Sets destination file path.
- // Call this method before Initialize() to set the destination path,
- // if this method is not called before Initialize(), Initialize() will create
- // a temporary file.
- void set_destination_file_path(const base::FilePath& file_path) {
- file_path_ = file_path;
- }
+ const base::FilePath& file_path() const { return file_path_; }
// URLFetcherResponseWriter overrides:
virtual int Initialize(const CompletionCallback& callback) OVERRIDE;
@@ -83,26 +94,19 @@ class URLFetcherFileWriter : public URLFetcherResponseWriter {
int num_bytes,
const CompletionCallback& callback) OVERRIDE;
virtual int Finish(const CompletionCallback& callback) OVERRIDE;
-
- // Called when a write has been done.
- void DidWrite(const CompletionCallback& callback, int result);
+ virtual URLFetcherFileWriter* AsFileWriter() OVERRIDE;
// Drops ownership of the file at |file_path_|.
// This class will not delete it or write to it again.
void DisownFile();
- // Closes the file if it is open.
- // |callback| is run with the result upon completion.
- void CloseFile(const CompletionCallback& callback);
+ private:
+ // Called when a write has been done.
+ void DidWrite(const CompletionCallback& callback, int result);
// Closes the file if it is open and then delete it.
void CloseAndDeleteFile();
- const base::FilePath& file_path() const { return file_path_; }
- int64 total_bytes_written() { return total_bytes_written_; }
- int error_code() const { return error_code_; }
-
- private:
// Callback which gets the result of a temporary file creation.
void DidCreateTempFile(const CompletionCallback& callback,
base::FilePath* temp_file_path,
@@ -115,14 +119,11 @@ class URLFetcherFileWriter : public URLFetcherResponseWriter {
// Callback which gets the result of closing a file.
void CloseComplete(const CompletionCallback& callback, int result);
- // The last error encountered on a file operation. OK if no error occurred.
- int error_code_;
-
// Callbacks are created for use with base::FileUtilProxy.
base::WeakPtrFactory<URLFetcherFileWriter> weak_factory_;
// Task runner on which file operations should happen.
- scoped_refptr<base::TaskRunner> file_task_runner_;
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
// Destination file path.
// Initialize() creates a temporary file if this variable is empty.
@@ -133,10 +134,6 @@ class URLFetcherFileWriter : public URLFetcherResponseWriter {
scoped_ptr<FileStream> file_stream_;
- // We always append to the file. Track the total number of bytes
- // written, so that writes know the offset to give.
- int64 total_bytes_written_;
-
DISALLOW_COPY_AND_ASSIGN(URLFetcherFileWriter);
};
diff --git a/chromium/net/url_request/url_request.cc b/chromium/net/url_request/url_request.cc
index bf031c8bd72..6b0124730d5 100644
--- a/chromium/net/url_request/url_request.cc
+++ b/chromium/net/url_request/url_request.cc
@@ -15,7 +15,9 @@
#include "base/metrics/histogram.h"
#include "base/metrics/stats_counters.h"
#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
+#include "base/values.h"
#include "net/base/auth.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
@@ -198,8 +200,8 @@ void URLRequest::Delegate::OnSSLCertificateError(URLRequest* request,
///////////////////////////////////////////////////////////////////////////////
// URLRequest
-// TODO(shalev): Get rid of this constructor in favour of the one below it.
URLRequest::URLRequest(const GURL& url,
+ RequestPriority priority,
Delegate* delegate,
const URLRequestContext* context)
: context_(context),
@@ -214,45 +216,10 @@ URLRequest::URLRequest(const GURL& url,
is_pending_(false),
is_redirecting_(false),
redirect_limit_(kMaxRedirects),
- priority_(DEFAULT_PRIORITY),
+ priority_(priority),
identifier_(GenerateURLRequestIdentifier()),
- blocked_on_delegate_(false),
- before_request_callback_(base::Bind(&URLRequest::BeforeRequestComplete,
- base::Unretained(this))),
- has_notified_completion_(false),
- received_response_content_length_(0),
- creation_time_(base::TimeTicks::Now()) {
- SIMPLE_STATS_COUNTER("URLRequestCount");
-
- // Sanity check out environment.
- DCHECK(base::MessageLoop::current())
- << "The current base::MessageLoop must exist";
-
- CHECK(context);
- context->url_requests()->insert(this);
-
- net_log_.BeginEvent(NetLog::TYPE_REQUEST_ALIVE);
-}
-
-URLRequest::URLRequest(const GURL& url,
- Delegate* delegate,
- const URLRequestContext* context,
- NetworkDelegate* network_delegate)
- : context_(context),
- network_delegate_(network_delegate),
- net_log_(BoundNetLog::Make(context->net_log(),
- NetLog::SOURCE_URL_REQUEST)),
- url_chain_(1, url),
- method_("GET"),
- referrer_policy_(CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
- load_flags_(LOAD_NORMAL),
- delegate_(delegate),
- is_pending_(false),
- is_redirecting_(false),
- redirect_limit_(kMaxRedirects),
- priority_(DEFAULT_PRIORITY),
- identifier_(GenerateURLRequestIdentifier()),
- blocked_on_delegate_(false),
+ calling_delegate_(false),
+ use_blocked_by_as_load_param_(false),
before_request_callback_(base::Bind(&URLRequest::BeforeRequestComplete,
base::Unretained(this))),
has_notified_completion_(false),
@@ -380,14 +347,97 @@ bool URLRequest::GetFullRequestHeaders(HttpRequestHeaders* headers) const {
}
LoadStateWithParam URLRequest::GetLoadState() const {
- if (blocked_on_delegate_) {
- return LoadStateWithParam(LOAD_STATE_WAITING_FOR_DELEGATE,
- load_state_param_);
+ // The !blocked_by_.empty() check allows |this| to report it's blocked on a
+ // delegate before it has been started.
+ if (calling_delegate_ || !blocked_by_.empty()) {
+ return LoadStateWithParam(
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ use_blocked_by_as_load_param_ ? UTF8ToUTF16(blocked_by_) :
+ base::string16());
}
return LoadStateWithParam(job_.get() ? job_->GetLoadState() : LOAD_STATE_IDLE,
base::string16());
}
+base::Value* URLRequest::GetStateAsValue() const {
+ DictionaryValue* dict = new DictionaryValue();
+ dict->SetString("url", original_url().possibly_invalid_spec());
+
+ if (url_chain_.size() > 1) {
+ ListValue* list = new ListValue();
+ for (std::vector<GURL>::const_iterator url = url_chain_.begin();
+ url != url_chain_.end(); ++url) {
+ list->AppendString(url->possibly_invalid_spec());
+ }
+ dict->Set("url_chain", list);
+ }
+
+ dict->SetInteger("load_flags", load_flags_);
+
+ LoadStateWithParam load_state = GetLoadState();
+ dict->SetInteger("load_state", load_state.state);
+ if (!load_state.param.empty())
+ dict->SetString("load_state_param", load_state.param);
+ if (!blocked_by_.empty())
+ dict->SetString("delegate_info", blocked_by_);
+
+ dict->SetString("method", method_);
+ dict->SetBoolean("has_upload", has_upload());
+ dict->SetBoolean("is_pending", is_pending_);
+
+ // Add the status of the request. The status should always be IO_PENDING, and
+ // the error should always be OK, unless something is holding onto a request
+ // that has finished or a request was leaked. Neither of these should happen.
+ switch (status_.status()) {
+ case URLRequestStatus::SUCCESS:
+ dict->SetString("status", "SUCCESS");
+ break;
+ case URLRequestStatus::IO_PENDING:
+ dict->SetString("status", "IO_PENDING");
+ break;
+ case URLRequestStatus::CANCELED:
+ dict->SetString("status", "CANCELED");
+ break;
+ case URLRequestStatus::FAILED:
+ dict->SetString("status", "FAILED");
+ break;
+ }
+ if (status_.error() != OK)
+ dict->SetInteger("net_error", status_.error());
+ return dict;
+}
+
+void URLRequest::LogBlockedBy(const char* blocked_by) {
+ DCHECK(blocked_by);
+ DCHECK_GT(strlen(blocked_by), 0u);
+
+ // Only log information to NetLog during startup and certain deferring calls
+ // to delegates. For all reads but the first, do nothing.
+ if (!calling_delegate_ && !response_info_.request_time.is_null())
+ return;
+
+ LogUnblocked();
+ blocked_by_ = blocked_by;
+ use_blocked_by_as_load_param_ = false;
+
+ net_log_.BeginEvent(
+ NetLog::TYPE_DELEGATE_INFO,
+ NetLog::StringCallback("delegate_info", &blocked_by_));
+}
+
+void URLRequest::LogAndReportBlockedBy(const char* source) {
+ LogBlockedBy(source);
+ use_blocked_by_as_load_param_ = true;
+}
+
+void URLRequest::LogUnblocked() {
+ if (blocked_by_.empty())
+ return;
+
+ net_log_.EndEvent(NetLog::TYPE_DELEGATE_INFO);
+ blocked_by_.clear();
+}
+
UploadProgress URLRequest::GetUploadProgress() const {
if (!job_.get()) {
// We haven't started or the request was cancelled
@@ -458,6 +508,20 @@ int URLRequest::GetResponseCode() const {
return job_->GetResponseCode();
}
+void URLRequest::SetLoadFlags(int flags) {
+ if ((load_flags_ & LOAD_IGNORE_LIMITS) != (flags & LOAD_IGNORE_LIMITS)) {
+ DCHECK(!job_);
+ DCHECK(flags & LOAD_IGNORE_LIMITS);
+ DCHECK_EQ(priority_, MAXIMUM_PRIORITY);
+ }
+ load_flags_ = flags;
+
+ // This should be a no-op given the above DCHECKs, but do this
+ // anyway for release mode.
+ if ((load_flags_ & LOAD_IGNORE_LIMITS) != 0)
+ SetPriority(MAXIMUM_PRIORITY);
+}
+
// static
void URLRequest::SetDefaultCookiePolicyToBlock() {
CHECK(!g_url_requests_started);
@@ -539,6 +603,9 @@ void URLRequest::set_delegate(Delegate* delegate) {
void URLRequest::Start() {
DCHECK_EQ(network_delegate_, context_->network_delegate());
+ // Anything that sets |blocked_by_| before start should have cleaned up after
+ // itself.
+ DCHECK(blocked_by_.empty());
g_url_requests_started = true;
response_info_.request_time = base::Time::Now();
@@ -549,14 +616,13 @@ void URLRequest::Start() {
// Only notify the delegate for the initial request.
if (network_delegate_) {
+ OnCallToDelegate();
int error = network_delegate_->NotifyBeforeURLRequest(
this, before_request_callback_, &delegate_redirect_url_);
- if (error == net::ERR_IO_PENDING) {
- // Paused on the delegate, will invoke |before_request_callback_| later.
- SetBlockedOnDelegate();
- } else {
+ // If ERR_IO_PENDING is returned, the delegate will invoke
+ // |before_request_callback_| later.
+ if (error != ERR_IO_PENDING)
BeforeRequestComplete(error);
- }
return;
}
@@ -574,8 +640,7 @@ void URLRequest::BeforeRequestComplete(int error) {
// Check that there are no callbacks to already canceled requests.
DCHECK_NE(URLRequestStatus::CANCELED, status_.status());
- if (blocked_on_delegate_)
- SetUnblockedOnDelegate();
+ OnCallToDelegateComplete();
if (error != OK) {
std::string source("delegate");
@@ -658,6 +723,11 @@ void URLRequest::CancelWithSSLError(int error, const SSLInfo& ssl_info) {
void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) {
DCHECK(error < 0);
+ // If cancelled while calling a delegate, clear delegate info.
+ if (calling_delegate_) {
+ LogUnblocked();
+ OnCallToDelegateComplete();
+ }
// If the URL request already has an error status, then canceling is a no-op.
// Plus, we don't want to change the error status once it has been set.
@@ -692,6 +762,10 @@ bool URLRequest::Read(IOBuffer* dest, int dest_size, int* bytes_read) {
DCHECK(bytes_read);
*bytes_read = 0;
+ // If this is the first read, end the delegate call that may have started in
+ // OnResponseStarted.
+ OnCallToDelegateComplete();
+
// This handles a cancel that happens while paused.
// TODO(ahendrickson): DCHECK() that it is not done after
// http://crbug.com/115705 is fixed.
@@ -732,6 +806,7 @@ void URLRequest::NotifyReceivedRedirect(const GURL& location,
if (job) {
RestartWithJob(job);
} else if (delegate_) {
+ OnCallToDelegate();
delegate_->OnReceivedRedirect(this, location, defer_redirect);
// |this| may be have been destroyed here.
}
@@ -762,6 +837,7 @@ void URLRequest::NotifyResponseStarted() {
if (!has_notified_completion_ && !status_.is_success())
NotifyRequestCompleted();
+ OnCallToDelegate();
delegate_->OnResponseStarted(this);
// Nothing may appear below this line as OnResponseStarted may delete
// |this|.
@@ -837,6 +913,8 @@ void URLRequest::OrphanJob() {
}
int URLRequest::Redirect(const GURL& location, int http_status_code) {
+ // Matches call in NotifyReceivedRedirect.
+ OnCallToDelegateComplete();
if (net_log_.IsLoggingAllEvents()) {
net_log_.AddEvent(
NetLog::TYPE_URL_REQUEST_REDIRECTED,
@@ -905,7 +983,15 @@ int64 URLRequest::GetExpectedContentSize() const {
void URLRequest::SetPriority(RequestPriority priority) {
DCHECK_GE(priority, MINIMUM_PRIORITY);
- DCHECK_LT(priority, NUM_PRIORITIES);
+ DCHECK_LE(priority, MAXIMUM_PRIORITY);
+
+ if ((load_flags_ & LOAD_IGNORE_LIMITS) && (priority != MAXIMUM_PRIORITY)) {
+ NOTREACHED();
+ // Maintain the invariant that requests with IGNORE_LIMITS set
+ // have MAXIMUM_PRIORITY for release mode.
+ return;
+ }
+
if (priority_ == priority)
return;
@@ -943,24 +1029,23 @@ void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) {
NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION;
auth_info_ = auth_info;
if (network_delegate_) {
+ OnCallToDelegate();
rv = network_delegate_->NotifyAuthRequired(
this,
*auth_info,
base::Bind(&URLRequest::NotifyAuthRequiredComplete,
base::Unretained(this)),
&auth_credentials_);
+ if (rv == NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING)
+ return;
}
- if (rv == NetworkDelegate::AUTH_REQUIRED_RESPONSE_IO_PENDING) {
- SetBlockedOnDelegate();
- } else {
- NotifyAuthRequiredComplete(rv);
- }
+ NotifyAuthRequiredComplete(rv);
}
void URLRequest::NotifyAuthRequiredComplete(
NetworkDelegate::AuthRequiredResponse result) {
- SetUnblockedOnDelegate();
+ OnCallToDelegateComplete();
// Check that there are no callbacks to already canceled requests.
DCHECK_NE(URLRequestStatus::CANCELED, status_.status());
@@ -1085,22 +1170,20 @@ void URLRequest::NotifyRequestCompleted() {
network_delegate_->NotifyCompleted(this, job_.get() != NULL);
}
-void URLRequest::SetBlockedOnDelegate() {
- blocked_on_delegate_ = true;
- if (!load_state_param_.empty()) {
- net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE,
- NetLog::StringCallback("delegate", &load_state_param_));
- } else {
- net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE);
- }
+void URLRequest::OnCallToDelegate() {
+ DCHECK(!calling_delegate_);
+ DCHECK(blocked_by_.empty());
+ calling_delegate_ = true;
+ net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_DELEGATE);
}
-void URLRequest::SetUnblockedOnDelegate() {
- if (!blocked_on_delegate_)
+void URLRequest::OnCallToDelegateComplete() {
+ // This should have been cleared before resuming the request.
+ DCHECK(blocked_by_.empty());
+ if (!calling_delegate_)
return;
- blocked_on_delegate_ = false;
- load_state_param_.clear();
- net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_BLOCKED_ON_DELEGATE);
+ calling_delegate_ = false;
+ net_log_.EndEvent(NetLog::TYPE_URL_REQUEST_DELEGATE);
}
void URLRequest::set_stack_trace(const base::debug::StackTrace& stack_trace) {
diff --git a/chromium/net/url_request/url_request.h b/chromium/net/url_request/url_request.h
index a01656c97bd..84f50505658 100644
--- a/chromium/net/url_request/url_request.h
+++ b/chromium/net/url_request/url_request.h
@@ -37,10 +37,12 @@ class TestAutomationProvider;
class URLRequestAutomationJob;
namespace base {
+class Value;
+
namespace debug {
class StackTrace;
-}
-}
+} // namespace debug
+} // namespace base
// Temporary layering violation to allow existing users of a deprecated
// interface.
@@ -297,17 +299,11 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
virtual ~Delegate() {}
};
- // TODO(shalev): Get rid of this constructor in favour of the one below it.
- // Initialize an URL request.
URLRequest(const GURL& url,
+ RequestPriority priority,
Delegate* delegate,
const URLRequestContext* context);
- URLRequest(const GURL& url,
- Delegate* delegate,
- const URLRequestContext* context,
- NetworkDelegate* network_delegate);
-
// If destroyed after Start() has been called but while IO is pending,
// then the request will be effectively canceled and the delegate
// will not have any more of its methods called.
@@ -442,13 +438,31 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
// 2. The OnResponseStarted callback is currently running or has run.
bool GetFullRequestHeaders(HttpRequestHeaders* headers) const;
- // Returns the current load state for the request. |param| is an optional
- // parameter describing details related to the load state. Not all load states
- // have a parameter.
+ // Returns the current load state for the request. The returned value's
+ // |param| field is an optional parameter describing details related to the
+ // load state. Not all load states have a parameter.
LoadStateWithParam GetLoadState() const;
- void SetLoadStateParam(const base::string16& param) {
- load_state_param_ = param;
- }
+
+ // Returns a partial representation of the request's state as a value, for
+ // debugging. Caller takes ownership of returned value.
+ base::Value* GetStateAsValue() const;
+
+ // Logs information about the what external object currently blocking the
+ // request. LogUnblocked must be called before resuming the request. This
+ // can be called multiple times in a row either with or without calling
+ // LogUnblocked between calls. |blocked_by| must not be NULL or have length
+ // 0.
+ void LogBlockedBy(const char* blocked_by);
+
+ // Just like LogBlockedBy, but also makes GetLoadState return source as the
+ // |param| in the value returned by GetLoadState. Calling LogUnblocked or
+ // LogBlockedBy will clear the load param. |blocked_by| must not be NULL or
+ // have length 0.
+ void LogAndReportBlockedBy(const char* blocked_by);
+
+ // Logs that the request is no longer blocked by the last caller to
+ // LogBlockedBy.
+ void LogUnblocked();
// Returns the current upload progress in bytes. When the upload data is
// chunked, size is set to zero, but position will not be.
@@ -535,7 +549,11 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
// Access the LOAD_* flags modifying this request (see load_flags.h).
int load_flags() const { return load_flags_; }
- void set_load_flags(int flags) { load_flags_ = flags; }
+
+ // The new flags may change the IGNORE_LIMITS flag only when called
+ // before Start() is called, it must only set the flag, and if set,
+ // the priority of this request must already be MAXIMUM_PRIORITY.
+ void SetLoadFlags(int flags);
// Returns true if the request is "pending" (i.e., if Start() has been called,
// and the response has not yet been called).
@@ -636,7 +654,9 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
// Returns the priority level for this request.
RequestPriority priority() const { return priority_; }
- // Sets the priority level for this request and any related jobs.
+ // Sets the priority level for this request and any related
+ // jobs. Must not change the priority to anything other than
+ // MAXIMUM_PRIORITY if the IGNORE_LIMITS load flag is set.
void SetPriority(RequestPriority priority);
// Returns true iff this request would be internally redirected to HTTPS
@@ -754,10 +774,11 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
CookieOptions* options) const;
bool CanEnablePrivacyMode() const;
- // Called when the delegate blocks or unblocks this request when intercepting
- // certain requests.
- void SetBlockedOnDelegate();
- void SetUnblockedOnDelegate();
+ // Called just before calling a delegate that may block a request.
+ void OnCallToDelegate();
+ // Called when the delegate lets a request continue. Also called on
+ // cancellation.
+ void OnCallToDelegateComplete();
// Contextual information used for this request. Cannot be NULL. This contains
// most of the dependencies which are shared between requests (disk cache,
@@ -811,8 +832,9 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
// first transaction in a request involving redirects.
UploadProgress final_upload_progress_;
- // The priority level for this request. Objects like ClientSocketPool use
- // this to determine which URLRequest to allocate sockets to first.
+ // The priority level for this request. Objects like
+ // ClientSocketPool use this to determine which URLRequest to
+ // allocate sockets to first.
RequestPriority priority_;
// TODO(battre): The only consumer of the identifier_ is currently the
@@ -824,13 +846,14 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe),
// A globally unique identifier for this request.
const uint64 identifier_;
- // True if this request is blocked waiting for the network delegate to resume
- // it.
- bool blocked_on_delegate_;
+ // True if this request is currently calling a delegate, or is blocked waiting
+ // for the URL request or network delegate to resume it.
+ bool calling_delegate_;
- // An optional parameter that provides additional information about the load
- // state. Only used with the LOAD_STATE_WAITING_FOR_DELEGATE state.
- base::string16 load_state_param_;
+ // An optional parameter that provides additional information about what
+ // |this| is currently being blocked by.
+ std::string blocked_by_;
+ bool use_blocked_by_as_load_param_;
base::debug::LeakTracker<URLRequest> leak_tracker_;
diff --git a/chromium/net/url_request/url_request_context.cc b/chromium/net/url_request/url_request_context.cc
index 45ac83f3752..ae531d10f4b 100644
--- a/chromium/net/url_request/url_request_context.cc
+++ b/chromium/net/url_request/url_request_context.cc
@@ -27,6 +27,7 @@ URLRequestContext::URLRequestContext()
network_delegate_(NULL),
http_user_agent_settings_(NULL),
transport_security_state_(NULL),
+ cert_transparency_verifier_(NULL),
http_transaction_factory_(NULL),
job_factory_(NULL),
throttler_manager_(NULL),
@@ -51,6 +52,7 @@ void URLRequestContext::CopyFrom(const URLRequestContext* other) {
set_http_server_properties(other->http_server_properties_);
set_cookie_store(other->cookie_store_.get());
set_transport_security_state(other->transport_security_state_);
+ set_cert_transparency_verifier(other->cert_transparency_verifier_);
set_http_transaction_factory(other->http_transaction_factory_);
set_job_factory(other->job_factory_);
set_throttler_manager(other->throttler_manager_);
@@ -68,9 +70,11 @@ const HttpNetworkSession::Params* URLRequestContext::GetNetworkSessionParams(
return &network_session->params();
}
-URLRequest* URLRequestContext::CreateRequest(
- const GURL& url, URLRequest::Delegate* delegate) const {
- return new URLRequest(url, delegate, this, network_delegate_);
+scoped_ptr<URLRequest> URLRequestContext::CreateRequest(
+ const GURL& url,
+ RequestPriority priority,
+ URLRequest::Delegate* delegate) const {
+ return scoped_ptr<URLRequest>(new URLRequest(url, priority, delegate, this));
}
void URLRequestContext::set_cookie_store(CookieStore* cookie_store) {
@@ -79,12 +83,12 @@ void URLRequestContext::set_cookie_store(CookieStore* cookie_store) {
std::string URLRequestContext::GetAcceptLanguage() const {
return http_user_agent_settings_ ?
- http_user_agent_settings_->GetAcceptLanguage() : EmptyString();
+ http_user_agent_settings_->GetAcceptLanguage() : std::string();
}
std::string URLRequestContext::GetUserAgent(const GURL& url) const {
return http_user_agent_settings_ ?
- http_user_agent_settings_->GetUserAgent(url) : EmptyString();
+ http_user_agent_settings_->GetUserAgent(url) : std::string();
}
void URLRequestContext::AssertNoURLRequests() const {
diff --git a/chromium/net/url_request/url_request_context.h b/chromium/net/url_request/url_request_context.h
index bf9921e4f76..2c8a3b850f9 100644
--- a/chromium/net/url_request/url_request_context.h
+++ b/chromium/net/url_request/url_request_context.h
@@ -19,6 +19,7 @@
#include "base/threading/non_thread_safe.h"
#include "net/base/net_export.h"
#include "net/base/net_log.h"
+#include "net/base/request_priority.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/transport_security_state.h"
@@ -28,6 +29,7 @@
namespace net {
class CertVerifier;
class CookieStore;
+class CTVerifier;
class FraudulentCertificateReporter;
class HostResolver;
class HttpAuthHandlerFactory;
@@ -56,8 +58,9 @@ class NET_EXPORT URLRequestContext
// May return NULL if this context doesn't have an associated network session.
const HttpNetworkSession::Params* GetNetworkSessionParams() const;
- URLRequest* CreateRequest(
- const GURL& url, URLRequest::Delegate* delegate) const;
+ scoped_ptr<URLRequest> CreateRequest(const GURL& url,
+ RequestPriority priority,
+ URLRequest::Delegate* delegate) const;
NetLog* net_log() const {
return net_log_;
@@ -150,13 +153,20 @@ class NET_EXPORT URLRequestContext
void set_cookie_store(CookieStore* cookie_store);
TransportSecurityState* transport_security_state() const {
- return transport_security_state_;
+ return transport_security_state_;
}
void set_transport_security_state(
TransportSecurityState* state) {
transport_security_state_ = state;
}
+ CTVerifier* cert_transparency_verifier() const {
+ return cert_transparency_verifier_;
+ }
+ void set_cert_transparency_verifier(CTVerifier* verifier) {
+ cert_transparency_verifier_ = verifier;
+ }
+
// ---------------------------------------------------------------------------
// Legacy accessors that delegate to http_user_agent_settings_.
// TODO(pauljensen): Remove after all clients are updated to directly access
@@ -220,6 +230,7 @@ class NET_EXPORT URLRequestContext
HttpUserAgentSettings* http_user_agent_settings_;
scoped_refptr<CookieStore> cookie_store_;
TransportSecurityState* transport_security_state_;
+ CTVerifier* cert_transparency_verifier_;
HttpTransactionFactory* http_transaction_factory_;
const URLRequestJobFactory* job_factory_;
URLRequestThrottlerManager* throttler_manager_;
diff --git a/chromium/net/url_request/url_request_context_builder.cc b/chromium/net/url_request/url_request_context_builder.cc
index dce8214dc85..465aa87a1b7 100644
--- a/chromium/net/url_request/url_request_context_builder.cc
+++ b/chromium/net/url_request/url_request_context_builder.cc
@@ -200,12 +200,10 @@ URLRequestContextBuilder::URLRequestContextBuilder()
URLRequestContextBuilder::~URLRequestContextBuilder() {}
-#if defined(OS_LINUX) || defined(OS_ANDROID)
void URLRequestContextBuilder::set_proxy_config_service(
ProxyConfigService* proxy_config_service) {
proxy_config_service_.reset(proxy_config_service);
}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
URLRequestContext* URLRequestContextBuilder::Build() {
BasicURLRequestContext* context = new BasicURLRequestContext;
@@ -219,7 +217,9 @@ URLRequestContext* URLRequestContextBuilder::Build() {
NetworkDelegate* network_delegate = network_delegate_.release();
storage->set_network_delegate(network_delegate);
- storage->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
+ if (!host_resolver_)
+ host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL);
+ storage->set_host_resolver(host_resolver_.Pass());
context->StartFileThread();
@@ -228,10 +228,15 @@ URLRequestContext* URLRequestContextBuilder::Build() {
#if defined(OS_LINUX) || defined(OS_ANDROID)
ProxyConfigService* proxy_config_service = proxy_config_service_.release();
#else
- ProxyConfigService* proxy_config_service =
- ProxyService::CreateSystemProxyConfigService(
- base::ThreadTaskRunnerHandle::Get().get(),
- context->file_message_loop());
+ ProxyConfigService* proxy_config_service = NULL;
+ if (proxy_config_service_) {
+ proxy_config_service = proxy_config_service_.release();
+ } else {
+ proxy_config_service =
+ ProxyService::CreateSystemProxyConfigService(
+ base::ThreadTaskRunnerHandle::Get().get(),
+ context->file_message_loop());
+ }
#endif // defined(OS_LINUX) || defined(OS_ANDROID)
storage->set_proxy_service(
ProxyService::CreateUsingSystemProxyResolver(
diff --git a/chromium/net/url_request/url_request_context_builder.h b/chromium/net/url_request/url_request_context_builder.h
index 20fc30ea9f6..899e74dff0e 100644
--- a/chromium/net/url_request/url_request_context_builder.h
+++ b/chromium/net/url_request/url_request_context_builder.h
@@ -26,6 +26,7 @@
namespace net {
class FtpTransactionFactory;
+class HostResolver;
class HostMappingRules;
class ProxyConfigService;
class URLRequestContext;
@@ -69,9 +70,7 @@ class NET_EXPORT URLRequestContextBuilder {
URLRequestContextBuilder();
~URLRequestContextBuilder();
-#if defined(OS_LINUX) || defined(OS_ANDROID)
void set_proxy_config_service(ProxyConfigService* proxy_config_service);
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
// Call these functions to specify hard-coded Accept-Language
// or User-Agent header values for all requests that don't
@@ -100,6 +99,11 @@ class NET_EXPORT URLRequestContextBuilder {
}
#endif
+ // By default host_resolver is constructed with CreateDefaultResolver.
+ void set_host_resolver(HostResolver* host_resolver) {
+ host_resolver_.reset(host_resolver);
+ }
+
// Uses BasicNetworkDelegate by default. Note that calling Build will unset
// any custom delegate in builder, so this must be called each time before
// Build is called.
@@ -138,9 +142,8 @@ class NET_EXPORT URLRequestContextBuilder {
bool http_cache_enabled_;
HttpCacheParams http_cache_params_;
HttpNetworkSessionParams http_network_session_params_;
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+ scoped_ptr<HostResolver> host_resolver_;
scoped_ptr<ProxyConfigService> proxy_config_service_;
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
scoped_ptr<NetworkDelegate> network_delegate_;
scoped_ptr<FtpTransactionFactory> ftp_transaction_factory_;
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 f747b4de705..e882253773f 100644
--- a/chromium/net/url_request/url_request_context_builder_unittest.cc
+++ b/chromium/net/url_request/url_request_context_builder_unittest.cc
@@ -5,6 +5,7 @@
#include "net/url_request/url_request_context_builder.h"
#include "build/build_config.h"
+#include "net/base/request_priority.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
@@ -55,8 +56,10 @@ TEST_F(URLRequestContextBuilderTest, DefaultSettings) {
scoped_ptr<URLRequestContext> context(builder_.Build());
TestDelegate delegate;
- URLRequest request(
- test_server_.GetURL("echoheader?Foo"), &delegate, context.get());
+ URLRequest request(test_server_.GetURL("echoheader?Foo"),
+ DEFAULT_PRIORITY,
+ &delegate,
+ context.get());
request.set_method("GET");
request.SetExtraRequestHeaderByName("Foo", "Bar", false);
request.Start();
@@ -70,8 +73,10 @@ TEST_F(URLRequestContextBuilderTest, UserAgent) {
builder_.set_user_agent("Bar");
scoped_ptr<URLRequestContext> context(builder_.Build());
TestDelegate delegate;
- URLRequest request(
- test_server_.GetURL("echoheader?User-Agent"), &delegate, context.get());
+ URLRequest request(test_server_.GetURL("echoheader?User-Agent"),
+ DEFAULT_PRIORITY,
+ &delegate,
+ context.get());
request.set_method("GET");
request.Start();
base::MessageLoop::current()->Run();
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 39093701095..d98da02ae91 100644
--- a/chromium/net/url_request/url_request_file_dir_job.cc
+++ b/chromium/net/url_request/url_request_file_dir_job.cc
@@ -119,7 +119,8 @@ void URLRequestFileDirJob::OnListFile(
std::string raw_bytes; // Empty on Windows means UTF-8 encoded name.
#elif defined(OS_POSIX)
// TOOD(jungshik): The same issue as for the directory name.
- const std::string& raw_bytes = data.info.GetName().value();
+ base::FilePath filename = data.info.GetName();
+ const std::string& raw_bytes = filename.value();
#endif
data_.append(GetDirectoryListingEntry(
data.info.GetName().LossyDisplayName(),
diff --git a/chromium/net/url_request/url_request_file_job.cc b/chromium/net/url_request/url_request_file_job.cc
index 053a22ed233..723e6a030b7 100644
--- a/chromium/net/url_request/url_request_file_job.cc
+++ b/chromium/net/url_request/url_request_file_job.cc
@@ -198,7 +198,7 @@ URLRequestFileJob::~URLRequestFileJob() {
void URLRequestFileJob::FetchMetaInfo(const base::FilePath& file_path,
FileMetaInfo* meta_info) {
base::PlatformFileInfo platform_info;
- meta_info->file_exists = file_util::GetFileInfo(file_path, &platform_info);
+ meta_info->file_exists = base::GetFileInfo(file_path, &platform_info);
if (meta_info->file_exists) {
meta_info->file_size = platform_info.size;
meta_info->is_directory = platform_info.is_directory;
diff --git a/chromium/net/url_request/url_request_filter.cc b/chromium/net/url_request/url_request_filter.cc
index da0b5803ab5..19a8747ea9b 100644
--- a/chromium/net/url_request/url_request_filter.cc
+++ b/chromium/net/url_request/url_request_filter.cc
@@ -95,9 +95,8 @@ void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme,
delete iter->second;
hostname_handler_map_.erase(iter);
// Note that we don't unregister from the URLRequest ProtocolFactory as
- // this would left no protocol factory for the scheme.
- // URLRequestFilter::Factory will keep forwarding the requests to the
- // URLRequestInetJob.
+ // this would leave no protocol factory for the remaining hostname and URL
+ // handlers.
}
bool URLRequestFilter::AddUrlHandler(
@@ -135,9 +134,8 @@ void URLRequestFilter::RemoveUrlHandler(const GURL& url) {
delete iter->second;
url_handler_map_.erase(iter);
// Note that we don't unregister from the URLRequest ProtocolFactory as
- // this would left no protocol factory for the scheme.
- // URLRequestFilter::Factory will keep forwarding the requests to the
- // URLRequestInetJob.
+ // this would leave no protocol factory for the remaining hostname and URL
+ // handlers.
}
void URLRequestFilter::ClearHandlers() {
diff --git a/chromium/net/url_request/url_request_filter.h b/chromium/net/url_request/url_request_filter.h
index 2859c98c1d8..418560df5c6 100644
--- a/chromium/net/url_request/url_request_filter.h
+++ b/chromium/net/url_request/url_request_filter.h
@@ -12,9 +12,9 @@
// GURL("http://foo.com/"),
// &URLRequestCustomJob::Factory);
//
-// If URLRequestFilter::Factory can't find a handle for the request, it passes
-// it through to URLRequestInetJob::Factory and lets the default network stack
-// handle it.
+// If URLRequestFilter::Factory can't find a handler for the request, it
+// returns null to URLRequestJobManager and lets a built-in protocol factory
+// handle the request.
#ifndef NET_URL_REQUEST_URL_REQUEST_FILTER_H_
#define NET_URL_REQUEST_URL_REQUEST_FILTER_H_
diff --git a/chromium/net/url_request/url_request_filter_unittest.cc b/chromium/net/url_request/url_request_filter_unittest.cc
index 3a4146672ad..2e024a285e6 100644
--- a/chromium/net/url_request/url_request_filter_unittest.cc
+++ b/chromium/net/url_request/url_request_filter_unittest.cc
@@ -5,6 +5,7 @@
#include "net/url_request/url_request_filter.h"
#include "base/memory/scoped_ptr.h"
+#include "net/base/request_priority.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
@@ -53,10 +54,12 @@ TEST(URLRequestFilter, BasicMatching) {
TestURLRequestContext request_context;
GURL url_1("http://foo.com/");
- TestURLRequest request_1(url_1, &delegate, &request_context, NULL);
+ TestURLRequest request_1(
+ url_1, DEFAULT_PRIORITY, &delegate, &request_context);
GURL url_2("http://bar.com/");
- TestURLRequest request_2(url_2, &delegate, &request_context, NULL);
+ TestURLRequest request_2(
+ url_2, DEFAULT_PRIORITY, &delegate, &request_context);
// Check AddUrlHandler checks for invalid URLs.
EXPECT_FALSE(URLRequestFilter::GetInstance()->AddUrlHandler(GURL(),
diff --git a/chromium/net/url_request/url_request_ftp_job.cc b/chromium/net/url_request/url_request_ftp_job.cc
index eda245ca761..6224141a8ee 100644
--- a/chromium/net/url_request/url_request_ftp_job.cc
+++ b/chromium/net/url_request/url_request_ftp_job.cc
@@ -178,15 +178,14 @@ void URLRequestFtpJob::StartHttpTransaction() {
DCHECK(!http_transaction_);
// Do not cache FTP responses sent through HTTP proxy.
- request_->set_load_flags(request_->load_flags() |
- LOAD_DISABLE_CACHE |
- LOAD_DO_NOT_SAVE_COOKIES |
- LOAD_DO_NOT_SEND_COOKIES);
+ request_->SetLoadFlags(request_->load_flags() |
+ LOAD_DISABLE_CACHE |
+ LOAD_DO_NOT_SAVE_COOKIES |
+ LOAD_DO_NOT_SEND_COOKIES);
http_request_info_.url = request_->url();
http_request_info_.method = request_->method();
http_request_info_.load_flags = request_->load_flags();
- http_request_info_.request_id = request_->identifier();
int rv = request_->context()->http_transaction_factory()->CreateTransaction(
priority_, &http_transaction_, NULL);
diff --git a/chromium/net/url_request/url_request_ftp_job_unittest.cc b/chromium/net/url_request/url_request_ftp_job_unittest.cc
index f9eafab54ba..4bc6675551d 100644
--- a/chromium/net/url_request/url_request_ftp_job_unittest.cc
+++ b/chromium/net/url_request/url_request_ftp_job_unittest.cc
@@ -7,6 +7,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/run_loop.h"
+#include "net/base/request_priority.h"
#include "net/ftp/ftp_auth_cache.h"
#include "net/http/http_transaction_unittest.h"
#include "net/proxy/mock_proxy_resolver.h"
@@ -121,7 +122,10 @@ class URLRequestFtpJobPriorityTest : public testing::Test {
protected:
URLRequestFtpJobPriorityTest()
: proxy_service_(new SimpleProxyConfigService, NULL, NULL),
- req_(GURL("ftp://ftp.example.com"), &delegate_, &context_, NULL) {
+ req_(GURL("ftp://ftp.example.com"),
+ DEFAULT_PRIORITY,
+ &delegate_,
+ &context_) {
context_.set_proxy_service(&proxy_service_);
context_.set_http_transaction_factory(&network_layer_);
}
@@ -262,9 +266,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequest) {
TestDelegate request_delegate;
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
socket_data(0)->RunFor(4);
@@ -287,9 +291,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestOrphanJob) {
TestDelegate request_delegate;
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
// Now |url_request| will be deleted before its completion,
@@ -315,9 +319,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthNoCredentials) {
TestDelegate request_delegate;
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
socket_data(0)->RunFor(5);
@@ -359,9 +363,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAuthWithCredentials) {
request_delegate.set_credentials(
AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
socket_data(0)->RunFor(9);
@@ -392,9 +396,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthNoCredentials) {
TestDelegate request_delegate;
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
socket_data(0)->RunFor(5);
@@ -436,9 +440,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedServerAuthWithCredentials) {
request_delegate.set_credentials(
AuthCredentials(ASCIIToUTF16("myuser"), ASCIIToUTF16("mypass")));
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
socket_data(0)->RunFor(9);
@@ -501,10 +505,8 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestNeedProxyAndServerAuth) {
TestDelegate request_delegate;
request_delegate.set_credentials(
AuthCredentials(ASCIIToUTF16("proxyuser"), ASCIIToUTF16("proxypass")));
- URLRequest url_request(url,
- &request_delegate,
- request_context(),
- network_delegate());
+ URLRequest url_request(
+ url, DEFAULT_PRIORITY, &request_delegate, request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
socket_data(0)->RunFor(5);
@@ -537,9 +539,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotSaveCookies) {
TestDelegate request_delegate;
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
ASSERT_TRUE(url_request.is_pending());
@@ -571,9 +573,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotFollowRedirects) {
TestDelegate request_delegate;
URLRequest url_request(GURL("ftp://ftp.example.com/"),
+ DEFAULT_PRIORITY,
&request_delegate,
- request_context(),
- network_delegate());
+ request_context());
url_request.Start();
EXPECT_TRUE(url_request.is_pending());
@@ -615,9 +617,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestReuseSocket) {
TestDelegate request_delegate1;
URLRequest url_request1(GURL("ftp://ftp.example.com/first"),
+ DEFAULT_PRIORITY,
&request_delegate1,
- request_context(),
- network_delegate());
+ request_context());
url_request1.Start();
ASSERT_TRUE(url_request1.is_pending());
socket_data(0)->RunFor(4);
@@ -630,9 +632,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestReuseSocket) {
TestDelegate request_delegate2;
URLRequest url_request2(GURL("ftp://ftp.example.com/second"),
+ DEFAULT_PRIORITY,
&request_delegate2,
- request_context(),
- network_delegate());
+ request_context());
url_request2.Start();
ASSERT_TRUE(url_request2.is_pending());
socket_data(0)->RunFor(4);
@@ -676,9 +678,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotReuseSocket) {
TestDelegate request_delegate1;
URLRequest url_request1(GURL("ftp://ftp.example.com/first"),
+ DEFAULT_PRIORITY,
&request_delegate1,
- request_context(),
- network_delegate());
+ request_context());
url_request1.Start();
ASSERT_TRUE(url_request1.is_pending());
socket_data(0)->RunFor(4);
@@ -691,9 +693,9 @@ TEST_F(URLRequestFtpJobTest, FtpProxyRequestDoNotReuseSocket) {
TestDelegate request_delegate2;
URLRequest url_request2(GURL("http://ftp.example.com/second"),
+ DEFAULT_PRIORITY,
&request_delegate2,
- request_context(),
- network_delegate());
+ request_context());
url_request2.Start();
ASSERT_TRUE(url_request2.is_pending());
socket_data(1)->RunFor(4);
diff --git a/chromium/net/url_request/url_request_http_job.cc b/chromium/net/url_request/url_request_http_job.cc
index dd11a1b6ef2..cac7e38aea8 100644
--- a/chromium/net/url_request/url_request_http_job.cc
+++ b/chromium/net/url_request/url_request_http_job.cc
@@ -46,6 +46,7 @@
#include "net/url_request/url_request_redirect_job.h"
#include "net/url_request/url_request_throttler_header_adapter.h"
#include "net/url_request/url_request_throttler_manager.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
static const char kAvailDictionaryHeader[] = "Avail-Dictionary";
@@ -214,7 +215,8 @@ void URLRequestHttpJob::HttpFilterContext::RecordPacketStats(
URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
NetworkDelegate* network_delegate,
const std::string& scheme) {
- DCHECK(scheme == "http" || scheme == "https");
+ DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" ||
+ scheme == "wss");
if (!request->context()->http_transaction_factory()) {
NOTREACHED() << "requires a valid context";
@@ -324,7 +326,6 @@ void URLRequestHttpJob::Start() {
request_info_.url = request_->url();
request_info_.method = request_->method();
request_info_.load_flags = request_->load_flags();
- request_info_.request_id = request_->identifier();
// Enable privacy mode if cookie settings or flags tell us not send or
// save cookies.
bool enable_privacy_mode =
@@ -352,7 +353,7 @@ void URLRequestHttpJob::Start() {
HttpRequestHeaders::kUserAgent,
http_user_agent_settings_ ?
http_user_agent_settings_->GetUserAgent(request_->url()) :
- EmptyString());
+ std::string());
AddExtraHeaders();
AddCookieHeaderAndStart();
@@ -440,15 +441,14 @@ void URLRequestHttpJob::DestroyTransaction() {
void URLRequestHttpJob::StartTransaction() {
if (network_delegate()) {
+ OnCallToDelegate();
int rv = network_delegate()->NotifyBeforeSendHeaders(
request_, notify_before_headers_sent_callback_,
&request_info_.extra_headers);
// If an extension blocks the request, we rely on the callback to
// MaybeStartTransactionInternal().
- if (rv == ERR_IO_PENDING) {
- SetBlockedOnDelegate();
+ if (rv == ERR_IO_PENDING)
return;
- }
MaybeStartTransactionInternal(rv);
return;
}
@@ -456,8 +456,6 @@ void URLRequestHttpJob::StartTransaction() {
}
void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(int result) {
- SetUnblockedOnDelegate();
-
// Check that there are no callbacks to already canceled requests.
DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
@@ -465,6 +463,7 @@ void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(int result) {
}
void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
+ OnCallToDelegateComplete();
if (result == OK) {
StartTransactionInternal();
} else {
@@ -497,6 +496,20 @@ void URLRequestHttpJob::StartTransactionInternal() {
rv = request_->context()->http_transaction_factory()->CreateTransaction(
priority_, &transaction_, http_transaction_delegate_.get());
+
+ if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
+ // TODO(ricea): Implement WebSocket throttling semantics as defined in
+ // RFC6455 Section 4.1.
+ base::SupportsUserData::Data* data = request_->GetUserData(
+ WebSocketHandshakeStreamBase::CreateHelper::DataKey());
+ if (data) {
+ transaction_->SetWebSocketHandshakeStreamCreateHelper(
+ static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
+ } else {
+ rv = ERR_DISALLOWED_URL_SCHEME;
+ }
+ }
+
if (rv == OK) {
if (!throttling_entry_.get() ||
!throttling_entry_->ShouldRejectRequest(*request_)) {
@@ -660,6 +673,9 @@ void URLRequestHttpJob::DoStartTransaction() {
}
void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
+ // End of the call started in OnStartCompleted.
+ OnCallToDelegateComplete();
+
if (result != net::OK) {
std::string source("delegate");
request_->net_log().AddEvent(NetLog::TYPE_CANCELLED,
@@ -868,6 +884,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
// Note that |this| may not be deleted until
// |on_headers_received_callback_| or
// |NetworkDelegate::URLRequestDestroyed()| has been called.
+ OnCallToDelegate();
int error = network_delegate()->NotifyHeadersReceived(
request_,
on_headers_received_callback_,
@@ -876,12 +893,12 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
if (error != net::OK) {
if (error == net::ERR_IO_PENDING) {
awaiting_callback_ = true;
- SetBlockedOnDelegate();
} else {
std::string source("delegate");
request_->net_log().AddEvent(NetLog::TYPE_CANCELLED,
NetLog::StringCallback("source",
&source));
+ OnCallToDelegateComplete();
NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
}
return;
@@ -890,18 +907,27 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
SaveCookiesAndNotifyHeadersComplete(net::OK);
} else if (IsCertificateError(result)) {
- // We encountered an SSL certificate error. Ask our delegate to decide
- // what we should do.
-
- TransportSecurityState::DomainState domain_state;
- const URLRequestContext* context = request_->context();
- const bool fatal = context->transport_security_state() &&
- context->transport_security_state()->GetDomainState(
- request_info_.url.host(),
- SSLConfigService::IsSNIAvailable(context->ssl_config_service()),
- &domain_state) &&
- domain_state.ShouldSSLErrorsBeFatal();
- NotifySSLCertificateError(transaction_->GetResponseInfo()->ssl_info, fatal);
+ // We encountered an SSL certificate error.
+ if (result == ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY ||
+ result == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN) {
+ // These are hard failures. They're handled separately and don't have
+ // the correct cert status, so set it here.
+ SSLInfo info(transaction_->GetResponseInfo()->ssl_info);
+ info.cert_status = MapNetErrorToCertStatus(result);
+ NotifySSLCertificateError(info, true);
+ } else {
+ // Maybe overridable, maybe not. Ask the delegate to decide.
+ TransportSecurityState::DomainState domain_state;
+ const URLRequestContext* context = request_->context();
+ const bool fatal = context->transport_security_state() &&
+ context->transport_security_state()->GetDomainState(
+ request_info_.url.host(),
+ SSLConfigService::IsSNIAvailable(context->ssl_config_service()),
+ &domain_state) &&
+ domain_state.ShouldSSLErrorsBeFatal();
+ NotifySSLCertificateError(
+ transaction_->GetResponseInfo()->ssl_info, fatal);
+ }
} else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
NotifyCertificateRequested(
transaction_->GetResponseInfo()->cert_request_info.get());
@@ -911,7 +937,6 @@ void URLRequestHttpJob::OnStartCompleted(int result) {
}
void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
- SetUnblockedOnDelegate();
awaiting_callback_ = false;
// Check that there are no callbacks to already canceled requests.
@@ -1480,6 +1505,10 @@ void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
}
}
+ if (request_info_.load_flags & LOAD_PREFETCH && !request_->was_cached())
+ UMA_HISTOGRAM_COUNTS("Net.Prefetch.PrefilterBytesReadFromNetwork",
+ prefilter_bytes_read());
+
start_time_ = base::TimeTicks();
}
diff --git a/chromium/net/url_request/url_request_http_job_unittest.cc b/chromium/net/url_request/url_request_http_job_unittest.cc
index ce7205407cf..9637917b9de 100644
--- a/chromium/net/url_request/url_request_http_job_unittest.cc
+++ b/chromium/net/url_request/url_request_http_job_unittest.cc
@@ -8,11 +8,16 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
#include "net/base/auth.h"
+#include "net/base/request_priority.h"
#include "net/http/http_transaction_factory.h"
#include "net/http/http_transaction_unittest.h"
+#include "net/socket/socket_test_util.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"
@@ -20,12 +25,14 @@ namespace net {
namespace {
+using ::testing::Return;
+
// Inherit from URLRequestHttpJob to expose the priority and some
// other hidden functions.
class TestURLRequestHttpJob : public URLRequestHttpJob {
public:
explicit TestURLRequestHttpJob(URLRequest* request)
- : URLRequestHttpJob(request, NULL,
+ : URLRequestHttpJob(request, request->context()->network_delegate(),
request->context()->http_user_agent_settings()) {}
using URLRequestHttpJob::SetPriority;
@@ -40,7 +47,10 @@ class TestURLRequestHttpJob : public URLRequestHttpJob {
class URLRequestHttpJobTest : public ::testing::Test {
protected:
URLRequestHttpJobTest()
- : req_(GURL("http://www.example.com"), &delegate_, &context_, NULL) {
+ : req_(GURL("http://www.example.com"),
+ DEFAULT_PRIORITY,
+ &delegate_,
+ &context_) {
context_.set_http_transaction_factory(&network_layer_);
}
@@ -115,6 +125,169 @@ TEST_F(URLRequestHttpJobTest, SetSubsequentTransactionPriority) {
EXPECT_EQ(LOW, network_layer_.last_transaction()->priority());
}
+// This base class just serves to set up some things before the TestURLRequest
+// constructor is called.
+class URLRequestHttpJobWebSocketTestBase : public ::testing::Test {
+ protected:
+ URLRequestHttpJobWebSocketTestBase() : socket_data_(NULL, 0, NULL, 0),
+ context_(true) {
+ // A Network Delegate is required for the WebSocketHandshakeStreamBase
+ // object to be passed on to the HttpNetworkTransaction.
+ context_.set_network_delegate(&network_delegate_);
+
+ // Attempting to create real ClientSocketHandles is not going to work out so
+ // well. Set up a fake socket factory.
+ socket_factory_.AddSocketDataProvider(&socket_data_);
+ context_.set_client_socket_factory(&socket_factory_);
+ context_.Init();
+ }
+
+ StaticSocketDataProvider socket_data_;
+ TestNetworkDelegate network_delegate_;
+ MockClientSocketFactory socket_factory_;
+ TestURLRequestContext context_;
+};
+
+class URLRequestHttpJobWebSocketTest
+ : public URLRequestHttpJobWebSocketTestBase {
+ protected:
+ URLRequestHttpJobWebSocketTest()
+ : req_(GURL("ws://www.example.com"),
+ DEFAULT_PRIORITY,
+ &delegate_,
+ &context_) {
+ // The TestNetworkDelegate expects a call to NotifyBeforeURLRequest before
+ // anything else happens.
+ GURL url("ws://localhost/");
+ TestCompletionCallback dummy;
+ network_delegate_.NotifyBeforeURLRequest(&req_, dummy.callback(), &url);
+ }
+
+ TestDelegate delegate_;
+ TestURLRequest req_;
+};
+
+class MockCreateHelper : public WebSocketHandshakeStreamBase::CreateHelper {
+ public:
+ // GoogleMock does not appear to play nicely with move-only types like
+ // scoped_ptr, so this forwarding method acts as a workaround.
+ virtual WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) OVERRIDE {
+ // Discard the arguments since we don't need them anyway.
+ return CreateBasicStreamMock();
+ }
+
+ MOCK_METHOD0(CreateBasicStreamMock,
+ WebSocketHandshakeStreamBase*());
+
+ MOCK_METHOD2(CreateSpdyStream,
+ WebSocketHandshakeStreamBase*(const base::WeakPtr<SpdySession>&,
+ bool));
+};
+
+class FakeWebSocketHandshakeStream : public WebSocketHandshakeStreamBase {
+ public:
+ FakeWebSocketHandshakeStream() : initialize_stream_was_called_(false) {}
+
+ bool initialize_stream_was_called() const {
+ return initialize_stream_was_called_;
+ }
+
+ // Fake implementation of HttpStreamBase methods.
+ virtual int InitializeStream(const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback) OVERRIDE {
+ initialize_stream_was_called_ = true;
+ return ERR_IO_PENDING;
+ }
+
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
+ HttpResponseInfo* response,
+ const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+
+ virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+
+ virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE {
+ return NULL;
+ }
+
+ virtual int ReadResponseBody(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) OVERRIDE {
+ return ERR_IO_PENDING;
+ }
+
+ virtual void Close(bool not_reusable) OVERRIDE {}
+
+ virtual bool IsResponseBodyComplete() const OVERRIDE { return false; }
+
+ virtual bool CanFindEndOfResponse() const OVERRIDE { return false; }
+
+ virtual bool IsConnectionReused() const OVERRIDE { return false; }
+ virtual void SetConnectionReused() OVERRIDE {}
+
+ virtual bool IsConnectionReusable() const OVERRIDE { return false; }
+
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE { return 0; }
+
+ virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const
+ OVERRIDE {
+ return false;
+ }
+
+ virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE {}
+
+ virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info)
+ OVERRIDE {}
+
+ virtual bool IsSpdyHttpStream() const OVERRIDE { return false; }
+
+ virtual void Drain(HttpNetworkSession* session) OVERRIDE {}
+
+ virtual void SetPriority(RequestPriority priority) OVERRIDE {}
+
+ // Fake implementation of WebSocketHandshakeStreamBase method(s)
+ virtual scoped_ptr<WebSocketStream> Upgrade() OVERRIDE {
+ return scoped_ptr<WebSocketStream>();
+ }
+
+ private:
+ bool initialize_stream_was_called_;
+};
+
+TEST_F(URLRequestHttpJobWebSocketTest, RejectedWithoutCreateHelper) {
+ scoped_refptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(&req_));
+ job->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_refptr<TestURLRequestHttpJob> job(new TestURLRequestHttpJob(&req_));
+ scoped_ptr<MockCreateHelper> create_helper(
+ new ::testing::StrictMock<MockCreateHelper>());
+ FakeWebSocketHandshakeStream* fake_handshake_stream(
+ new FakeWebSocketHandshakeStream);
+ // Ownership of fake_handshake_stream is transferred when CreateBasicStream()
+ // is called.
+ EXPECT_CALL(*create_helper, CreateBasicStreamMock())
+ .WillOnce(Return(fake_handshake_stream));
+ req_.SetUserData(WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
+ create_helper.release());
+ req_.SetLoadFlags(LOAD_DISABLE_CACHE);
+ job->Start();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(URLRequestStatus::IO_PENDING, req_.status().status());
+ EXPECT_TRUE(fake_handshake_stream->initialize_stream_was_called());
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/url_request/url_request_job.cc b/chromium/net/url_request/url_request_job.cc
index bf4aafcb8c6..1d6f0b49d19 100644
--- a/chromium/net/url_request/url_request_job.cc
+++ b/chromium/net/url_request/url_request_job.cc
@@ -204,8 +204,6 @@ void URLRequestJob::FollowDeferredRedirect() {
// It is also possible that FollowRedirect will drop the last reference to
// this job, so we need to reset our members before calling it.
- SetUnblockedOnDelegate();
-
GURL redirect_url = deferred_redirect_url_;
int redirect_status_code = deferred_redirect_status_code_;
@@ -336,7 +334,6 @@ void URLRequestJob::NotifyHeadersComplete() {
if (defer_redirect) {
deferred_redirect_url_ = new_location;
deferred_redirect_status_code_ = http_status_code;
- SetBlockedOnDelegate();
} else {
FollowRedirect(new_location, http_status_code);
}
@@ -488,12 +485,12 @@ void URLRequestJob::NotifyRestartRequired() {
request_->Restart();
}
-void URLRequestJob::SetBlockedOnDelegate() {
- request_->SetBlockedOnDelegate();
+void URLRequestJob::OnCallToDelegate() {
+ request_->OnCallToDelegate();
}
-void URLRequestJob::SetUnblockedOnDelegate() {
- request_->SetUnblockedOnDelegate();
+void URLRequestJob::OnCallToDelegateComplete() {
+ request_->OnCallToDelegateComplete();
}
bool URLRequestJob::ReadRawData(IOBuffer* buf, int buf_size,
diff --git a/chromium/net/url_request/url_request_job.h b/chromium/net/url_request/url_request_job.h
index 1acf4750d11..9695f6a7aa9 100644
--- a/chromium/net/url_request/url_request_job.h
+++ b/chromium/net/url_request/url_request_job.h
@@ -260,10 +260,9 @@ class NET_EXPORT URLRequestJob
// Should only be called if the job has not started a resposne.
void NotifyRestartRequired();
- // Called when the network delegate blocks or unblocks this request when
- // intercepting certain requests.
- void SetBlockedOnDelegate();
- void SetUnblockedOnDelegate();
+ // See corresponding functions in url_request.h.
+ void OnCallToDelegate();
+ void OnCallToDelegateComplete();
// Called to read raw (pre-filtered) data from this Job.
// If returning true, data was read from the job. buf will contain
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 078e16a8df0..93ca0f83f37 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
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
+#include "net/base/request_priority.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_test_util.h"
@@ -59,7 +60,8 @@ class DummyProtocolHandler : public URLRequestJobFactory::ProtocolHandler {
TEST(URLRequestJobFactoryTest, NoProtocolHandler) {
TestDelegate delegate;
TestURLRequestContext request_context;
- TestURLRequest request(GURL("foo://bar"), &delegate, &request_context, NULL);
+ TestURLRequest request(
+ GURL("foo://bar"), DEFAULT_PRIORITY, &delegate, &request_context);
request.Start();
base::MessageLoop::current()->Run();
@@ -73,7 +75,8 @@ TEST(URLRequestJobFactoryTest, BasicProtocolHandler) {
TestURLRequestContext request_context;
request_context.set_job_factory(&job_factory);
job_factory.SetProtocolHandler("foo", new DummyProtocolHandler);
- TestURLRequest request(GURL("foo://bar"), &delegate, &request_context, NULL);
+ TestURLRequest request(
+ GURL("foo://bar"), DEFAULT_PRIORITY, &delegate, &request_context);
request.Start();
base::MessageLoop::current()->Run();
diff --git a/chromium/net/url_request/url_request_job_manager.cc b/chromium/net/url_request/url_request_job_manager.cc
index a089c6b4f5c..9ccf1d4e352 100644
--- a/chromium/net/url_request/url_request_job_manager.cc
+++ b/chromium/net/url_request/url_request_job_manager.cc
@@ -32,6 +32,12 @@ struct SchemeToFactory {
static const SchemeToFactory kBuiltinFactories[] = {
{ "http", URLRequestHttpJob::Factory },
{ "https", URLRequestHttpJob::Factory },
+
+#if !defined(OS_IOS)
+ { "ws", URLRequestHttpJob::Factory },
+ { "wss", URLRequestHttpJob::Factory },
+#endif // !defined(OS_IOS)
+
};
// static
diff --git a/chromium/net/url_request/url_request_job_unittest.cc b/chromium/net/url_request/url_request_job_unittest.cc
index 5f63b0927de..99f43141d98 100644
--- a/chromium/net/url_request/url_request_job_unittest.cc
+++ b/chromium/net/url_request/url_request_job_unittest.cc
@@ -4,66 +4,71 @@
#include "net/url_request/url_request_job.h"
+#include "net/base/request_priority.h"
#include "net/http/http_transaction_unittest.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace net {
+
namespace {
// This is a header that signals the end of the data.
const char kGzipGata[] = "\x1f\x08b\x08\0\0\0\0\0\0\3\3\0\0\0\0\0\0\0\0";
-void GZipServer(const net::HttpRequestInfo* request,
- std::string* response_status, std::string* response_headers,
+void GZipServer(const HttpRequestInfo* request,
+ std::string* response_status,
+ std::string* response_headers,
std::string* response_data) {
response_data->assign(kGzipGata, sizeof(kGzipGata));
}
const MockTransaction kGZip_Transaction = {
- "http://www.google.com/gzyp",
- "GET",
- base::Time(),
- "",
- net::LOAD_NORMAL,
- "HTTP/1.1 200 OK",
- "Cache-Control: max-age=10000\n"
- "Content-Encoding: gzip\n"
- "Content-Length: 30\n", // Intentionally wrong.
- base::Time(),
- "",
- TEST_MODE_NORMAL,
- &GZipServer,
- 0,
- net::OK
+ "http://www.google.com/gzyp",
+ "GET",
+ base::Time(),
+ "",
+ LOAD_NORMAL,
+ "HTTP/1.1 200 OK",
+ "Cache-Control: max-age=10000\n"
+ "Content-Encoding: gzip\n"
+ "Content-Length: 30\n", // Intentionally wrong.
+ base::Time(),
+ "",
+ TEST_MODE_NORMAL,
+ &GZipServer,
+ 0,
+ OK
};
const MockTransaction kRedirect_Transaction = {
- "http://www.google.com/redirect",
- "GET",
- base::Time(),
- "",
- net::LOAD_NORMAL,
- "HTTP/1.1 302 Found",
- "Cache-Control: max-age=10000\n"
- "Location: http://www.google.com/destination\n"
- "Content-Length: 5\n",
- base::Time(),
- "hello",
- TEST_MODE_NORMAL,
- NULL,
- 0,
- net::OK
+ "http://www.google.com/redirect",
+ "GET",
+ base::Time(),
+ "",
+ LOAD_NORMAL,
+ "HTTP/1.1 302 Found",
+ "Cache-Control: max-age=10000\n"
+ "Location: http://www.google.com/destination\n"
+ "Content-Length: 5\n",
+ base::Time(),
+ "hello",
+ TEST_MODE_NORMAL,
+ NULL,
+ 0,
+ OK
};
} // namespace
TEST(URLRequestJob, TransactionNotifiedWhenDone) {
MockNetworkLayer network_layer;
- net::TestURLRequestContext context;
+ TestURLRequestContext context;
context.set_http_transaction_factory(&network_layer);
- net::TestDelegate d;
- net::TestURLRequest req(GURL(kGZip_Transaction.url), &d, &context, NULL);
+ TestDelegate d;
+ TestURLRequest req(
+ GURL(kGZip_Transaction.url), DEFAULT_PRIORITY, &d, &context);
AddMockTransaction(&kGZip_Transaction);
req.set_method("GET");
@@ -78,11 +83,12 @@ TEST(URLRequestJob, TransactionNotifiedWhenDone) {
TEST(URLRequestJob, SyncTransactionNotifiedWhenDone) {
MockNetworkLayer network_layer;
- net::TestURLRequestContext context;
+ TestURLRequestContext context;
context.set_http_transaction_factory(&network_layer);
- net::TestDelegate d;
- net::TestURLRequest req(GURL(kGZip_Transaction.url), &d, &context, NULL);
+ TestDelegate d;
+ TestURLRequest req(
+ GURL(kGZip_Transaction.url), DEFAULT_PRIORITY, &d, &context);
MockTransaction transaction(kGZip_Transaction);
transaction.test_mode = TEST_MODE_SYNC_ALL;
AddMockTransaction(&transaction);
@@ -99,11 +105,12 @@ TEST(URLRequestJob, SyncTransactionNotifiedWhenDone) {
TEST(URLRequestJob, RedirectTransactionNotifiedWhenDone) {
MockNetworkLayer network_layer;
- net::TestURLRequestContext context;
+ TestURLRequestContext context;
context.set_http_transaction_factory(&network_layer);
- net::TestDelegate d;
- net::TestURLRequest req(GURL(kRedirect_Transaction.url), &d, &context, NULL);
+ TestDelegate d;
+ TestURLRequest req(
+ GURL(kRedirect_Transaction.url), DEFAULT_PRIORITY, &d, &context);
AddMockTransaction(&kRedirect_Transaction);
req.set_method("GET");
@@ -115,3 +122,5 @@ TEST(URLRequestJob, RedirectTransactionNotifiedWhenDone) {
RemoveMockTransaction(&kRedirect_Transaction);
}
+
+} // namespace net
diff --git a/chromium/net/url_request/url_request_netlog_params.cc b/chromium/net/url_request/url_request_netlog_params.cc
index 12c0d5d3d65..a1e8243b73e 100644
--- a/chromium/net/url_request/url_request_netlog_params.cc
+++ b/chromium/net/url_request/url_request_netlog_params.cc
@@ -20,7 +20,7 @@ base::Value* NetLogURLRequestStartCallback(const GURL* url,
dict->SetString("url", url->possibly_invalid_spec());
dict->SetString("method", *method);
dict->SetInteger("load_flags", load_flags);
- dict->SetInteger("priority", static_cast<int>(priority));
+ dict->SetString("priority", RequestPriorityToString(priority));
if (upload_id > -1)
dict->SetString("upload_id", base::Int64ToString(upload_id));
return dict;
diff --git a/chromium/net/url_request/url_request_test_job.cc b/chromium/net/url_request/url_request_test_job.cc
index e0a32b38db6..31a07feaa88 100644
--- a/chromium/net/url_request/url_request_test_job.cc
+++ b/chromium/net/url_request/url_request_test_job.cc
@@ -36,9 +36,15 @@ GURL URLRequestTestJob::test_url_2() {
GURL URLRequestTestJob::test_url_3() {
return GURL("test:url3");
}
+GURL URLRequestTestJob::test_url_4() {
+ return GURL("test:url4");
+}
GURL URLRequestTestJob::test_url_error() {
return GURL("test:error");
}
+GURL URLRequestTestJob::test_url_redirect_to_url_2() {
+ return GURL("test:redirect_to_2");
+}
// static getters for known URL responses
std::string URLRequestTestJob::test_data_1() {
@@ -50,6 +56,9 @@ std::string URLRequestTestJob::test_data_2() {
std::string URLRequestTestJob::test_data_3() {
return std::string("<html><title>Test Three Three Three</title></html>");
}
+std::string URLRequestTestJob::test_data_4() {
+ return std::string("<html><title>Test Four Four Four Four</title></html>");
+}
// static getter for simple response headers
std::string URLRequestTestJob::test_headers() {
@@ -69,6 +78,17 @@ std::string URLRequestTestJob::test_redirect_headers() {
return std::string(kHeaders, arraysize(kHeaders));
}
+// static getter for redirect response headers
+std::string URLRequestTestJob::test_redirect_to_url_2_headers() {
+ std::string headers = "HTTP/1.1 302 MOVED";
+ headers.push_back('\0');
+ headers += "Location: ";
+ headers += test_url_2().spec();
+ headers.push_back('\0');
+ headers.push_back('\0');
+ return headers;
+}
+
// static getter for error response headers
std::string URLRequestTestJob::test_error_headers() {
static const char kHeaders[] =
@@ -162,6 +182,11 @@ void URLRequestTestJob::StartAsync() {
response_data_ = test_data_2();
} else if (request_->url().spec() == test_url_3().spec()) {
response_data_ = test_data_3();
+ } else if (request_->url().spec() == test_url_4().spec()) {
+ response_data_ = test_data_4();
+ } else if (request_->url().spec() == test_url_redirect_to_url_2().spec()) {
+ response_headers_ =
+ new HttpResponseHeaders(test_redirect_to_url_2_headers());
} else {
AdvanceJob();
diff --git a/chromium/net/url_request/url_request_test_job.h b/chromium/net/url_request/url_request_test_job.h
index d7f33d70400..717cc0f2d88 100644
--- a/chromium/net/url_request/url_request_test_job.h
+++ b/chromium/net/url_request/url_request_test_job.h
@@ -18,7 +18,7 @@ namespace net {
// probably want to inherit from it to set up the state you want. Then install
// it as the protocol handler for the "test" scheme.
//
-// It will respond to three URLs, which you can retrieve using the test_url*
+// It will respond to several URLs, which you can retrieve using the test_url*
// getters, which will in turn respond with the corresponding responses returned
// by test_data*. Any other URLs that begin with "test:" will return an error,
// which might also be useful, you can use test_url_error() to retreive a
@@ -57,18 +57,21 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
const std::string& response_data,
bool auto_advance);
- // The three canned URLs this handler will respond to without having been
+ // The canned URLs this handler will respond to without having been
// explicitly initialized with response headers and data.
// FIXME(brettw): we should probably also have a redirect one
static GURL test_url_1();
static GURL test_url_2();
static GURL test_url_3();
+ static GURL test_url_4();
static GURL test_url_error();
+ static GURL test_url_redirect_to_url_2();
// The data that corresponds to each of the URLs above
static std::string test_data_1();
static std::string test_data_2();
static std::string test_data_3();
+ static std::string test_data_4();
// The headers that correspond to each of the URLs above
static std::string test_headers();
@@ -76,6 +79,9 @@ class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
// The headers for a redirect response
static std::string test_redirect_headers();
+ // The headers for a redirect response to the second test url.
+ static std::string test_redirect_to_url_2_headers();
+
// The headers for a server error response
static std::string test_error_headers();
diff --git a/chromium/net/url_request/url_request_test_util.cc b/chromium/net/url_request/url_request_test_util.cc
index 8b209f9c6dc..ea3c7ae6074 100644
--- a/chromium/net/url_request/url_request_test_util.cc
+++ b/chromium/net/url_request/url_request_test_util.cc
@@ -120,18 +120,17 @@ void TestURLRequestContext::Init() {
}
if (!http_user_agent_settings()) {
context_storage_.set_http_user_agent_settings(
- new StaticHttpUserAgentSettings("en-us,fr", EmptyString()));
+ new StaticHttpUserAgentSettings("en-us,fr", std::string()));
}
if (!job_factory())
context_storage_.set_job_factory(new URLRequestJobFactoryImpl);
}
TestURLRequest::TestURLRequest(const GURL& url,
+ RequestPriority priority,
Delegate* delegate,
- TestURLRequestContext* context,
- NetworkDelegate* network_delegate)
- : URLRequest(url, delegate, context, network_delegate) {
-}
+ TestURLRequestContext* context)
+ : URLRequest(url, priority, delegate, context) {}
TestURLRequest::~TestURLRequest() {
}
@@ -306,12 +305,15 @@ TestNetworkDelegate::TestNetworkDelegate()
created_requests_(0),
destroyed_requests_(0),
completed_requests_(0),
+ canceled_requests_(0),
cookie_options_bit_mask_(0),
blocked_get_cookies_count_(0),
blocked_set_cookie_count_(0),
set_cookie_count_(0),
has_load_timing_info_before_redirect_(false),
- has_load_timing_info_before_auth_(false) {
+ has_load_timing_info_before_auth_(false),
+ can_access_files_(true),
+ can_throttle_requests_(true) {
}
TestNetworkDelegate::~TestNetworkDelegate() {
@@ -336,7 +338,11 @@ bool TestNetworkDelegate::GetLoadTimingInfoBeforeAuth(
void TestNetworkDelegate::InitRequestStatesIfNew(int request_id) {
if (next_states_.find(request_id) == next_states_.end()) {
- next_states_[request_id] = kStageBeforeURLRequest;
+ // TODO(davidben): Although the URLRequest documentation does not allow
+ // calling Cancel() before Start(), the ResourceLoader does so. URLRequest's
+ // destructor also calls Cancel. Either officially support this or fix the
+ // ResourceLoader code.
+ next_states_[request_id] = kStageBeforeURLRequest | kStageCompletedError;
event_order_[request_id] = "";
}
}
@@ -476,6 +482,10 @@ void TestNetworkDelegate::OnCompleted(URLRequest* request, bool started) {
if (request->status().status() == URLRequestStatus::FAILED) {
error_count_++;
last_error_ = request->status().error();
+ } else if (request->status().status() == URLRequestStatus::CANCELED) {
+ canceled_requests_++;
+ } else {
+ DCHECK_EQ(URLRequestStatus::SUCCESS, request->status().status());
}
}
@@ -550,12 +560,12 @@ bool TestNetworkDelegate::OnCanSetCookie(const URLRequest& request,
bool TestNetworkDelegate::OnCanAccessFile(const URLRequest& request,
const base::FilePath& path) const {
- return true;
+ return can_access_files_;
}
bool TestNetworkDelegate::OnCanThrottleRequest(
const URLRequest& request) const {
- return true;
+ return can_throttle_requests_;
}
int TestNetworkDelegate::OnBeforeSocketStreamConnect(
diff --git a/chromium/net/url_request/url_request_test_util.h b/chromium/net/url_request/url_request_test_util.h
index 796b9131387..0369baa2ebc 100644
--- a/chromium/net/url_request/url_request_test_util.h
+++ b/chromium/net/url_request/url_request_test_util.h
@@ -23,6 +23,7 @@
#include "net/base/load_timing_info.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate.h"
+#include "net/base/request_priority.h"
#include "net/cert/cert_verifier.h"
#include "net/cookies/cookie_monster.h"
#include "net/disk_cache/disk_cache.h"
@@ -107,9 +108,10 @@ class TestURLRequestContextGetter : public URLRequestContextGetter {
class TestURLRequest : public URLRequest {
public:
- TestURLRequest(
- const GURL& url, Delegate* delegate,
- TestURLRequestContext* context, NetworkDelegate* network_delegate);
+ TestURLRequest(const GURL& url,
+ RequestPriority priority,
+ Delegate* delegate,
+ TestURLRequestContext* context);
virtual ~TestURLRequest();
};
@@ -230,10 +232,17 @@ class TestNetworkDelegate : public NetworkDelegate {
int created_requests() const { return created_requests_; }
int destroyed_requests() const { return destroyed_requests_; }
int completed_requests() const { return completed_requests_; }
+ int canceled_requests() const { return canceled_requests_; }
int blocked_get_cookies_count() const { return blocked_get_cookies_count_; }
int blocked_set_cookie_count() const { return blocked_set_cookie_count_; }
int set_cookie_count() const { return set_cookie_count_; }
+ void set_can_access_files(bool val) { can_access_files_ = val; }
+ bool can_access_files() const { return can_access_files_; }
+
+ void set_can_throttle_requests(bool val) { can_throttle_requests_ = val; }
+ bool can_throttle_requests() const { return can_throttle_requests_; }
+
protected:
// NetworkDelegate:
virtual int OnBeforeURLRequest(URLRequest* request,
@@ -285,6 +294,7 @@ class TestNetworkDelegate : public NetworkDelegate {
int created_requests_;
int destroyed_requests_;
int completed_requests_;
+ int canceled_requests_;
int cookie_options_bit_mask_;
int blocked_get_cookies_count_;
int blocked_set_cookie_count_;
@@ -305,6 +315,9 @@ class TestNetworkDelegate : public NetworkDelegate {
LoadTimingInfo load_timing_info_before_auth_;
bool has_load_timing_info_before_auth_;
+
+ bool can_access_files_; // true by default
+ bool can_throttle_requests_; // true by default
};
// Overrides the host used by the LocalHttpTestServer in
diff --git a/chromium/net/url_request/url_request_throttler_simulation_unittest.cc b/chromium/net/url_request/url_request_throttler_simulation_unittest.cc
index 059c80fd647..c68f59a4139 100644
--- a/chromium/net/url_request/url_request_throttler_simulation_unittest.cc
+++ b/chromium/net/url_request/url_request_throttler_simulation_unittest.cc
@@ -20,6 +20,7 @@
#include "base/memory/scoped_vector.h"
#include "base/rand_util.h"
#include "base/time/time.h"
+#include "net/base/request_priority.h"
#include "net/url_request/url_request_test_util.h"
#include "net/url_request/url_request_throttler_manager.h"
#include "net/url_request/url_request_throttler_test_support.h"
@@ -116,16 +117,14 @@ class DiscreteTimeSimulation {
// after all |Requester| objects.
class Server : public DiscreteTimeSimulation::Actor {
public:
- Server(int max_queries_per_tick,
- double request_drop_ratio)
+ Server(int max_queries_per_tick, double request_drop_ratio)
: max_queries_per_tick_(max_queries_per_tick),
request_drop_ratio_(request_drop_ratio),
num_overloaded_ticks_remaining_(0),
num_current_tick_queries_(0),
num_overloaded_ticks_(0),
max_experienced_queries_per_tick_(0),
- mock_request_(GURL(), NULL, &context_, NULL) {
- }
+ mock_request_(GURL(), DEFAULT_PRIORITY, NULL, &context_) {}
void SetDowntime(const TimeTicks& start_time, const TimeDelta& duration) {
start_downtime_ = start_time;
diff --git a/chromium/net/url_request/url_request_throttler_unittest.cc b/chromium/net/url_request/url_request_throttler_unittest.cc
index e47da30ef9a..b964b108551 100644
--- a/chromium/net/url_request/url_request_throttler_unittest.cc
+++ b/chromium/net/url_request/url_request_throttler_unittest.cc
@@ -14,6 +14,7 @@
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "net/base/load_flags.h"
+#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_test_util.h"
@@ -172,8 +173,8 @@ struct GurlAndString {
class URLRequestThrottlerEntryTest : public testing::Test {
protected:
- URLRequestThrottlerEntryTest() : request_(GURL(), NULL, &context_, NULL) {
- }
+ URLRequestThrottlerEntryTest()
+ : request_(GURL(), DEFAULT_PRIORITY, NULL, &context_) {}
virtual void SetUp();
virtual void TearDown();
@@ -202,7 +203,7 @@ const char* kHistogramNames[] = {
};
void URLRequestThrottlerEntryTest::SetUp() {
- request_.set_load_flags(0);
+ request_.SetLoadFlags(0);
now_ = TimeTicks::Now();
entry_ = new MockURLRequestThrottlerEntry(&manager_);
@@ -251,13 +252,25 @@ std::ostream& operator<<(std::ostream& out, const base::TimeTicks& time) {
return out << time.ToInternalValue();
}
+TEST_F(URLRequestThrottlerEntryTest, CanThrottleRequest) {
+ TestNetworkDelegate d;
+ context_.set_network_delegate(&d);
+ entry_->set_exponential_backoff_release_time(
+ entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1));
+
+ d.set_can_throttle_requests(false);
+ EXPECT_FALSE(entry_->ShouldRejectRequest(request_));
+ d.set_can_throttle_requests(true);
+ EXPECT_TRUE(entry_->ShouldRejectRequest(request_));
+}
+
TEST_F(URLRequestThrottlerEntryTest, InterfaceDuringExponentialBackoff) {
entry_->set_exponential_backoff_release_time(
entry_->fake_time_now_ + TimeDelta::FromMilliseconds(1));
EXPECT_TRUE(entry_->ShouldRejectRequest(request_));
// Also end-to-end test the load flags exceptions.
- request_.set_load_flags(LOAD_MAYBE_USER_GESTURE);
+ request_.SetLoadFlags(LOAD_MAYBE_USER_GESTURE);
EXPECT_FALSE(entry_->ShouldRejectRequest(request_));
CalculateHistogramDeltas();
@@ -391,11 +404,10 @@ TEST_F(URLRequestThrottlerEntryTest, ExplicitUserRequest) {
class URLRequestThrottlerManagerTest : public testing::Test {
protected:
URLRequestThrottlerManagerTest()
- : request_(GURL(), NULL, &context_, NULL) {
- }
+ : request_(GURL(), DEFAULT_PRIORITY, NULL, &context_) {}
virtual void SetUp() {
- request_.set_load_flags(0);
+ request_.SetLoadFlags(0);
}
// context_ must be declared before request_.
diff --git a/chromium/net/url_request/url_request_unittest.cc b/chromium/net/url_request/url_request_unittest.cc
index d18de134416..fbc90d237f1 100644
--- a/chromium/net/url_request/url_request_unittest.cc
+++ b/chromium/net/url_request/url_request_unittest.cc
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
@@ -37,17 +38,20 @@
#include "net/base/net_log_unittest.h"
#include "net/base/net_module.h"
#include "net/base/net_util.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/cert/ev_root_ca_metadata.h"
+#include "net/cert/mock_cert_verifier.h"
#include "net/cert/test_root_certs.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store_test_helpers.h"
#include "net/disk_cache/disk_cache.h"
#include "net/dns/mock_host_resolver.h"
#include "net/ftp/ftp_network_layer.h"
+#include "net/http/http_byte_range.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
@@ -159,6 +163,26 @@ void TestLoadTimingReusedWithProxy(
// Tests load timing information in the case of a cache hit, when no cache
// validation request was sent over the wire.
+base::StringPiece TestNetResourceProvider(int key) {
+ return "header";
+}
+
+void FillBuffer(char* buffer, size_t len) {
+ static bool called = false;
+ if (!called) {
+ called = true;
+ int seed = static_cast<int>(Time::Now().ToInternalValue());
+ srand(seed);
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ buffer[i] = static_cast<char>(rand());
+ if (!buffer[i])
+ buffer[i] = 'g';
+ }
+}
+
+#if !defined(OS_IOS)
void TestLoadTimingCacheHitNoNetwork(
const net::LoadTimingInfo& load_timing_info) {
EXPECT_FALSE(load_timing_info.socket_reused);
@@ -196,10 +220,6 @@ void TestLoadTimingNoHttpResponse(
EXPECT_TRUE(load_timing_info.receive_headers_end.is_null());
}
-base::StringPiece TestNetResourceProvider(int key) {
- return "header";
-}
-
// Do a case-insensitive search through |haystack| for |needle|.
bool ContainsString(const std::string& haystack, const char* needle) {
std::string::const_iterator it =
@@ -211,21 +231,6 @@ bool ContainsString(const std::string& haystack, const char* needle) {
return it != haystack.end();
}
-void FillBuffer(char* buffer, size_t len) {
- static bool called = false;
- if (!called) {
- called = true;
- int seed = static_cast<int>(Time::Now().ToInternalValue());
- srand(seed);
- }
-
- for (size_t i = 0; i < len; i++) {
- buffer[i] = static_cast<char>(rand());
- if (!buffer[i])
- buffer[i] = 'g';
- }
-}
-
UploadDataStream* CreateSimpleUploadData(const char* data) {
scoped_ptr<UploadElementReader> reader(
new UploadBytesElementReader(data, strlen(data)));
@@ -275,6 +280,7 @@ bool FingerprintsEqual(const HashValueVector& a, const HashValueVector& b) {
return true;
}
+#endif // !defined(OS_IOS)
// A network delegate that allows the user to choose a subset of request stages
// to block in. When blocking, the delegate can do one of the following:
@@ -621,7 +627,7 @@ class URLRequestTest : public PlatformTest {
TEST_F(URLRequestTest, AboutBlankTest) {
TestDelegate d;
{
- URLRequest r(GURL("about:blank"), &d, &default_context_);
+ URLRequest r(GURL("about:blank"), DEFAULT_PRIORITY, &d, &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -643,7 +649,8 @@ TEST_F(URLRequestTest, DataURLImageTest) {
TestDelegate d;
{
// Use our nice little Chrome logo.
- URLRequest r(GURL(
+ URLRequest r(
+ GURL(
"data:image/png;base64,"
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADVklEQVQ4jX2TfUwUBBjG3"
"w1y+HGcd9dxhXR8T4awOccJGgOSWclHImznLkTlSw0DDQXkrmgYgbUYnlQTqQxIEVxitD"
@@ -663,6 +670,7 @@ TEST_F(URLRequestTest, DataURLImageTest) {
"nlm2O34uI4b9tflqp1+QEFGzoW/ulmcofcpkZCYJhDfSpme7QcrHa+Xfji8paEQkTkSfm"
"moRWRNZr/F1KfVMjW+IKEnv2FwZfKdzt0BQR6lClcZR0EfEXEfv/G6W9iLiIyCoReV5En"
"hORIBHx+ufPj/gLB/zGI/G4Bk0AAAAASUVORK5CYII="),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
@@ -689,7 +697,7 @@ TEST_F(URLRequestTest, FileTest) {
TestDelegate d;
{
- URLRequest r(app_url, &d, &default_context_);
+ URLRequest r(app_url, DEFAULT_PRIORITY, &d, &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -697,7 +705,7 @@ TEST_F(URLRequestTest, FileTest) {
base::RunLoop().Run();
int64 file_size = -1;
- EXPECT_TRUE(file_util::GetFileSize(app_path, &file_size));
+ EXPECT_TRUE(base::GetFileSize(app_path, &file_size));
EXPECT_TRUE(!r.is_pending());
EXPECT_EQ(1, d.response_started_count());
@@ -718,7 +726,7 @@ TEST_F(URLRequestTest, FileTestCancel) {
TestDelegate d;
{
- URLRequest r(app_url, &d, &default_context_);
+ URLRequest r(app_url, DEFAULT_PRIORITY, &d, &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -735,12 +743,12 @@ TEST_F(URLRequestTest, FileTestFullSpecifiedRange) {
FillBuffer(buffer.get(), buffer_size);
base::FilePath temp_path;
- EXPECT_TRUE(file_util::CreateTemporaryFile(&temp_path));
+ EXPECT_TRUE(base::CreateTemporaryFile(&temp_path));
GURL temp_url = FilePathToFileURL(temp_path);
EXPECT_TRUE(file_util::WriteFile(temp_path, buffer.get(), buffer_size));
int64 file_size;
- EXPECT_TRUE(file_util::GetFileSize(temp_path, &file_size));
+ EXPECT_TRUE(base::GetFileSize(temp_path, &file_size));
const size_t first_byte_position = 500;
const size_t last_byte_position = buffer_size - first_byte_position;
@@ -750,13 +758,13 @@ TEST_F(URLRequestTest, FileTestFullSpecifiedRange) {
TestDelegate d;
{
- URLRequest r(temp_url, &d, &default_context_);
+ URLRequest r(temp_url, DEFAULT_PRIORITY, &d, &default_context_);
HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kRange,
- base::StringPrintf(
- "bytes=%" PRIuS "-%" PRIuS,
- first_byte_position, last_byte_position));
+ headers.SetHeader(
+ HttpRequestHeaders::kRange,
+ net::HttpByteRange::Bounded(
+ first_byte_position, last_byte_position).GetHeaderValue());
r.SetExtraRequestHeaders(headers);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -779,12 +787,12 @@ TEST_F(URLRequestTest, FileTestHalfSpecifiedRange) {
FillBuffer(buffer.get(), buffer_size);
base::FilePath temp_path;
- EXPECT_TRUE(file_util::CreateTemporaryFile(&temp_path));
+ EXPECT_TRUE(base::CreateTemporaryFile(&temp_path));
GURL temp_url = FilePathToFileURL(temp_path);
EXPECT_TRUE(file_util::WriteFile(temp_path, buffer.get(), buffer_size));
int64 file_size;
- EXPECT_TRUE(file_util::GetFileSize(temp_path, &file_size));
+ EXPECT_TRUE(base::GetFileSize(temp_path, &file_size));
const size_t first_byte_position = 500;
const size_t last_byte_position = buffer_size - 1;
@@ -794,12 +802,12 @@ TEST_F(URLRequestTest, FileTestHalfSpecifiedRange) {
TestDelegate d;
{
- URLRequest r(temp_url, &d, &default_context_);
+ URLRequest r(temp_url, DEFAULT_PRIORITY, &d, &default_context_);
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kRange,
- base::StringPrintf("bytes=%" PRIuS "-",
- first_byte_position));
+ net::HttpByteRange::RightUnbounded(
+ first_byte_position).GetHeaderValue());
r.SetExtraRequestHeaders(headers);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -822,20 +830,19 @@ TEST_F(URLRequestTest, FileTestMultipleRanges) {
FillBuffer(buffer.get(), buffer_size);
base::FilePath temp_path;
- EXPECT_TRUE(file_util::CreateTemporaryFile(&temp_path));
+ EXPECT_TRUE(base::CreateTemporaryFile(&temp_path));
GURL temp_url = FilePathToFileURL(temp_path);
EXPECT_TRUE(file_util::WriteFile(temp_path, buffer.get(), buffer_size));
int64 file_size;
- EXPECT_TRUE(file_util::GetFileSize(temp_path, &file_size));
+ EXPECT_TRUE(base::GetFileSize(temp_path, &file_size));
TestDelegate d;
{
- URLRequest r(temp_url, &d, &default_context_);
+ URLRequest r(temp_url, DEFAULT_PRIORITY, &d, &default_context_);
HttpRequestHeaders headers;
- headers.SetHeader(HttpRequestHeaders::kRange,
- "bytes=0-0,10-200,200-300");
+ headers.SetHeader(HttpRequestHeaders::kRange, "bytes=0-0,10-200,200-300");
r.SetExtraRequestHeaders(headers);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -847,10 +854,44 @@ TEST_F(URLRequestTest, FileTestMultipleRanges) {
EXPECT_TRUE(base::DeleteFile(temp_path, false));
}
+TEST_F(URLRequestTest, AllowFileURLs) {
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath test_file;
+ ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &test_file));
+ std::string test_data("monkey");
+ file_util::WriteFile(test_file, test_data.data(), test_data.size());
+ GURL test_file_url = net::FilePathToFileURL(test_file);
+
+ {
+ TestDelegate d;
+ TestNetworkDelegate network_delegate;
+ network_delegate.set_can_access_files(true);
+ default_context_.set_network_delegate(&network_delegate);
+ URLRequest r(test_file_url, DEFAULT_PRIORITY, &d, &default_context_);
+ r.Start();
+ base::RunLoop().Run();
+ EXPECT_FALSE(d.request_failed());
+ EXPECT_EQ(test_data, d.data_received());
+ }
+
+ {
+ TestDelegate d;
+ TestNetworkDelegate network_delegate;
+ network_delegate.set_can_access_files(false);
+ default_context_.set_network_delegate(&network_delegate);
+ URLRequest r(test_file_url, DEFAULT_PRIORITY, &d, &default_context_);
+ r.Start();
+ base::RunLoop().Run();
+ EXPECT_TRUE(d.request_failed());
+ EXPECT_EQ("", d.data_received());
+ }
+}
+
TEST_F(URLRequestTest, InvalidUrlTest) {
TestDelegate d;
{
- URLRequest r(GURL("invalid url"), &d, &default_context_);
+ URLRequest r(GURL("invalid url"), DEFAULT_PRIORITY, &d, &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -887,7 +928,9 @@ TEST_F(URLRequestTest, ResolveShortcutTest) {
TestDelegate d;
{
- URLRequest r(FilePathToFileURL(base::FilePath(lnk_path)), &d,
+ URLRequest r(FilePathToFileURL(base::FilePath(lnk_path)),
+ DEFAULT_PRIORITY,
+ &d,
&default_context_);
r.Start();
@@ -931,7 +974,8 @@ TEST_F(URLRequestTest, FileDirCancelTest) {
file_path = file_path.Append(FILE_PATH_LITERAL("net"));
file_path = file_path.Append(FILE_PATH_LITERAL("data"));
- URLRequest req(FilePathToFileURL(file_path), &d, &default_context_);
+ URLRequest req(
+ FilePathToFileURL(file_path), DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
EXPECT_TRUE(req.is_pending());
@@ -944,6 +988,44 @@ TEST_F(URLRequestTest, FileDirCancelTest) {
NetModule::SetResourceProvider(NULL);
}
+TEST_F(URLRequestTest, FileDirOutputSanity) {
+ // Verify the general sanity of the the output of the file:
+ // directory lister by checking for the output of a known existing
+ // file.
+ const char sentinel_name[] = "filedir-sentinel";
+
+ base::FilePath path;
+ PathService::Get(base::DIR_SOURCE_ROOT, &path);
+ path = path.Append(FILE_PATH_LITERAL("net"));
+ path = path.Append(FILE_PATH_LITERAL("data"));
+ path = path.Append(FILE_PATH_LITERAL("url_request_unittest"));
+
+ TestDelegate d;
+ URLRequest req(
+ FilePathToFileURL(path), DEFAULT_PRIORITY, &d, &default_context_);
+ req.Start();
+ base::RunLoop().Run();
+
+ // Generate entry for the sentinel file.
+ base::FilePath sentinel_path = path.AppendASCII(sentinel_name);
+ base::PlatformFileInfo info;
+ EXPECT_TRUE(base::GetFileInfo(sentinel_path, &info));
+ EXPECT_GT(info.size, 0);
+ std::string sentinel_output = GetDirectoryListingEntry(
+ base::string16(sentinel_name, sentinel_name + strlen(sentinel_name)),
+ std::string(sentinel_name),
+ false /* is_dir */,
+ info.size,
+ info.last_modified);
+
+ ASSERT_LT(0, d.bytes_received());
+ ASSERT_FALSE(d.request_failed());
+ ASSERT_TRUE(req.status().is_success());
+ // Check for the entry generated for the "sentinel" file.
+ const std::string& data = d.data_received();
+ ASSERT_NE(data.find(sentinel_output), std::string::npos);
+}
+
TEST_F(URLRequestTest, FileDirRedirectNoCrash) {
// There is an implicit redirect when loading a file path that matches a
// directory and does not end with a slash. Ensure that following such
@@ -956,7 +1038,8 @@ TEST_F(URLRequestTest, FileDirRedirectNoCrash) {
path = path.Append(FILE_PATH_LITERAL("url_request_unittest"));
TestDelegate d;
- URLRequest req(FilePathToFileURL(path), &d, &default_context_);
+ URLRequest req(
+ FilePathToFileURL(path), DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
@@ -970,7 +1053,7 @@ TEST_F(URLRequestTest, FileDirRedirectNoCrash) {
// Don't accept the url "file:///" on windows. See http://crbug.com/1474.
TEST_F(URLRequestTest, FileDirRedirectSingleSlash) {
TestDelegate d;
- URLRequest req(GURL("file:///"), &d, &default_context_);
+ URLRequest req(GURL("file:///"), DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
@@ -1191,7 +1274,10 @@ TEST_F(URLRequestTest, Intercept) {
interceptor.main_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
base::SupportsUserData::Data* user_data0 = new base::SupportsUserData::Data();
base::SupportsUserData::Data* user_data1 = new base::SupportsUserData::Data();
base::SupportsUserData::Data* user_data2 = new base::SupportsUserData::Data();
@@ -1232,7 +1318,10 @@ TEST_F(URLRequestTest, InterceptRedirect) {
interceptor.redirect_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1265,7 +1354,10 @@ TEST_F(URLRequestTest, InterceptServerError) {
interceptor.final_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1294,7 +1386,10 @@ TEST_F(URLRequestTest, InterceptNetworkError) {
interceptor.final_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1323,7 +1418,10 @@ TEST_F(URLRequestTest, InterceptRestartRequired) {
interceptor.main_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1354,7 +1452,10 @@ TEST_F(URLRequestTest, InterceptRespectsCancelMain) {
interceptor.final_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1385,7 +1486,10 @@ TEST_F(URLRequestTest, InterceptRespectsCancelRedirect) {
interceptor.final_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1410,7 +1514,10 @@ TEST_F(URLRequestTest, InterceptRespectsCancelFinal) {
interceptor.cancel_final_request_ = true;
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1436,7 +1543,10 @@ TEST_F(URLRequestTest, InterceptRespectsCancelInRestart) {
interceptor.final_data_ = TestInterceptor::ok_data();
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("GET");
req.Start();
base::RunLoop().Run();
@@ -1456,7 +1566,8 @@ LoadTimingInfo RunLoadTimingTest(const LoadTimingInfo& job_load_timing,
interceptor.intercept_main_request_ = true;
interceptor.main_request_load_timing_info_ = job_load_timing;
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, context);
+ URLRequest req(
+ GURL("http://test_intercept/foo"), DEFAULT_PRIORITY, &d, context);
req.Start();
base::RunLoop().Run();
@@ -1530,8 +1641,8 @@ TEST_F(URLRequestTest, InterceptLoadTiming) {
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_DNS_TIMES, false);
- LoadTimingInfo load_timing_result = RunLoadTimingTest(job_load_timing,
- &default_context_);
+ LoadTimingInfo load_timing_result =
+ RunLoadTimingTest(job_load_timing, &default_context_);
// Nothing should have been changed by the URLRequest.
EXPECT_EQ(job_load_timing.proxy_resolve_start,
@@ -1561,8 +1672,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingProxy) {
LoadTimingInfo job_load_timing =
NormalLoadTimingInfo(now, CONNECT_TIMING_HAS_SSL_TIMES, true);
- LoadTimingInfo load_timing_result = RunLoadTimingTest(job_load_timing,
- &default_context_);
+ LoadTimingInfo load_timing_result =
+ RunLoadTimingTest(job_load_timing, &default_context_);
// Nothing should have been changed by the URLRequest.
EXPECT_EQ(job_load_timing.proxy_resolve_start,
@@ -1606,8 +1717,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolution) {
job_load_timing.connect_timing.connect_end =
now - base::TimeDelta::FromDays(1);
- LoadTimingInfo load_timing_result = RunLoadTimingTest(job_load_timing,
- &default_context_);
+ LoadTimingInfo load_timing_result =
+ RunLoadTimingTest(job_load_timing, &default_context_);
// Proxy times, connect times, and DNS times should all be replaced with
// request_start.
@@ -1636,8 +1747,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyProxyResolutionReused) {
job_load_timing.proxy_resolve_start = now - base::TimeDelta::FromDays(4);
job_load_timing.proxy_resolve_end = now - base::TimeDelta::FromDays(3);
- LoadTimingInfo load_timing_result = RunLoadTimingTest(job_load_timing,
- &default_context_);
+ LoadTimingInfo load_timing_result =
+ RunLoadTimingTest(job_load_timing, &default_context_);
// Proxy times and connect times should all be replaced with request_start.
EXPECT_EQ(load_timing_result.request_start,
@@ -1665,8 +1776,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnect) {
job_load_timing.connect_timing.connect_end =
now - base::TimeDelta::FromDays(4);
- LoadTimingInfo load_timing_result = RunLoadTimingTest(job_load_timing,
- &default_context_);
+ LoadTimingInfo load_timing_result =
+ RunLoadTimingTest(job_load_timing, &default_context_);
// Connect times, and SSL times should be replaced with request_start.
EXPECT_EQ(load_timing_result.request_start,
@@ -1697,8 +1808,8 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnectWithProxy) {
job_load_timing.connect_timing.connect_end =
now - base::TimeDelta::FromDays(2);
- LoadTimingInfo load_timing_result = RunLoadTimingTest(job_load_timing,
- &default_context_);
+ LoadTimingInfo load_timing_result =
+ RunLoadTimingTest(job_load_timing, &default_context_);
// Connect times should be replaced with proxy_resolve_end.
EXPECT_EQ(load_timing_result.proxy_resolve_end,
@@ -1715,8 +1826,10 @@ TEST_F(URLRequestTest, InterceptLoadTimingEarlyConnectWithProxy) {
TEST_F(URLRequestTest, Identifiers) {
TestDelegate d;
TestURLRequestContext context;
- TestURLRequest req(GURL("http://example.com"), &d, &context, NULL);
- TestURLRequest other_req(GURL("http://example.com"), &d, &context, NULL);
+ TestURLRequest req(
+ GURL("http://example.com"), DEFAULT_PRIORITY, &d, &context);
+ TestURLRequest other_req(
+ GURL("http://example.com"), DEFAULT_PRIORITY, &d, &context);
ASSERT_NE(req.identifier(), other_req.identifier());
}
@@ -1731,7 +1844,7 @@ TEST_F(URLRequestTest, NetworkDelegateProxyError) {
TestURLRequestContextWithProxy context("myproxy:70", &network_delegate);
TestDelegate d;
- URLRequest req(GURL("http://example.com"), &d, &context);
+ URLRequest req(GURL("http://example.com"), DEFAULT_PRIORITY, &d, &context);
req.set_method("GET");
req.Start();
@@ -1751,7 +1864,7 @@ TEST_F(URLRequestTest, NetworkDelegateProxyError) {
// content is empty.
TEST_F(URLRequestTest, RequestCompletionForEmptyResponse) {
TestDelegate d;
- URLRequest req(GURL("data:,"), &d, &default_context_);
+ URLRequest req(GURL("data:,"), DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
EXPECT_EQ("", d.data_received());
@@ -1762,7 +1875,10 @@ TEST_F(URLRequestTest, RequestCompletionForEmptyResponse) {
// correctly, both before and after start.
TEST_F(URLRequestTest, SetPriorityBasic) {
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
EXPECT_EQ(DEFAULT_PRIORITY, req.priority());
req.SetPriority(LOW);
@@ -1779,7 +1895,10 @@ TEST_F(URLRequestTest, SetPriorityBasic) {
// Start on it.
TEST_F(URLRequestTest, SetJobPriorityBeforeJobStart) {
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
EXPECT_EQ(DEFAULT_PRIORITY, req.priority());
scoped_refptr<URLRequestTestJob> job =
@@ -1797,7 +1916,10 @@ TEST_F(URLRequestTest, SetJobPriorityBeforeJobStart) {
// job.
TEST_F(URLRequestTest, SetJobPriority) {
TestDelegate d;
- URLRequest req(GURL("http://test_intercept/foo"), &d, &default_context_);
+ URLRequest req(GURL("http://test_intercept/foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
scoped_refptr<URLRequestTestJob> job =
new URLRequestTestJob(&req, &default_network_delegate_);
@@ -1812,6 +1934,31 @@ TEST_F(URLRequestTest, SetJobPriority) {
EXPECT_EQ(MEDIUM, job->priority());
}
+// Setting the IGNORE_LIMITS load flag should be okay if the priority
+// is MAXIMUM_PRIORITY.
+TEST_F(URLRequestTest, PriorityIgnoreLimits) {
+ TestDelegate d;
+ URLRequest req(GURL("http://test_intercept/foo"),
+ MAXIMUM_PRIORITY,
+ &d,
+ &default_context_);
+ EXPECT_EQ(MAXIMUM_PRIORITY, req.priority());
+
+ scoped_refptr<URLRequestTestJob> job =
+ new URLRequestTestJob(&req, &default_network_delegate_);
+ AddTestInterceptor()->set_main_intercept_job(job.get());
+
+ req.SetLoadFlags(LOAD_IGNORE_LIMITS);
+ EXPECT_EQ(MAXIMUM_PRIORITY, req.priority());
+
+ req.SetPriority(MAXIMUM_PRIORITY);
+ EXPECT_EQ(MAXIMUM_PRIORITY, req.priority());
+
+ req.Start();
+ EXPECT_EQ(MAXIMUM_PRIORITY, req.priority());
+ EXPECT_EQ(MAXIMUM_PRIORITY, job->priority());
+}
+
// TODO(droger): Support SpawnedTestServer on iOS (see http://crbug.com/148666).
#if !defined(OS_IOS)
// A subclass of SpawnedTestServer that uses a statically-configured hostname.
@@ -1844,8 +1991,10 @@ TEST_F(URLRequestTest, DelayedCookieCallback) {
TestNetworkDelegate network_delegate;
context.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("set-cookie?CookieToNotSend=1"), &d, &context);
+ URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"),
+ DEFAULT_PRIORITY,
+ &d,
+ &context);
req.Start();
base::RunLoop().Run();
EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
@@ -1858,7 +2007,10 @@ TEST_F(URLRequestTest, DelayedCookieCallback) {
TestNetworkDelegate network_delegate;
context.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(test_server.GetURL("echoheader?Cookie"), &d, &context);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &context);
req.Start();
base::RunLoop().Run();
@@ -1879,6 +2031,7 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -1892,8 +2045,10 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -1908,9 +2063,11 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
- req.set_load_flags(LOAD_DO_NOT_SEND_COOKIES);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
+ req.SetLoadFlags(LOAD_DO_NOT_SEND_COOKIES);
req.Start();
base::RunLoop().Run();
@@ -1933,6 +2090,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -1950,9 +2108,10 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
TestDelegate d;
URLRequest req(
test_server.GetURL("set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
- req.set_load_flags(LOAD_DO_NOT_SAVE_COOKIES);
+ req.SetLoadFlags(LOAD_DO_NOT_SAVE_COOKIES);
req.Start();
base::RunLoop().Run();
@@ -1968,8 +2127,10 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -1994,6 +2155,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2008,8 +2170,10 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2026,8 +2190,10 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
network_delegate.set_cookie_options(TestNetworkDelegate::NO_GET_COOKIES);
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2049,6 +2215,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2066,6 +2233,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
network_delegate.set_cookie_options(TestNetworkDelegate::NO_SET_COOKIE);
URLRequest req(
test_server.GetURL("set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2081,8 +2249,10 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2105,7 +2275,10 @@ TEST_F(URLRequestTest, DoNotSaveEmptyCookies) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(test_server.GetURL("set-cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("set-cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2125,6 +2298,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
URLRequest req(test_server.GetURL("set-cookie?CookieToNotSend=1"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2139,8 +2313,10 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2157,8 +2333,10 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
network_delegate.set_cookie_options(TestNetworkDelegate::NO_GET_COOKIES);
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2180,6 +2358,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
URLRequest req(test_server.GetURL("set-cookie?CookieToNotUpdate=2"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2197,6 +2376,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
network_delegate.set_cookie_options(TestNetworkDelegate::NO_SET_COOKIE);
URLRequest req(
test_server.GetURL("set-cookie?CookieToNotSave=1&CookieToNotUpdate=1"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2212,8 +2392,10 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2279,8 +2461,10 @@ TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(test_server.GetURL(
- "set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
+ URLRequest req(
+ test_server.GetURL(
+ "set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2291,8 +2475,10 @@ TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2303,8 +2489,10 @@ TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) {
FixedDateNetworkDelegate network_delegate("18-Apr-1977 22:49:13 UTC");
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(test_server.GetURL(
- "set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
+ URLRequest req(
+ test_server.GetURL(
+ "set-cookie?StillGood=1;expires=Mon,18-Apr-1977,22:50:13,GMT"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -2315,8 +2503,10 @@ TEST_F(URLRequestTest, AcceptClockSkewCookieWithWrongDateTimezone) {
TestNetworkDelegate network_delegate;
default_context_.set_network_delegate(&network_delegate);
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Cookie"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Cookie"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -2335,8 +2525,10 @@ TEST_F(URLRequestTest, DoNotOverrideReferrer) {
// only the latter shall be respected.
{
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Referer"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Referer"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.SetReferrer("http://foo.com/");
HttpRequestHeaders headers;
@@ -2353,13 +2545,15 @@ TEST_F(URLRequestTest, DoNotOverrideReferrer) {
// shall be sent in the header.
{
TestDelegate d;
- URLRequest req(
- test_server.GetURL("echoheader?Referer"), &d, &default_context_);
+ URLRequest req(test_server.GetURL("echoheader?Referer"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
HttpRequestHeaders headers;
headers.SetHeader(HttpRequestHeaders::kReferer, "http://bar.com/");
req.SetExtraRequestHeaders(headers);
- req.set_load_flags(LOAD_VALIDATE_CACHE);
+ req.SetLoadFlags(LOAD_VALIDATE_CACHE);
req.Start();
base::RunLoop().Run();
@@ -2389,7 +2583,7 @@ class URLRequestTestHTTP : public URLRequestTest {
bool include_data) {
static const char kData[] = "hello world";
TestDelegate d;
- URLRequest req(redirect_url, &d, &default_context_);
+ URLRequest req(redirect_url, DEFAULT_PRIORITY, &d, &default_context_);
req.set_method(request_method);
if (include_data) {
req.set_upload(make_scoped_ptr(CreateSimpleUploadData(kData)));
@@ -2434,7 +2628,8 @@ class URLRequestTestHTTP : public URLRequestTest {
for (int i = 0; i < kIterations; ++i) {
TestDelegate d;
- URLRequest r(test_server_.GetURL("echo"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, &default_context_);
r.set_method(method.c_str());
r.set_upload(make_scoped_ptr(CreateSimpleUploadData(uploadBytes)));
@@ -2482,8 +2677,9 @@ class URLRequestTestHTTP : public URLRequestTest {
TestDelegate d;
URLRequest r(test_server_.GetURL("set-many-cookies?" +
base::IntToString(num_cookies)),
- &d,
- &default_context_);
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -2518,12 +2714,12 @@ TEST_F(URLRequestTestHTTP, ProxyTunnelRedirectTest) {
TestNetworkDelegate network_delegate; // Must outlive URLRequest.
TestURLRequestContextWithProxy context(
- test_server_.host_port_pair().ToString(),
- &network_delegate);
+ test_server_.host_port_pair().ToString(), &network_delegate);
TestDelegate d;
{
- URLRequest r(GURL("https://www.redirect.com/"), &d, &context);
+ URLRequest r(
+ GURL("https://www.redirect.com/"), DEFAULT_PRIORITY, &d, &context);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -2544,12 +2740,12 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateTunnelConnectionFailed) {
TestNetworkDelegate network_delegate; // Must outlive URLRequest.
TestURLRequestContextWithProxy context(
- test_server_.host_port_pair().ToString(),
- &network_delegate);
+ test_server_.host_port_pair().ToString(), &network_delegate);
TestDelegate d;
{
- URLRequest r(GURL("https://www.redirect.com/"), &d, &context);
+ URLRequest r(
+ GURL("https://www.redirect.com/"), DEFAULT_PRIORITY, &d, &context);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -2590,7 +2786,8 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateBlockAsynchronously) {
context.Init();
{
- URLRequest r(test_server_.GetURL("empty.html"), &d, &context);
+ URLRequest r(
+ test_server_.GetURL("empty.html"), DEFAULT_PRIORITY, &d, &context);
r.Start();
for (size_t i = 0; i < blocking_stages_length; ++i) {
@@ -2619,11 +2816,11 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelRequest) {
network_delegate.set_retval(ERR_EMPTY_RESPONSE);
TestURLRequestContextWithProxy context(
- test_server_.host_port_pair().ToString(),
- &network_delegate);
+ test_server_.host_port_pair().ToString(), &network_delegate);
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &context);
+ URLRequest r(
+ test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2653,7 +2850,7 @@ void NetworkDelegateCancelRequest(BlockingNetworkDelegate::BlockMode block_mode,
context.Init();
{
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2725,12 +2922,11 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequest) {
network_delegate.set_redirect_url(redirect_url);
TestURLRequestContextWithProxy context(
- test_server_.host_port_pair().ToString(),
- &network_delegate);
+ test_server_.host_port_pair().ToString(), &network_delegate);
{
GURL original_url(test_server_.GetURL("empty.html"));
- URLRequest r(original_url, &d, &context);
+ URLRequest r(original_url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2758,12 +2954,11 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestSynchronously) {
network_delegate.set_redirect_url(redirect_url);
TestURLRequestContextWithProxy context(
- test_server_.host_port_pair().ToString(),
- &network_delegate);
+ test_server_.host_port_pair().ToString(), &network_delegate);
{
GURL original_url(test_server_.GetURL("empty.html"));
- URLRequest r(original_url, &d, &context);
+ URLRequest r(original_url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2798,7 +2993,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestPost) {
{
GURL original_url(test_server_.GetURL("empty.html"));
- URLRequest r(original_url, &d, &context);
+ URLRequest r(original_url, DEFAULT_PRIORITY, &d, &context);
r.set_method("POST");
r.set_upload(make_scoped_ptr(CreateSimpleUploadData(kData)));
HttpRequestHeaders headers;
@@ -2840,7 +3035,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncNoAction) {
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2871,7 +3066,7 @@ TEST_F(URLRequestTestHTTP,
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
{
@@ -2912,7 +3107,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncSetAuth) {
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2947,7 +3142,7 @@ TEST_F(URLRequestTestHTTP,
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -2985,7 +3180,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredSyncCancel) {
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3019,7 +3214,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredAsyncNoAction) {
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3054,7 +3249,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredAsyncSetAuth) {
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3087,7 +3282,7 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateOnAuthRequiredAsyncCancel) {
{
GURL url(test_server_.GetURL("auth-basic"));
- URLRequest r(url, &d, &context);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3117,7 +3312,8 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting1) {
context.Init();
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &context);
+ URLRequest r(
+ test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3153,7 +3349,8 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting2) {
context.Init();
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &context);
+ URLRequest r(
+ test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3188,7 +3385,8 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting3) {
context.Init();
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &context);
+ URLRequest r(
+ test_server_.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3223,7 +3421,8 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateCancelWhileWaiting4) {
context.Init();
{
- URLRequest r(test_server_.GetURL("auth-basic"), &d, &context);
+ URLRequest r(
+ test_server_.GetURL("auth-basic"), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -3250,12 +3449,12 @@ TEST_F(URLRequestTestHTTP, UnexpectedServerAuthTest) {
TestNetworkDelegate network_delegate; // Must outlive URLRequest.
TestURLRequestContextWithProxy context(
- test_server_.host_port_pair().ToString(),
- &network_delegate);
+ test_server_.host_port_pair().ToString(), &network_delegate);
TestDelegate d;
{
- URLRequest r(GURL("https://www.server-auth.com/"), &d, &context);
+ URLRequest r(
+ GURL("https://www.server-auth.com/"), DEFAULT_PRIORITY, &d, &context);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3272,7 +3471,10 @@ TEST_F(URLRequestTestHTTP, GetTest_NoCache) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server_.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3338,7 +3540,10 @@ TEST_F(URLRequestTestHTTP, GetTest) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server_.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3361,7 +3566,7 @@ TEST_F(URLRequestTestHTTP, GetTest_GetFullRequestHeaders) {
TestDelegate d;
{
GURL test_url(test_server_.GetURL(std::string()));
- URLRequest r(test_url, &d, &default_context_);
+ URLRequest r(test_url, DEFAULT_PRIORITY, &d, &default_context_);
HttpRequestHeaders headers;
EXPECT_FALSE(r.GetFullRequestHeaders(&headers));
@@ -3389,7 +3594,10 @@ TEST_F(URLRequestTestHTTP, GetTestLoadTiming) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server_.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3439,7 +3647,8 @@ TEST_F(URLRequestTestHTTP, GetZippedTest) {
context.set_network_delegate(&network_delegate);
context.Init();
- URLRequest r(test_server_.GetURL(test_file), &d, &context);
+ URLRequest r(
+ test_server_.GetURL(test_file), DEFAULT_PRIORITY, &d, &context);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3475,8 +3684,11 @@ TEST_F(URLRequestTestHTTP, HTTPSToHTTPRedirectNoRefererTest) {
// server should not be sent the referer.
GURL http_destination = test_server_.GetURL(std::string());
TestDelegate d;
- URLRequest req(https_test_server.GetURL(
- "server-redirect?" + http_destination.spec()), &d, &default_context_);
+ URLRequest req(
+ https_test_server.GetURL("server-redirect?" + http_destination.spec()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.SetReferrer("https://www.referrer.com/");
req.Start();
base::RunLoop().Run();
@@ -3494,7 +3706,7 @@ TEST_F(URLRequestTestHTTP, RedirectLoadTiming) {
GURL original_url =
test_server_.GetURL("server-redirect?" + destination_url.spec());
TestDelegate d;
- URLRequest req(original_url, &d, &default_context_);
+ URLRequest req(original_url, DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
@@ -3534,7 +3746,7 @@ TEST_F(URLRequestTestHTTP, MultipleRedirectTest) {
GURL original_url = test_server_.GetURL(
"server-redirect?" + middle_redirect_url.spec());
TestDelegate d;
- URLRequest req(original_url, &d, &default_context_);
+ URLRequest req(original_url, DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
@@ -3548,6 +3760,693 @@ TEST_F(URLRequestTestHTTP, MultipleRedirectTest) {
EXPECT_EQ(destination_url, req.url_chain()[2]);
}
+// First and second pieces of information logged by delegates to URLRequests.
+const char kFirstDelegateInfo[] = "Wonderful delegate";
+const char kSecondDelegateInfo[] = "Exciting delegate";
+
+// Logs delegate information to a URLRequest. The first string is logged
+// synchronously on Start(), using DELEGATE_INFO_DEBUG_ONLY. The second is
+// logged asynchronously, using DELEGATE_INFO_DISPLAY_TO_USER. Then
+// another asynchronous call is used to clear the delegate information
+// before calling a callback. The object then deletes itself.
+class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> {
+ public:
+ typedef base::Callback<void()> Callback;
+
+ // Each time delegate information is added to the URLRequest, the resulting
+ // load state is checked. The expected load state after each request is
+ // passed in as an argument.
+ static void Run(URLRequest* url_request,
+ LoadState expected_first_load_state,
+ LoadState expected_second_load_state,
+ LoadState expected_third_load_state,
+ const Callback& callback) {
+ AsyncDelegateLogger* logger = new AsyncDelegateLogger(
+ url_request,
+ expected_first_load_state,
+ expected_second_load_state,
+ expected_third_load_state,
+ callback);
+ logger->Start();
+ }
+
+ // Checks that the log entries, starting with log_position, contain the
+ // DELEGATE_INFO NetLog events that an AsyncDelegateLogger should have
+ // recorded. Returns the index of entry after the expected number of
+ // events this logged, or entries.size() if there aren't enough entries.
+ static size_t CheckDelegateInfo(
+ const CapturingNetLog::CapturedEntryList& entries, size_t log_position) {
+ // There should be 4 DELEGATE_INFO events: Two begins and two ends.
+ if (log_position + 3 >= entries.size()) {
+ ADD_FAILURE() << "Not enough log entries";
+ return entries.size();
+ }
+ std::string delegate_info;
+ EXPECT_EQ(NetLog::TYPE_DELEGATE_INFO, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_BEGIN, entries[log_position].phase);
+ EXPECT_TRUE(entries[log_position].GetStringValue("delegate_info",
+ &delegate_info));
+ EXPECT_EQ(kFirstDelegateInfo, delegate_info);
+
+ ++log_position;
+ EXPECT_EQ(NetLog::TYPE_DELEGATE_INFO, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+
+ ++log_position;
+ EXPECT_EQ(NetLog::TYPE_DELEGATE_INFO, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_BEGIN, entries[log_position].phase);
+ EXPECT_TRUE(entries[log_position].GetStringValue("delegate_info",
+ &delegate_info));
+ EXPECT_EQ(kSecondDelegateInfo, delegate_info);
+
+ ++log_position;
+ EXPECT_EQ(NetLog::TYPE_DELEGATE_INFO, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+
+ return log_position + 1;
+ }
+
+ private:
+ friend class base::RefCounted<AsyncDelegateLogger>;
+
+ AsyncDelegateLogger(URLRequest* url_request,
+ LoadState expected_first_load_state,
+ LoadState expected_second_load_state,
+ LoadState expected_third_load_state,
+ const Callback& callback)
+ : url_request_(url_request),
+ expected_first_load_state_(expected_first_load_state),
+ expected_second_load_state_(expected_second_load_state),
+ expected_third_load_state_(expected_third_load_state),
+ callback_(callback) {
+ }
+
+ ~AsyncDelegateLogger() {}
+
+ void Start() {
+ url_request_->LogBlockedBy(kFirstDelegateInfo);
+ LoadStateWithParam load_state = url_request_->GetLoadState();
+ EXPECT_EQ(expected_first_load_state_, load_state.state);
+ EXPECT_NE(ASCIIToUTF16(kFirstDelegateInfo), load_state.param);
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AsyncDelegateLogger::LogSecondDelegate, this));
+ }
+
+ void LogSecondDelegate() {
+ url_request_->LogAndReportBlockedBy(kSecondDelegateInfo);
+ LoadStateWithParam load_state = url_request_->GetLoadState();
+ EXPECT_EQ(expected_second_load_state_, load_state.state);
+ if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE) {
+ EXPECT_EQ(ASCIIToUTF16(kSecondDelegateInfo), load_state.param);
+ } else {
+ EXPECT_NE(ASCIIToUTF16(kSecondDelegateInfo), load_state.param);
+ }
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AsyncDelegateLogger::LogComplete, this));
+ }
+
+ void LogComplete() {
+ url_request_->LogUnblocked();
+ LoadStateWithParam load_state = url_request_->GetLoadState();
+ EXPECT_EQ(expected_third_load_state_, load_state.state);
+ if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE)
+ EXPECT_EQ(string16(), load_state.param);
+ callback_.Run();
+ }
+
+ URLRequest* url_request_;
+ const int expected_first_load_state_;
+ const int expected_second_load_state_;
+ const int expected_third_load_state_;
+ const Callback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncDelegateLogger);
+};
+
+// NetworkDelegate that logs delegate information before a request is started,
+// before headers are sent, when headers are read, and when auth information
+// is requested. Uses AsyncDelegateLogger.
+class AsyncLoggingNetworkDelegate : public TestNetworkDelegate {
+ public:
+ AsyncLoggingNetworkDelegate() {}
+ virtual ~AsyncLoggingNetworkDelegate() {}
+
+ // NetworkDelegate implementation.
+ virtual int OnBeforeURLRequest(URLRequest* request,
+ const CompletionCallback& callback,
+ GURL* new_url) OVERRIDE {
+ TestNetworkDelegate::OnBeforeURLRequest(request, callback, new_url);
+ return RunCallbackAsynchronously(request, callback);
+ }
+
+ virtual int OnBeforeSendHeaders(URLRequest* request,
+ const CompletionCallback& callback,
+ HttpRequestHeaders* headers) OVERRIDE {
+ TestNetworkDelegate::OnBeforeSendHeaders(request, callback, headers);
+ return RunCallbackAsynchronously(request, callback);
+ }
+
+ virtual int OnHeadersReceived(
+ URLRequest* request,
+ const CompletionCallback& callback,
+ const HttpResponseHeaders* original_response_headers,
+ scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE {
+ TestNetworkDelegate::OnHeadersReceived(request, callback,
+ original_response_headers,
+ override_response_headers);
+ return RunCallbackAsynchronously(request, callback);
+ }
+
+ virtual NetworkDelegate::AuthRequiredResponse OnAuthRequired(
+ URLRequest* request,
+ const AuthChallengeInfo& auth_info,
+ const AuthCallback& callback,
+ AuthCredentials* credentials) OVERRIDE {
+ AsyncDelegateLogger::Run(
+ request,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ base::Bind(&AsyncLoggingNetworkDelegate::SetAuthAndResume,
+ callback, credentials));
+ return AUTH_REQUIRED_RESPONSE_IO_PENDING;
+ }
+
+ private:
+ static int RunCallbackAsynchronously(
+ URLRequest* request,
+ const CompletionCallback& callback) {
+ AsyncDelegateLogger::Run(
+ request,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ base::Bind(callback, OK));
+ return ERR_IO_PENDING;
+ }
+
+ static void SetAuthAndResume(const AuthCallback& callback,
+ AuthCredentials* credentials) {
+ *credentials = AuthCredentials(kUser, kSecret);
+ callback.Run(NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncLoggingNetworkDelegate);
+};
+
+// URLRequest::Delegate that logs delegate information when the headers
+// are received, when each read completes, and during redirects. Uses
+// AsyncDelegateLogger. Can optionally cancel a request in any phase.
+//
+// Inherits from TestDelegate to reuse the TestDelegate code to handle
+// advancing to the next step in most cases, as well as cancellation.
+class AsyncLoggingUrlRequestDelegate : public TestDelegate {
+ public:
+ enum CancelStage {
+ NO_CANCEL = 0,
+ CANCEL_ON_RECEIVED_REDIRECT,
+ CANCEL_ON_RESPONSE_STARTED,
+ CANCEL_ON_READ_COMPLETED
+ };
+
+ explicit AsyncLoggingUrlRequestDelegate(CancelStage cancel_stage)
+ : cancel_stage_(cancel_stage) {
+ if (cancel_stage == CANCEL_ON_RECEIVED_REDIRECT)
+ set_cancel_in_received_redirect(true);
+ else if (cancel_stage == CANCEL_ON_RESPONSE_STARTED)
+ set_cancel_in_response_started(true);
+ else if (cancel_stage == CANCEL_ON_READ_COMPLETED)
+ set_cancel_in_received_data(true);
+ }
+ virtual ~AsyncLoggingUrlRequestDelegate() {}
+
+ // URLRequest::Delegate implementation:
+ void virtual OnReceivedRedirect(URLRequest* request,
+ const GURL& new_url,
+ bool* defer_redirect) OVERRIDE {
+ *defer_redirect = true;
+ AsyncDelegateLogger::Run(
+ request,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ base::Bind(
+ &AsyncLoggingUrlRequestDelegate::OnReceivedRedirectLoggingComplete,
+ base::Unretained(this), request, new_url));
+ }
+
+ virtual void OnResponseStarted(URLRequest* request) OVERRIDE {
+ AsyncDelegateLogger::Run(
+ request,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ base::Bind(
+ &AsyncLoggingUrlRequestDelegate::OnResponseStartedLoggingComplete,
+ base::Unretained(this), request));
+ }
+
+ virtual void OnReadCompleted(URLRequest* request,
+ int bytes_read) OVERRIDE {
+ AsyncDelegateLogger::Run(
+ request,
+ LOAD_STATE_IDLE,
+ LOAD_STATE_IDLE,
+ LOAD_STATE_IDLE,
+ base::Bind(
+ &AsyncLoggingUrlRequestDelegate::AfterReadCompletedLoggingComplete,
+ base::Unretained(this), request, bytes_read));
+ }
+
+ private:
+ void OnReceivedRedirectLoggingComplete(URLRequest* request,
+ const GURL& new_url) {
+ bool defer_redirect = false;
+ TestDelegate::OnReceivedRedirect(request, new_url, &defer_redirect);
+ // FollowDeferredRedirect should not be called after cancellation.
+ if (cancel_stage_ == CANCEL_ON_RECEIVED_REDIRECT)
+ return;
+ if (!defer_redirect)
+ request->FollowDeferredRedirect();
+ }
+
+ void OnResponseStartedLoggingComplete(URLRequest* request) {
+ // The parent class continues the request.
+ TestDelegate::OnResponseStarted(request);
+ }
+
+ void AfterReadCompletedLoggingComplete(URLRequest* request, int bytes_read) {
+ // The parent class continues the request.
+ TestDelegate::OnReadCompleted(request, bytes_read);
+ }
+
+ const CancelStage cancel_stage_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncLoggingUrlRequestDelegate);
+};
+
+// Tests handling of delegate info before a request starts.
+TEST_F(URLRequestTestHTTP, DelegateInfoBeforeStart) {
+ ASSERT_TRUE(test_server_.Start());
+
+ TestDelegate request_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_delegate(NULL);
+ context.set_net_log(&net_log_);
+ context.Init();
+
+ {
+ URLRequest r(test_server_.GetURL("empty.html"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
+ EXPECT_EQ(string16(), load_state.param);
+
+ AsyncDelegateLogger::Run(
+ &r,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_WAITING_FOR_DELEGATE,
+ LOAD_STATE_IDLE,
+ base::Bind(&URLRequest::Start, base::Unretained(&r)));
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(200, r.GetResponseCode());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ }
+
+ CapturingNetLog::CapturedEntryList entries;
+ net_log_.GetEntries(&entries);
+ size_t log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ 0,
+ NetLog::TYPE_DELEGATE_INFO,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries, log_position);
+
+ // Nothing else should add any delegate info to the request.
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+}
+
+// Tests handling of delegate info from a network delegate.
+TEST_F(URLRequestTestHTTP, NetworkDelegateInfo) {
+ ASSERT_TRUE(test_server_.Start());
+
+ TestDelegate request_delegate;
+ AsyncLoggingNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_delegate(&network_delegate);
+ context.set_net_log(&net_log_);
+ context.Init();
+
+ {
+ URLRequest r(test_server_.GetURL("simple.html"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
+ EXPECT_EQ(string16(), load_state.param);
+
+ r.Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(200, r.GetResponseCode());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ EXPECT_EQ(1, network_delegate.created_requests());
+ EXPECT_EQ(0, network_delegate.destroyed_requests());
+ }
+ EXPECT_EQ(1, network_delegate.destroyed_requests());
+
+ size_t log_position = 0;
+ CapturingNetLog::CapturedEntryList entries;
+ net_log_.GetEntries(&entries);
+ for (size_t i = 0; i < 3; ++i) {
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position + 1,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+ }
+
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+}
+
+// Tests handling of delegate info from a network delegate in the case of an
+// HTTP redirect.
+TEST_F(URLRequestTestHTTP, NetworkDelegateInfoRedirect) {
+ ASSERT_TRUE(test_server_.Start());
+
+ TestDelegate request_delegate;
+ AsyncLoggingNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_delegate(&network_delegate);
+ context.set_net_log(&net_log_);
+ context.Init();
+
+ {
+ URLRequest r(test_server_.GetURL("server-redirect?simple.html"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
+ EXPECT_EQ(string16(), load_state.param);
+
+ r.Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(200, r.GetResponseCode());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ EXPECT_EQ(2, network_delegate.created_requests());
+ EXPECT_EQ(0, network_delegate.destroyed_requests());
+ }
+ EXPECT_EQ(1, network_delegate.destroyed_requests());
+
+ size_t log_position = 0;
+ CapturingNetLog::CapturedEntryList entries;
+ net_log_.GetEntries(&entries);
+ // The NetworkDelegate logged information in OnBeforeURLRequest,
+ // OnBeforeSendHeaders, and OnHeadersReceived.
+ for (size_t i = 0; i < 3; ++i) {
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position + 1,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+ }
+
+ // The URLRequest::Delegate then gets informed about the redirect.
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position + 1,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ // The NetworkDelegate logged information in the same three events as before.
+ for (size_t i = 0; i < 3; ++i) {
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position + 1,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+ }
+
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+}
+
+// Tests handling of delegate info from a network delegate in the case of HTTP
+// AUTH.
+TEST_F(URLRequestTestHTTP, NetworkDelegateInfoAuth) {
+ ASSERT_TRUE(test_server_.Start());
+
+ TestDelegate request_delegate;
+ AsyncLoggingNetworkDelegate network_delegate;
+ TestURLRequestContext context(true);
+ context.set_network_delegate(&network_delegate);
+ context.set_net_log(&net_log_);
+ context.Init();
+
+ {
+ URLRequest r(test_server_.GetURL("auth-basic"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ EXPECT_EQ(LOAD_STATE_IDLE, load_state.state);
+ EXPECT_EQ(string16(), load_state.param);
+
+ r.Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(200, r.GetResponseCode());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ EXPECT_EQ(1, network_delegate.created_requests());
+ EXPECT_EQ(0, network_delegate.destroyed_requests());
+ }
+ EXPECT_EQ(1, network_delegate.destroyed_requests());
+
+ size_t log_position = 0;
+ CapturingNetLog::CapturedEntryList entries;
+ net_log_.GetEntries(&entries);
+ // The NetworkDelegate should have logged information in OnBeforeURLRequest,
+ // OnBeforeSendHeaders, OnHeadersReceived, OnAuthRequired, and then again in
+ // OnBeforeURLRequest and OnBeforeSendHeaders.
+ for (size_t i = 0; i < 6; ++i) {
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position + 1,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+ }
+
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+}
+
+// Tests handling of delegate info from a URLRequest::Delegate.
+TEST_F(URLRequestTestHTTP, URLRequestDelegateInfo) {
+ ASSERT_TRUE(test_server_.Start());
+
+ AsyncLoggingUrlRequestDelegate request_delegate(
+ AsyncLoggingUrlRequestDelegate::NO_CANCEL);
+ TestURLRequestContext context(true);
+ context.set_network_delegate(NULL);
+ context.set_net_log(&net_log_);
+ context.Init();
+
+ {
+ // A chunked response with delays between chunks is used to make sure that
+ // attempts by the URLRequest delegate to log information while reading the
+ // body are ignored. Since they are ignored, this test is robust against
+ // the possability of multiple reads being combined in the unlikely event
+ // that it occurs.
+ URLRequest r(test_server_.GetURL("chunked?waitBetweenChunks=20"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ r.Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(200, r.GetResponseCode());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ }
+
+ CapturingNetLog::CapturedEntryList entries;
+ net_log_.GetEntries(&entries);
+
+ // The delegate info should only have been logged on header complete. Other
+ // times it should silently be ignored.
+
+ size_t log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ 0,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_URL_REQUEST_DELEGATE));
+}
+
+// Tests handling of delegate info from a URLRequest::Delegate in the case of
+// an HTTP redirect.
+TEST_F(URLRequestTestHTTP, URLRequestDelegateInfoOnRedirect) {
+ ASSERT_TRUE(test_server_.Start());
+
+ AsyncLoggingUrlRequestDelegate request_delegate(
+ AsyncLoggingUrlRequestDelegate::NO_CANCEL);
+ TestURLRequestContext context(true);
+ context.set_network_delegate(NULL);
+ context.set_net_log(&net_log_);
+ context.Init();
+
+ {
+ URLRequest r(test_server_.GetURL("server-redirect?simple.html"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ r.Start();
+ base::RunLoop().Run();
+
+ EXPECT_EQ(200, r.GetResponseCode());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ }
+
+ CapturingNetLog::CapturedEntryList entries;
+ net_log_.GetEntries(&entries);
+
+ // Delegate info should only have been logged in OnReceivedRedirect and
+ // OnResponseStarted.
+ size_t log_position = 0;
+ for (int i = 0; i < 2; ++i) {
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+ }
+
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_URL_REQUEST_DELEGATE));
+}
+
+// Tests handling of delegate info from a URLRequest::Delegate in the case of
+// an HTTP redirect, with cancellation at various points.
+TEST_F(URLRequestTestHTTP, URLRequestDelegateOnRedirectCancelled) {
+ ASSERT_TRUE(test_server_.Start());
+
+ const AsyncLoggingUrlRequestDelegate::CancelStage kCancelStages[] = {
+ AsyncLoggingUrlRequestDelegate::CANCEL_ON_RECEIVED_REDIRECT,
+ AsyncLoggingUrlRequestDelegate::CANCEL_ON_RESPONSE_STARTED,
+ AsyncLoggingUrlRequestDelegate::CANCEL_ON_READ_COMPLETED,
+ };
+
+ for (size_t test_case = 0; test_case < arraysize(kCancelStages);
+ ++test_case) {
+ AsyncLoggingUrlRequestDelegate request_delegate(kCancelStages[test_case]);
+ TestURLRequestContext context(true);
+ CapturingNetLog net_log;
+ context.set_network_delegate(NULL);
+ context.set_net_log(&net_log);
+ context.Init();
+
+ {
+ URLRequest r(test_server_.GetURL("server-redirect?simple.html"),
+ DEFAULT_PRIORITY,
+ &request_delegate,
+ &context);
+ LoadStateWithParam load_state = r.GetLoadState();
+ r.Start();
+ base::RunLoop().Run();
+ EXPECT_EQ(URLRequestStatus::CANCELED, r.status().status());
+ }
+
+ CapturingNetLog::CapturedEntryList entries;
+ net_log.GetEntries(&entries);
+
+ // Delegate info is always logged in both OnReceivedRedirect and
+ // OnResponseStarted. In the CANCEL_ON_RECEIVED_REDIRECT, the
+ // OnResponseStarted delegate call is after cancellation, but logging is
+ // still currently supported in that call.
+ size_t log_position = 0;
+ for (int i = 0; i < 2; ++i) {
+ log_position = ExpectLogContainsSomewhereAfter(
+ entries,
+ log_position,
+ NetLog::TYPE_URL_REQUEST_DELEGATE,
+ NetLog::PHASE_BEGIN);
+
+ log_position = AsyncDelegateLogger::CheckDelegateInfo(entries,
+ log_position + 1);
+
+ ASSERT_LT(log_position, entries.size());
+ EXPECT_EQ(NetLog::TYPE_URL_REQUEST_DELEGATE, entries[log_position].type);
+ EXPECT_EQ(NetLog::PHASE_END, entries[log_position].phase);
+ }
+
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_DELEGATE_INFO));
+ EXPECT_FALSE(LogContainsEntryWithTypeAfter(
+ entries, log_position + 1, NetLog::TYPE_URL_REQUEST_DELEGATE));
+ }
+}
+
namespace {
const char kExtraHeader[] = "Allow-Snafu";
@@ -3572,7 +4471,7 @@ TEST_F(URLRequestTestHTTP, RedirectWithAdditionalHeadersTest) {
GURL original_url = test_server_.GetURL(
"server-redirect?" + destination_url.spec());
RedirectWithAdditionalHeadersDelegate d;
- URLRequest req(original_url, &d, &default_context_);
+ URLRequest req(original_url, DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
@@ -3608,7 +4507,7 @@ TEST_F(URLRequestTestHTTP, RedirectWithHeaderRemovalTest) {
GURL original_url = test_server_.GetURL(
"server-redirect?" + destination_url.spec());
RedirectWithHeaderRemovalDelegate d;
- URLRequest req(original_url, &d, &default_context_);
+ URLRequest req(original_url, DEFAULT_PRIORITY, &d, &default_context_);
req.SetExtraRequestHeaderByName(kExtraHeaderToRemove, "dummy", false);
req.Start();
base::RunLoop().Run();
@@ -3624,7 +4523,10 @@ TEST_F(URLRequestTestHTTP, RedirectWithHeaderRemovalTest) {
TEST_F(URLRequestTestHTTP, CancelTest) {
TestDelegate d;
{
- URLRequest r(GURL("http://www.google.com/"), &d, &default_context_);
+ URLRequest r(GURL("http://www.google.com/"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3646,7 +4548,10 @@ TEST_F(URLRequestTestHTTP, CancelTest2) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server_.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
d.set_cancel_in_response_started(true);
@@ -3667,7 +4572,10 @@ TEST_F(URLRequestTestHTTP, CancelTest3) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server_.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
d.set_cancel_in_received_data(true);
@@ -3691,7 +4599,10 @@ TEST_F(URLRequestTestHTTP, CancelTest4) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server_.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3717,7 +4628,10 @@ TEST_F(URLRequestTestHTTP, CancelTest5) {
// populate cache
{
TestDelegate d;
- URLRequest r(test_server_.GetURL("cachetime"), &d, &default_context_);
+ URLRequest r(test_server_.GetURL("cachetime"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
base::RunLoop().Run();
EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
@@ -3726,7 +4640,10 @@ TEST_F(URLRequestTestHTTP, CancelTest5) {
// cancel read from cache (see bug 990242)
{
TestDelegate d;
- URLRequest r(test_server_.GetURL("cachetime"), &d, &default_context_);
+ URLRequest r(test_server_.GetURL("cachetime"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
r.Cancel();
base::RunLoop().Run();
@@ -3753,7 +4670,8 @@ TEST_F(URLRequestTestHTTP, PostEmptyTest) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("echo"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, &default_context_);
r.set_method("POST");
r.Start();
@@ -3775,7 +4693,8 @@ TEST_F(URLRequestTestHTTP, PostFileTest) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("echo"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, &default_context_);
r.set_method("POST");
base::FilePath dir;
@@ -3796,16 +4715,8 @@ TEST_F(URLRequestTestHTTP, PostFileTest) {
0,
kuint64max,
base::Time()));
-
- // This file should just be ignored in the upload stream.
- element_readers.push_back(new UploadFileElementReader(
- base::MessageLoopProxy::current().get(),
- base::FilePath(FILE_PATH_LITERAL(
- "c:\\path\\to\\non\\existant\\file.randomness.12345")),
- 0,
- kuint64max,
- base::Time()));
- r.set_upload(make_scoped_ptr(new UploadDataStream(&element_readers, 0)));
+ r.set_upload(make_scoped_ptr(
+ new UploadDataStream(element_readers.Pass(), 0)));
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -3813,10 +4724,10 @@ TEST_F(URLRequestTestHTTP, PostFileTest) {
base::RunLoop().Run();
int64 size = 0;
- ASSERT_EQ(true, file_util::GetFileSize(path, &size));
+ ASSERT_EQ(true, base::GetFileSize(path, &size));
scoped_ptr<char[]> buf(new char[size]);
- ASSERT_EQ(size, file_util::ReadFile(path, buf.get(), size));
+ ASSERT_EQ(size, base::ReadFile(path, buf.get(), size));
ASSERT_EQ(1, d.response_started_count())
<< "request failed: " << r.status().status()
@@ -3829,12 +4740,57 @@ TEST_F(URLRequestTestHTTP, PostFileTest) {
}
}
+TEST_F(URLRequestTestHTTP, PostUnreadableFileTest) {
+ ASSERT_TRUE(test_server_.Start());
+
+ TestDelegate d;
+ {
+ URLRequest r(test_server_.GetURL("echo"), DEFAULT_PRIORITY,
+ &d, &default_context_);
+ r.set_method("POST");
+
+ ScopedVector<UploadElementReader> element_readers;
+
+ element_readers.push_back(new UploadFileElementReader(
+ base::MessageLoopProxy::current().get(),
+ base::FilePath(FILE_PATH_LITERAL(
+ "c:\\path\\to\\non\\existant\\file.randomness.12345")),
+ 0,
+ kuint64max,
+ base::Time()));
+ r.set_upload(make_scoped_ptr(
+ new UploadDataStream(element_readers.Pass(), 0)));
+
+ r.Start();
+ EXPECT_TRUE(r.is_pending());
+
+ base::RunLoop().Run();
+
+ // TODO(tzik): Remove this #if after we stop supporting Chrome Frame.
+ // http://crbug.com/317432
+#if defined(CHROME_FRAME_NET_TESTS)
+ EXPECT_FALSE(d.request_failed());
+ EXPECT_FALSE(d.received_data_before_response());
+ EXPECT_EQ(0, d.bytes_received());
+ EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+ EXPECT_EQ(OK, r.status().error());
+#else
+ EXPECT_TRUE(d.request_failed());
+ EXPECT_FALSE(d.received_data_before_response());
+ EXPECT_EQ(0, d.bytes_received());
+ EXPECT_EQ(URLRequestStatus::FAILED, r.status().status());
+ EXPECT_EQ(ERR_FILE_NOT_FOUND, r.status().error());
+#endif // defined(CHROME_FRAME_NET_TESTS)
+ }
+}
+
TEST_F(URLRequestTestHTTP, TestPostChunkedDataBeforeStart) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("echo"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, &default_context_);
r.EnableChunkedUpload();
r.set_method("POST");
AddChunksToUpload(&r);
@@ -3852,7 +4808,8 @@ TEST_F(URLRequestTestHTTP, TestPostChunkedDataJustAfterStart) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("echo"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, &default_context_);
r.EnableChunkedUpload();
r.set_method("POST");
r.Start();
@@ -3869,7 +4826,8 @@ TEST_F(URLRequestTestHTTP, TestPostChunkedDataAfterStart) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("echo"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("echo"), DEFAULT_PRIORITY, &d, &default_context_);
r.EnableChunkedUpload();
r.set_method("POST");
r.Start();
@@ -3887,8 +4845,10 @@ TEST_F(URLRequestTestHTTP, ResponseHeadersTest) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("files/with-headers.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/with-headers.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -3921,10 +4881,10 @@ TEST_F(URLRequestTestHTTP, ProcessSTS) {
ASSERT_TRUE(https_test_server.Start());
TestDelegate d;
- URLRequest request(
- https_test_server.GetURL("files/hsts-headers.html"),
- &d,
- &default_context_);
+ URLRequest request(https_test_server.GetURL("files/hsts-headers.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
request.Start();
base::RunLoop().Run();
@@ -3965,10 +4925,10 @@ TEST_F(URLRequestTestHTTP, MAYBE_ProcessPKP) {
ASSERT_TRUE(https_test_server.Start());
TestDelegate d;
- URLRequest request(
- https_test_server.GetURL("files/hpkp-headers.html"),
- &d,
- &default_context_);
+ URLRequest request(https_test_server.GetURL("files/hpkp-headers.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
request.Start();
base::RunLoop().Run();
@@ -3998,6 +4958,7 @@ TEST_F(URLRequestTestHTTP, ProcessSTSOnce) {
TestDelegate d;
URLRequest request(
https_test_server.GetURL("files/hsts-multiple-headers.html"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
request.Start();
@@ -4027,6 +4988,7 @@ TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP) {
TestDelegate d;
URLRequest request(
https_test_server.GetURL("files/hsts-and-hpkp-headers.html"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
request.Start();
@@ -4069,6 +5031,7 @@ TEST_F(URLRequestTestHTTP, ProcessSTSAndPKP2) {
TestDelegate d;
URLRequest request(
https_test_server.GetURL("files/hsts-and-hpkp-headers2.html"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
request.Start();
@@ -4098,8 +5061,10 @@ TEST_F(URLRequestTestHTTP, ContentTypeNormalizationTest) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(test_server_.GetURL(
- "files/content-type-normalization.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/content-type-normalization.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -4131,8 +5096,10 @@ TEST_F(URLRequestTestHTTP, RestrictFileRedirects) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(test_server_.GetURL(
- "files/redirect-to-file.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/redirect-to-file.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -4144,8 +5111,10 @@ TEST_F(URLRequestTestHTTP, RestrictDataRedirects) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(test_server_.GetURL(
- "files/redirect-to-data.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/redirect-to-data.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::MessageLoop::current()->Run();
@@ -4157,8 +5126,10 @@ TEST_F(URLRequestTestHTTP, RedirectToInvalidURL) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(test_server_.GetURL(
- "files/redirect-to-invalid-url.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/redirect-to-invalid-url.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -4170,8 +5141,10 @@ TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheader?Referer"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("echoheader?Referer"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.SetReferrer("http://user:pass@foo.com/");
req.Start();
base::RunLoop().Run();
@@ -4183,8 +5156,10 @@ TEST_F(URLRequestTestHTTP, NoFragmentInReferrer) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheader?Referer"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("echoheader?Referer"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.SetReferrer("http://foo.com/test#fragment");
req.Start();
base::RunLoop().Run();
@@ -4196,8 +5171,10 @@ TEST_F(URLRequestTestHTTP, EmptyReferrerAfterValidReferrer) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheader?Referer"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("echoheader?Referer"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.SetReferrer("http://foo.com/test#fragment");
req.SetReferrer("");
req.Start();
@@ -4212,8 +5189,10 @@ TEST_F(URLRequestTestHTTP, CancelRedirect) {
TestDelegate d;
{
d.set_cancel_in_received_redirect(true);
- URLRequest req(
- test_server_.GetURL("files/redirect-test.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/redirect-test.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -4231,7 +5210,7 @@ TEST_F(URLRequestTestHTTP, DeferredRedirect) {
{
d.set_quit_on_redirect(true);
GURL test_url(test_server_.GetURL("files/redirect-test.html"));
- URLRequest req(test_url, &d, &default_context_);
+ URLRequest req(test_url, DEFAULT_PRIORITY, &d, &default_context_);
req.Start();
base::RunLoop().Run();
@@ -4265,7 +5244,7 @@ TEST_F(URLRequestTestHTTP, DeferredRedirect_GetFullRequestHeaders) {
{
d.set_quit_on_redirect(true);
GURL test_url(test_server_.GetURL("files/redirect-test.html"));
- URLRequest req(test_url, &d, &default_context_);
+ URLRequest req(test_url, DEFAULT_PRIORITY, &d, &default_context_);
EXPECT_FALSE(d.have_full_request_headers());
@@ -4306,8 +5285,10 @@ TEST_F(URLRequestTestHTTP, CancelDeferredRedirect) {
TestDelegate d;
{
d.set_quit_on_redirect(true);
- URLRequest req(
- test_server_.GetURL("files/redirect-test.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/redirect-test.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.Start();
base::RunLoop().Run();
@@ -4329,8 +5310,10 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
// Populate the cache.
{
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheadercache?foo"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("echoheadercache?foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
HttpRequestHeaders headers;
headers.SetHeader("foo", "1");
req.SetExtraRequestHeaders(headers);
@@ -4345,8 +5328,10 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
// Expect a cache hit.
{
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheadercache?foo"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("echoheadercache?foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
HttpRequestHeaders headers;
headers.SetHeader("foo", "1");
req.SetExtraRequestHeaders(headers);
@@ -4363,8 +5348,10 @@ TEST_F(URLRequestTestHTTP, VaryHeader) {
// Expect a cache miss.
{
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheadercache?foo"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("echoheadercache?foo"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
HttpRequestHeaders headers;
headers.SetHeader("foo", "2");
req.SetExtraRequestHeaders(headers);
@@ -4387,7 +5374,10 @@ TEST_F(URLRequestTestHTTP, BasicAuth) {
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
- URLRequest r(test_server_.GetURL("auth-basic"), &d, &default_context_);
+ URLRequest r(test_server_.GetURL("auth-basic"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
base::RunLoop().Run();
@@ -4402,8 +5392,11 @@ TEST_F(URLRequestTestHTTP, BasicAuth) {
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
- URLRequest r(test_server_.GetURL("auth-basic"), &d, &default_context_);
- r.set_load_flags(LOAD_VALIDATE_CACHE);
+ URLRequest r(test_server_.GetURL("auth-basic"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
+ r.SetLoadFlags(LOAD_VALIDATE_CACHE);
r.Start();
base::RunLoop().Run();
@@ -4434,7 +5427,7 @@ TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
- URLRequest r(url_requiring_auth, &d, &context);
+ URLRequest r(url_requiring_auth, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -4463,7 +5456,7 @@ TEST_F(URLRequestTestHTTP, BasicAuthWithCookies) {
replacements.SetPasswordStr(password);
GURL url_with_identity = url_requiring_auth.ReplaceComponents(replacements);
- URLRequest r(url_with_identity, &d, &context);
+ URLRequest r(url_with_identity, DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -4485,7 +5478,10 @@ TEST_F(URLRequestTestHTTP, BasicAuthLoadTiming) {
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
- URLRequest r(test_server_.GetURL("auth-basic"), &d, &default_context_);
+ URLRequest r(test_server_.GetURL("auth-basic"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
base::RunLoop().Run();
@@ -4516,8 +5512,11 @@ TEST_F(URLRequestTestHTTP, BasicAuthLoadTiming) {
TestDelegate d;
d.set_credentials(AuthCredentials(kUser, kSecret));
- URLRequest r(test_server_.GetURL("auth-basic"), &d, &default_context_);
- r.set_load_flags(LOAD_VALIDATE_CACHE);
+ URLRequest r(test_server_.GetURL("auth-basic"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
+ r.SetLoadFlags(LOAD_VALIDATE_CACHE);
r.Start();
base::RunLoop().Run();
@@ -4545,8 +5544,10 @@ TEST_F(URLRequestTestHTTP, Post302RedirectGet) {
const char kData[] = "hello world";
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("files/redirect-to-echoall"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("files/redirect-to-echoall"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("POST");
req.set_upload(make_scoped_ptr(CreateSimpleUploadData(kData)));
@@ -4632,7 +5633,10 @@ TEST_F(URLRequestTestHTTP, InterceptPost302RedirectGet) {
const char kData[] = "hello world";
TestDelegate d;
- URLRequest req(test_server_.GetURL("empty.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("empty.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("POST");
req.set_upload(make_scoped_ptr(CreateSimpleUploadData(kData)));
HttpRequestHeaders headers;
@@ -4656,7 +5660,10 @@ TEST_F(URLRequestTestHTTP, InterceptPost307RedirectPost) {
const char kData[] = "hello world";
TestDelegate d;
- URLRequest req(test_server_.GetURL("empty.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("empty.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
req.set_method("POST");
req.set_upload(make_scoped_ptr(CreateSimpleUploadData(kData)));
HttpRequestHeaders headers;
@@ -4679,7 +5686,7 @@ TEST_F(URLRequestTestHTTP, InterceptPost307RedirectPost) {
TEST_F(URLRequestTestHTTP, DefaultAcceptLanguage) {
ASSERT_TRUE(test_server_.Start());
- StaticHttpUserAgentSettings settings("en", EmptyString());
+ StaticHttpUserAgentSettings settings("en", std::string());
TestNetworkDelegate network_delegate; // Must outlive URLRequests.
TestURLRequestContext context(true);
context.set_network_delegate(&network_delegate);
@@ -4687,8 +5694,10 @@ TEST_F(URLRequestTestHTTP, DefaultAcceptLanguage) {
context.Init();
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheader?Accept-Language"), &d, &context);
+ URLRequest req(test_server_.GetURL("echoheader?Accept-Language"),
+ DEFAULT_PRIORITY,
+ &d,
+ &context);
req.Start();
base::RunLoop().Run();
EXPECT_EQ("en", d.data_received());
@@ -4698,7 +5707,8 @@ TEST_F(URLRequestTestHTTP, DefaultAcceptLanguage) {
TEST_F(URLRequestTestHTTP, EmptyAcceptLanguage) {
ASSERT_TRUE(test_server_.Start());
- StaticHttpUserAgentSettings settings(EmptyString(), EmptyString());
+ std::string empty_string; // Avoid most vexing parse on line below.
+ StaticHttpUserAgentSettings settings(empty_string, empty_string);
TestNetworkDelegate network_delegate; // Must outlive URLRequests.
TestURLRequestContext context(true);
context.set_network_delegate(&network_delegate);
@@ -4708,8 +5718,10 @@ TEST_F(URLRequestTestHTTP, EmptyAcceptLanguage) {
context.set_http_user_agent_settings(&settings);
TestDelegate d;
- URLRequest req(
- test_server_.GetURL("echoheader?Accept-Language"), &d, &context);
+ URLRequest req(test_server_.GetURL("echoheader?Accept-Language"),
+ DEFAULT_PRIORITY,
+ &d,
+ &context);
req.Start();
base::RunLoop().Run();
EXPECT_EQ("None", d.data_received());
@@ -4722,6 +5734,7 @@ TEST_F(URLRequestTestHTTP, OverrideAcceptLanguage) {
TestDelegate d;
URLRequest req(test_server_.GetURL("echoheader?Accept-Language"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
HttpRequestHeaders headers;
@@ -4738,6 +5751,7 @@ TEST_F(URLRequestTestHTTP, DefaultAcceptEncoding) {
TestDelegate d;
URLRequest req(test_server_.GetURL("echoheader?Accept-Encoding"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
HttpRequestHeaders headers;
@@ -4754,6 +5768,7 @@ TEST_F(URLRequestTestHTTP, OverrideAcceptEncoding) {
TestDelegate d;
URLRequest req(test_server_.GetURL("echoheader?Accept-Encoding"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
HttpRequestHeaders headers;
@@ -4771,6 +5786,7 @@ TEST_F(URLRequestTestHTTP, SetAcceptCharset) {
TestDelegate d;
URLRequest req(test_server_.GetURL("echoheader?Accept-Charset"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
HttpRequestHeaders headers;
@@ -4787,6 +5803,7 @@ TEST_F(URLRequestTestHTTP, DefaultUserAgent) {
TestDelegate d;
URLRequest req(test_server_.GetURL("echoheader?User-Agent"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
req.Start();
@@ -4801,6 +5818,7 @@ TEST_F(URLRequestTestHTTP, OverrideUserAgent) {
TestDelegate d;
URLRequest req(test_server_.GetURL("echoheader?User-Agent"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
HttpRequestHeaders headers;
@@ -4837,7 +5855,8 @@ TEST_F(URLRequestTestHTTP, EmptyHttpUserAgentSettings) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); i++) {
TestDelegate d;
- URLRequest req(test_server_.GetURL(tests[i].request), &d, &context);
+ URLRequest req(
+ test_server_.GetURL(tests[i].request), DEFAULT_PRIORITY, &d, &context);
req.Start();
base::RunLoop().Run();
EXPECT_EQ(tests[i].expected_response, d.data_received())
@@ -4851,7 +5870,10 @@ TEST_F(URLRequestTestHTTP, SetSubsequentJobPriority) {
ASSERT_TRUE(test_server_.Start());
TestDelegate d;
- URLRequest req(test_server_.GetURL("empty.html"), &d, &default_context_);
+ URLRequest req(test_server_.GetURL("empty.html"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
EXPECT_EQ(DEFAULT_PRIORITY, req.priority());
scoped_refptr<URLRequestRedirectJob> redirect_job =
@@ -4895,7 +5917,10 @@ TEST_F(HTTPSRequestTest, HTTPSGetTest) {
TestDelegate d;
{
- URLRequest r(test_server.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -4926,7 +5951,10 @@ TEST_F(HTTPSRequestTest, HTTPSMismatchedTest) {
TestDelegate d;
{
d.set_allow_certificate_errors(err_allowed);
- URLRequest r(test_server.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -4962,7 +5990,10 @@ TEST_F(HTTPSRequestTest, HTTPSExpiredTest) {
TestDelegate d;
{
d.set_allow_certificate_errors(err_allowed);
- URLRequest r(test_server.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5007,7 +6038,8 @@ TEST_F(HTTPSRequestTest, TLSv1Fallback) {
TestURLRequestContext context(true);
context.Init();
d.set_allow_certificate_errors(true);
- URLRequest r(test_server.GetURL(std::string()), &d, &context);
+ URLRequest r(
+ test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -5019,6 +6051,46 @@ TEST_F(HTTPSRequestTest, TLSv1Fallback) {
EXPECT_TRUE(r.ssl_info().connection_status & SSL_CONNECTION_VERSION_FALLBACK);
}
+// Tests that we don't fallback with servers that implement TLS_FALLBACK_SCSV.
+#if defined(USE_OPENSSL)
+TEST_F(HTTPSRequestTest, DISABLED_FallbackSCSV) {
+#else
+TEST_F(HTTPSRequestTest, FallbackSCSV) {
+#endif
+ SpawnedTestServer::SSLOptions ssl_options(
+ SpawnedTestServer::SSLOptions::CERT_OK);
+ // Configure HTTPS server to be intolerant of TLS >= 1.0 in order to trigger
+ // a version fallback.
+ ssl_options.tls_intolerant =
+ SpawnedTestServer::SSLOptions::TLS_INTOLERANT_ALL;
+ // Have the server process TLS_FALLBACK_SCSV so that version fallback
+ // connections are rejected.
+ ssl_options.fallback_scsv_enabled = true;
+
+ SpawnedTestServer test_server(
+ SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
+ ASSERT_TRUE(test_server.Start());
+
+ TestDelegate d;
+ TestURLRequestContext context(true);
+ context.Init();
+ d.set_allow_certificate_errors(true);
+ URLRequest r(
+ test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
+ r.Start();
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+ // ERR_SSL_VERSION_OR_CIPHER_MISMATCH is how the server simulates version
+ // intolerance. If the fallback SCSV is processed when the original error
+ // that caused the fallback should be returned, which should be
+ // ERR_SSL_VERSION_OR_CIPHER_MISMATCH.
+ EXPECT_EQ(ERR_SSL_VERSION_OR_CIPHER_MISMATCH, r.status().error());
+}
+
// This tests that a load of www.google.com with a certificate error sets
// the |certificate_errors_are_fatal| flag correctly. This flag will cause
// the interstitial to be fatal.
@@ -5048,6 +6120,7 @@ TEST_F(HTTPSRequestTest, HTTPSPreloadedHSTSTest) {
TestDelegate d;
URLRequest r(GURL(base::StringPrintf("https://www.google.com:%d",
test_server.host_port_pair().port())),
+ DEFAULT_PRIORITY,
&d,
&context);
@@ -5096,6 +6169,7 @@ TEST_F(HTTPSRequestTest, HTTPSErrorsNoClobberTSSTest) {
TestDelegate d;
URLRequest r(GURL(base::StringPrintf("https://www.google.com:%d",
test_server.host_port_pair().port())),
+ DEFAULT_PRIORITY,
&d,
&context);
@@ -5167,6 +6241,7 @@ TEST_F(HTTPSRequestTest, HSTSPreservesPosts) {
URLRequest req(GURL(base::StringPrintf("http://www.somewhere.com:%d/echo",
test_server.host_port_pair().port())),
+ DEFAULT_PRIORITY,
&d,
&context);
req.set_method("POST");
@@ -5200,7 +6275,8 @@ TEST_F(HTTPSRequestTest, SSLv3Fallback) {
TestURLRequestContext context(true);
context.Init();
d.set_allow_certificate_errors(true);
- URLRequest r(test_server.GetURL(std::string()), &d, &context);
+ URLRequest r(
+ test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context);
r.Start();
base::RunLoop().Run();
@@ -5249,7 +6325,10 @@ TEST_F(HTTPSRequestTest, ClientAuthTest) {
SSLClientAuthTestDelegate d;
{
- URLRequest r(test_server.GetURL(std::string()), &d, &default_context_);
+ URLRequest r(test_server.GetURL(std::string()),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5288,8 +6367,10 @@ TEST_F(HTTPSRequestTest, ResumeTest) {
{
TestDelegate d;
- URLRequest r(
- test_server.GetURL("ssl-session-cache"), &d, &default_context_);
+ URLRequest r(test_server.GetURL("ssl-session-cache"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5304,8 +6385,10 @@ TEST_F(HTTPSRequestTest, ResumeTest) {
{
TestDelegate d;
- URLRequest r(
- test_server.GetURL("ssl-session-cache"), &d, &default_context_);
+ URLRequest r(test_server.GetURL("ssl-session-cache"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5357,8 +6440,10 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
{
TestDelegate d;
- URLRequest r(
- test_server.GetURL("ssl-session-cache"), &d, &default_context_);
+ URLRequest r(test_server.GetURL("ssl-session-cache"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5389,8 +6474,10 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
{
TestDelegate d;
- URLRequest r(
- test_server.GetURL("ssl-session-cache"), &d, &default_context_);
+ URLRequest r(test_server.GetURL("ssl-session-cache"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5424,6 +6511,104 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
}
}
+class HTTPSSessionTest : public testing::Test {
+ public:
+ HTTPSSessionTest() : default_context_(true) {
+ cert_verifier_.set_default_result(net::OK);
+
+ default_context_.set_network_delegate(&default_network_delegate_);
+ default_context_.set_cert_verifier(&cert_verifier_);
+ default_context_.Init();
+ }
+ virtual ~HTTPSSessionTest() {}
+
+ protected:
+ MockCertVerifier cert_verifier_;
+ TestNetworkDelegate default_network_delegate_; // Must outlive URLRequest.
+ TestURLRequestContext default_context_;
+};
+
+// Tests that session resumption is not attempted if an invalid certificate
+// is presented.
+TEST_F(HTTPSSessionTest, DontResumeSessionsForInvalidCertificates) {
+ SpawnedTestServer::SSLOptions ssl_options;
+ ssl_options.record_resume = true;
+ SpawnedTestServer test_server(
+ SpawnedTestServer::TYPE_HTTPS,
+ ssl_options,
+ base::FilePath(FILE_PATH_LITERAL("net/data/ssl")));
+ ASSERT_TRUE(test_server.Start());
+
+ SSLClientSocket::ClearSessionCache();
+
+ // Simulate the certificate being expired and attempt a connection.
+ cert_verifier_.set_default_result(net::ERR_CERT_DATE_INVALID);
+ {
+ TestDelegate d;
+ URLRequest r(test_server.GetURL("ssl-session-cache"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
+
+ r.Start();
+ EXPECT_TRUE(r.is_pending());
+
+ base::RunLoop().Run();
+
+ EXPECT_EQ(1, d.response_started_count());
+ }
+
+ reinterpret_cast<HttpCache*>(default_context_.http_transaction_factory())->
+ CloseAllConnections();
+
+ // Now change the certificate to be acceptable (so that the response is
+ // loaded), and ensure that no session id is presented to the peer.
+ cert_verifier_.set_default_result(net::OK);
+ {
+ TestDelegate d;
+ URLRequest r(test_server.GetURL("ssl-session-cache"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
+
+ r.Start();
+ EXPECT_TRUE(r.is_pending());
+
+ base::RunLoop().Run();
+
+ // The response will look like;
+ // insert abc
+ // insert xyz
+ //
+ // With a newline at the end which makes the split think that there are
+ // three lines.
+ //
+ // If a session was presented (eg: a bug), then the response would look
+ // like;
+ // insert abc
+ // lookup abc
+ // insert xyz
+
+ EXPECT_EQ(1, d.response_started_count());
+ std::vector<std::string> lines;
+ base::SplitString(d.data_received(), '\n', &lines);
+ ASSERT_EQ(3u, lines.size()) << d.data_received();
+
+ std::string session_id;
+ for (size_t i = 0; i < 2; i++) {
+ std::vector<std::string> parts;
+ base::SplitString(lines[i], '\t', &parts);
+ ASSERT_EQ(2u, parts.size());
+ EXPECT_EQ("insert", parts[0]);
+ if (i == 0) {
+ session_id = parts[1];
+ } else {
+ EXPECT_NE(session_id, parts[1]);
+ }
+ }
+ }
+}
+
class TestSSLConfigService : public SSLConfigService {
public:
TestSSLConfigService(bool ev_enabled,
@@ -5508,7 +6693,8 @@ class HTTPSOCSPTest : public HTTPSRequestTest {
TestDelegate d;
d.set_allow_certificate_errors(true);
- URLRequest r(test_server.GetURL(std::string()), &d, &context_);
+ URLRequest r(
+ test_server.GetURL(std::string()), DEFAULT_PRIORITY, &d, &context_);
r.Start();
base::RunLoop().Run();
@@ -5963,7 +7149,7 @@ TEST_F(URLRequestTestFTP, UnsafePort) {
TestDelegate d;
{
- URLRequest r(url, &d, &default_context_);
+ URLRequest r(url, DEFAULT_PRIORITY, &d, &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -5981,7 +7167,8 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPDirectoryListing) {
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("/"), &d, &default_context_);
+ URLRequest r(
+ test_server_.GetURL("/"), DEFAULT_PRIORITY, &d, &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
@@ -6007,14 +7194,17 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPGetTestAnonymous) {
app_path = app_path.AppendASCII("LICENSE");
TestDelegate d;
{
- URLRequest r(test_server_.GetURL("/LICENSE"), &d, &default_context_);
+ URLRequest r(test_server_.GetURL("/LICENSE"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d.response_started_count());
@@ -6038,6 +7228,7 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPGetTest) {
{
URLRequest r(
test_server_.GetURLWithUserAndPassword("/LICENSE", "chrome", "chrome"),
+ DEFAULT_PRIORITY,
&d,
&default_context_);
r.Start();
@@ -6046,7 +7237,7 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPGetTest) {
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(test_server_.host_port_pair().host(),
@@ -6072,19 +7263,18 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCheckWrongPassword) {
app_path = app_path.AppendASCII("LICENSE");
TestDelegate d;
{
- URLRequest r(
- test_server_.GetURLWithUserAndPassword("/LICENSE",
- "chrome",
- "wrong_password"),
- &d,
- &default_context_);
+ URLRequest r(test_server_.GetURLWithUserAndPassword(
+ "/LICENSE", "chrome", "wrong_password"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d.response_started_count());
@@ -6105,19 +7295,18 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCheckWrongPasswordRestart) {
// the initial login with wrong credentials will fail.
d.set_credentials(AuthCredentials(kChrome, kChrome));
{
- URLRequest r(
- test_server_.GetURLWithUserAndPassword("/LICENSE",
- "chrome",
- "wrong_password"),
- &d,
- &default_context_);
+ URLRequest r(test_server_.GetURLWithUserAndPassword(
+ "/LICENSE", "chrome", "wrong_password"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d.response_started_count());
@@ -6135,19 +7324,18 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCheckWrongUser) {
app_path = app_path.AppendASCII("LICENSE");
TestDelegate d;
{
- URLRequest r(
- test_server_.GetURLWithUserAndPassword("/LICENSE",
- "wrong_user",
- "chrome"),
- &d,
- &default_context_);
+ URLRequest r(test_server_.GetURLWithUserAndPassword(
+ "/LICENSE", "wrong_user", "chrome"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d.response_started_count());
@@ -6168,19 +7356,18 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCheckWrongUserRestart) {
// the initial login with wrong credentials will fail.
d.set_credentials(AuthCredentials(kChrome, kChrome));
{
- URLRequest r(
- test_server_.GetURLWithUserAndPassword("/LICENSE",
- "wrong_user",
- "chrome"),
- &d,
- &default_context_);
+ URLRequest r(test_server_.GetURLWithUserAndPassword(
+ "/LICENSE", "wrong_user", "chrome"),
+ DEFAULT_PRIORITY,
+ &d,
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d.response_started_count());
@@ -6201,9 +7388,8 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCacheURLCredentials) {
{
// Pass correct login identity in the URL.
URLRequest r(
- test_server_.GetURLWithUserAndPassword("/LICENSE",
- "chrome",
- "chrome"),
+ test_server_.GetURLWithUserAndPassword("/LICENSE", "chrome", "chrome"),
+ DEFAULT_PRIORITY,
d.get(),
&default_context_);
r.Start();
@@ -6212,7 +7398,7 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCacheURLCredentials) {
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d->response_started_count());
@@ -6223,14 +7409,17 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCacheURLCredentials) {
d.reset(new TestDelegate);
{
// This request should use cached identity from previous request.
- URLRequest r(test_server_.GetURL("/LICENSE"), d.get(), &default_context_);
+ URLRequest r(test_server_.GetURL("/LICENSE"),
+ DEFAULT_PRIORITY,
+ d.get(),
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d->response_started_count());
@@ -6252,19 +7441,18 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCacheLoginBoxCredentials) {
// the initial login with wrong credentials will fail.
d->set_credentials(AuthCredentials(kChrome, kChrome));
{
- URLRequest r(
- test_server_.GetURLWithUserAndPassword("/LICENSE",
- "chrome",
- "wrong_password"),
- d.get(),
- &default_context_);
+ URLRequest r(test_server_.GetURLWithUserAndPassword(
+ "/LICENSE", "chrome", "wrong_password"),
+ DEFAULT_PRIORITY,
+ d.get(),
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d->response_started_count());
@@ -6278,14 +7466,17 @@ TEST_F(URLRequestTestFTP, DISABLED_FTPCacheLoginBoxCredentials) {
{
// Don't pass wrong credentials in the URL, they would override valid cached
// ones.
- URLRequest r(test_server_.GetURL("/LICENSE"), d.get(), &default_context_);
+ URLRequest r(test_server_.GetURL("/LICENSE"),
+ DEFAULT_PRIORITY,
+ d.get(),
+ &default_context_);
r.Start();
EXPECT_TRUE(r.is_pending());
base::RunLoop().Run();
int64 file_size = 0;
- file_util::GetFileSize(app_path, &file_size);
+ base::GetFileSize(app_path, &file_size);
EXPECT_FALSE(r.is_pending());
EXPECT_EQ(1, d->response_started_count());
diff --git a/chromium/net/url_request/websocket_handshake_userdata_key.cc b/chromium/net/url_request/websocket_handshake_userdata_key.cc
new file mode 100644
index 00000000000..8a37de5b883
--- /dev/null
+++ b/chromium/net/url_request/websocket_handshake_userdata_key.cc
@@ -0,0 +1,11 @@
+// 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/url_request/websocket_handshake_userdata_key.h"
+
+namespace net {
+
+const char kWebSocketHandshakeUserDataKey[] = "WebSocket";
+
+} // namespace net
diff --git a/chromium/net/url_request/websocket_handshake_userdata_key.h b/chromium/net/url_request/websocket_handshake_userdata_key.h
new file mode 100644
index 00000000000..63b75b79402
--- /dev/null
+++ b/chromium/net/url_request/websocket_handshake_userdata_key.h
@@ -0,0 +1,21 @@
+// 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.
+
+// The key for WebSocket UserData in URLRequest objects. This is included in
+// net/url_request because net/websockets is not linked in on iOS.
+
+#ifndef NET_URL_REQUEST_WEBSOCKET_HANDSHAKE_USERDATA_KEY_H_
+#define NET_URL_REQUEST_WEBSOCKET_HANDSHAKE_USERDATA_KEY_H_
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// This variable has a unique address, which is used as the key to store
+// WebSocket-handshake related data in a URLRequest object.
+extern NET_EXPORT_PRIVATE const char kWebSocketHandshakeUserDataKey[];
+
+} // namespace net
+
+#endif // NET_URL_REQUEST_WEBSOCKET_HANDSHAKE_USERDATA_KEY_H_
diff --git a/chromium/net/websockets/README b/chromium/net/websockets/README
index 1d1e1c3538f..fab4c203bc8 100644
--- a/chromium/net/websockets/README
+++ b/chromium/net/websockets/README
@@ -10,8 +10,6 @@ low-level socket-like interface to the renderer process. It is described in the
design doc at
https://docs.google.com/a/google.com/document/d/1_R6YjCIrm4kikJ3YeapcOU2Keqr3lVUPd-OeaIJ93qQ/preview
-websocket_handshake_handler.cc
-websocket_handshake_handler.h
websocket_handshake_handler_test.cc
websocket_handshake_handler_spdy_test.cc
websocket_job.cc
@@ -29,39 +27,59 @@ performs framing and implements protocol semantics in the browser process, and
presents a high-level interface to the renderer process similar to a
multiplexing proxy. This is not yet used in any stable Chromium version.
+websocket_basic_handshake_stream.cc
+websocket_basic_handshake_stream.h
websocket_basic_stream.cc
websocket_basic_stream.h
websocket_basic_stream_test.cc
websocket_channel.cc
websocket_channel.h
websocket_channel_test.cc
-websocket_deflater.h
+websocket_deflate_predictor.h
+websocket_deflate_predictor_impl.cc
+websocket_deflate_predictor_impl.h
+websocket_deflate_predictor_impl_test.cc
+websocket_deflate_stream.cc
+websocket_deflate_stream.h
+websocket_deflate_stream_test.cc
websocket_deflater.cc
+websocket_deflater.h
websocket_deflater_test.cc
websocket_errors.cc
websocket_errors.h
+websocket_errors_test.cc
+websocket_event_interface.h
websocket_extension.cc
websocket_extension.h
websocket_extension_parser.cc
websocket_extension_parser.h
websocket_extension_parser_test.cc
-websocket_errors_test.cc
-websocket_event_interface.h
websocket_frame.cc
websocket_frame.h
websocket_frame_parser.cc
websocket_frame_parser.h
websocket_frame_parser_test.cc
websocket_frame_test.cc
+websocket_handshake_stream_base.h
+websocket_handshake_stream_create_helper.cc
+websocket_handshake_stream_create_helper.h
+websocket_handshake_stream_create_helper_test.cc
+websocket_inflater.cc
+websocket_inflater.h
+websocket_inflater_test.cc
websocket_mux.h
-websocket_stream_base.h
websocket_stream.cc
websocket_stream.h
+websocket_stream_test.cc
+websocket_test_util.cc
+websocket_test_util.h
These files are shared between the old and new implementations.
websocket_handshake_constants.cc
websocket_handshake_constants.h
+websocket_handshake_handler.cc
+websocket_handshake_handler.h
A pre-submit check helps us keep this README file up-to-date:
diff --git a/chromium/net/websockets/websocket_basic_handshake_stream.cc b/chromium/net/websockets/websocket_basic_handshake_stream.cc
new file mode 100644
index 00000000000..73a10453be0
--- /dev/null
+++ b/chromium/net/websockets/websocket_basic_handshake_stream.cc
@@ -0,0 +1,318 @@
+// 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/websockets/websocket_basic_handshake_stream.h"
+
+#include <algorithm>
+#include <iterator>
+
+#include "base/base64.h"
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/containers/hash_tables.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "crypto/random.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_request_info.h"
+#include "net/http/http_response_body_drainer.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/http/http_stream_parser.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/websockets/websocket_basic_stream.h"
+#include "net/websockets/websocket_handshake_constants.h"
+#include "net/websockets/websocket_handshake_handler.h"
+#include "net/websockets/websocket_stream.h"
+
+namespace net {
+namespace {
+
+std::string GenerateHandshakeChallenge() {
+ std::string raw_challenge(websockets::kRawChallengeLength, '\0');
+ crypto::RandBytes(string_as_array(&raw_challenge), raw_challenge.length());
+ std::string encoded_challenge;
+ base::Base64Encode(raw_challenge, &encoded_challenge);
+ return encoded_challenge;
+}
+
+void AddVectorHeaderIfNonEmpty(const char* name,
+ const std::vector<std::string>& value,
+ HttpRequestHeaders* headers) {
+ if (value.empty())
+ return;
+ headers->SetHeader(name, JoinString(value, ", "));
+}
+
+// If |case_sensitive| is false, then |value| must be in lower-case.
+bool ValidateSingleTokenHeader(
+ const scoped_refptr<HttpResponseHeaders>& headers,
+ const base::StringPiece& name,
+ const std::string& value,
+ bool case_sensitive) {
+ void* state = NULL;
+ std::string token;
+ int tokens = 0;
+ bool has_value = false;
+ while (headers->EnumerateHeader(&state, name, &token)) {
+ if (++tokens > 1)
+ return false;
+ has_value = case_sensitive ? value == token
+ : LowerCaseEqualsASCII(token, value.c_str());
+ }
+ return has_value;
+}
+
+bool ValidateSubProtocol(
+ const scoped_refptr<HttpResponseHeaders>& headers,
+ const std::vector<std::string>& requested_sub_protocols,
+ std::string* sub_protocol) {
+ void* state = NULL;
+ std::string token;
+ base::hash_set<std::string> requested_set(requested_sub_protocols.begin(),
+ requested_sub_protocols.end());
+ int accepted = 0;
+ while (headers->EnumerateHeader(
+ &state, websockets::kSecWebSocketProtocol, &token)) {
+ if (requested_set.count(token) == 0)
+ return false;
+
+ *sub_protocol = token;
+ // The server is only allowed to accept one protocol.
+ if (++accepted > 1)
+ return false;
+ }
+ // If the browser requested > 0 protocols, the server is required to accept
+ // one.
+ return requested_set.empty() || accepted == 1;
+}
+
+bool ValidateExtensions(const scoped_refptr<HttpResponseHeaders>& headers,
+ const std::vector<std::string>& requested_extensions,
+ std::string* extensions) {
+ void* state = NULL;
+ std::string token;
+ while (headers->EnumerateHeader(
+ &state, websockets::kSecWebSocketExtensions, &token)) {
+ // TODO(ricea): Accept permessage-deflate with valid parameters.
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+WebSocketBasicHandshakeStream::WebSocketBasicHandshakeStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy,
+ std::vector<std::string> requested_sub_protocols,
+ std::vector<std::string> requested_extensions)
+ : state_(connection.release(), using_proxy),
+ http_response_info_(NULL),
+ requested_sub_protocols_(requested_sub_protocols),
+ requested_extensions_(requested_extensions) {}
+
+WebSocketBasicHandshakeStream::~WebSocketBasicHandshakeStream() {}
+
+int WebSocketBasicHandshakeStream::InitializeStream(
+ const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback) {
+ state_.Initialize(request_info, priority, net_log, callback);
+ return OK;
+}
+
+int WebSocketBasicHandshakeStream::SendRequest(
+ const HttpRequestHeaders& headers,
+ HttpResponseInfo* response,
+ const CompletionCallback& callback) {
+ DCHECK(!headers.HasHeader(websockets::kSecWebSocketKey));
+ DCHECK(!headers.HasHeader(websockets::kSecWebSocketProtocol));
+ DCHECK(!headers.HasHeader(websockets::kSecWebSocketExtensions));
+ DCHECK(headers.HasHeader(HttpRequestHeaders::kOrigin));
+ DCHECK(headers.HasHeader(websockets::kUpgrade));
+ DCHECK(headers.HasHeader(HttpRequestHeaders::kConnection));
+ DCHECK(headers.HasHeader(websockets::kSecWebSocketVersion));
+ DCHECK(parser());
+
+ http_response_info_ = response;
+
+ // Create a copy of the headers object, so that we can add the
+ // Sec-WebSockey-Key header.
+ HttpRequestHeaders enriched_headers;
+ enriched_headers.CopyFrom(headers);
+ std::string handshake_challenge;
+ if (handshake_challenge_for_testing_) {
+ handshake_challenge = *handshake_challenge_for_testing_;
+ handshake_challenge_for_testing_.reset();
+ } else {
+ handshake_challenge = GenerateHandshakeChallenge();
+ }
+ enriched_headers.SetHeader(websockets::kSecWebSocketKey, handshake_challenge);
+
+ AddVectorHeaderIfNonEmpty(websockets::kSecWebSocketProtocol,
+ requested_sub_protocols_,
+ &enriched_headers);
+ AddVectorHeaderIfNonEmpty(websockets::kSecWebSocketExtensions,
+ requested_extensions_,
+ &enriched_headers);
+
+ ComputeSecWebSocketAccept(handshake_challenge,
+ &handshake_challenge_response_);
+
+ return parser()->SendRequest(
+ state_.GenerateRequestLine(), enriched_headers, response, callback);
+}
+
+int WebSocketBasicHandshakeStream::ReadResponseHeaders(
+ const CompletionCallback& callback) {
+ // HttpStreamParser uses a weak pointer when reading from the
+ // socket, so it won't be called back after being destroyed. The
+ // HttpStreamParser is owned by HttpBasicState which is owned by this object,
+ // so this use of base::Unretained() is safe.
+ int rv = parser()->ReadResponseHeaders(
+ base::Bind(&WebSocketBasicHandshakeStream::ReadResponseHeadersCallback,
+ base::Unretained(this),
+ callback));
+ return rv == OK ? ValidateResponse() : rv;
+}
+
+const HttpResponseInfo* WebSocketBasicHandshakeStream::GetResponseInfo() const {
+ return parser()->GetResponseInfo();
+}
+
+int WebSocketBasicHandshakeStream::ReadResponseBody(
+ IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) {
+ return parser()->ReadResponseBody(buf, buf_len, callback);
+}
+
+void WebSocketBasicHandshakeStream::Close(bool not_reusable) {
+ // This class ignores the value of |not_reusable| and never lets the socket be
+ // re-used.
+ if (parser())
+ parser()->Close(true);
+}
+
+bool WebSocketBasicHandshakeStream::IsResponseBodyComplete() const {
+ return parser()->IsResponseBodyComplete();
+}
+
+bool WebSocketBasicHandshakeStream::CanFindEndOfResponse() const {
+ return parser() && parser()->CanFindEndOfResponse();
+}
+
+bool WebSocketBasicHandshakeStream::IsConnectionReused() const {
+ return parser()->IsConnectionReused();
+}
+
+void WebSocketBasicHandshakeStream::SetConnectionReused() {
+ parser()->SetConnectionReused();
+}
+
+bool WebSocketBasicHandshakeStream::IsConnectionReusable() const {
+ return false;
+}
+
+int64 WebSocketBasicHandshakeStream::GetTotalReceivedBytes() const {
+ return 0;
+}
+
+bool WebSocketBasicHandshakeStream::GetLoadTimingInfo(
+ LoadTimingInfo* load_timing_info) const {
+ return state_.connection()->GetLoadTimingInfo(IsConnectionReused(),
+ load_timing_info);
+}
+
+void WebSocketBasicHandshakeStream::GetSSLInfo(SSLInfo* ssl_info) {
+ parser()->GetSSLInfo(ssl_info);
+}
+
+void WebSocketBasicHandshakeStream::GetSSLCertRequestInfo(
+ SSLCertRequestInfo* cert_request_info) {
+ parser()->GetSSLCertRequestInfo(cert_request_info);
+}
+
+bool WebSocketBasicHandshakeStream::IsSpdyHttpStream() const { return false; }
+
+void WebSocketBasicHandshakeStream::Drain(HttpNetworkSession* session) {
+ HttpResponseBodyDrainer* drainer = new HttpResponseBodyDrainer(this);
+ drainer->Start(session);
+ // |drainer| will delete itself.
+}
+
+void WebSocketBasicHandshakeStream::SetPriority(RequestPriority priority) {
+ // TODO(ricea): See TODO comment in HttpBasicStream::SetPriority(). If it is
+ // gone, then copy whatever has happened there over here.
+}
+
+scoped_ptr<WebSocketStream> WebSocketBasicHandshakeStream::Upgrade() {
+ // TODO(ricea): Add deflate support.
+
+ // The HttpStreamParser object has a pointer to our ClientSocketHandle. Make
+ // sure it does not touch it again before it is destroyed.
+ state_.DeleteParser();
+ return scoped_ptr<WebSocketStream>(
+ new WebSocketBasicStream(state_.ReleaseConnection(),
+ state_.read_buf(),
+ sub_protocol_,
+ extensions_));
+}
+
+void WebSocketBasicHandshakeStream::SetWebSocketKeyForTesting(
+ const std::string& key) {
+ handshake_challenge_for_testing_.reset(new std::string(key));
+}
+
+void WebSocketBasicHandshakeStream::ReadResponseHeadersCallback(
+ const CompletionCallback& callback,
+ int result) {
+ if (result == OK)
+ result = ValidateResponse();
+ callback.Run(result);
+}
+
+int WebSocketBasicHandshakeStream::ValidateResponse() {
+ DCHECK(http_response_info_);
+ const scoped_refptr<HttpResponseHeaders>& headers =
+ http_response_info_->headers;
+
+ switch (headers->response_code()) {
+ case HTTP_SWITCHING_PROTOCOLS:
+ return ValidateUpgradeResponse(headers);
+
+ // We need to pass these through for authentication to work.
+ case HTTP_UNAUTHORIZED:
+ case HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ return OK;
+
+ // Other status codes are potentially risky (see the warnings in the
+ // WHATWG WebSocket API spec) and so are dropped by default.
+ default:
+ return ERR_INVALID_RESPONSE;
+ }
+}
+
+int WebSocketBasicHandshakeStream::ValidateUpgradeResponse(
+ const scoped_refptr<HttpResponseHeaders>& headers) {
+ if (ValidateSingleTokenHeader(headers,
+ websockets::kUpgrade,
+ websockets::kWebSocketLowercase,
+ false) &&
+ ValidateSingleTokenHeader(headers,
+ websockets::kSecWebSocketAccept,
+ handshake_challenge_response_,
+ true) &&
+ headers->HasHeaderValue(HttpRequestHeaders::kConnection,
+ websockets::kUpgrade) &&
+ ValidateSubProtocol(headers, requested_sub_protocols_, &sub_protocol_) &&
+ ValidateExtensions(headers, requested_extensions_, &extensions_)) {
+ return OK;
+ }
+ return ERR_INVALID_RESPONSE;
+}
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_basic_handshake_stream.h b/chromium/net/websockets/websocket_basic_handshake_stream.h
new file mode 100644
index 00000000000..2e5b628cde6
--- /dev/null
+++ b/chromium/net/websockets/websocket_basic_handshake_stream.h
@@ -0,0 +1,122 @@
+// 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_WEBSOCKETS_WEBSOCKET_BASIC_HANDSHAKE_STREAM_H_
+#define NET_WEBSOCKETS_WEBSOCKET_BASIC_HANDSHAKE_STREAM_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+#include "net/http/http_basic_state.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
+
+namespace net {
+
+class ClientSocketHandle;
+class HttpResponseHeaders;
+class HttpResponseInfo;
+class HttpStreamParser;
+
+class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream
+ : public WebSocketHandshakeStreamBase {
+ public:
+ WebSocketBasicHandshakeStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy,
+ std::vector<std::string> requested_sub_protocols,
+ std::vector<std::string> requested_extensions);
+
+ virtual ~WebSocketBasicHandshakeStream();
+
+ // HttpStreamBase methods
+ virtual int InitializeStream(const HttpRequestInfo* request_info,
+ RequestPriority priority,
+ const BoundNetLog& net_log,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual int SendRequest(const HttpRequestHeaders& request_headers,
+ HttpResponseInfo* response,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual int ReadResponseHeaders(const CompletionCallback& callback) OVERRIDE;
+ virtual const HttpResponseInfo* GetResponseInfo() const OVERRIDE;
+ virtual int ReadResponseBody(IOBuffer* buf,
+ int buf_len,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual void Close(bool not_reusable) OVERRIDE;
+ virtual bool IsResponseBodyComplete() const OVERRIDE;
+ virtual bool CanFindEndOfResponse() const OVERRIDE;
+ virtual bool IsConnectionReused() const OVERRIDE;
+ virtual void SetConnectionReused() OVERRIDE;
+ virtual bool IsConnectionReusable() const OVERRIDE;
+ virtual int64 GetTotalReceivedBytes() const OVERRIDE;
+ virtual bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const
+ OVERRIDE;
+ virtual void GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
+ virtual void GetSSLCertRequestInfo(
+ SSLCertRequestInfo* cert_request_info) OVERRIDE;
+ virtual bool IsSpdyHttpStream() const OVERRIDE;
+ virtual void Drain(HttpNetworkSession* session) OVERRIDE;
+ virtual void SetPriority(RequestPriority priority) OVERRIDE;
+
+ // This is called from the top level once correct handshake response headers
+ // have been received. It creates an appropriate subclass of WebSocketStream
+ // depending on what extensions were negotiated. This object is unusable after
+ // Upgrade() has been called and should be disposed of as soon as possible.
+ virtual scoped_ptr<WebSocketStream> Upgrade() OVERRIDE;
+
+ // Set the value used for the next Sec-WebSocket-Key header
+ // deterministically. The key is only used once, and then discarded.
+ // For tests only.
+ void SetWebSocketKeyForTesting(const std::string& key);
+
+ private:
+ // A wrapper for the ReadResponseHeaders callback that checks whether or not
+ // the connection has been accepted.
+ void ReadResponseHeadersCallback(const CompletionCallback& callback,
+ int result);
+
+ // Validates the response from the server and returns OK or
+ // ERR_INVALID_RESPONSE.
+ int ValidateResponse();
+
+ // Check that the headers are well-formed for a 101 response, and returns
+ // OK if they are, otherwise returns ERR_INVALID_RESPONSE.
+ int ValidateUpgradeResponse(
+ const scoped_refptr<HttpResponseHeaders>& headers);
+
+ HttpStreamParser* parser() const { return state_.parser(); }
+
+ // HttpBasicState holds most of the handshake-related state.
+ HttpBasicState state_;
+
+ // This is stored in SendRequest() for use by ReadResponseHeaders().
+ HttpResponseInfo* http_response_info_;
+
+ // The key to be sent in the next Sec-WebSocket-Key header. Usually NULL (the
+ // key is generated on the fly).
+ scoped_ptr<std::string> handshake_challenge_for_testing_;
+
+ // The required value for the Sec-WebSocket-Accept header.
+ std::string handshake_challenge_response_;
+
+ // The sub-protocols we requested.
+ std::vector<std::string> requested_sub_protocols_;
+
+ // The extensions we requested.
+ std::vector<std::string> requested_extensions_;
+
+ // The sub-protocol selected by the server.
+ std::string sub_protocol_;
+
+ // The extension(s) selected by the server.
+ std::string extensions_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketBasicHandshakeStream);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_BASIC_HANDSHAKE_STREAM_H_
diff --git a/chromium/net/websockets/websocket_basic_stream.cc b/chromium/net/websockets/websocket_basic_stream.cc
index 5b02b18cb61..12472b48d1d 100644
--- a/chromium/net/websockets/websocket_basic_stream.cc
+++ b/chromium/net/websockets/websocket_basic_stream.cc
@@ -12,6 +12,7 @@
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/logging.h"
+#include "base/safe_numerics.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/socket/client_socket_handle.h"
@@ -23,6 +24,10 @@ namespace net {
namespace {
+// This uses type uint64 to match the definition of
+// WebSocketFrameHeader::payload_length in websocket_frame.h.
+const uint64 kMaxControlFramePayload = 125;
+
// The number of bytes to attempt to read at a time.
// TODO(ricea): See if there is a better number or algorithm to fulfill our
// requirements:
@@ -35,22 +40,55 @@ namespace {
// packet sizes / encryption block sizes / IPC alignment issues, etc.
const int kReadBufferSize = 32 * 1024;
+typedef ScopedVector<WebSocketFrame>::const_iterator WebSocketFrameIterator;
+
+// Returns the total serialized size of |frames|. This function assumes that
+// |frames| will be serialized with mask field. This function forces the
+// masked bit of the frames on.
+int CalculateSerializedSizeAndTurnOnMaskBit(
+ ScopedVector<WebSocketFrame>* frames) {
+ const int kMaximumTotalSize = std::numeric_limits<int>::max();
+
+ int total_size = 0;
+ for (WebSocketFrameIterator it = frames->begin(); it != frames->end(); ++it) {
+ WebSocketFrame* frame = *it;
+ // Force the masked bit on.
+ frame->header.masked = true;
+ // We enforce flow control so the renderer should never be able to force us
+ // to cache anywhere near 2GB of frames.
+ int frame_size = frame->header.payload_length +
+ GetWebSocketFrameHeaderSize(frame->header);
+ CHECK_GE(kMaximumTotalSize - total_size, frame_size)
+ << "Aborting to prevent overflow";
+ total_size += frame_size;
+ }
+ return total_size;
+}
+
} // namespace
WebSocketBasicStream::WebSocketBasicStream(
- scoped_ptr<ClientSocketHandle> connection)
+ scoped_ptr<ClientSocketHandle> connection,
+ const scoped_refptr<GrowableIOBuffer>& http_read_buffer,
+ const std::string& sub_protocol,
+ const std::string& extensions)
: read_buffer_(new IOBufferWithSize(kReadBufferSize)),
connection_(connection.Pass()),
+ http_read_buffer_(http_read_buffer),
+ sub_protocol_(sub_protocol),
+ extensions_(extensions),
generate_websocket_masking_key_(&GenerateWebSocketMaskingKey) {
+ // http_read_buffer_ should not be set if it contains no data.
+ if (http_read_buffer_ && http_read_buffer_->offset() == 0)
+ http_read_buffer_ = NULL;
DCHECK(connection_->is_initialized());
}
WebSocketBasicStream::~WebSocketBasicStream() { Close(); }
-int WebSocketBasicStream::ReadFrames(
- ScopedVector<WebSocketFrameChunk>* frame_chunks,
- const CompletionCallback& callback) {
- DCHECK(frame_chunks->empty());
+int WebSocketBasicStream::ReadFrames(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
+ DCHECK(frames->empty());
// If there is data left over after parsing the HTTP headers, attempt to parse
// it as WebSocket frames.
if (http_read_buffer_) {
@@ -60,80 +98,67 @@ int WebSocketBasicStream::ReadFrames(
scoped_refptr<GrowableIOBuffer> buffered_data;
buffered_data.swap(http_read_buffer_);
DCHECK(http_read_buffer_.get() == NULL);
+ ScopedVector<WebSocketFrameChunk> frame_chunks;
if (!parser_.Decode(buffered_data->StartOfBuffer(),
buffered_data->offset(),
- frame_chunks))
+ &frame_chunks))
return WebSocketErrorToNetError(parser_.websocket_error());
- if (!frame_chunks->empty())
- return OK;
+ if (!frame_chunks.empty()) {
+ int result = ConvertChunksToFrames(&frame_chunks, frames);
+ if (result != ERR_IO_PENDING)
+ return result;
+ }
}
- // Run until socket stops giving us data or we get some chunks.
+ // Run until socket stops giving us data or we get some frames.
while (true) {
// base::Unretained(this) here is safe because net::Socket guarantees not to
// call any callbacks after Disconnect(), which we call from the
- // destructor. The caller of ReadFrames() is required to keep |frame_chunks|
+ // destructor. The caller of ReadFrames() is required to keep |frames|
// valid.
- int result = connection_->socket()
- ->Read(read_buffer_.get(),
- read_buffer_->size(),
- base::Bind(&WebSocketBasicStream::OnReadComplete,
- base::Unretained(this),
- base::Unretained(frame_chunks),
- callback));
+ int result = connection_->socket()->Read(
+ read_buffer_.get(),
+ read_buffer_->size(),
+ base::Bind(&WebSocketBasicStream::OnReadComplete,
+ base::Unretained(this),
+ base::Unretained(frames),
+ callback));
if (result == ERR_IO_PENDING)
return result;
- result = HandleReadResult(result, frame_chunks);
+ result = HandleReadResult(result, frames);
if (result != ERR_IO_PENDING)
return result;
+ DCHECK(frames->empty());
}
}
-int WebSocketBasicStream::WriteFrames(
- ScopedVector<WebSocketFrameChunk>* frame_chunks,
- const CompletionCallback& callback) {
+int WebSocketBasicStream::WriteFrames(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
// This function always concatenates all frames into a single buffer.
// TODO(ricea): Investigate whether it would be better in some cases to
// perform multiple writes with smaller buffers.
//
// First calculate the size of the buffer we need to allocate.
- typedef ScopedVector<WebSocketFrameChunk>::const_iterator Iterator;
- const int kMaximumTotalSize = std::numeric_limits<int>::max();
- int total_size = 0;
- for (Iterator it = frame_chunks->begin(); it != frame_chunks->end(); ++it) {
- WebSocketFrameChunk* chunk = *it;
- DCHECK(chunk->header)
- << "Only complete frames are supported by WebSocketBasicStream";
- DCHECK(chunk->final_chunk)
- << "Only complete frames are supported by WebSocketBasicStream";
- // Force the masked bit on.
- chunk->header->masked = true;
- // We enforce flow control so the renderer should never be able to force us
- // to cache anywhere near 2GB of frames.
- int chunk_size =
- chunk->data->size() + GetWebSocketFrameHeaderSize(*(chunk->header));
- CHECK_GE(kMaximumTotalSize - total_size, chunk_size)
- << "Aborting to prevent overflow";
- total_size += chunk_size;
- }
+ int total_size = CalculateSerializedSizeAndTurnOnMaskBit(frames);
scoped_refptr<IOBufferWithSize> combined_buffer(
new IOBufferWithSize(total_size));
+
char* dest = combined_buffer->data();
int remaining_size = total_size;
- for (Iterator it = frame_chunks->begin(); it != frame_chunks->end(); ++it) {
- WebSocketFrameChunk* chunk = *it;
+ for (WebSocketFrameIterator it = frames->begin(); it != frames->end(); ++it) {
+ WebSocketFrame* frame = *it;
WebSocketMaskingKey mask = generate_websocket_masking_key_();
- int result = WriteWebSocketFrameHeader(
- *(chunk->header), &mask, dest, remaining_size);
- DCHECK(result != ERR_INVALID_ARGUMENT)
+ int result =
+ WriteWebSocketFrameHeader(frame->header, &mask, dest, remaining_size);
+ DCHECK_NE(ERR_INVALID_ARGUMENT, result)
<< "WriteWebSocketFrameHeader() says that " << remaining_size
<< " is not enough to write the header in. This should not happen.";
CHECK_GE(result, 0) << "Potentially security-critical check failed";
dest += result;
remaining_size -= result;
- const char* const frame_data = chunk->data->data();
- const int frame_size = chunk->data->size();
+ const char* const frame_data = frame->data->data();
+ const int frame_size = frame->header.payload_length;
CHECK_GE(remaining_size, frame_size);
std::copy(frame_data, frame_data + frame_size, dest);
MaskWebSocketFramePayload(mask, 0, dest, frame_size);
@@ -155,22 +180,6 @@ std::string WebSocketBasicStream::GetSubProtocol() const {
std::string WebSocketBasicStream::GetExtensions() const { return extensions_; }
-int WebSocketBasicStream::SendHandshakeRequest(
- const GURL& url,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response_info,
- const CompletionCallback& callback) {
- // TODO(ricea): Implement handshake-related functionality.
- NOTREACHED();
- return ERR_NOT_IMPLEMENTED;
-}
-
-int WebSocketBasicStream::ReadHandshakeResponse(
- const CompletionCallback& callback) {
- NOTREACHED();
- return ERR_NOT_IMPLEMENTED;
-}
-
/*static*/
scoped_ptr<WebSocketBasicStream>
WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
@@ -179,13 +188,8 @@ WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
const std::string& sub_protocol,
const std::string& extensions,
WebSocketMaskingKeyGeneratorFunction key_generator_function) {
- scoped_ptr<WebSocketBasicStream> stream(
- new WebSocketBasicStream(connection.Pass()));
- if (http_read_buffer) {
- stream->http_read_buffer_ = http_read_buffer;
- }
- stream->sub_protocol_ = sub_protocol;
- stream->extensions_ = extensions;
+ scoped_ptr<WebSocketBasicStream> stream(new WebSocketBasicStream(
+ connection.Pass(), http_read_buffer, sub_protocol, extensions));
stream->generate_websocket_masking_key_ = key_generator_function;
return stream.Pass();
}
@@ -196,13 +200,13 @@ int WebSocketBasicStream::WriteEverything(
while (buffer->BytesRemaining() > 0) {
// The use of base::Unretained() here is safe because on destruction we
// disconnect the socket, preventing any further callbacks.
- int result = connection_->socket()
- ->Write(buffer.get(),
- buffer->BytesRemaining(),
- base::Bind(&WebSocketBasicStream::OnWriteComplete,
- base::Unretained(this),
- buffer,
- callback));
+ int result = connection_->socket()->Write(
+ buffer.get(),
+ buffer->BytesRemaining(),
+ base::Bind(&WebSocketBasicStream::OnWriteComplete,
+ base::Unretained(this),
+ buffer,
+ callback));
if (result > 0) {
buffer->DidConsume(result);
} else {
@@ -217,12 +221,12 @@ void WebSocketBasicStream::OnWriteComplete(
const CompletionCallback& callback,
int result) {
if (result < 0) {
- DCHECK(result != ERR_IO_PENDING);
+ DCHECK_NE(ERR_IO_PENDING, result);
callback.Run(result);
return;
}
- DCHECK(result != 0);
+ DCHECK_NE(0, result);
buffer->DidConsume(result);
result = WriteEverything(buffer, callback);
if (result != ERR_IO_PENDING)
@@ -231,27 +235,179 @@ void WebSocketBasicStream::OnWriteComplete(
int WebSocketBasicStream::HandleReadResult(
int result,
- ScopedVector<WebSocketFrameChunk>* frame_chunks) {
+ ScopedVector<WebSocketFrame>* frames) {
DCHECK_NE(ERR_IO_PENDING, result);
- DCHECK(frame_chunks->empty());
+ DCHECK(frames->empty());
if (result < 0)
return result;
if (result == 0)
return ERR_CONNECTION_CLOSED;
- if (!parser_.Decode(read_buffer_->data(), result, frame_chunks))
+ ScopedVector<WebSocketFrameChunk> frame_chunks;
+ if (!parser_.Decode(read_buffer_->data(), result, &frame_chunks))
return WebSocketErrorToNetError(parser_.websocket_error());
- if (!frame_chunks->empty())
- return OK;
- return ERR_IO_PENDING;
+ if (frame_chunks.empty())
+ return ERR_IO_PENDING;
+ return ConvertChunksToFrames(&frame_chunks, frames);
}
-void WebSocketBasicStream::OnReadComplete(
+int WebSocketBasicStream::ConvertChunksToFrames(
ScopedVector<WebSocketFrameChunk>* frame_chunks,
- const CompletionCallback& callback,
- int result) {
- result = HandleReadResult(result, frame_chunks);
+ ScopedVector<WebSocketFrame>* frames) {
+ for (size_t i = 0; i < frame_chunks->size(); ++i) {
+ scoped_ptr<WebSocketFrame> frame;
+ int result = ConvertChunkToFrame(
+ scoped_ptr<WebSocketFrameChunk>((*frame_chunks)[i]), &frame);
+ (*frame_chunks)[i] = NULL;
+ if (result != OK)
+ return result;
+ if (frame)
+ frames->push_back(frame.release());
+ }
+ // All the elements of |frame_chunks| are now NULL, so there is no point in
+ // calling delete on them all.
+ frame_chunks->weak_clear();
+ if (frames->empty())
+ return ERR_IO_PENDING;
+ return OK;
+}
+
+int WebSocketBasicStream::ConvertChunkToFrame(
+ scoped_ptr<WebSocketFrameChunk> chunk,
+ scoped_ptr<WebSocketFrame>* frame) {
+ DCHECK(frame->get() == NULL);
+ bool is_first_chunk = false;
+ if (chunk->header) {
+ DCHECK(current_frame_header_ == NULL)
+ << "Received the header for a new frame without notification that "
+ << "the previous frame was complete (bug in WebSocketFrameParser?)";
+ is_first_chunk = true;
+ current_frame_header_.swap(chunk->header);
+ }
+ const int chunk_size = chunk->data ? chunk->data->size() : 0;
+ DCHECK(current_frame_header_) << "Unexpected header-less chunk received "
+ << "(final_chunk = " << chunk->final_chunk
+ << ", data size = " << chunk_size
+ << ") (bug in WebSocketFrameParser?)";
+ scoped_refptr<IOBufferWithSize> data_buffer;
+ data_buffer.swap(chunk->data);
+ const bool is_final_chunk = chunk->final_chunk;
+ const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode;
+ if (WebSocketFrameHeader::IsKnownControlOpCode(opcode)) {
+ bool protocol_error = false;
+ if (!current_frame_header_->final) {
+ DVLOG(1) << "WebSocket protocol error. Control frame, opcode=" << opcode
+ << " received with FIN bit unset.";
+ protocol_error = true;
+ }
+ if (current_frame_header_->payload_length > kMaxControlFramePayload) {
+ DVLOG(1) << "WebSocket protocol error. Control frame, opcode=" << opcode
+ << ", payload_length=" << current_frame_header_->payload_length
+ << " exceeds maximum payload length for a control message.";
+ protocol_error = true;
+ }
+ if (protocol_error) {
+ current_frame_header_.reset();
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ if (!is_final_chunk) {
+ DVLOG(2) << "Encountered a split control frame, opcode " << opcode;
+ if (incomplete_control_frame_body_) {
+ DVLOG(3) << "Appending to an existing split control frame.";
+ AddToIncompleteControlFrameBody(data_buffer);
+ } else {
+ DVLOG(3) << "Creating new storage for an incomplete control frame.";
+ incomplete_control_frame_body_ = new GrowableIOBuffer();
+ // This method checks for oversize control frames above, so as long as
+ // the frame parser is working correctly, this won't overflow. If a bug
+ // does cause it to overflow, it will CHECK() in
+ // AddToIncompleteControlFrameBody() without writing outside the buffer.
+ incomplete_control_frame_body_->SetCapacity(kMaxControlFramePayload);
+ AddToIncompleteControlFrameBody(data_buffer);
+ }
+ return OK;
+ }
+ if (incomplete_control_frame_body_) {
+ DVLOG(2) << "Rejoining a split control frame, opcode " << opcode;
+ AddToIncompleteControlFrameBody(data_buffer);
+ const int body_size = incomplete_control_frame_body_->offset();
+ DCHECK_EQ(body_size,
+ static_cast<int>(current_frame_header_->payload_length));
+ scoped_refptr<IOBufferWithSize> body = new IOBufferWithSize(body_size);
+ memcpy(body->data(),
+ incomplete_control_frame_body_->StartOfBuffer(),
+ body_size);
+ incomplete_control_frame_body_ = NULL; // Frame now complete.
+ DCHECK(is_final_chunk);
+ *frame = CreateFrame(is_final_chunk, body);
+ return OK;
+ }
+ }
+
+ // Apply basic sanity checks to the |payload_length| field from the frame
+ // header. A check for exact equality can only be used when the whole frame
+ // arrives in one chunk.
+ DCHECK_GE(current_frame_header_->payload_length,
+ base::checked_numeric_cast<uint64>(chunk_size));
+ DCHECK(!is_first_chunk || !is_final_chunk ||
+ current_frame_header_->payload_length ==
+ base::checked_numeric_cast<uint64>(chunk_size));
+
+ // Convert the chunk to a complete frame.
+ *frame = CreateFrame(is_final_chunk, data_buffer);
+ return OK;
+}
+
+scoped_ptr<WebSocketFrame> WebSocketBasicStream::CreateFrame(
+ bool is_final_chunk,
+ const scoped_refptr<IOBufferWithSize>& data) {
+ scoped_ptr<WebSocketFrame> result_frame;
+ const bool is_final_chunk_in_message =
+ is_final_chunk && current_frame_header_->final;
+ const int data_size = data ? data->size() : 0;
+ const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode;
+ // Empty frames convey no useful information unless they are the first frame
+ // (containing the type and flags) or have the "final" bit set.
+ if (is_final_chunk_in_message || data_size > 0 ||
+ current_frame_header_->opcode !=
+ WebSocketFrameHeader::kOpCodeContinuation) {
+ result_frame.reset(new WebSocketFrame(opcode));
+ result_frame->header.CopyFrom(*current_frame_header_);
+ result_frame->header.final = is_final_chunk_in_message;
+ result_frame->header.payload_length = data_size;
+ result_frame->data = data;
+ // Ensure that opcodes Text and Binary are only used for the first frame in
+ // the message.
+ if (WebSocketFrameHeader::IsKnownDataOpCode(opcode))
+ current_frame_header_->opcode = WebSocketFrameHeader::kOpCodeContinuation;
+ }
+ // Make sure that a frame header is not applied to any chunks that do not
+ // belong to it.
+ if (is_final_chunk)
+ current_frame_header_.reset();
+ return result_frame.Pass();
+}
+
+void WebSocketBasicStream::AddToIncompleteControlFrameBody(
+ const scoped_refptr<IOBufferWithSize>& data_buffer) {
+ if (!data_buffer)
+ return;
+ const int new_offset =
+ incomplete_control_frame_body_->offset() + data_buffer->size();
+ CHECK_GE(incomplete_control_frame_body_->capacity(), new_offset)
+ << "Control frame body larger than frame header indicates; frame parser "
+ "bug?";
+ memcpy(incomplete_control_frame_body_->data(),
+ data_buffer->data(),
+ data_buffer->size());
+ incomplete_control_frame_body_->set_offset(new_offset);
+}
+
+void WebSocketBasicStream::OnReadComplete(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback,
+ int result) {
+ result = HandleReadResult(result, frames);
if (result == ERR_IO_PENDING)
- result = ReadFrames(frame_chunks, callback);
+ result = ReadFrames(frames, callback);
if (result != ERR_IO_PENDING)
callback.Run(result);
}
diff --git a/chromium/net/websockets/websocket_basic_stream.h b/chromium/net/websockets/websocket_basic_stream.h
index 1231da8142b..ccfebd8e0cb 100644
--- a/chromium/net/websockets/websocket_basic_stream.h
+++ b/chromium/net/websockets/websocket_basic_stream.h
@@ -19,9 +19,8 @@ namespace net {
class ClientSocketHandle;
class DrainableIOBuffer;
class GrowableIOBuffer;
-class HttpRequestHeaders;
-class HttpResponseInfo;
class IOBufferWithSize;
+struct WebSocketFrame;
struct WebSocketFrameChunk;
// Implementation of WebSocketStream for non-multiplexed ws:// connections (or
@@ -31,18 +30,23 @@ class NET_EXPORT_PRIVATE WebSocketBasicStream : public WebSocketStream {
typedef WebSocketMaskingKey (*WebSocketMaskingKeyGeneratorFunction)();
// This class should not normally be constructed directly; see
- // WebSocketStream::CreateAndConnectStream.
- explicit WebSocketBasicStream(scoped_ptr<ClientSocketHandle> connection);
+ // WebSocketStream::CreateAndConnectStream() and
+ // WebSocketBasicHandshakeStream::Upgrade().
+ WebSocketBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ const scoped_refptr<GrowableIOBuffer>& http_read_buffer,
+ const std::string& sub_protocol,
+ const std::string& extensions);
// The destructor has to make sure the connection is closed when we finish so
// that it does not get returned to the pool.
virtual ~WebSocketBasicStream();
// WebSocketStream implementation.
- virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE;
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE;
virtual void Close() OVERRIDE;
@@ -51,16 +55,6 @@ class NET_EXPORT_PRIVATE WebSocketBasicStream : public WebSocketStream {
virtual std::string GetExtensions() const OVERRIDE;
- // Writes WebSocket handshake request HTTP-style to the connection. Adds
- // "Sec-WebSocket-Key" header; this should not be included in |headers|.
- virtual int SendHandshakeRequest(const GURL& url,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response_info,
- const CompletionCallback& callback) OVERRIDE;
-
- virtual int ReadHandshakeResponse(
- const CompletionCallback& callback) OVERRIDE;
-
////////////////////////////////////////////////////////////////////////////
// Methods for testing only.
@@ -83,13 +77,43 @@ class NET_EXPORT_PRIVATE WebSocketBasicStream : public WebSocketStream {
int result);
// Attempts to parse the output of a read as WebSocket frames. On success,
- // returns OK and places the frame(s) in frame_chunks.
- int HandleReadResult(int result,
- ScopedVector<WebSocketFrameChunk>* frame_chunks);
+ // returns OK and places the frame(s) in |frames|.
+ int HandleReadResult(int result, ScopedVector<WebSocketFrame>* frames);
+
+ // Converts the chunks in |frame_chunks| into frames and writes them to
+ // |frames|. |frame_chunks| is destroyed in the process. Returns
+ // ERR_WS_PROTOCOL_ERROR if an invalid chunk was found. If one or more frames
+ // was added to |frames|, then returns OK, otherwise returns ERR_IO_PENDING.
+ int ConvertChunksToFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ ScopedVector<WebSocketFrame>* frames);
+
+ // Converts a |chunk| to a |frame|. |*frame| should be NULL on entry to this
+ // method. If |chunk| is an incomplete control frame, or an empty middle
+ // frame, then |*frame| may still be NULL on exit. If an invalid control frame
+ // is found, returns ERR_WS_PROTOCOL_ERROR and the stream is no longer
+ // usable. Otherwise returns OK (even if frame is still NULL).
+ int ConvertChunkToFrame(scoped_ptr<WebSocketFrameChunk> chunk,
+ scoped_ptr<WebSocketFrame>* frame);
+
+ // Creates a frame based on the value of |is_final_chunk|, |data| and
+ // |current_frame_header_|. Clears |current_frame_header_| if |is_final_chunk|
+ // is true. |data| may be NULL if the frame has an empty payload. A frame in
+ // the middle of a message with no data is not useful; in this case the
+ // returned frame will be NULL. Otherwise, |current_frame_header_->opcode| is
+ // set to Continuation after use if it was Text or Binary, in accordance with
+ // WebSocket RFC6455 section 5.4.
+ scoped_ptr<WebSocketFrame> CreateFrame(
+ bool is_final_chunk,
+ const scoped_refptr<IOBufferWithSize>& data);
+
+ // Adds |data_buffer| to the end of |incomplete_control_frame_body_|, applying
+ // bounds checks.
+ void AddToIncompleteControlFrameBody(
+ const scoped_refptr<IOBufferWithSize>& data_buffer);
// Called when a read completes. Parses the result and (unless no complete
// header has been received) calls |callback|.
- void OnReadComplete(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ void OnReadComplete(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback,
int result);
@@ -102,6 +126,18 @@ class NET_EXPORT_PRIVATE WebSocketBasicStream : public WebSocketStream {
// from being returned to the pool.
scoped_ptr<ClientSocketHandle> connection_;
+ // Frame header for the frame currently being received. Only non-NULL while we
+ // are processing the frame. If the frame arrives in multiple chunks, it can
+ // remain non-NULL until additional chunks arrive. If the header of the frame
+ // was invalid, this is set to NULL, the channel is failed, and subsequent
+ // chunks of the same frame will be ignored.
+ scoped_ptr<WebSocketFrameHeader> current_frame_header_;
+
+ // Although it should rarely happen in practice, a control frame can arrive
+ // broken into chunks. This variable provides storage for a partial control
+ // frame until the rest arrives. It will be NULL the rest of the time.
+ scoped_refptr<GrowableIOBuffer> incomplete_control_frame_body_;
+
// Only used during handshake. Some data may be left in this buffer after the
// handshake, in which case it will be picked up during the first call to
// ReadFrames(). The type is GrowableIOBuffer for compatibility with
@@ -113,10 +149,10 @@ class NET_EXPORT_PRIVATE WebSocketBasicStream : public WebSocketStream {
WebSocketFrameParser parser_;
// The negotated sub-protocol, or empty for none.
- std::string sub_protocol_;
+ const std::string sub_protocol_;
// The extensions negotiated with the remote server.
- std::string extensions_;
+ const std::string extensions_;
// This can be overridden in tests to make the output deterministic. We don't
// use a Callback here because a function pointer is faster and good enough
diff --git a/chromium/net/websockets/websocket_basic_stream_test.cc b/chromium/net/websockets/websocket_basic_stream_test.cc
index ec2e51a6d0f..cb936a5f01e 100644
--- a/chromium/net/websockets/websocket_basic_stream_test.cc
+++ b/chromium/net/websockets/websocket_basic_stream_test.cc
@@ -8,8 +8,13 @@
#include "net/websockets/websocket_basic_stream.h"
+#include <string.h> // for memcpy() and memset().
+
+#include <string>
+
#include "base/basictypes.h"
#include "base/port.h"
+#include "net/base/big_endian.h"
#include "net/base/capturing_net_log.h"
#include "net/base/test_completion_callback.h"
#include "net/socket/socket_test_util.h"
@@ -18,56 +23,52 @@
namespace net {
namespace {
-// TODO(ricea): Add tests for
-// - Empty frames (data & control)
-// - Non-NULL masking key
-// - A frame larger than kReadBufferSize;
+#define WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(name, value) \
+ const char k##name[] = value; \
+ const size_t k##name##Size = arraysize(k##name) - 1;
-const char kSampleFrame[] = "\x81\x06Sample";
-const size_t kSampleFrameSize = arraysize(kSampleFrame) - 1;
-const char kPartialLargeFrame[] =
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(SampleFrame, "\x81\x06Sample");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
+ PartialLargeFrame,
"\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF"
- "chromiunum ad pasco per loca insanis pullum manducat frumenti";
-const size_t kPartialLargeFrameSize = arraysize(kPartialLargeFrame) - 1;
+ "chromiunum ad pasco per loca insanis pullum manducat frumenti");
const size_t kLargeFrameHeaderSize = 10;
-const size_t kLargeFrameDeclaredPayloadSize = 0x7FFFFFFF;
-const char kMultipleFrames[] = "\x81\x01X\x81\x01Y\x81\x01Z";
-const size_t kMultipleFramesSize = arraysize(kMultipleFrames) - 1;
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MultipleFrames,
+ "\x81\x01X\x81\x01Y\x81\x01Z");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFirstFrame, "\x01\x00");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyMiddleFrame, "\x00\x00");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalTextFrame, "\x81\x00");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalContinuationFrame,
+ "\x80\x00");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(ValidPong, "\x8A\x00");
// This frame encodes a payload length of 7 in two bytes, which is always
// invalid.
-const char kInvalidFrame[] = "\x81\x7E\x00\x07Invalid";
-const size_t kInvalidFrameSize = arraysize(kInvalidFrame) - 1;
-const char kWriteFrame[] = "\x81\x85\x00\x00\x00\x00Write";
-const size_t kWriteFrameSize = arraysize(kWriteFrame) - 1;
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(InvalidFrame,
+ "\x81\x7E\x00\x07Invalid");
+// Control frames must have the FIN bit set. This one does not.
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(PingFrameWithoutFin, "\x09\x00");
+// Control frames must have a payload of 125 bytes or less. This one has
+// a payload of 126 bytes.
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
+ 126BytePong,
+ "\x8a\x7e\x00\x7eZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
+ "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(CloseFrame,
+ "\x88\x09\x03\xe8occludo");
+WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(WriteFrame,
+ "\x81\x85\x00\x00\x00\x00Write");
const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
-
-// Generates a ScopedVector<WebSocketFrameChunk> which will have a wire format
-// matching kWriteFrame.
-ScopedVector<WebSocketFrameChunk> GenerateWriteFrame() {
- scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
- const size_t payload_size =
- kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
- WebSocketFrameHeader::kMaskingKeyLength);
- chunk->data = new IOBufferWithSize(payload_size);
- memcpy(chunk->data->data(),
- kWriteFrame + kWriteFrameSize - payload_size,
- payload_size);
- chunk->final_chunk = true;
- scoped_ptr<WebSocketFrameHeader> header(
- new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeText));
- header->final = true;
- header->masked = true;
- header->payload_length = payload_size;
- chunk->header = header.Pass();
- ScopedVector<WebSocketFrameChunk> chunks;
- chunks.push_back(chunk.release());
- return chunks.Pass();
-}
+const WebSocketMaskingKey kNonNulMaskingKey = {
+ {'\x0d', '\x1b', '\x06', '\x17'}};
// A masking key generator function which generates the identity mask,
// ie. "\0\0\0\0".
WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
+// A masking key generation function which generates a fixed masking key with no
+// nul characters.
+WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; }
+
// Base class for WebSocketBasicStream test fixtures.
class WebSocketBasicStreamTest : public ::testing::Test {
protected:
@@ -75,11 +76,37 @@ class WebSocketBasicStreamTest : public ::testing::Test {
CapturingNetLog net_log_;
};
+// A subclass of StaticSocketDataProvider modified to require that all data
+// expected to be read or written actually is.
+class StrictStaticSocketDataProvider : public StaticSocketDataProvider {
+ public:
+ StrictStaticSocketDataProvider(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count,
+ bool strict_mode)
+ : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
+ strict_mode_(strict_mode) {}
+
+ virtual ~StrictStaticSocketDataProvider() {
+ if (strict_mode_) {
+ EXPECT_EQ(read_count(), read_index());
+ EXPECT_EQ(write_count(), write_index());
+ }
+ }
+
+ private:
+ const bool strict_mode_;
+};
+
// A fixture for tests which only perform normal socket operations.
class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
protected:
WebSocketBasicStreamSocketTest()
- : histograms_("a"), pool_(1, 1, &histograms_, &factory_) {}
+ : histograms_("a"),
+ pool_(1, 1, &histograms_, &factory_),
+ generator_(&GenerateNulMaskingKey),
+ expect_all_io_to_complete_(true) {}
virtual ~WebSocketBasicStreamSocketTest() {
// stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
@@ -91,8 +118,8 @@ class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
size_t reads_count,
MockWrite writes[],
size_t writes_count) {
- socket_data_.reset(
- new StaticSocketDataProvider(reads, reads_count, writes, writes_count));
+ socket_data_.reset(new StrictStaticSocketDataProvider(
+ reads, reads_count, writes, writes_count, expect_all_io_to_complete_));
socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
factory_.AddSocketDataProvider(socket_data_.get());
@@ -123,7 +150,7 @@ class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
http_read_buffer_,
sub_protocol_,
extensions_,
- &GenerateNulMaskingKey);
+ generator_);
}
template <size_t N>
@@ -131,11 +158,6 @@ class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
CreateStream(reads, N, NULL, 0);
}
- template <size_t N>
- void CreateWriteOnly(MockWrite (&writes)[N]) {
- CreateStream(NULL, 0, writes, N);
- }
-
void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
scoped_ptr<SocketDataProvider> socket_data_;
@@ -143,66 +165,147 @@ class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
ClientSocketPoolHistograms histograms_;
MockTransportClientSocketPool pool_;
CapturingBoundNetLog(bound_net_log_);
- ScopedVector<WebSocketFrameChunk> frame_chunks_;
+ ScopedVector<WebSocketFrame> frames_;
TestCompletionCallback cb_;
scoped_refptr<GrowableIOBuffer> http_read_buffer_;
std::string sub_protocol_;
std::string extensions_;
+ WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_;
+ bool expect_all_io_to_complete_;
+};
+
+// A test fixture for the common case of tests that only perform a single read.
+class WebSocketBasicStreamSocketSingleReadTest
+ : public WebSocketBasicStreamSocketTest {
+ protected:
+ void CreateRead(const MockRead& read) {
+ reads_[0] = read;
+ CreateStream(reads_, 1U, NULL, 0);
+ }
+
+ MockRead reads_[1];
+};
+
+// A test fixture for tests that perform chunked reads.
+class WebSocketBasicStreamSocketChunkedReadTest
+ : public WebSocketBasicStreamSocketTest {
+ protected:
+ // Specify the behaviour if there aren't enough chunks to use all the data. If
+ // LAST_FRAME_BIG is specified, then the rest of the data will be
+ // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
+ // frame will be no bigger than the rest of the frames (but it can be smaller,
+ // if not enough data remains).
+ enum LastFrameBehaviour {
+ LAST_FRAME_BIG,
+ LAST_FRAME_NOT_BIG
+ };
+
+ // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
+ // each of |chunk_size| (except that the last chunk may be larger or
+ // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
+ // and errors cannot be simulated. Once data is exhausted, further reads will
+ // return 0 (ie. connection closed).
+ void CreateChunkedRead(IoMode mode,
+ const char data[],
+ size_t data_size,
+ int chunk_size,
+ int number_of_chunks,
+ LastFrameBehaviour last_frame_behaviour) {
+ reads_.reset(new MockRead[number_of_chunks]);
+ const char* start = data;
+ for (int i = 0; i < number_of_chunks; ++i) {
+ int len = chunk_size;
+ const bool is_last_chunk = (i == number_of_chunks - 1);
+ if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) ||
+ static_cast<int>(data + data_size - start) < len) {
+ len = static_cast<int>(data + data_size - start);
+ }
+ reads_[i] = MockRead(mode, start, len);
+ start += len;
+ }
+ CreateStream(reads_.get(), number_of_chunks, NULL, 0);
+ }
+
+ scoped_ptr<MockRead[]> reads_;
+};
+
+// Test fixture for write tests.
+class WebSocketBasicStreamSocketWriteTest
+ : public WebSocketBasicStreamSocketTest {
+ protected:
+ // All write tests use the same frame, so it is easiest to create it during
+ // test creation.
+ virtual void SetUp() OVERRIDE { PrepareWriteFrame(); }
+
+ // Creates a WebSocketFrame with a wire format matching kWriteFrame and adds
+ // it to |frames_|.
+ void PrepareWriteFrame() {
+ scoped_ptr<WebSocketFrame> frame(
+ new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
+ const size_t payload_size =
+ kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
+ WebSocketFrameHeader::kMaskingKeyLength);
+ frame->data = new IOBuffer(payload_size);
+ memcpy(frame->data->data(),
+ kWriteFrame + kWriteFrameSize - payload_size,
+ payload_size);
+ WebSocketFrameHeader& header = frame->header;
+ header.final = true;
+ header.masked = true;
+ header.payload_length = payload_size;
+ frames_.push_back(frame.release());
+ }
+
+ // Creates a stream that expects the listed writes.
+ template <size_t N>
+ void CreateWriteOnly(MockWrite (&writes)[N]) {
+ CreateStream(NULL, 0, writes, N);
+ }
};
TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
CreateNullStream();
}
-TEST_F(WebSocketBasicStreamSocketTest, SyncReadWorks) {
- MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)};
- CreateReadOnly(reads);
- int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
+ CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
+ int result = stream_->ReadFrames(&frames_, cb_.callback());
EXPECT_EQ(OK, result);
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
- EXPECT_TRUE(frame_chunks_[0]->header->final);
- EXPECT_TRUE(frame_chunks_[0]->final_chunk);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
+ EXPECT_TRUE(frames_[0]->header.final);
}
-TEST_F(WebSocketBasicStreamSocketTest, AsyncReadWorks) {
- MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kSampleFrameSize)};
- CreateReadOnly(reads);
- int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
+ CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
+ int result = stream_->ReadFrames(&frames_, cb_.callback());
ASSERT_EQ(ERR_IO_PENDING, result);
EXPECT_EQ(OK, cb_.WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
// Don't repeat all the tests from SyncReadWorks; just enough to be sure the
// frame was really read.
}
// ReadFrames will not return a frame whose header has not been wholly received.
-TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSync) {
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, kSampleFrame, 1),
- MockRead(SYNCHRONOUS, kSampleFrame + 1, kSampleFrameSize - 1)};
- CreateReadOnly(reads);
- int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
- ASSERT_EQ(OK, result);
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
+ CreateChunkedRead(
+ SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
+ int result = stream_->ReadFrames(&frames_, cb_.callback());
+ EXPECT_EQ(OK, result);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
}
// The same behaviour applies to asynchronous reads.
-TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedAsync) {
- MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1),
- MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
- CreateReadOnly(reads);
- int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
+ CreateChunkedRead(
+ ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
+ int result = stream_->ReadFrames(&frames_, cb_.callback());
ASSERT_EQ(ERR_IO_PENDING, result);
EXPECT_EQ(OK, cb_.WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
}
// If it receives an incomplete header in a synchronous call, then has to wait
@@ -211,12 +314,11 @@ TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
CreateReadOnly(reads);
- int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
+ int result = stream_->ReadFrames(&frames_, cb_.callback());
ASSERT_EQ(ERR_IO_PENDING, result);
EXPECT_EQ(OK, cb_.WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
}
// An extended header should also return ERR_IO_PENDING if it is not completely
@@ -226,112 +328,156 @@ TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
CreateReadOnly(reads);
- EXPECT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
}
-// A frame that does not arrive in a single read should arrive in chunks.
-TEST_F(WebSocketBasicStreamSocketTest, LargeFrameFirstChunk) {
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)};
- CreateReadOnly(reads);
- EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(kLargeFrameDeclaredPayloadSize,
- frame_chunks_[0]->header->payload_length);
- EXPECT_TRUE(frame_chunks_[0]->header->final);
- EXPECT_FALSE(frame_chunks_[0]->final_chunk);
+// A frame that does not arrive in a single read should be broken into separate
+// frames.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
+ CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_FALSE(frames_[0]->header.final);
EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
- static_cast<size_t>(frame_chunks_[0]->data->size()));
+ static_cast<size_t>(frames_[0]->header.payload_length));
}
-// If only the header arrives, we should get a zero-byte chunk.
-TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) {
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)};
- CreateReadOnly(reads);
- EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- ASSERT_EQ(1U, frame_chunks_.size());
- EXPECT_FALSE(frame_chunks_[0]->final_chunk);
- EXPECT_TRUE(frame_chunks_[0]->data.get() == NULL);
+// If only the header of a data frame arrives, we should receive a frame with a
+// zero-size payload.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, HeaderOnlyChunk) {
+ CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize));
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(NULL, frames_[0]->data.get());
+ EXPECT_EQ(0U, frames_[0]->header.payload_length);
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
}
-// The second and subsequent chunks of a frame have no header.
-TEST_F(WebSocketBasicStreamSocketTest, LargeFrameTwoChunks) {
- static const size_t kChunkSize = 16;
+// If the header and the body of a data frame arrive seperately, we should see
+// them as separate frames.
+TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
MockRead reads[] = {
- MockRead(ASYNC, kPartialLargeFrame, kChunkSize),
- MockRead(ASYNC, kPartialLargeFrame + kChunkSize, kChunkSize)};
+ MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
+ MockRead(ASYNC,
+ kPartialLargeFrame + kLargeFrameHeaderSize,
+ kPartialLargeFrameSize - kLargeFrameHeaderSize)};
CreateReadOnly(reads);
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(NULL, frames_[0]->data.get());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
+ frames_.clear();
+ EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(OK, cb_.WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
+ frames_[0]->header.payload_length);
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames_[0]->header.opcode);
+}
+
+// Every frame has a header with a correct payload_length field.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
+ const size_t kChunkSize = 16;
+ CreateChunkedRead(ASYNC,
+ kPartialLargeFrame,
+ kPartialLargeFrameSize,
+ kChunkSize,
+ 2,
+ LAST_FRAME_NOT_BIG);
TestCompletionCallback cb[2];
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
EXPECT_EQ(OK, cb[0].WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->header);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
+ frames_[0]->header.payload_length);
- frame_chunks_.clear();
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
+ frames_.clear();
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
EXPECT_EQ(OK, cb[1].WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_FALSE(frame_chunks_[0]->header);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
}
-// Only the final chunk of a frame has final_chunk set.
-TEST_F(WebSocketBasicStreamSocketTest, OnlyFinalChunkIsFinal) {
+// Only the final frame of a fragmented message has |final| bit set.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
static const size_t kFirstChunkSize = 4;
- MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kFirstChunkSize),
- MockRead(ASYNC,
- kSampleFrame + kFirstChunkSize,
- kSampleFrameSize - kFirstChunkSize)};
- CreateReadOnly(reads);
+ CreateChunkedRead(ASYNC,
+ kSampleFrame,
+ kSampleFrameSize,
+ kFirstChunkSize,
+ 2,
+ LAST_FRAME_BIG);
TestCompletionCallback cb[2];
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
EXPECT_EQ(OK, cb[0].WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_FALSE(frame_chunks_[0]->final_chunk);
+ ASSERT_EQ(1U, frames_.size());
+ ASSERT_FALSE(frames_[0]->header.final);
- frame_chunks_.clear();
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
+ frames_.clear();
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
EXPECT_EQ(OK, cb[1].WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->final_chunk);
+ ASSERT_EQ(1U, frames_.size());
+ ASSERT_TRUE(frames_[0]->header.final);
}
-// Multiple frames that arrive together should be parsed correctly.
-TEST_F(WebSocketBasicStreamSocketTest, ThreeFramesTogether) {
- MockRead reads[] = {
- MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)};
- CreateReadOnly(reads);
+// All frames after the first have their opcode changed to Continuation.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) {
+ const size_t kFirstChunkSize = 3;
+ const int kChunkCount = 3;
+ // The input data is one frame with opcode Text, which arrives in three
+ // separate chunks.
+ CreateChunkedRead(ASYNC,
+ kSampleFrame,
+ kSampleFrameSize,
+ kFirstChunkSize,
+ kChunkCount,
+ LAST_FRAME_BIG);
+ TestCompletionCallback cb[kChunkCount];
+
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
+ EXPECT_EQ(OK, cb[0].WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
+
+ // This test uses a loop to verify that the opcode for every frames generated
+ // after the first is converted to Continuation.
+ for (int i = 1; i < kChunkCount; ++i) {
+ frames_.clear();
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[i].callback()));
+ EXPECT_EQ(OK, cb[i].WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames_[0]->header.opcode);
+ }
+}
- ASSERT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- ASSERT_EQ(3U, frame_chunks_.size());
- EXPECT_TRUE(frame_chunks_[0]->final_chunk);
- EXPECT_TRUE(frame_chunks_[1]->final_chunk);
- EXPECT_TRUE(frame_chunks_[2]->final_chunk);
+// Multiple frames that arrive together should be parsed correctly.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
+ CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(3U, frames_.size());
+ EXPECT_TRUE(frames_[0]->header.final);
+ EXPECT_TRUE(frames_[1]->header.final);
+ EXPECT_TRUE(frames_[2]->header.final);
}
// ERR_CONNECTION_CLOSED must be returned on close.
-TEST_F(WebSocketBasicStreamSocketTest, SyncClose) {
- MockRead reads[] = {MockRead(SYNCHRONOUS, "", 0)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
+ CreateRead(MockRead(SYNCHRONOUS, "", 0));
EXPECT_EQ(ERR_CONNECTION_CLOSED,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ stream_->ReadFrames(&frames_, cb_.callback()));
}
-TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) {
- MockRead reads[] = {MockRead(ASYNC, "", 0)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
+ CreateRead(MockRead(ASYNC, "", 0));
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
}
@@ -339,53 +485,52 @@ TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) {
// ERR_CONNECTION_CLOSED. This is not expected to happen on an established
// connection; a Read of size 0 is the expected behaviour. The key point of this
// test is to confirm that ReadFrames() behaviour is identical in both cases.
-TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) {
- MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
+ CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
EXPECT_EQ(ERR_CONNECTION_CLOSED,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ stream_->ReadFrames(&frames_, cb_.callback()));
}
-TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) {
- MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
+ CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
}
-TEST_F(WebSocketBasicStreamSocketTest, SyncErrorsPassedThrough) {
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
// ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
// WebSocketBasicStream gives no special handling to.
- MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES)};
- CreateReadOnly(reads);
+ CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ stream_->ReadFrames(&frames_, cb_.callback()));
}
-TEST_F(WebSocketBasicStreamSocketTest, AsyncErrorsPassedThrough) {
- MockRead reads[] = {MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
+ CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
}
// If we get a frame followed by a close, we should receive them separately.
-TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) {
- MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize),
- MockRead(SYNCHRONOUS, "", 0)};
- CreateReadOnly(reads);
-
- EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- EXPECT_EQ(1U, frame_chunks_.size());
- frame_chunks_.clear();
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
+ // The chunk size equals the data size, so the second chunk is 0 size, closing
+ // the connection.
+ CreateChunkedRead(SYNCHRONOUS,
+ kSampleFrame,
+ kSampleFrameSize,
+ kSampleFrameSize,
+ 2,
+ LAST_FRAME_NOT_BIG);
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(1U, frames_.size());
+ frames_.clear();
EXPECT_EQ(ERR_CONNECTION_CLOSED,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ stream_->ReadFrames(&frames_, cb_.callback()));
}
// Synchronous close after an async frame header is handled by a different code
@@ -395,9 +540,8 @@ TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
MockRead(SYNCHRONOUS, "", 0)};
CreateReadOnly(reads);
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
}
// When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
@@ -407,9 +551,82 @@ TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
CreateReadOnly(reads);
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
+}
+
+// An empty first frame is not ignored.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
+ CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(NULL, frames_[0]->data.get());
+ EXPECT_EQ(0U, frames_[0]->header.payload_length);
+}
+
+// An empty frame in the middle of a message is ignored.
+TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrame) {
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
+ MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
+ CreateReadOnly(reads);
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(1U, frames_.size());
+ frames_.clear();
+ EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+}
+
+// An empty frame in the middle of a message that arrives separately is still
+// ignored.
+TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrameAsync) {
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
+ MockRead(ASYNC, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
+ // We include a pong message to verify the middle frame was actually
+ // processed.
+ MockRead(ASYNC, kValidPong, kValidPongSize)};
+ CreateReadOnly(reads);
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(1U, frames_.size());
+ frames_.clear();
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(OK, cb_.WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodePong, frames_[0]->header.opcode);
+}
+
+// An empty final frame is not ignored.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
+ CreateRead(
+ MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(NULL, frames_[0]->data.get());
+ EXPECT_EQ(0U, frames_[0]->header.payload_length);
+}
+
+// An empty middle frame is ignored with a final frame present.
+TEST_F(WebSocketBasicStreamSocketTest, ThreeFrameEmptyMessage) {
+ MockRead reads[] = {
+ MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
+ MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
+ MockRead(SYNCHRONOUS,
+ kEmptyFinalContinuationFrame,
+ kEmptyFinalContinuationFrameSize)};
+ CreateReadOnly(reads);
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
+ frames_.clear();
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_TRUE(frames_[0]->header.final);
}
// If there was a frame read at the same time as the response headers (and the
@@ -418,83 +635,252 @@ TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
CreateNullStream();
- EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->data);
- EXPECT_EQ(6, frame_chunks_[0]->data->size());
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ ASSERT_TRUE(frames_[0]->data);
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
}
// Check that a frame whose header partially arrived at the end of the response
// headers works correctly.
-TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) {
+TEST_F(WebSocketBasicStreamSocketSingleReadTest,
+ PartialFrameHeaderInHttpResponse) {
SetHttpReadBuffer(kSampleFrame, 1);
- MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
- CreateReadOnly(reads);
+ CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(OK, cb_.WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ ASSERT_TRUE(frames_[0]->data);
+ EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
+}
+
+// Check that a control frame which partially arrives at the end of the response
+// headers works correctly.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest,
+ PartialControlFrameInHttpResponse) {
+ const size_t kPartialFrameBytes = 3;
+ SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
+ CreateRead(MockRead(ASYNC,
+ kCloseFrame + kPartialFrameBytes,
+ kCloseFrameSize - kPartialFrameBytes));
+
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
EXPECT_EQ(OK, cb_.WaitForResult());
- ASSERT_EQ(1U, frame_chunks_.size());
- ASSERT_TRUE(frame_chunks_[0]->data);
- EXPECT_EQ(6, frame_chunks_[0]->data->size());
- ASSERT_TRUE(frame_chunks_[0]->header);
- EXPECT_EQ(WebSocketFrameHeader::kOpCodeText,
- frame_chunks_[0]->header->opcode);
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
+ EXPECT_EQ(kCloseFrameSize - 2, frames_[0]->header.payload_length);
+ EXPECT_EQ(
+ 0,
+ memcmp(frames_[0]->data->data(), kCloseFrame + 2, kCloseFrameSize - 2));
+}
+
+// Check that a control frame which partially arrives at the end of the response
+// headers works correctly. Synchronous version (unlikely in practice).
+TEST_F(WebSocketBasicStreamSocketSingleReadTest,
+ PartialControlFrameInHttpResponseSync) {
+ const size_t kPartialFrameBytes = 3;
+ SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
+ CreateRead(MockRead(SYNCHRONOUS,
+ kCloseFrame + kPartialFrameBytes,
+ kCloseFrameSize - kPartialFrameBytes));
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
}
// Check that an invalid frame results in an error.
-TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) {
- MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
+ CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ stream_->ReadFrames(&frames_, cb_.callback()));
}
-TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) {
- MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)};
- CreateReadOnly(reads);
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
+ CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->ReadFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
}
+// A control frame without a FIN flag is invalid and should not be passed
+// through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
+// fragmented."
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
+ CreateRead(
+ MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
+
+ EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
+ stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_TRUE(frames_.empty());
+}
+
+// A control frame over 125 characters is invalid. RFC6455 5.5 "All control
+// frames MUST have a payload length of 125 bytes or less". Since we use a
+// 125-byte buffer to assemble fragmented control frames, we need to detect this
+// error before attempting to assemble the fragments.
+TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
+ CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
+
+ EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
+ stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_TRUE(frames_.empty());
+}
+
+// A control frame over 125 characters should still be rejected if it is split
+// into multiple chunks.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
+ const size_t kFirstChunkSize = 16;
+ expect_all_io_to_complete_ = false;
+ CreateChunkedRead(SYNCHRONOUS,
+ k126BytePong,
+ k126BytePongSize,
+ kFirstChunkSize,
+ 2,
+ LAST_FRAME_BIG);
+
+ EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
+ stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_TRUE(frames_.empty());
+}
+
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
+ AsyncSplitOverlongControlFrame) {
+ const size_t kFirstChunkSize = 16;
+ expect_all_io_to_complete_ = false;
+ CreateChunkedRead(ASYNC,
+ k126BytePong,
+ k126BytePongSize,
+ kFirstChunkSize,
+ 2,
+ LAST_FRAME_BIG);
+
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
+ // The caller should not call ReadFrames() again after receiving an error
+ // other than ERR_IO_PENDING.
+ EXPECT_TRUE(frames_.empty());
+}
+
+// In the synchronous case, ReadFrames assembles the whole control frame before
+// returning.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
+ const size_t kChunkSize = 3;
+ CreateChunkedRead(
+ SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
+
+ EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
+}
+
+// In the asynchronous case, the callback is not called until the control frame
+// has been completely assembled.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
+ const size_t kChunkSize = 3;
+ CreateChunkedRead(
+ ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
+
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(OK, cb_.WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
+}
+
+// A frame with a 1MB payload that has to be read in chunks.
+TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OneMegFrame) {
+ // This should be equal to the definition of kReadBufferSize in
+ // websocket_basic_stream.cc.
+ const int kReadBufferSize = 32 * 1024;
+ const uint64 kPayloadSize = 1 << 20;
+ const size_t kWireSize = kPayloadSize + kLargeFrameHeaderSize;
+ const size_t kExpectedFrameCount =
+ (kWireSize + kReadBufferSize - 1) / kReadBufferSize;
+ scoped_ptr<char[]> big_frame(new char[kWireSize]);
+ memcpy(big_frame.get(), "\x81\x7F", 2);
+ WriteBigEndian(big_frame.get() + 2, kPayloadSize);
+ memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize);
+
+ CreateChunkedRead(ASYNC,
+ big_frame.get(),
+ kWireSize,
+ kReadBufferSize,
+ kExpectedFrameCount,
+ LAST_FRAME_BIG);
+
+ for (size_t frame = 0; frame < kExpectedFrameCount; ++frame) {
+ frames_.clear();
+ ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
+ EXPECT_EQ(OK, cb_.WaitForResult());
+ ASSERT_EQ(1U, frames_.size());
+ size_t expected_payload_size = kReadBufferSize;
+ if (frame == 0) {
+ expected_payload_size = kReadBufferSize - kLargeFrameHeaderSize;
+ } else if (frame == kExpectedFrameCount - 1) {
+ expected_payload_size = kLargeFrameHeaderSize;
+ }
+ EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
+ }
+}
+
// Check that writing a frame all at once works.
-TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) {
+TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
CreateWriteOnly(writes);
- frame_chunks_ = GenerateWriteFrame();
- EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback()));
+ EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
}
// Check that completely async writing works.
-TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) {
+TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
CreateWriteOnly(writes);
- frame_chunks_ = GenerateWriteFrame();
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->WriteFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
EXPECT_EQ(OK, cb_.WaitForResult());
}
// Check that writing a frame to an extremely full kernel buffer (so that it
// ends up being sent in bits) works. The WriteFrames() callback should not be
// called until all parts have been written.
-TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) {
+TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
MockWrite(ASYNC, kWriteFrame + 4, 4),
MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
CreateWriteOnly(writes);
- frame_chunks_ = GenerateWriteFrame();
- ASSERT_EQ(ERR_IO_PENDING,
- stream_->WriteFrames(&frame_chunks_, cb_.callback()));
+ ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
EXPECT_EQ(OK, cb_.WaitForResult());
}
+// Check that writing with a non-NULL mask works correctly.
+TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) {
+ std::string masked_frame = std::string("\x81\x88");
+ masked_frame += std::string(kNonNulMaskingKey.key, 4);
+ masked_frame += "jiggered";
+ MockWrite writes[] = {
+ MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())};
+ generator_ = &GenerateNonNulMaskingKey;
+ CreateStream(NULL, 0, writes, arraysize(writes));
+
+ scoped_ptr<WebSocketFrame> frame(
+ new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
+ const std::string unmasked_payload = "graphics";
+ const size_t payload_size = unmasked_payload.size();
+ frame->data = new IOBuffer(payload_size);
+ memcpy(frame->data->data(), unmasked_payload.data(), payload_size);
+ WebSocketFrameHeader& header = frame->header;
+ header.final = true;
+ header.masked = true;
+ header.payload_length = payload_size;
+ frames_.push_back(frame.release());
+
+ EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
+}
+
TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
extensions_ = "inflate-uuencode";
CreateNullStream();
diff --git a/chromium/net/websockets/websocket_channel.cc b/chromium/net/websockets/websocket_channel.cc
index 3db457c08f4..61a47b71eb8 100644
--- a/chromium/net/websockets/websocket_channel.cc
+++ b/chromium/net/websockets/websocket_channel.cc
@@ -8,11 +8,14 @@
#include "base/basictypes.h" // for size_t
#include "base/bind.h"
+#include "base/compiler_specific.h"
#include "base/safe_numerics.h"
#include "base/strings/string_util.h"
+#include "base/time/time.h"
#include "net/base/big_endian.h"
#include "net/base/io_buffer.h"
#include "net/base/net_log.h"
+#include "net/http/http_util.h"
#include "net/websockets/websocket_errors.h"
#include "net/websockets/websocket_event_interface.h"
#include "net/websockets/websocket_frame.h"
@@ -26,10 +29,47 @@ namespace {
const int kDefaultSendQuotaLowWaterMark = 1 << 16;
const int kDefaultSendQuotaHighWaterMark = 1 << 17;
const size_t kWebSocketCloseCodeLength = 2;
+// This timeout is based on TCPMaximumSegmentLifetime * 2 from
+// MainThreadWebSocketChannel.cpp in Blink.
+const int kClosingHandshakeTimeoutSeconds = 2 * 2 * 60;
+
+typedef WebSocketEventInterface::ChannelState ChannelState;
+const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
+const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED;
+
+// Maximum close reason length = max control frame payload -
+// status code length
+// = 125 - 2
+const size_t kMaximumCloseReasonLength = 125 - kWebSocketCloseCodeLength;
+
+// Check a close status code for strict compliance with RFC6455. This is only
+// used for close codes received from a renderer that we are intending to send
+// out over the network. See ParseClose() for the restrictions on incoming close
+// codes. The |code| parameter is type int for convenience of implementation;
+// the real type is uint16.
+bool IsStrictlyValidCloseStatusCode(int code) {
+ static const int kInvalidRanges[] = {
+ // [BAD, OK)
+ 0, 1000, // 1000 is the first valid code
+ 1005, 1007, // 1005 and 1006 MUST NOT be set.
+ 1014, 3000, // 1014 unassigned; 1015 up to 2999 are reserved.
+ 5000, 65536, // Codes above 5000 are invalid.
+ };
+ const int* const kInvalidRangesEnd =
+ kInvalidRanges + arraysize(kInvalidRanges);
+
+ DCHECK_GE(code, 0);
+ DCHECK_LT(code, 65536);
+ const int* upper = std::upper_bound(kInvalidRanges, kInvalidRangesEnd, code);
+ DCHECK_NE(kInvalidRangesEnd, upper);
+ DCHECK_GT(upper, kInvalidRanges);
+ DCHECK_GT(*upper, code);
+ DCHECK_LE(*(upper - 1), code);
+ return ((upper - kInvalidRanges) % 2) == 0;
+}
-// This uses type uint64 to match the definition of
-// WebSocketFrameHeader::payload_length in websocket_frame.h.
-const uint64 kMaxControlFramePayload = 125;
+// This function avoids a bunch of boilerplate code.
+void AllowUnused(ChannelState ALLOW_UNUSED unused) {}
} // namespace
@@ -39,26 +79,25 @@ class WebSocketChannel::SendBuffer {
public:
SendBuffer() : total_bytes_(0) {}
- // Add a WebSocketFrameChunk to the buffer and increase total_bytes_.
- void AddFrame(scoped_ptr<WebSocketFrameChunk> chunk);
+ // Add a WebSocketFrame to the buffer and increase total_bytes_.
+ void AddFrame(scoped_ptr<WebSocketFrame> chunk);
// Return a pointer to the frames_ for write purposes.
- ScopedVector<WebSocketFrameChunk>* frames() { return &frames_; }
+ ScopedVector<WebSocketFrame>* frames() { return &frames_; }
private:
// The frames_ that will be sent in the next call to WriteFrames().
- ScopedVector<WebSocketFrameChunk> frames_;
+ ScopedVector<WebSocketFrame> frames_;
- // The total size of the buffers in |frames_|. This will be used to measure
- // the throughput of the link.
+ // The total size of the payload data in |frames_|. This will be used to
+ // measure the throughput of the link.
// TODO(ricea): Measure the throughput of the link.
size_t total_bytes_;
};
-void WebSocketChannel::SendBuffer::AddFrame(
- scoped_ptr<WebSocketFrameChunk> chunk) {
- total_bytes_ += chunk->data->size();
- frames_.push_back(chunk.release());
+void WebSocketChannel::SendBuffer::AddFrame(scoped_ptr<WebSocketFrame> frame) {
+ total_bytes_ += frame->header.payload_length;
+ frames_.push_back(frame.release());
}
// Implementation of WebSocketStream::ConnectDelegate that simply forwards the
@@ -70,10 +109,12 @@ class WebSocketChannel::ConnectDelegate
virtual void OnSuccess(scoped_ptr<WebSocketStream> stream) OVERRIDE {
creator_->OnConnectSuccess(stream.Pass());
+ // |this| may have been deleted.
}
virtual void OnFailure(uint16 websocket_error) OVERRIDE {
creator_->OnConnectFailure(websocket_error);
+ // |this| has been deleted.
}
private:
@@ -87,31 +128,35 @@ class WebSocketChannel::ConnectDelegate
};
WebSocketChannel::WebSocketChannel(
- const GURL& socket_url,
- scoped_ptr<WebSocketEventInterface> event_interface)
- : socket_url_(socket_url),
- event_interface_(event_interface.Pass()),
+ scoped_ptr<WebSocketEventInterface> event_interface,
+ URLRequestContext* url_request_context)
+ : event_interface_(event_interface.Pass()),
+ url_request_context_(url_request_context),
send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark),
send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark),
current_send_quota_(0),
+ timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)),
closing_code_(0),
state_(FRESHLY_CONSTRUCTED) {}
WebSocketChannel::~WebSocketChannel() {
- // The stream may hold a pointer to read_frame_chunks_, and so it needs to be
+ // The stream may hold a pointer to read_frames_, and so it needs to be
// destroyed first.
stream_.reset();
+ // The timer may have a callback pointing back to us, so stop it just in case
+ // someone decides to run the event loop from their destructor.
+ timer_.Stop();
}
void WebSocketChannel::SendAddChannelRequest(
+ const GURL& socket_url,
const std::vector<std::string>& requested_subprotocols,
- const GURL& origin,
- URLRequestContext* url_request_context) {
+ const GURL& origin) {
// Delegate to the tested version.
- SendAddChannelRequestWithFactory(
+ SendAddChannelRequestWithSuppliedCreator(
+ socket_url,
requested_subprotocols,
origin,
- url_request_context,
base::Bind(&WebSocketStream::CreateAndConnectStream));
}
@@ -146,9 +191,10 @@ void WebSocketChannel::SendFrame(bool fin,
return;
}
if (data.size() > base::checked_numeric_cast<size_t>(current_send_quota_)) {
- FailChannel(SEND_GOING_AWAY,
- kWebSocketMuxErrorSendQuotaViolation,
- "Send quota exceeded");
+ AllowUnused(FailChannel(SEND_GOING_AWAY,
+ kWebSocketMuxErrorSendQuotaViolation,
+ "Send quota exceeded"));
+ // |this| has been deleted.
return;
}
if (!WebSocketFrameHeader::IsKnownDataOpCode(op_code)) {
@@ -163,13 +209,15 @@ void WebSocketChannel::SendFrame(bool fin,
// water mark" and "high water mark", but only if the link to the WebSocket
// server is not saturated.
// TODO(ricea): For kOpCodeText, do UTF-8 validation?
- scoped_refptr<IOBufferWithSize> buffer(new IOBufferWithSize(data.size()));
+ scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size()));
std::copy(data.begin(), data.end(), buffer->data());
- SendIOBufferWithSize(fin, op_code, buffer);
+ AllowUnused(SendIOBuffer(fin, op_code, buffer, data.size()));
+ // |this| may have been deleted.
}
void WebSocketChannel::SendFlowControl(int64 quota) {
- DCHECK_EQ(CONNECTED, state_);
+ DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED ||
+ state_ == CLOSE_WAIT);
// TODO(ricea): Add interface to WebSocketStream and implement.
// stream_->SendFlowControl(quota);
}
@@ -185,32 +233,58 @@ void WebSocketChannel::StartClosingHandshake(uint16 code,
NOTREACHED() << "StartClosingHandshake() called in state " << state_;
return;
}
- // TODO(ricea): Validate |code|? Check that |reason| is valid UTF-8?
- // TODO(ricea): There should be a timeout for the closing handshake.
- SendClose(code, reason); // Sets state_ to SEND_CLOSED
+ // Javascript actually only permits 1000 and 3000-4999, but the implementation
+ // itself may produce different codes. The length of |reason| is also checked
+ // by Javascript.
+ if (!IsStrictlyValidCloseStatusCode(code) ||
+ reason.size() > kMaximumCloseReasonLength) {
+ // "InternalServerError" is actually used for errors from any endpoint, per
+ // errata 3227 to RFC6455. If the renderer is sending us an invalid code or
+ // reason it must be malfunctioning in some way, and based on that we
+ // interpret this as an internal error.
+ AllowUnused(
+ SendClose(kWebSocketErrorInternalServerError, "Internal Error"));
+ // |this| may have been deleted.
+ return;
+ }
+ AllowUnused(SendClose(code, IsStringUTF8(reason) ? reason : std::string()));
+ // |this| may have been deleted.
}
void WebSocketChannel::SendAddChannelRequestForTesting(
+ const GURL& socket_url,
const std::vector<std::string>& requested_subprotocols,
const GURL& origin,
- URLRequestContext* url_request_context,
- const WebSocketStreamFactory& factory) {
- SendAddChannelRequestWithFactory(
- requested_subprotocols, origin, url_request_context, factory);
+ const WebSocketStreamCreator& creator) {
+ SendAddChannelRequestWithSuppliedCreator(
+ socket_url, requested_subprotocols, origin, creator);
+}
+
+void WebSocketChannel::SetClosingHandshakeTimeoutForTesting(
+ base::TimeDelta delay) {
+ timeout_ = delay;
}
-void WebSocketChannel::SendAddChannelRequestWithFactory(
+void WebSocketChannel::SendAddChannelRequestWithSuppliedCreator(
+ const GURL& socket_url,
const std::vector<std::string>& requested_subprotocols,
const GURL& origin,
- URLRequestContext* url_request_context,
- const WebSocketStreamFactory& factory) {
+ const WebSocketStreamCreator& creator) {
DCHECK_EQ(FRESHLY_CONSTRUCTED, state_);
+ if (!socket_url.SchemeIsWSOrWSS()) {
+ // TODO(ricea): Kill the renderer (this error should have been caught by
+ // Javascript).
+ AllowUnused(event_interface_->OnAddChannelResponse(true, ""));
+ // |this| is deleted here.
+ return;
+ }
+ socket_url_ = socket_url;
scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate(
new ConnectDelegate(this));
- stream_request_ = factory.Run(socket_url_,
+ stream_request_ = creator.Run(socket_url_,
requested_subprotocols,
origin,
- url_request_context,
+ url_request_context_,
BoundNetLog(),
connect_delegate.Pass());
state_ = CONNECTING;
@@ -221,41 +295,50 @@ void WebSocketChannel::OnConnectSuccess(scoped_ptr<WebSocketStream> stream) {
DCHECK_EQ(CONNECTING, state_);
stream_ = stream.Pass();
state_ = CONNECTED;
- event_interface_->OnAddChannelResponse(false, stream_->GetSubProtocol());
+ if (event_interface_->OnAddChannelResponse(
+ false, stream_->GetSubProtocol()) == CHANNEL_DELETED)
+ return;
// TODO(ricea): Get flow control information from the WebSocketStream once we
// have a multiplexing WebSocketStream.
current_send_quota_ = send_quota_high_water_mark_;
- event_interface_->OnFlowControl(send_quota_high_water_mark_);
+ if (event_interface_->OnFlowControl(send_quota_high_water_mark_) ==
+ CHANNEL_DELETED)
+ return;
// |stream_request_| is not used once the connection has succeeded.
stream_request_.reset();
- ReadFrames();
+ AllowUnused(ReadFrames());
+ // |this| may have been deleted.
}
void WebSocketChannel::OnConnectFailure(uint16 websocket_error) {
DCHECK_EQ(CONNECTING, state_);
state_ = CLOSED;
stream_request_.reset();
- event_interface_->OnAddChannelResponse(true, "");
+ AllowUnused(event_interface_->OnAddChannelResponse(true, ""));
+ // |this| has been deleted.
}
-void WebSocketChannel::WriteFrames() {
+ChannelState WebSocketChannel::WriteFrames() {
int result = OK;
do {
// This use of base::Unretained is safe because this object owns the
// WebSocketStream and destroying it cancels all callbacks.
result = stream_->WriteFrames(
data_being_sent_->frames(),
- base::Bind(
- &WebSocketChannel::OnWriteDone, base::Unretained(this), false));
+ base::Bind(base::IgnoreResult(&WebSocketChannel::OnWriteDone),
+ base::Unretained(this),
+ false));
if (result != ERR_IO_PENDING) {
- OnWriteDone(true, result);
+ if (OnWriteDone(true, result) == CHANNEL_DELETED)
+ return CHANNEL_DELETED;
}
} while (result == OK && data_being_sent_);
+ return CHANNEL_ALIVE;
}
-void WebSocketChannel::OnWriteDone(bool synchronous, int result) {
+ChannelState WebSocketChannel::OnWriteDone(bool synchronous, int result) {
DCHECK_NE(FRESHLY_CONSTRUCTED, state_);
DCHECK_NE(CONNECTING, state_);
DCHECK_NE(ERR_IO_PENDING, result);
@@ -264,9 +347,8 @@ void WebSocketChannel::OnWriteDone(bool synchronous, int result) {
case OK:
if (data_to_send_next_) {
data_being_sent_ = data_to_send_next_.Pass();
- if (!synchronous) {
- WriteFrames();
- }
+ if (!synchronous)
+ return WriteFrames();
} else {
data_being_sent_.reset();
if (current_send_quota_ < send_quota_low_water_mark_) {
@@ -281,10 +363,10 @@ void WebSocketChannel::OnWriteDone(bool synchronous, int result) {
// server, if the protocol in use supports quota.
int fresh_quota = send_quota_high_water_mark_ - current_send_quota_;
current_send_quota_ += fresh_quota;
- event_interface_->OnFlowControl(fresh_quota);
+ return event_interface_->OnFlowControl(fresh_quota);
}
}
- return;
+ return CHANNEL_ALIVE;
// If a recoverable error condition existed, it would go here.
@@ -292,32 +374,34 @@ void WebSocketChannel::OnWriteDone(bool synchronous, int result) {
DCHECK_LT(result, 0)
<< "WriteFrames() should only return OK or ERR_ codes";
stream_->Close();
- if (state_ != CLOSED) {
- state_ = CLOSED;
- event_interface_->OnDropChannel(kWebSocketErrorAbnormalClosure,
- "Abnormal Closure");
- }
- return;
+ DCHECK_NE(CLOSED, state_);
+ state_ = CLOSED;
+ return event_interface_->OnDropChannel(kWebSocketErrorAbnormalClosure,
+ "Abnormal Closure");
}
}
-void WebSocketChannel::ReadFrames() {
+ChannelState WebSocketChannel::ReadFrames() {
int result = OK;
do {
// This use of base::Unretained is safe because this object owns the
// WebSocketStream, and any pending reads will be cancelled when it is
// destroyed.
result = stream_->ReadFrames(
- &read_frame_chunks_,
- base::Bind(
- &WebSocketChannel::OnReadDone, base::Unretained(this), false));
+ &read_frames_,
+ base::Bind(base::IgnoreResult(&WebSocketChannel::OnReadDone),
+ base::Unretained(this),
+ false));
if (result != ERR_IO_PENDING) {
- OnReadDone(true, result);
+ if (OnReadDone(true, result) == CHANNEL_DELETED)
+ return CHANNEL_DELETED;
}
- } while (result == OK && state_ != CLOSED);
+ DCHECK_NE(CLOSED, state_);
+ } while (result == OK);
+ return CHANNEL_ALIVE;
}
-void WebSocketChannel::OnReadDone(bool synchronous, int result) {
+ChannelState WebSocketChannel::OnReadDone(bool synchronous, int result) {
DCHECK_NE(FRESHLY_CONSTRUCTED, state_);
DCHECK_NE(CONNECTING, state_);
DCHECK_NE(ERR_IO_PENDING, result);
@@ -325,158 +409,74 @@ void WebSocketChannel::OnReadDone(bool synchronous, int result) {
case OK:
// ReadFrames() must use ERR_CONNECTION_CLOSED for a closed connection
// with no data read, not an empty response.
- DCHECK(!read_frame_chunks_.empty())
+ DCHECK(!read_frames_.empty())
<< "ReadFrames() returned OK, but nothing was read.";
- for (size_t i = 0; i < read_frame_chunks_.size(); ++i) {
- scoped_ptr<WebSocketFrameChunk> chunk(read_frame_chunks_[i]);
- read_frame_chunks_[i] = NULL;
- ProcessFrameChunk(chunk.Pass());
+ for (size_t i = 0; i < read_frames_.size(); ++i) {
+ scoped_ptr<WebSocketFrame> frame(read_frames_[i]);
+ read_frames_[i] = NULL;
+ if (ProcessFrame(frame.Pass()) == CHANNEL_DELETED)
+ return CHANNEL_DELETED;
}
- read_frame_chunks_.clear();
+ read_frames_.clear();
// There should always be a call to ReadFrames pending.
- if (!synchronous && state_ != CLOSED) {
- ReadFrames();
- }
- return;
+ // TODO(ricea): Unless we are out of quota.
+ DCHECK_NE(CLOSED, state_);
+ if (!synchronous)
+ return ReadFrames();
+ return CHANNEL_ALIVE;
+
+ case ERR_WS_PROTOCOL_ERROR:
+ return FailChannel(SEND_REAL_ERROR,
+ kWebSocketErrorProtocolError,
+ "WebSocket Protocol Error");
default:
DCHECK_LT(result, 0)
<< "ReadFrames() should only return OK or ERR_ codes";
stream_->Close();
- if (state_ != CLOSED) {
- state_ = CLOSED;
- uint16 code = kWebSocketErrorAbnormalClosure;
- std::string reason = "Abnormal Closure";
- if (closing_code_ != 0) {
- code = closing_code_;
- reason = closing_reason_;
- }
- event_interface_->OnDropChannel(code, reason);
+ DCHECK_NE(CLOSED, state_);
+ state_ = CLOSED;
+ uint16 code = kWebSocketErrorAbnormalClosure;
+ std::string reason = "Abnormal Closure";
+ if (closing_code_ != 0) {
+ code = closing_code_;
+ reason = closing_reason_;
}
- return;
+ return event_interface_->OnDropChannel(code, reason);
}
}
-void WebSocketChannel::ProcessFrameChunk(
- scoped_ptr<WebSocketFrameChunk> chunk) {
- bool is_first_chunk = false;
- if (chunk->header) {
- DCHECK(current_frame_header_ == NULL)
- << "Received the header for a new frame without notification that "
- << "the previous frame was complete.";
- is_first_chunk = true;
- current_frame_header_.swap(chunk->header);
- if (current_frame_header_->masked) {
- // RFC6455 Section 5.1 "A client MUST close a connection if it detects a
- // masked frame."
- FailChannel(SEND_REAL_ERROR,
- kWebSocketErrorProtocolError,
- "Masked frame from server");
- return;
- }
+ChannelState WebSocketChannel::ProcessFrame(scoped_ptr<WebSocketFrame> frame) {
+ if (frame->header.masked) {
+ // RFC6455 Section 5.1 "A client MUST close a connection if it detects a
+ // masked frame."
+ return FailChannel(SEND_REAL_ERROR,
+ kWebSocketErrorProtocolError,
+ "Masked frame from server");
}
- if (!current_frame_header_) {
- // If this channel rejected the previous chunk as invalid, then it will have
- // reset |current_frame_header_| and closed the channel. More chunks of the
- // invalid frame may still arrive, and it is not necessarily a bug for that
- // to happen. However, if this happens when state_ is CONNECTED, it is
- // definitely a bug.
- DCHECK(state_ != CONNECTED) << "Unexpected header-less frame received "
- << "(final_chunk = " << chunk->final_chunk
- << ", data size = " << chunk->data->size()
- << ")";
- return;
- }
- scoped_refptr<IOBufferWithSize> data_buffer;
- data_buffer.swap(chunk->data);
- const bool is_final_chunk = chunk->final_chunk;
- chunk.reset();
- const WebSocketFrameHeader::OpCode opcode = current_frame_header_->opcode;
- if (WebSocketFrameHeader::IsKnownControlOpCode(opcode)) {
- if (!current_frame_header_->final) {
- FailChannel(SEND_REAL_ERROR,
- kWebSocketErrorProtocolError,
- "Control message with FIN bit unset received");
- return;
- }
- if (current_frame_header_->payload_length > kMaxControlFramePayload) {
- FailChannel(SEND_REAL_ERROR,
- kWebSocketErrorProtocolError,
- "Control message has payload over 125 bytes");
- return;
- }
- if (!is_final_chunk) {
- VLOG(2) << "Encountered a split control frame, opcode " << opcode;
- if (incomplete_control_frame_body_) {
- VLOG(3) << "Appending to an existing split control frame.";
- AddToIncompleteControlFrameBody(data_buffer);
- } else {
- VLOG(3) << "Creating new storage for an incomplete control frame.";
- incomplete_control_frame_body_ = new GrowableIOBuffer();
- // This method checks for oversize control frames above, so as long as
- // the frame parser is working correctly, this won't overflow. If a bug
- // does cause it to overflow, it will CHECK() in
- // AddToIncompleteControlFrameBody() without writing outside the buffer.
- incomplete_control_frame_body_->SetCapacity(kMaxControlFramePayload);
- AddToIncompleteControlFrameBody(data_buffer);
- }
- return; // Handle when complete.
- }
- if (incomplete_control_frame_body_) {
- VLOG(2) << "Rejoining a split control frame, opcode " << opcode;
- AddToIncompleteControlFrameBody(data_buffer);
- const int body_size = incomplete_control_frame_body_->offset();
- data_buffer = new IOBufferWithSize(body_size);
- memcpy(data_buffer->data(),
- incomplete_control_frame_body_->StartOfBuffer(),
- body_size);
- incomplete_control_frame_body_ = NULL; // Frame now complete.
- }
+ const WebSocketFrameHeader::OpCode opcode = frame->header.opcode;
+ if (WebSocketFrameHeader::IsKnownControlOpCode(opcode) &&
+ !frame->header.final) {
+ return FailChannel(SEND_REAL_ERROR,
+ kWebSocketErrorProtocolError,
+ "Control message with FIN bit unset received");
}
- // Apply basic sanity checks to the |payload_length| field from the frame
- // header. A check for exact equality can only be used when the whole frame
- // arrives in one chunk.
- DCHECK_GE(current_frame_header_->payload_length,
- base::checked_numeric_cast<uint64>(data_buffer->size()));
- DCHECK(!is_first_chunk || !is_final_chunk ||
- current_frame_header_->payload_length ==
- base::checked_numeric_cast<uint64>(data_buffer->size()));
-
// Respond to the frame appropriately to its type.
- HandleFrame(opcode, is_first_chunk, is_final_chunk, data_buffer);
-
- if (is_final_chunk) {
- // Make sure that this frame header is not applied to any future chunks.
- current_frame_header_.reset();
- }
-}
-
-void WebSocketChannel::AddToIncompleteControlFrameBody(
- const scoped_refptr<IOBufferWithSize>& data_buffer) {
- const int new_offset =
- incomplete_control_frame_body_->offset() + data_buffer->size();
- CHECK_GE(incomplete_control_frame_body_->capacity(), new_offset)
- << "Control frame body larger than frame header indicates; frame parser "
- "bug?";
- memcpy(incomplete_control_frame_body_->data(),
- data_buffer->data(),
- data_buffer->size());
- incomplete_control_frame_body_->set_offset(new_offset);
+ return HandleFrame(
+ opcode, frame->header.final, frame->data, frame->header.payload_length);
}
-void WebSocketChannel::HandleFrame(
+ChannelState WebSocketChannel::HandleFrame(
const WebSocketFrameHeader::OpCode opcode,
- bool is_first_chunk,
- bool is_final_chunk,
- const scoped_refptr<IOBufferWithSize>& data_buffer) {
+ bool final,
+ const scoped_refptr<IOBuffer>& data_buffer,
+ size_t size) {
DCHECK_NE(RECV_CLOSED, state_)
<< "HandleFrame() does not support being called re-entrantly from within "
"SendClose()";
- if (state_ == CLOSED || state_ == CLOSE_WAIT) {
- DVLOG_IF(1, state_ == CLOSED) << "A frame was received while in the CLOSED "
- "state. This is possible after a channel "
- "failed, but should be very rare.";
+ DCHECK_NE(CLOSED, state_);
+ if (state_ == CLOSE_WAIT) {
std::string frame_name;
switch (opcode) {
case WebSocketFrameHeader::kOpCodeText: // fall-thru
@@ -503,22 +503,20 @@ void WebSocketChannel::HandleFrame(
}
// SEND_REAL_ERROR makes no difference here, as FailChannel() won't send
// another Close frame.
- FailChannel(SEND_REAL_ERROR,
- kWebSocketErrorProtocolError,
- frame_name + " received after close");
- return;
+ return FailChannel(SEND_REAL_ERROR,
+ kWebSocketErrorProtocolError,
+ frame_name + " received after close");
}
switch (opcode) {
case WebSocketFrameHeader::kOpCodeText: // fall-thru
case WebSocketFrameHeader::kOpCodeBinary: // fall-thru
case WebSocketFrameHeader::kOpCodeContinuation:
if (state_ == CONNECTED) {
- const bool final = is_final_chunk && current_frame_header_->final;
// TODO(ricea): Need to fail the connection if UTF-8 is invalid
// post-reassembly. Requires a streaming UTF-8 validator.
// TODO(ricea): Can this copy be eliminated?
- const char* const data_begin = data_buffer->data();
- const char* const data_end = data_begin + data_buffer->size();
+ const char* const data_begin = size ? data_buffer->data() : NULL;
+ const char* const data_end = data_begin + size;
const std::vector<char> data(data_begin, data_end);
// TODO(ricea): Handle the case when ReadFrames returns far
// more data at once than should be sent in a single IPC. This needs to
@@ -526,42 +524,39 @@ void WebSocketChannel::HandleFrame(
// cause of receiving very large chunks.
// Sends the received frame to the renderer process.
- event_interface_->OnDataFrame(
- final,
- is_first_chunk ? opcode : WebSocketFrameHeader::kOpCodeContinuation,
- data);
- } else {
- VLOG(3) << "Ignored data packet received in state " << state_;
+ return event_interface_->OnDataFrame(final, opcode, data);
}
- return;
+ VLOG(3) << "Ignored data packet received in state " << state_;
+ return CHANNEL_ALIVE;
case WebSocketFrameHeader::kOpCodePing:
- VLOG(1) << "Got Ping of size " << data_buffer->size();
- if (state_ == CONNECTED) {
- SendIOBufferWithSize(
- true, WebSocketFrameHeader::kOpCodePong, data_buffer);
- } else {
- VLOG(3) << "Ignored ping in state " << state_;
- }
- return;
+ VLOG(1) << "Got Ping of size " << size;
+ if (state_ == CONNECTED)
+ return SendIOBuffer(
+ true, WebSocketFrameHeader::kOpCodePong, data_buffer, size);
+ VLOG(3) << "Ignored ping in state " << state_;
+ return CHANNEL_ALIVE;
case WebSocketFrameHeader::kOpCodePong:
- VLOG(1) << "Got Pong of size " << data_buffer->size();
+ VLOG(1) << "Got Pong of size " << size;
// There is no need to do anything with pong messages.
- return;
+ return CHANNEL_ALIVE;
case WebSocketFrameHeader::kOpCodeClose: {
uint16 code = kWebSocketNormalClosure;
std::string reason;
- ParseClose(data_buffer, &code, &reason);
+ ParseClose(data_buffer, size, &code, &reason);
// TODO(ricea): Find a way to safely log the message from the close
// message (escape control codes and so on).
VLOG(1) << "Got Close with code " << code;
switch (state_) {
case CONNECTED:
state_ = RECV_CLOSED;
- SendClose(code, reason); // Sets state_ to CLOSE_WAIT
- event_interface_->OnClosingHandshake();
+ if (SendClose(code, reason) == // Sets state_ to CLOSE_WAIT
+ CHANNEL_DELETED)
+ return CHANNEL_DELETED;
+ if (event_interface_->OnClosingHandshake() == CHANNEL_DELETED)
+ return CHANNEL_DELETED;
closing_code_ = code;
closing_reason_ = reason;
break;
@@ -579,30 +574,28 @@ void WebSocketChannel::HandleFrame(
LOG(DFATAL) << "Got Close in unexpected state " << state_;
break;
}
- return;
+ return CHANNEL_ALIVE;
}
default:
- FailChannel(
+ return FailChannel(
SEND_REAL_ERROR, kWebSocketErrorProtocolError, "Unknown opcode");
- return;
}
}
-void WebSocketChannel::SendIOBufferWithSize(
+ChannelState WebSocketChannel::SendIOBuffer(
bool fin,
WebSocketFrameHeader::OpCode op_code,
- const scoped_refptr<IOBufferWithSize>& buffer) {
+ const scoped_refptr<IOBuffer>& buffer,
+ size_t size) {
DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED);
DCHECK(stream_);
- scoped_ptr<WebSocketFrameHeader> header(new WebSocketFrameHeader(op_code));
- header->final = fin;
- header->masked = true;
- header->payload_length = buffer->size();
- scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk());
- chunk->header = header.Pass();
- chunk->final_chunk = true;
- chunk->data = buffer;
+ scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(op_code));
+ WebSocketFrameHeader& header = frame->header;
+ header.final = fin;
+ header.masked = true;
+ header.payload_length = size;
+ frame->data = buffer;
if (data_being_sent_) {
// Either the link to the WebSocket server is saturated, or several messages
// are being sent in a batch.
@@ -610,21 +603,21 @@ void WebSocketChannel::SendIOBufferWithSize(
// quota appropriately.
if (!data_to_send_next_)
data_to_send_next_.reset(new SendBuffer);
- data_to_send_next_->AddFrame(chunk.Pass());
- } else {
- data_being_sent_.reset(new SendBuffer);
- data_being_sent_->AddFrame(chunk.Pass());
- WriteFrames();
+ data_to_send_next_->AddFrame(frame.Pass());
+ return CHANNEL_ALIVE;
}
+ data_being_sent_.reset(new SendBuffer);
+ data_being_sent_->AddFrame(frame.Pass());
+ return WriteFrames();
}
-void WebSocketChannel::FailChannel(ExposeError expose,
- uint16 code,
- const std::string& reason) {
+ChannelState WebSocketChannel::FailChannel(ExposeError expose,
+ uint16 code,
+ const std::string& reason) {
DCHECK_NE(FRESHLY_CONSTRUCTED, state_);
DCHECK_NE(CONNECTING, state_);
+ DCHECK_NE(CLOSED, state_);
// TODO(ricea): Logging.
- State old_state = state_;
if (state_ == CONNECTED) {
uint16 send_code = kWebSocketErrorGoingAway;
std::string send_reason = "Internal Error";
@@ -632,7 +625,9 @@ void WebSocketChannel::FailChannel(ExposeError expose,
send_code = code;
send_reason = reason;
}
- SendClose(send_code, send_reason); // Sets state_ to SEND_CLOSED
+ if (SendClose(send_code, send_reason) == // Sets state_ to SEND_CLOSED
+ CHANNEL_DELETED)
+ return CHANNEL_DELETED;
}
// Careful study of RFC6455 section 7.1.7 and 7.1.1 indicates the browser
// should close the connection itself without waiting for the closing
@@ -640,51 +635,59 @@ void WebSocketChannel::FailChannel(ExposeError expose,
stream_->Close();
state_ = CLOSED;
- // The channel may be in the middle of processing several chunks. It should
- // not use this frame header for subsequent chunks.
- current_frame_header_.reset();
- if (old_state != CLOSED) {
- event_interface_->OnDropChannel(code, reason);
- }
+ return event_interface_->OnDropChannel(code, reason);
}
-void WebSocketChannel::SendClose(uint16 code, const std::string& reason) {
+ChannelState WebSocketChannel::SendClose(uint16 code,
+ const std::string& reason) {
DCHECK(state_ == CONNECTED || state_ == RECV_CLOSED);
- // TODO(ricea): Ensure reason.length() <= 123
- scoped_refptr<IOBufferWithSize> body;
+ DCHECK_LE(reason.size(), kMaximumCloseReasonLength);
+ scoped_refptr<IOBuffer> body;
+ size_t size = 0;
if (code == kWebSocketErrorNoStatusReceived) {
// Special case: translate kWebSocketErrorNoStatusReceived into a Close
// frame with no payload.
- body = new IOBufferWithSize(0);
+ body = new IOBuffer(0);
} else {
const size_t payload_length = kWebSocketCloseCodeLength + reason.length();
- body = new IOBufferWithSize(payload_length);
+ body = new IOBuffer(payload_length);
+ size = payload_length;
WriteBigEndian(body->data(), code);
COMPILE_ASSERT(sizeof(code) == kWebSocketCloseCodeLength,
they_should_both_be_two);
std::copy(
reason.begin(), reason.end(), body->data() + kWebSocketCloseCodeLength);
}
- SendIOBufferWithSize(true, WebSocketFrameHeader::kOpCodeClose, body);
+ // This use of base::Unretained() is safe because we stop the timer in the
+ // destructor.
+ timer_.Start(
+ FROM_HERE,
+ timeout_,
+ base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this)));
+ if (SendIOBuffer(true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
+ CHANNEL_DELETED)
+ return CHANNEL_DELETED;
+ // SendIOBuffer() checks |state_|, so it is best not to change it until after
+ // SendIOBuffer() returns.
state_ = (state_ == CONNECTED) ? SEND_CLOSED : CLOSE_WAIT;
+ return CHANNEL_ALIVE;
}
-void WebSocketChannel::ParseClose(const scoped_refptr<IOBufferWithSize>& buffer,
+void WebSocketChannel::ParseClose(const scoped_refptr<IOBuffer>& buffer,
+ size_t size,
uint16* code,
std::string* reason) {
- const char* data = buffer->data();
- size_t size = base::checked_numeric_cast<size_t>(buffer->size());
reason->clear();
if (size < kWebSocketCloseCodeLength) {
*code = kWebSocketErrorNoStatusReceived;
if (size != 0) {
VLOG(1) << "Close frame with payload size " << size << " received "
- << "(the first byte is " << std::hex << static_cast<int>(data[0])
- << ")";
- return;
+ << "(the first byte is " << std::hex
+ << static_cast<int>(buffer->data()[0]) << ")";
}
return;
}
+ const char* data = buffer->data();
uint16 unchecked_code = 0;
ReadBigEndian(data, &unchecked_code);
COMPILE_ASSERT(sizeof(unchecked_code) == kWebSocketCloseCodeLength,
@@ -699,11 +702,20 @@ void WebSocketChannel::ParseClose(const scoped_refptr<IOBufferWithSize>& buffer,
*code = kWebSocketErrorAbnormalClosure;
}
std::string text(data + kWebSocketCloseCodeLength, data + size);
- // TODO(ricea): Is this check strict enough? In particular, check the
- // "Security Considerations" from RFC3629.
+ // IsStringUTF8() blocks surrogate pairs and non-characters, so it is strictly
+ // stronger than required by RFC3629.
if (IsStringUTF8(text)) {
reason->swap(text);
}
}
+void WebSocketChannel::CloseTimeout() {
+ stream_->Close();
+ DCHECK_NE(CLOSED, state_);
+ state_ = CLOSED;
+ AllowUnused(event_interface_->OnDropChannel(kWebSocketErrorAbnormalClosure,
+ "Abnormal Closure"));
+ // |this| has been deleted.
+}
+
} // namespace net
diff --git a/chromium/net/websockets/websocket_channel.h b/chromium/net/websockets/websocket_channel.h
index c997d6adef4..61f191af978 100644
--- a/chromium/net/websockets/websocket_channel.h
+++ b/chromium/net/websockets/websocket_channel.h
@@ -10,19 +10,22 @@
#include "base/basictypes.h"
#include "base/callback.h"
+#include "base/compiler_specific.h" // for WARN_UNUSED_RESULT
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "net/base/net_export.h"
+#include "net/websockets/websocket_event_interface.h"
#include "net/websockets/websocket_frame.h"
#include "net/websockets/websocket_stream.h"
#include "url/gurl.h"
namespace net {
-class GrowableIOBuffer;
-class URLRequestContext;
-class WebSocketEventInterface;
class BoundNetLog;
+class IOBuffer;
+class URLRequestContext;
// Transport-independent implementation of WebSockets. Implements protocol
// semantics that do not depend on the underlying transport. Provides the
@@ -31,7 +34,7 @@ class BoundNetLog;
// clarification.
class NET_EXPORT WebSocketChannel {
public:
- // The type of a WebSocketStream factory callback. Must match the signature of
+ // The type of a WebSocketStream creator callback. Must match the signature of
// WebSocketStream::CreateAndConnectStream().
typedef base::Callback<scoped_ptr<WebSocketStreamRequest>(
const GURL&,
@@ -39,20 +42,20 @@ class NET_EXPORT WebSocketChannel {
const GURL&,
URLRequestContext*,
const BoundNetLog&,
- scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamFactory;
+ scoped_ptr<WebSocketStream::ConnectDelegate>)> WebSocketStreamCreator;
- // Creates a new WebSocketChannel with the specified parameters.
+ // Creates a new WebSocketChannel in an idle state.
// SendAddChannelRequest() must be called immediately afterwards to start the
// connection process.
- WebSocketChannel(const GURL& socket_url,
- scoped_ptr<WebSocketEventInterface> event_interface);
+ WebSocketChannel(scoped_ptr<WebSocketEventInterface> event_interface,
+ URLRequestContext* url_request_context);
virtual ~WebSocketChannel();
// Starts the connection process.
void SendAddChannelRequest(
+ const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
- const GURL& origin,
- URLRequestContext* url_request_context);
+ const GURL& origin);
// Sends a data frame to the remote side. The frame should usually be no
// larger than 32KB to prevent the time required to copy the buffers from from
@@ -85,15 +88,25 @@ class NET_EXPORT WebSocketChannel {
// processing to OnClosingHandshake() if necessary.
void StartClosingHandshake(uint16 code, const std::string& reason);
- // Starts the connection process, using a specified factory function rather
+ // Starts the connection process, using a specified creator callback rather
// than the default. This is exposed for testing.
void SendAddChannelRequestForTesting(
+ const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const GURL& origin,
- URLRequestContext* url_request_context,
- const WebSocketStreamFactory& factory);
+ const WebSocketStreamCreator& creator);
+
+ // The default timout for the closing handshake is a sensible value (see
+ // kClosingHandshakeTimeoutSeconds in websocket_channel.cc). However, we can
+ // set it to a very small value for testing purposes.
+ void SetClosingHandshakeTimeoutForTesting(base::TimeDelta delay);
private:
+ // Methods which return a value of type ChannelState may delete |this|. If the
+ // return value is CHANNEL_DELETED, then the caller must return without making
+ // any further access to member variables or methods.
+ typedef WebSocketEventInterface::ChannelState ChannelState;
+
// The object passes through a linear progression of states from
// FRESHLY_CONSTRUCTED to CLOSED, except that the SEND_CLOSED and RECV_CLOSED
// states may be skipped in case of error.
@@ -127,97 +140,107 @@ class NET_EXPORT WebSocketChannel {
// connection process.
class ConnectDelegate;
- // Starts the connection progress, using a specified factory function.
- void SendAddChannelRequestWithFactory(
+ // Starts the connection process, using the supplied creator callback.
+ void SendAddChannelRequestWithSuppliedCreator(
+ const GURL& socket_url,
const std::vector<std::string>& requested_protocols,
const GURL& origin,
- URLRequestContext* url_request_context,
- const WebSocketStreamFactory& factory);
+ const WebSocketStreamCreator& creator);
// Success callback from WebSocketStream::CreateAndConnectStream(). Reports
- // success to the event interface.
+ // success to the event interface. May delete |this|.
void OnConnectSuccess(scoped_ptr<WebSocketStream> stream);
// Failure callback from WebSocketStream::CreateAndConnectStream(). Reports
- // failure to the event interface.
+ // failure to the event interface. May delete |this|.
void OnConnectFailure(uint16 websocket_error);
// Returns true if state_ is SEND_CLOSED, CLOSE_WAIT or CLOSED.
bool InClosingState() const;
// Calls WebSocketStream::WriteFrames() with the appropriate arguments
- void WriteFrames();
+ ChannelState WriteFrames() WARN_UNUSED_RESULT;
// Callback from WebSocketStream::WriteFrames. Sends pending data or adjusts
// the send quota of the renderer channel as appropriate. |result| is a net
// error code, usually OK. If |synchronous| is true, then OnWriteDone() is
// being called from within the WriteFrames() loop and does not need to call
// WriteFrames() itself.
- void OnWriteDone(bool synchronous, int result);
+ ChannelState OnWriteDone(bool synchronous, int result) WARN_UNUSED_RESULT;
// Calls WebSocketStream::ReadFrames() with the appropriate arguments.
- void ReadFrames();
+ ChannelState ReadFrames() WARN_UNUSED_RESULT;
// Callback from WebSocketStream::ReadFrames. Handles any errors and processes
// the returned chunks appropriately to their type. |result| is a net error
// code. If |synchronous| is true, then OnReadDone() is being called from
// within the ReadFrames() loop and does not need to call ReadFrames() itself.
- void OnReadDone(bool synchronous, int result);
-
- // Processes a single chunk that has been read from the stream.
- void ProcessFrameChunk(scoped_ptr<WebSocketFrameChunk> chunk);
+ ChannelState OnReadDone(bool synchronous, int result) WARN_UNUSED_RESULT;
- // Appends |data_buffer| to |incomplete_control_frame_body_|.
- void AddToIncompleteControlFrameBody(
- const scoped_refptr<IOBufferWithSize>& data_buffer);
+ // Processes a single frame that has been read from the stream.
+ ChannelState ProcessFrame(
+ scoped_ptr<WebSocketFrame> frame) WARN_UNUSED_RESULT;
// Handles a frame that the object has received enough of to process. May call
- // event_interface_ methods, send responses to the server, and change the
- // value of state_.
- void HandleFrame(const WebSocketFrameHeader::OpCode opcode,
- bool is_first_chunk,
- bool is_final_chunk,
- const scoped_refptr<IOBufferWithSize>& data_buffer);
+ // |event_interface_| methods, send responses to the server, and change the
+ // value of |state_|.
+ ChannelState HandleFrame(const WebSocketFrameHeader::OpCode opcode,
+ bool final,
+ const scoped_refptr<IOBuffer>& data_buffer,
+ size_t size) WARN_UNUSED_RESULT;
// Low-level method to send a single frame. Used for both data and control
// frames. Either sends the frame immediately or buffers it to be scheduled
// when the current write finishes. |fin| and |op_code| are defined as for
// SendFrame() above, except that |op_code| may also be a control frame
// opcode.
- void SendIOBufferWithSize(bool fin,
+ ChannelState SendIOBuffer(bool fin,
WebSocketFrameHeader::OpCode op_code,
- const scoped_refptr<IOBufferWithSize>& buffer);
+ const scoped_refptr<IOBuffer>& buffer,
+ size_t size) WARN_UNUSED_RESULT;
// Performs the "Fail the WebSocket Connection" operation as defined in
// RFC6455. The supplied code and reason are sent back to the renderer in an
// OnDropChannel message. If state_ is CONNECTED then a Close message is sent
// to the remote host. If |expose| is SEND_REAL_ERROR then the remote host is
// given the same status code passed to the renderer; otherwise it is sent a
- // fixed "Going Away" code. Resets current_frame_header_, closes the stream_,
- // and sets state_ to CLOSED.
- void FailChannel(ExposeError expose, uint16 code, const std::string& reason);
+ // fixed "Going Away" code. Closes the stream_ and sets state_ to CLOSED.
+ // FailChannel() always returns CHANNEL_DELETED. It is not valid to access any
+ // member variables or methods after calling FailChannel().
+ ChannelState FailChannel(ExposeError expose,
+ uint16 code,
+ const std::string& reason) WARN_UNUSED_RESULT;
// Sends a Close frame to Start the WebSocket Closing Handshake, or to respond
// to a Close frame from the server. As a special case, setting |code| to
// kWebSocketErrorNoStatusReceived will create a Close frame with no payload;
// this is symmetric with the behaviour of ParseClose.
- void SendClose(uint16 code, const std::string& reason);
+ ChannelState SendClose(uint16 code,
+ const std::string& reason) WARN_UNUSED_RESULT;
// Parses a Close frame. If no status code is supplied, then |code| is set to
// 1005 (No status code) with empty |reason|. If the supplied code is
// outside the valid range, then 1002 (Protocol error) is set instead. If the
// reason text is not valid UTF-8, then |reason| is set to an empty string
// instead.
- void ParseClose(const scoped_refptr<IOBufferWithSize>& buffer,
+ void ParseClose(const scoped_refptr<IOBuffer>& buffer,
+ size_t size,
uint16* code,
std::string* reason);
+ // Called if the closing handshake times out. Closes the connection and
+ // informs the |event_interface_| if appropriate.
+ void CloseTimeout();
+
// The URL of the remote server.
- const GURL socket_url_;
+ GURL socket_url_;
// The object receiving events.
const scoped_ptr<WebSocketEventInterface> event_interface_;
+ // The URLRequestContext to pass to the WebSocketStream creator.
+ URLRequestContext* const url_request_context_;
+
// The WebSocketStream on which to send and receive data.
scoped_ptr<WebSocketStream> stream_;
@@ -231,20 +254,12 @@ class NET_EXPORT WebSocketChannel {
scoped_ptr<SendBuffer> data_to_send_next_;
// Destination for the current call to WebSocketStream::ReadFrames
- ScopedVector<WebSocketFrameChunk> read_frame_chunks_;
- // Frame header for the frame currently being received. Only non-NULL while we
- // are processing the frame. If the frame arrives in multiple chunks, it can
- // remain non-NULL until additional chunks arrive. If the header of the frame
- // was invalid, this is set to NULL, the channel is failed, and subsequent
- // chunks of the same frame will be ignored.
- scoped_ptr<WebSocketFrameHeader> current_frame_header_;
+ ScopedVector<WebSocketFrame> read_frames_;
+
// Handle to an in-progress WebSocketStream creation request. Only non-NULL
// during the connection process.
scoped_ptr<WebSocketStreamRequest> stream_request_;
- // Although it should rarely happen in practice, a control frame can arrive
- // broken into chunks. This variable provides storage for a partial control
- // frame until the rest arrives. It will be NULL the rest of the time.
- scoped_refptr<GrowableIOBuffer> incomplete_control_frame_body_;
+
// If the renderer's send quota reaches this level, it is sent a quota
// refresh. "quota units" are currently bytes. TODO(ricea): Update the
// definition of quota units when necessary.
@@ -256,6 +271,12 @@ class NET_EXPORT WebSocketChannel {
// on this logical channel (quota units).
int current_send_quota_;
+ // Timer for the closing handshake.
+ base::OneShotTimer<WebSocketChannel> timer_;
+
+ // Timeout for the closing handshake.
+ base::TimeDelta timeout_;
+
// Storage for the status code and reason from the time the Close frame
// arrives until the connection is closed and they are passed to
// OnDropChannel().
diff --git a/chromium/net/websockets/websocket_channel_test.cc b/chromium/net/websockets/websocket_channel_test.cc
index 25e9cdc0508..1bd75db2eb1 100644
--- a/chromium/net/websockets/websocket_channel_test.cc
+++ b/chromium/net/websockets/websocket_channel_test.cc
@@ -16,10 +16,12 @@
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/safe_numerics.h"
#include "base/strings/string_piece.h"
#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
#include "net/url_request/url_request_context.h"
#include "net/websockets/websocket_errors.h"
#include "net/websockets/websocket_event_interface.h"
@@ -34,40 +36,37 @@
#define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string
#define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8"
#define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9"
+#define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea"
#define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3"
namespace net {
-// Printing helpers to allow GoogleMock to print frame chunks. These are
-// explicitly designed to look like the static initialisation format we use in
-// these tests. They have to live in the net namespace in order to be found by
+// Printing helpers to allow GoogleMock to print frames. These are explicitly
+// designed to look like the static initialisation format we use in these
+// tests. They have to live in the net namespace in order to be found by
// GoogleMock; a nested anonymous namespace will not work.
std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) {
- return os << "{" << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
+ return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
<< header.opcode << ", "
- << (header.masked ? "MASKED" : "NOT_MASKED") << ", "
- << header.payload_length << "}";
+ << (header.masked ? "MASKED" : "NOT_MASKED");
}
-std::ostream& operator<<(std::ostream& os, const WebSocketFrameChunk& chunk) {
- os << "{";
- if (chunk.header) {
- os << *chunk.header;
- } else {
- os << "{NO_HEADER}";
+std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) {
+ os << "{" << frame.header << ", ";
+ if (frame.data) {
+ return os << "\"" << base::StringPiece(frame.data->data(),
+ frame.header.payload_length)
+ << "\"}";
}
- return os << ", " << (chunk.final_chunk ? "FINAL_CHUNK" : "NOT_FINAL_CHUNK")
- << ", \""
- << base::StringPiece(chunk.data->data(), chunk.data->size())
- << "\"}";
+ return os << "NULL}";
}
std::ostream& operator<<(std::ostream& os,
- const ScopedVector<WebSocketFrameChunk>& vector) {
+ const ScopedVector<WebSocketFrame>& vector) {
os << "{";
bool first = true;
- for (ScopedVector<WebSocketFrameChunk>::const_iterator it = vector.begin();
+ for (ScopedVector<WebSocketFrame>::const_iterator it = vector.begin();
it != vector.end();
++it) {
if (!first) {
@@ -81,13 +80,16 @@ std::ostream& operator<<(std::ostream& os,
}
std::ostream& operator<<(std::ostream& os,
- const ScopedVector<WebSocketFrameChunk>* vector) {
+ const ScopedVector<WebSocketFrame>* vector) {
return os << '&' << *vector;
}
namespace {
+using ::base::TimeDelta;
+
using ::testing::AnyNumber;
+using ::testing::DefaultValue;
using ::testing::InSequence;
using ::testing::MockFunction;
using ::testing::Return;
@@ -97,7 +99,7 @@ using ::testing::_;
// A selection of characters that have traditionally been mangled in some
// environment or other, for testing 8-bit cleanliness.
-const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
+const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
'\0', // nul
'\x7F', // DEL
'\x80', '\xFF', // NOT VALID UTF-8
@@ -119,29 +121,54 @@ const size_t kDefaultInitialQuota = 1 << 17;
// kDefaultSendQuotaLowWaterMark change.
const size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1;
+// TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world
+// in that time! I would like my tests to run a bit quicker.
+const int kVeryTinyTimeoutMillis = 1;
+
+typedef WebSocketEventInterface::ChannelState ChannelState;
+const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
+const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED;
+
+// This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
+// all over the place.
+typedef MockFunction<void(int)> Checkpoint; // NOLINT
+
// This mock is for testing expectations about how the EventInterface is used.
class MockWebSocketEventInterface : public WebSocketEventInterface {
public:
- MOCK_METHOD2(OnAddChannelResponse, void(bool, const std::string&));
+ MOCK_METHOD2(OnAddChannelResponse,
+ ChannelState(bool, const std::string&)); // NOLINT
MOCK_METHOD3(OnDataFrame,
- void(bool, WebSocketMessageType, const std::vector<char>&));
- MOCK_METHOD1(OnFlowControl, void(int64));
- MOCK_METHOD0(OnClosingHandshake, void(void));
- MOCK_METHOD2(OnDropChannel, void(uint16, const std::string&));
+ ChannelState(bool,
+ WebSocketMessageType,
+ const std::vector<char>&)); // NOLINT
+ MOCK_METHOD1(OnFlowControl, ChannelState(int64)); // NOLINT
+ MOCK_METHOD0(OnClosingHandshake, ChannelState(void)); // NOLINT
+ MOCK_METHOD2(OnDropChannel,
+ ChannelState(uint16, const std::string&)); // NOLINT
};
// This fake EventInterface is for tests which need a WebSocketEventInterface
// implementation but are not verifying how it is used.
class FakeWebSocketEventInterface : public WebSocketEventInterface {
- virtual void OnAddChannelResponse(
+ virtual ChannelState OnAddChannelResponse(
bool fail,
- const std::string& selected_protocol) OVERRIDE {}
- virtual void OnDataFrame(bool fin,
- WebSocketMessageType type,
- const std::vector<char>& data) OVERRIDE {}
- virtual void OnFlowControl(int64 quota) OVERRIDE {}
- virtual void OnClosingHandshake() OVERRIDE {}
- virtual void OnDropChannel(uint16 code, const std::string& reason) OVERRIDE {}
+ const std::string& selected_protocol) OVERRIDE {
+ return fail ? CHANNEL_DELETED : CHANNEL_ALIVE;
+ }
+ virtual ChannelState OnDataFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) OVERRIDE {
+ return CHANNEL_ALIVE;
+ }
+ virtual ChannelState OnFlowControl(int64 quota) OVERRIDE {
+ return CHANNEL_ALIVE;
+ }
+ virtual ChannelState OnClosingHandshake() OVERRIDE { return CHANNEL_ALIVE; }
+ virtual ChannelState OnDropChannel(uint16 code,
+ const std::string& reason) OVERRIDE {
+ return CHANNEL_DELETED;
+ }
};
// This fake WebSocketStream is for tests that require a WebSocketStream but are
@@ -157,25 +184,12 @@ class FakeWebSocketStream : public WebSocketStream {
const std::string& extensions)
: protocol_(protocol), extensions_(extensions) {}
- virtual int SendHandshakeRequest(
- const GURL& url,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response_info,
- const CompletionCallback& callback) OVERRIDE {
- return ERR_IO_PENDING;
- }
-
- virtual int ReadHandshakeResponse(
- const CompletionCallback& callback) OVERRIDE {
- return ERR_IO_PENDING;
- }
-
- virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
return ERR_IO_PENDING;
}
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
return ERR_IO_PENDING;
}
@@ -198,12 +212,7 @@ class FakeWebSocketStream : public WebSocketStream {
// To make the static initialisers easier to read, we use enums rather than
// bools.
-
-// NO_HEADER means there shouldn't be a header included in the generated
-// WebSocketFrameChunk. The static initialiser always has a header, but we can
-// avoid specifying the rest of the fields.
enum IsFinal {
- NO_HEADER,
NOT_FINAL_FRAME,
FINAL_FRAME
};
@@ -213,54 +222,33 @@ enum IsMasked {
MASKED
};
-enum IsFinalChunk {
- NOT_FINAL_CHUNK,
- FINAL_CHUNK
-};
-
-// This is used to initialise a WebSocketFrameChunk but is statically
-// initialisable.
-struct InitFrameChunk {
- struct FrameHeader {
- IsFinal final;
- // Reserved fields omitted for now. Add them if you need them.
- WebSocketFrameHeader::OpCode opcode;
- IsMasked masked;
- // payload_length is the length of the whole frame. The length of the data
- // members from every chunk in the frame must add up to the payload_length.
- uint64 payload_length;
- };
- FrameHeader header;
-
- // Directly equivalent to WebSocketFrameChunk::final_chunk
- IsFinalChunk final_chunk;
+// This is used to initialise a WebSocketFrame but is statically initialisable.
+struct InitFrame {
+ IsFinal final;
+ // Reserved fields omitted for now. Add them if you need them.
+ WebSocketFrameHeader::OpCode opcode;
+ IsMasked masked;
// Will be used to create the IOBuffer member. Can be NULL for NULL data. Is a
- // nul-terminated string for ease-of-use. This means it is not 8-bit clean,
- // but this is not an issue for test data.
+ // nul-terminated string for ease-of-use. |header.payload_length| is
+ // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
+ // is not an issue for test data.
const char* const data;
};
// For GoogleMock
-std::ostream& operator<<(std::ostream& os, const InitFrameChunk& chunk) {
- os << "{";
- if (chunk.header.final != NO_HEADER) {
- os << "{" << (chunk.header.final == FINAL_FRAME ? "FINAL_FRAME"
- : "NOT_FINAL_FRAME") << ", "
- << chunk.header.opcode << ", "
- << (chunk.header.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", "
- << chunk.header.payload_length << "}";
-
- } else {
- os << "{NO_HEADER}";
+std::ostream& operator<<(std::ostream& os, const InitFrame& frame) {
+ os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME")
+ << ", " << frame.opcode << ", "
+ << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", ";
+ if (frame.data) {
+ return os << "\"" << frame.data << "\"}";
}
- return os << ", " << (chunk.final_chunk == FINAL_CHUNK ? "FINAL_CHUNK"
- : "NOT_FINAL_CHUNK")
- << ", \"" << chunk.data << "\"}";
+ return os << "NULL}";
}
template <size_t N>
-std::ostream& operator<<(std::ostream& os, const InitFrameChunk (&chunks)[N]) {
+std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) {
os << "{";
bool first = true;
for (size_t i = 0; i < N; ++i) {
@@ -269,119 +257,92 @@ std::ostream& operator<<(std::ostream& os, const InitFrameChunk (&chunks)[N]) {
} else {
first = false;
}
- os << chunks[i];
+ os << frames[i];
}
return os << "}";
}
-// Convert a const array of InitFrameChunks to the format used at
+// Convert a const array of InitFrame structs to the format used at
// runtime. Templated on the size of the array to save typing.
template <size_t N>
-ScopedVector<WebSocketFrameChunk> CreateFrameChunkVector(
- const InitFrameChunk (&source_chunks)[N]) {
- ScopedVector<WebSocketFrameChunk> result_chunks;
- result_chunks.reserve(N);
+ScopedVector<WebSocketFrame> CreateFrameVector(
+ const InitFrame (&source_frames)[N]) {
+ ScopedVector<WebSocketFrame> result_frames;
+ result_frames.reserve(N);
for (size_t i = 0; i < N; ++i) {
- scoped_ptr<WebSocketFrameChunk> result_chunk(new WebSocketFrameChunk);
- size_t chunk_length =
- source_chunks[i].data ? strlen(source_chunks[i].data) : 0;
- if (source_chunks[i].header.final != NO_HEADER) {
- const InitFrameChunk::FrameHeader& source_header =
- source_chunks[i].header;
- scoped_ptr<WebSocketFrameHeader> result_header(
- new WebSocketFrameHeader(source_header.opcode));
- result_header->final = (source_header.final == FINAL_FRAME);
- result_header->masked = (source_header.masked == MASKED);
- result_header->payload_length = source_header.payload_length;
- DCHECK(chunk_length <= source_header.payload_length);
- result_chunk->header.swap(result_header);
+ const InitFrame& source_frame = source_frames[i];
+ scoped_ptr<WebSocketFrame> result_frame(
+ new WebSocketFrame(source_frame.opcode));
+ size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0;
+ WebSocketFrameHeader& result_header = result_frame->header;
+ result_header.final = (source_frame.final == FINAL_FRAME);
+ result_header.masked = (source_frame.masked == MASKED);
+ result_header.payload_length = frame_length;
+ if (source_frame.data) {
+ result_frame->data = new IOBuffer(frame_length);
+ memcpy(result_frame->data->data(), source_frame.data, frame_length);
}
- result_chunk->final_chunk = (source_chunks[i].final_chunk == FINAL_CHUNK);
- if (source_chunks[i].data) {
- result_chunk->data = new IOBufferWithSize(chunk_length);
- memcpy(result_chunk->data->data(), source_chunks[i].data, chunk_length);
- }
- result_chunks.push_back(result_chunk.release());
+ result_frames.push_back(result_frame.release());
}
- return result_chunks.Pass();
+ return result_frames.Pass();
}
// A GoogleMock action which can be used to respond to call to ReadFrames with
-// some frames. Use like ReadFrames(_, _).WillOnce(ReturnChunks(&chunks));
-// |chunks| is an array of InitFrameChunks needs to be passed by pointer because
-// otherwise it will be reduced to a pointer and lose the array size
-// information.
-ACTION_P(ReturnChunks, source_chunks) {
- *arg0 = CreateFrameChunkVector(*source_chunks);
+// some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames));
+// |frames| is an array of InitFrame. |frames| needs to be passed by pointer
+// because otherwise it will be treated as a pointer and the array size
+// information will be lost.
+ACTION_P(ReturnFrames, source_frames) {
+ *arg0 = CreateFrameVector(*source_frames);
return OK;
}
// The implementation of a GoogleMock matcher which can be used to compare a
-// ScopedVector<WebSocketFrameChunk>* against an expectation defined as an array
-// of InitFrameChunks. Although it is possible to compose built-in GoogleMock
-// matchers to check the contents of a WebSocketFrameChunk, the results are so
+// ScopedVector<WebSocketFrame>* against an expectation defined as an array of
+// InitFrame objects. Although it is possible to compose built-in GoogleMock
+// matchers to check the contents of a WebSocketFrame, the results are so
// unreadable that it is better to use this matcher.
template <size_t N>
-class EqualsChunksMatcher
- : public ::testing::MatcherInterface<ScopedVector<WebSocketFrameChunk>*> {
+class EqualsFramesMatcher
+ : public ::testing::MatcherInterface<ScopedVector<WebSocketFrame>*> {
public:
- EqualsChunksMatcher(const InitFrameChunk (*expect_chunks)[N])
- : expect_chunks_(expect_chunks) {}
+ EqualsFramesMatcher(const InitFrame (*expect_frames)[N])
+ : expect_frames_(expect_frames) {}
- virtual bool MatchAndExplain(ScopedVector<WebSocketFrameChunk>* actual_chunks,
+ virtual bool MatchAndExplain(ScopedVector<WebSocketFrame>* actual_frames,
::testing::MatchResultListener* listener) const {
- if (actual_chunks->size() != N) {
- *listener << "the vector size is " << actual_chunks->size();
+ if (actual_frames->size() != N) {
+ *listener << "the vector size is " << actual_frames->size();
return false;
}
for (size_t i = 0; i < N; ++i) {
- const WebSocketFrameChunk& actual_chunk = *(*actual_chunks)[i];
- const InitFrameChunk& expected_chunk = (*expect_chunks_)[i];
- // Testing that the absence or presence of a header is the same for both.
- if ((!actual_chunk.header) !=
- (expected_chunk.header.final == NO_HEADER)) {
- *listener << "the header is "
- << (actual_chunk.header ? "present" : "absent");
+ const WebSocketFrame& actual_frame = *(*actual_frames)[i];
+ const InitFrame& expected_frame = (*expect_frames_)[i];
+ if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) {
+ *listener << "the frame is marked as "
+ << (actual_frame.header.final ? "" : "not ") << "final";
return false;
}
- if (actual_chunk.header) {
- if (actual_chunk.header->final !=
- (expected_chunk.header.final == FINAL_FRAME)) {
- *listener << "the frame is marked as "
- << (actual_chunk.header->final ? "" : "not ") << "final";
- return false;
- }
- if (actual_chunk.header->opcode != expected_chunk.header.opcode) {
- *listener << "the opcode is " << actual_chunk.header->opcode;
- return false;
- }
- if (actual_chunk.header->masked !=
- (expected_chunk.header.masked == MASKED)) {
- *listener << "the frame is "
- << (actual_chunk.header->masked ? "masked" : "not masked");
- return false;
- }
- if (actual_chunk.header->payload_length !=
- expected_chunk.header.payload_length) {
- *listener << "the payload length is "
- << actual_chunk.header->payload_length;
- return false;
- }
+ if (actual_frame.header.opcode != expected_frame.opcode) {
+ *listener << "the opcode is " << actual_frame.header.opcode;
+ return false;
}
- if (actual_chunk.final_chunk !=
- (expected_chunk.final_chunk == FINAL_CHUNK)) {
- *listener << "the chunk is marked as "
- << (actual_chunk.final_chunk ? "" : "not ") << "final";
+ if (actual_frame.header.masked != (expected_frame.masked == MASKED)) {
+ *listener << "the frame is "
+ << (actual_frame.header.masked ? "masked" : "not masked");
return false;
}
- if (actual_chunk.data->size() !=
- base::checked_numeric_cast<int>(strlen(expected_chunk.data))) {
- *listener << "the data size is " << actual_chunk.data->size();
+ const size_t expected_length =
+ expected_frame.data ? strlen(expected_frame.data) : 0;
+ if (actual_frame.header.payload_length != expected_length) {
+ *listener << "the payload length is "
+ << actual_frame.header.payload_length;
return false;
}
- if (memcmp(actual_chunk.data->data(),
- expected_chunk.data,
- actual_chunk.data->size()) != 0) {
+ if (expected_length != 0 &&
+ memcmp(actual_frame.data->data(),
+ expected_frame.data,
+ actual_frame.header.payload_length) != 0) {
*listener << "the data content differs";
return false;
}
@@ -390,23 +351,44 @@ class EqualsChunksMatcher
}
virtual void DescribeTo(std::ostream* os) const {
- *os << "matches " << *expect_chunks_;
+ *os << "matches " << *expect_frames_;
}
virtual void DescribeNegationTo(std::ostream* os) const {
- *os << "does not match " << *expect_chunks_;
+ *os << "does not match " << *expect_frames_;
}
private:
- const InitFrameChunk (*expect_chunks_)[N];
+ const InitFrame (*expect_frames_)[N];
};
-// The definition of EqualsChunks GoogleMock matcher. Unlike the ReturnChunks
+// The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
// action, this can take the array by reference.
template <size_t N>
-::testing::Matcher<ScopedVector<WebSocketFrameChunk>*> EqualsChunks(
- const InitFrameChunk (&chunks)[N]) {
- return ::testing::MakeMatcher(new EqualsChunksMatcher<N>(&chunks));
+::testing::Matcher<ScopedVector<WebSocketFrame>*> EqualsFrames(
+ const InitFrame (&frames)[N]) {
+ return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames));
+}
+
+// TestClosure works like TestCompletionCallback, but doesn't take an argument.
+class TestClosure {
+ public:
+ base::Closure closure() { return base::Bind(callback_.callback(), OK); }
+
+ void WaitForResult() { callback_.WaitForResult(); }
+
+ private:
+ // Delegate to TestCompletionCallback for the implementation.
+ TestCompletionCallback callback_;
+};
+
+// A GoogleMock action to run a Closure.
+ACTION_P(InvokeClosure, closure) { closure.Run(); }
+
+// A GoogleMock action to run a Closure and return CHANNEL_DELETED.
+ACTION_P(InvokeClosureReturnDeleted, closure) {
+ closure.Run();
+ return WebSocketEventInterface::CHANNEL_DELETED;
}
// A FakeWebSocketStream whose ReadFrames() function returns data.
@@ -427,39 +409,38 @@ class ReadableFakeWebSocketStream : public FakeWebSocketStream {
CHECK(!read_frames_pending_);
}
- // Prepares a fake responses. Fake responses will be returned from
- // ReadFrames() in the same order they were prepared with PrepareReadFrames()
- // and PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
+ // Prepares a fake response. Fake responses will be returned from ReadFrames()
+ // in the same order they were prepared with PrepareReadFrames() and
+ // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
// return ERR_IO_PENDING and the callback will be scheduled to run on the
// message loop. This requires the test case to run the message loop. If
// |async| is SYNC, the response will be returned synchronously. |error| is
// returned directly from ReadFrames() in the synchronous case, or passed to
- // the callback in the asynchronous case. |chunks| will be converted to a
- // ScopedVector<WebSocketFrameChunks> and copied to the pointer that was
- // passed to ReadFrames().
+ // the callback in the asynchronous case. |frames| will be converted to a
+ // ScopedVector<WebSocketFrame> and copied to the pointer that was passed to
+ // ReadFrames().
template <size_t N>
void PrepareReadFrames(IsSync async,
int error,
- const InitFrameChunk (&chunks)[N]) {
- responses_.push_back(
- new Response(async, error, CreateFrameChunkVector(chunks)));
+ const InitFrame (&frames)[N]) {
+ responses_.push_back(new Response(async, error, CreateFrameVector(frames)));
}
// An alternate version of PrepareReadFrames for when we need to construct
// the frames manually.
void PrepareRawReadFrames(IsSync async,
int error,
- ScopedVector<WebSocketFrameChunk> chunks) {
- responses_.push_back(new Response(async, error, chunks.Pass()));
+ ScopedVector<WebSocketFrame> frames) {
+ responses_.push_back(new Response(async, error, frames.Pass()));
}
// Prepares a fake error response (ie. there is no data).
void PrepareReadFramesError(IsSync async, int error) {
responses_.push_back(
- new Response(async, error, ScopedVector<WebSocketFrameChunk>()));
+ new Response(async, error, ScopedVector<WebSocketFrame>()));
}
- virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
CHECK(!read_frames_pending_);
if (index_ >= responses_.size())
@@ -470,34 +451,34 @@ class ReadableFakeWebSocketStream : public FakeWebSocketStream {
FROM_HERE,
base::Bind(&ReadableFakeWebSocketStream::DoCallback,
base::Unretained(this),
- frame_chunks,
+ frames,
callback));
return ERR_IO_PENDING;
} else {
- frame_chunks->swap(responses_[index_]->chunks);
+ frames->swap(responses_[index_]->frames);
return responses_[index_++]->error;
}
}
private:
- void DoCallback(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ void DoCallback(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) {
read_frames_pending_ = false;
- frame_chunks->swap(responses_[index_]->chunks);
+ frames->swap(responses_[index_]->frames);
callback.Run(responses_[index_++]->error);
return;
}
struct Response {
- Response(IsSync async, int error, ScopedVector<WebSocketFrameChunk> chunks)
- : async(async), error(error), chunks(chunks.Pass()) {}
+ Response(IsSync async, int error, ScopedVector<WebSocketFrame> frames)
+ : async(async), error(error), frames(frames.Pass()) {}
IsSync async;
int error;
- ScopedVector<WebSocketFrameChunk> chunks;
+ ScopedVector<WebSocketFrame> frames;
private:
- // Bad things will happen if we attempt to copy or assign "chunks".
+ // Bad things will happen if we attempt to copy or assign |frames|.
DISALLOW_COPY_AND_ASSIGN(Response);
};
ScopedVector<Response> responses_;
@@ -516,7 +497,7 @@ class ReadableFakeWebSocketStream : public FakeWebSocketStream {
// synchronously.
class WriteableFakeWebSocketStream : public FakeWebSocketStream {
public:
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
return OK;
}
@@ -525,7 +506,7 @@ class WriteableFakeWebSocketStream : public FakeWebSocketStream {
// A FakeWebSocketStream where writes always fail.
class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
public:
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
return ERR_CONNECTION_RESET;
}
@@ -539,23 +520,22 @@ class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
// otherwise the ReadFrames() callback will never be called.
class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
public:
- EchoeyFakeWebSocketStream() : read_frame_chunks_(NULL), done_(false) {}
+ EchoeyFakeWebSocketStream() : read_frames_(NULL), done_(false) {}
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
// Users of WebSocketStream will not expect the ReadFrames() callback to be
// called from within WriteFrames(), so post it to the message loop instead.
- stored_frame_chunks_.insert(
- stored_frame_chunks_.end(), frame_chunks->begin(), frame_chunks->end());
- frame_chunks->weak_clear();
+ stored_frames_.insert(stored_frames_.end(), frames->begin(), frames->end());
+ frames->weak_clear();
PostCallback();
return OK;
}
- virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
read_callback_ = callback;
- read_frame_chunks_ = frame_chunks;
+ read_frames_ = frames;
if (done_)
PostCallback();
return ERR_IO_PENDING;
@@ -572,36 +552,34 @@ class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
void DoCallback() {
if (done_) {
read_callback_.Run(ERR_CONNECTION_CLOSED);
- } else if (!stored_frame_chunks_.empty()) {
- done_ = MoveFrameChunks(read_frame_chunks_);
- read_frame_chunks_ = NULL;
+ } else if (!stored_frames_.empty()) {
+ done_ = MoveFrames(read_frames_);
+ read_frames_ = NULL;
read_callback_.Run(OK);
}
}
- // Copy the chunks stored in stored_frame_chunks_ to |out|, while clearing the
+ // Copy the frames stored in stored_frames_ to |out|, while clearing the
// "masked" header bit. Returns true if a Close Frame was seen, false
// otherwise.
- bool MoveFrameChunks(ScopedVector<WebSocketFrameChunk>* out) {
+ bool MoveFrames(ScopedVector<WebSocketFrame>* out) {
bool seen_close = false;
- *out = stored_frame_chunks_.Pass();
- for (ScopedVector<WebSocketFrameChunk>::iterator it = out->begin();
+ *out = stored_frames_.Pass();
+ for (ScopedVector<WebSocketFrame>::iterator it = out->begin();
it != out->end();
++it) {
- WebSocketFrameHeader* header = (*it)->header.get();
- if (header) {
- header->masked = false;
- if (header->opcode == WebSocketFrameHeader::kOpCodeClose)
- seen_close = true;
- }
+ WebSocketFrameHeader& header = (*it)->header;
+ header.masked = false;
+ if (header.opcode == WebSocketFrameHeader::kOpCodeClose)
+ seen_close = true;
}
return seen_close;
}
- ScopedVector<WebSocketFrameChunk> stored_frame_chunks_;
+ ScopedVector<WebSocketFrame> stored_frames_;
CompletionCallback read_callback_;
// Owned by the caller of ReadFrames().
- ScopedVector<WebSocketFrameChunk>* read_frame_chunks_;
+ ScopedVector<WebSocketFrame>* read_frames_;
// True if we should close the connection.
bool done_;
};
@@ -609,26 +587,50 @@ class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
// A FakeWebSocketStream where writes trigger a connection reset.
// This differs from UnWriteableFakeWebSocketStream in that it is asynchronous
// and triggers ReadFrames to return a reset as well. Tests using this need to
-// run the message loop.
+// run the message loop. There are two tricky parts here:
+// 1. Calling the write callback may call Close(), after which the read callback
+// should not be called.
+// 2. Calling either callback may delete the stream altogether.
class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
public:
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ ResetOnWriteFakeWebSocketStream() : closed_(false), weak_ptr_factory_(this) {}
+
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(callback, ERR_CONNECTION_RESET));
+ FROM_HERE,
+ base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback,
+ ERR_CONNECTION_RESET));
base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(read_callback_, ERR_CONNECTION_RESET));
+ FROM_HERE,
+ base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
+ weak_ptr_factory_.GetWeakPtr(),
+ read_callback_,
+ ERR_CONNECTION_RESET));
return ERR_IO_PENDING;
}
- virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) OVERRIDE {
read_callback_ = callback;
return ERR_IO_PENDING;
}
+ virtual void Close() OVERRIDE { closed_ = true; }
+
private:
+ void CallCallbackUnlessClosed(const CompletionCallback& callback, int value) {
+ if (!closed_)
+ callback.Run(value);
+ }
+
CompletionCallback read_callback_;
+ bool closed_;
+ // An IO error can result in the socket being deleted, so we use weak pointers
+ // to ensure correct behaviour in that case.
+ base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_;
};
// This mock is for verifying that WebSocket protocol semantics are obeyed (to
@@ -636,25 +638,19 @@ class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
class MockWebSocketStream : public WebSocketStream {
public:
MOCK_METHOD2(ReadFrames,
- int(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ int(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback));
MOCK_METHOD2(WriteFrames,
- int(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ int(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback));
MOCK_METHOD0(Close, void());
MOCK_CONST_METHOD0(GetSubProtocol, std::string());
MOCK_CONST_METHOD0(GetExtensions, std::string());
MOCK_METHOD0(AsWebSocketStream, WebSocketStream*());
- MOCK_METHOD4(SendHandshakeRequest,
- int(const GURL& url,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response_info,
- const CompletionCallback& callback));
- MOCK_METHOD1(ReadHandshakeResponse, int(const CompletionCallback& callback));
};
-struct ArgumentCopyingWebSocketFactory {
- scoped_ptr<WebSocketStreamRequest> Factory(
+struct ArgumentCopyingWebSocketStreamCreator {
+ scoped_ptr<WebSocketStreamRequest> Create(
const GURL& socket_url,
const std::vector<std::string>& requested_subprotocols,
const GURL& origin,
@@ -693,21 +689,21 @@ class WebSocketChannelTest : public ::testing::Test {
// Creates a new WebSocketChannel and connects it, using the settings stored
// in |connect_data_|.
void CreateChannelAndConnect() {
- channel_.reset(
- new WebSocketChannel(connect_data_.url, CreateEventInterface()));
+ channel_.reset(new WebSocketChannel(CreateEventInterface(),
+ &connect_data_.url_request_context));
channel_->SendAddChannelRequestForTesting(
+ connect_data_.socket_url,
connect_data_.requested_subprotocols,
connect_data_.origin,
- &connect_data_.url_request_context,
- base::Bind(&ArgumentCopyingWebSocketFactory::Factory,
- base::Unretained(&connect_data_.factory)));
+ base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create,
+ base::Unretained(&connect_data_.creator)));
}
// Same as CreateChannelAndConnect(), but calls the on_success callback as
// well. This method is virtual so that subclasses can also set the stream.
virtual void CreateChannelAndConnectSuccessfully() {
CreateChannelAndConnect();
- connect_data_.factory.connect_delegate->OnSuccess(stream_.Pass());
+ connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
}
// Returns a WebSocketEventInterface to be passed to the WebSocketChannel.
@@ -729,17 +725,25 @@ class WebSocketChannelTest : public ::testing::Test {
}
// A struct containing the data that will be used to connect the channel.
+ // Grouped for readability.
struct ConnectData {
+ ConnectData() :
+ socket_url("ws://ws/"),
+ origin("http://ws/")
+ {}
+
+ // URLRequestContext object.
+ URLRequestContext url_request_context;
+
// URL to (pretend to) connect to.
- GURL url;
- // Origin of the request
- GURL origin;
+ GURL socket_url;
// Requested protocols for the request.
std::vector<std::string> requested_subprotocols;
- // URLRequestContext object.
- URLRequestContext url_request_context;
- // A fake WebSocketFactory that just records its arguments.
- ArgumentCopyingWebSocketFactory factory;
+ // Origin of the request
+ GURL origin;
+
+ // A fake WebSocketStreamCreator that just records its arguments.
+ ArgumentCopyingWebSocketStreamCreator creator;
};
ConnectData connect_data_;
@@ -750,14 +754,41 @@ class WebSocketChannelTest : public ::testing::Test {
scoped_ptr<WebSocketStream> stream_;
};
+// enum of WebSocketEventInterface calls. These are intended to be or'd together
+// in order to instruct WebSocketChannelDeletingTest when it should fail.
+enum EventInterfaceCall {
+ EVENT_ON_ADD_CHANNEL_RESPONSE = 0x1,
+ EVENT_ON_DATA_FRAME = 0x2,
+ EVENT_ON_FLOW_CONTROL = 0x4,
+ EVENT_ON_CLOSING_HANDSHAKE = 0x8,
+ EVENT_ON_DROP_CHANNEL = 0x10,
+};
+
class WebSocketChannelDeletingTest : public WebSocketChannelTest {
public:
- void ResetChannel() { channel_.reset(); }
+ ChannelState DeleteIfDeleting(EventInterfaceCall call) {
+ if (deleting_ & call) {
+ channel_.reset();
+ return CHANNEL_DELETED;
+ } else {
+ return CHANNEL_ALIVE;
+ }
+ }
protected:
+ WebSocketChannelDeletingTest()
+ : deleting_(EVENT_ON_ADD_CHANNEL_RESPONSE | EVENT_ON_DATA_FRAME |
+ EVENT_ON_FLOW_CONTROL |
+ EVENT_ON_CLOSING_HANDSHAKE |
+ EVENT_ON_DROP_CHANNEL) {}
// Create a ChannelDeletingFakeWebSocketEventInterface. Defined out-of-line to
// avoid circular dependency.
virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE;
+
+ // Tests can set deleting_ to a bitmap of EventInterfaceCall members that they
+ // want to cause Channel deletion. The default is for all calls to cause
+ // deletion.
+ int deleting_;
};
// A FakeWebSocketEventInterface that deletes the WebSocketChannel on failure to
@@ -769,12 +800,29 @@ class ChannelDeletingFakeWebSocketEventInterface
WebSocketChannelDeletingTest* fixture)
: fixture_(fixture) {}
- virtual void OnAddChannelResponse(
+ virtual ChannelState OnAddChannelResponse(
bool fail,
const std::string& selected_protocol) OVERRIDE {
- if (fail) {
- fixture_->ResetChannel();
- }
+ return fixture_->DeleteIfDeleting(EVENT_ON_ADD_CHANNEL_RESPONSE);
+ }
+
+ virtual ChannelState OnDataFrame(bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) OVERRIDE {
+ return fixture_->DeleteIfDeleting(EVENT_ON_DATA_FRAME);
+ }
+
+ virtual ChannelState OnFlowControl(int64 quota) OVERRIDE {
+ return fixture_->DeleteIfDeleting(EVENT_ON_FLOW_CONTROL);
+ }
+
+ virtual ChannelState OnClosingHandshake() OVERRIDE {
+ return fixture_->DeleteIfDeleting(EVENT_ON_CLOSING_HANDSHAKE);
+ }
+
+ virtual ChannelState OnDropChannel(uint16 code,
+ const std::string& reason) OVERRIDE {
+ return fixture_->DeleteIfDeleting(EVENT_ON_DROP_CHANNEL);
}
private:
@@ -794,7 +842,17 @@ WebSocketChannelDeletingTest::CreateEventInterface() {
class WebSocketChannelEventInterfaceTest : public WebSocketChannelTest {
protected:
WebSocketChannelEventInterfaceTest()
- : event_interface_(new StrictMock<MockWebSocketEventInterface>) {}
+ : event_interface_(new StrictMock<MockWebSocketEventInterface>) {
+ DefaultValue<ChannelState>::Set(CHANNEL_ALIVE);
+ ON_CALL(*event_interface_, OnAddChannelResponse(true, _))
+ .WillByDefault(Return(CHANNEL_DELETED));
+ ON_CALL(*event_interface_, OnDropChannel(_, _))
+ .WillByDefault(Return(CHANNEL_DELETED));
+ }
+
+ virtual ~WebSocketChannelEventInterfaceTest() {
+ DefaultValue<ChannelState>::Clear();
+ }
// Tests using this fixture must set expectations on the event_interface_ mock
// object before calling CreateChannelAndConnect() or
@@ -822,32 +880,266 @@ class WebSocketChannelStreamTest : public WebSocketChannelTest {
scoped_ptr<MockWebSocketStream> mock_stream_;
};
-// Simple test that everything that should be passed to the factory function is
-// passed to the factory function.
-TEST_F(WebSocketChannelTest, EverythingIsPassedToTheFactoryFunction) {
- connect_data_.url = GURL("ws://example.com/test");
+// Simple test that everything that should be passed to the creator function is
+// passed to the creator function.
+TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) {
+ connect_data_.socket_url = GURL("ws://example.com/test");
connect_data_.origin = GURL("http://example.com/test");
connect_data_.requested_subprotocols.push_back("Sinbad");
CreateChannelAndConnect();
- EXPECT_EQ(connect_data_.url, connect_data_.factory.socket_url);
- EXPECT_EQ(connect_data_.origin, connect_data_.factory.origin);
+ const ArgumentCopyingWebSocketStreamCreator& actual = connect_data_.creator;
+
+ EXPECT_EQ(&connect_data_.url_request_context, actual.url_request_context);
+
+ EXPECT_EQ(connect_data_.socket_url, actual.socket_url);
EXPECT_EQ(connect_data_.requested_subprotocols,
- connect_data_.factory.requested_subprotocols);
- EXPECT_EQ(&connect_data_.url_request_context,
- connect_data_.factory.url_request_context);
+ actual.requested_subprotocols);
+ EXPECT_EQ(connect_data_.origin, actual.origin);
+}
+
+// Verify that calling SendFlowControl before the connection is established does
+// not cause a crash.
+TEST_F(WebSocketChannelTest, SendFlowControlDuringHandshakeOkay) {
+ CreateChannelAndConnect();
+ ASSERT_TRUE(channel_);
+ channel_->SendFlowControl(65536);
}
-// The documentation for WebSocketEventInterface::OnAddChannelResponse() says
-// that if the first argument is true, ie. the connection failed, then we can
-// safely synchronously delete the WebSocketChannel. This test will only
-// reliably find problems if run with a memory debugger such as
-// AddressSanitizer.
-TEST_F(WebSocketChannelDeletingTest, DeletingFromOnAddChannelResponseWorks) {
+// Any WebSocketEventInterface methods can delete the WebSocketChannel and
+// return CHANNEL_DELETED. The WebSocketChannelDeletingTests are intended to
+// verify that there are no use-after-free bugs when this happens. Problems will
+// probably only be found when running under Address Sanitizer or a similar
+// tool.
+TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseFail) {
CreateChannelAndConnect();
- connect_data_.factory.connect_delegate
- ->OnFailure(kWebSocketErrorNoStatusReceived);
+ EXPECT_TRUE(channel_);
+ connect_data_.creator.connect_delegate->OnFailure(
+ kWebSocketErrorNoStatusReceived);
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+// Deletion is possible (due to IPC failure) even if the connect succeeds.
+TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseSuccess) {
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnDataFrameSync) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DATA_FRAME;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnDataFrameAsync) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DATA_FRAME;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_TRUE(channel_);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterConnect) {
+ deleting_ = EVENT_ON_FLOW_CONTROL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterSend) {
+ set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
+ // Avoid deleting the channel yet.
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+ CreateChannelAndConnectSuccessfully();
+ ASSERT_TRUE(channel_);
+ deleting_ = EVENT_ON_FLOW_CONTROL;
+ channel_->SendFrame(true,
+ WebSocketFrameHeader::kOpCodeText,
+ std::vector<char>(kDefaultInitialQuota, 'B'));
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeSync) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_CLOSING_HANDSHAKE;
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeAsync) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_CLOSING_HANDSHAKE;
+ CreateChannelAndConnectSuccessfully();
+ ASSERT_TRUE(channel_);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnDropChannelWriteError) {
+ set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream));
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+ CreateChannelAndConnectSuccessfully();
+ ASSERT_TRUE(channel_);
+ channel_->SendFrame(
+ true, WebSocketFrameHeader::kOpCodeText, AsVector("this will fail"));
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, OnDropChannelReadError) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
+ ERR_FAILED);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+ CreateChannelAndConnectSuccessfully();
+ ASSERT_TRUE(channel_);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelInSendFrame) {
+ set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+ CreateChannelAndConnectSuccessfully();
+ ASSERT_TRUE(channel_);
+ channel_->SendFrame(true,
+ WebSocketFrameHeader::kOpCodeText,
+ std::vector<char>(kDefaultInitialQuota * 2, 'T'));
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelInOnReadDone) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
+ ERR_WS_PROTOCOL_ERROR);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+ CreateChannelAndConnectSuccessfully();
+ ASSERT_TRUE(channel_);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToMaskedFrame) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrame) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+// Version of above test with NULL data.
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrameNull) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterClose) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
+ CLOSE_DATA(NORMAL_CLOSURE, "Success")},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterCloseNull) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED,
+ CLOSE_DATA(NORMAL_CLOSURE, "Success")},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCode) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, ""}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
+ EXPECT_EQ(NULL, channel_.get());
+}
+
+TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCodeNull) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, NULL}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ set_stream(stream.Pass());
+ deleting_ = EVENT_ON_DROP_CHANNEL;
+
+ CreateChannelAndConnectSuccessfully();
EXPECT_EQ(NULL, channel_.get());
}
@@ -860,7 +1152,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) {
CreateChannelAndConnect();
- connect_data_.factory.connect_delegate->OnSuccess(stream_.Pass());
+ connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
}
TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
@@ -869,8 +1161,14 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
CreateChannelAndConnect();
- connect_data_.factory.connect_delegate
- ->OnFailure(kWebSocketErrorNoStatusReceived);
+ connect_data_.creator.connect_delegate->OnFailure(
+ kWebSocketErrorNoStatusReceived);
+}
+
+TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) {
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(true, ""));
+ connect_data_.socket_url = GURL("http://www.google.com/");
+ CreateChannelAndConnect();
}
TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
@@ -879,7 +1177,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
CreateChannelAndConnect();
- connect_data_.factory.connect_delegate->OnSuccess(
+ connect_data_.creator.connect_delegate->OnSuccess(
scoped_ptr<WebSocketStream>(new FakeWebSocketStream("Bob", "")));
}
@@ -889,10 +1187,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
- FINAL_CHUNK, "HELLO"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
set_stream(stream.Pass());
{
InSequence s;
@@ -912,10 +1209,10 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 23},
- FINAL_CHUNK, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
ERR_CONNECTION_CLOSED);
set_stream(stream.Pass());
@@ -954,13 +1251,12 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) {
TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
- FINAL_CHUNK, "HELLO"}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
// We use this checkpoint object to verify that the callback isn't called
// until we expect it to be.
- MockFunction<void(int)> checkpoint;
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
+ Checkpoint checkpoint;
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
set_stream(stream.Pass());
{
InSequence s;
@@ -985,14 +1281,12 @@ TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks1[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
- FINAL_CHUNK, "HELLO"}};
- static const InitFrameChunk chunks2[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
- FINAL_CHUNK, "WORLD"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks2);
+ static const InitFrame frames1[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
+ static const InitFrame frames2[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2);
set_stream(stream.Pass());
{
InSequence s;
@@ -1012,31 +1306,29 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
base::MessageLoop::current()->RunUntilIdle();
}
-// Data frames that arrive in fragments are turned into individual frames
-TEST_F(WebSocketChannelEventInterfaceTest, FragmentedFrames) {
+// Data frames are delivered the same regardless of how many reads they arrive
+// as.
+TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- // Here we have one message split into 3 frames which arrive in 3 chunks. The
- // first frame is entirely in the first chunk, the second frame is split
- // across all the chunks, and the final frame is entirely in the final
- // chunk. The frame fragments are converted to separate frames so that they
- // can be delivered immediatedly. So the EventInterface should see a Text
- // message with 5 frames.
- static const InitFrameChunk chunks1[] = {
- {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
- FINAL_CHUNK, "THREE"},
- {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED,
- 7},
- NOT_FINAL_CHUNK, " "}};
- static const InitFrameChunk chunks2[] = {
- {{NO_HEADER}, NOT_FINAL_CHUNK, "SMALL"}};
- static const InitFrameChunk chunks3[] = {
- {{NO_HEADER}, FINAL_CHUNK, " "},
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 6},
- FINAL_CHUNK, "FRAMES"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
+ // Here we have one message which arrived in five frames split across three
+ // reads. It may have been reframed on arrival, but this class doesn't care
+ // about that.
+ static const InitFrame frames1[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"},
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ NOT_MASKED, " "}};
+ static const InitFrame frames2[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ NOT_MASKED, "SMALL"}};
+ static const InitFrame frames3[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ NOT_MASKED, " "},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ NOT_MASKED, "FRAMES"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
set_stream(stream.Pass());
{
InSequence s;
@@ -1068,98 +1360,19 @@ TEST_F(WebSocketChannelEventInterfaceTest, FragmentedFrames) {
base::MessageLoop::current()->RunUntilIdle();
}
-// In the case when a single-frame message because fragmented, it must be
-// correctly transformed to multiple frames.
-TEST_F(WebSocketChannelEventInterfaceTest, MessageFragmentation) {
- scoped_ptr<ReadableFakeWebSocketStream> stream(
- new ReadableFakeWebSocketStream);
- // A single-frame Text message arrives in three chunks. This should be
- // delivered as three frames.
- static const InitFrameChunk chunks1[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 12},
- NOT_FINAL_CHUNK, "TIME"}};
- static const InitFrameChunk chunks2[] = {
- {{NO_HEADER}, NOT_FINAL_CHUNK, " FOR "}};
- static const InitFrameChunk chunks3[] = {{{NO_HEADER}, FINAL_CHUNK, "TEA"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
- set_stream(stream.Pass());
- {
- InSequence s;
- EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
- EXPECT_CALL(*event_interface_, OnFlowControl(_));
- EXPECT_CALL(
- *event_interface_,
- OnDataFrame(
- false, WebSocketFrameHeader::kOpCodeText, AsVector("TIME")));
- EXPECT_CALL(*event_interface_,
- OnDataFrame(false,
- WebSocketFrameHeader::kOpCodeContinuation,
- AsVector(" FOR ")));
- EXPECT_CALL(
- *event_interface_,
- OnDataFrame(
- true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("TEA")));
- }
-
- CreateChannelAndConnectSuccessfully();
- base::MessageLoop::current()->RunUntilIdle();
-}
-
-// If a control message is fragmented, it must be re-assembled before being
-// delivered. A control message can only be fragmented at the network level; it
-// is not permitted to be split into multiple frames.
-TEST_F(WebSocketChannelEventInterfaceTest, FragmentedControlMessage) {
- scoped_ptr<ReadableFakeWebSocketStream> stream(
- new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks1[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
- NOT_FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "")}};
- static const InitFrameChunk chunks2[] = {
- {{NO_HEADER}, NOT_FINAL_CHUNK, "Clo"}};
- static const InitFrameChunk chunks3[] = {{{NO_HEADER}, FINAL_CHUNK, "se"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
- stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
- ERR_CONNECTION_CLOSED);
- set_stream(stream.Pass());
- {
- InSequence s;
- EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
- EXPECT_CALL(*event_interface_, OnFlowControl(_));
- EXPECT_CALL(*event_interface_, OnClosingHandshake());
- EXPECT_CALL(*event_interface_,
- OnDropChannel(kWebSocketNormalClosure, "Close"));
- }
-
- CreateChannelAndConnectSuccessfully();
- base::MessageLoop::current()->RunUntilIdle();
-}
-
-// The payload of a control frame is not permitted to exceed 125 bytes. RFC6455
-// 5.5 "All control frames MUST have a payload length of 125 bytes or less"
-TEST_F(WebSocketChannelEventInterfaceTest, OversizeControlMessageIsRejected) {
+// A message can consist of one frame with NULL payload.
+TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const size_t kPayloadLen = 126;
- char payload[kPayloadLen + 1]; // allow space for trailing NUL
- std::fill(payload, payload + kPayloadLen, 'A');
- payload[kPayloadLen] = '\0';
- // Not static because "payload" is constructed at runtime.
- const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED,
- kPayloadLen},
- FINAL_CHUNK, payload}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, NULL}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
set_stream(stream.Pass());
-
EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
- EXPECT_CALL(*event_interface_,
- OnDropChannel(kWebSocketErrorProtocolError, _));
-
+ EXPECT_CALL(
+ *event_interface_,
+ OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("")));
CreateChannelAndConnectSuccessfully();
}
@@ -1168,12 +1381,11 @@ TEST_F(WebSocketChannelEventInterfaceTest, OversizeControlMessageIsRejected) {
TEST_F(WebSocketChannelEventInterfaceTest, MultiFrameControlMessageIsRejected) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 2},
- FINAL_CHUNK, "Pi"},
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 2},
- FINAL_CHUNK, "ng"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
+ static const InitFrame frames[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, "Pi"},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ NOT_MASKED, "ng"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
set_stream(stream.Pass());
{
InSequence s;
@@ -1225,39 +1437,14 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) {
base::MessageLoop::current()->RunUntilIdle();
}
-// Connection closed in the middle of a Close message (server bug, etc.)
-TEST_F(WebSocketChannelEventInterfaceTest, ConnectionClosedInMessage) {
- scoped_ptr<ReadableFakeWebSocketStream> stream(
- new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
- NOT_FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "")}};
-
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
- stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
- ERR_CONNECTION_CLOSED);
- set_stream(stream.Pass());
- {
- InSequence s;
- EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
- EXPECT_CALL(*event_interface_, OnFlowControl(_));
- EXPECT_CALL(*event_interface_,
- OnDropChannel(kWebSocketErrorAbnormalClosure, _));
- }
-
- CreateChannelAndConnectSuccessfully();
- base::MessageLoop::current()->RunUntilIdle();
-}
-
// RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 5}, FINAL_CHUNK,
- "HELLO"}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
set_stream(stream.Pass());
{
InSequence s;
@@ -1276,10 +1463,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, 4, NOT_MASKED, 5}, FINAL_CHUNK, "HELLO"}};
+ static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
set_stream(stream.Pass());
{
InSequence s;
@@ -1300,18 +1486,17 @@ TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
new ReadableFakeWebSocketStream);
// We have one message of type Text split into two frames. In the middle is a
// control message of type Pong.
- static const InitFrameChunk chunks1[] = {
- {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 6},
- FINAL_CHUNK, "SPLIT "}};
- static const InitFrameChunk chunks2[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, 0},
- FINAL_CHUNK, ""}};
- static const InitFrameChunk chunks3[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 7},
- FINAL_CHUNK, "MESSAGE"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
+ static const InitFrame frames1[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
+ NOT_MASKED, "SPLIT "}};
+ static const InitFrame frames2[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
+ static const InitFrame frames3[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ NOT_MASKED, "MESSAGE"}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
set_stream(stream.Pass());
{
InSequence s;
@@ -1331,17 +1516,32 @@ TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
base::MessageLoop::current()->RunUntilIdle();
}
-// If a chunk has an invalid header, then the connection is closed and
-// subsequent chunks must not trigger events.
-TEST_F(WebSocketChannelEventInterfaceTest, HeaderlessChunkAfterInvalidChunk) {
+// It seems redundant to repeat the entirety of the above test, so just test a
+// Pong with NULL data.
+TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
+ set_stream(stream.Pass());
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
+ EXPECT_CALL(*event_interface_, OnFlowControl(_));
+
+ CreateChannelAndConnectSuccessfully();
+ base::MessageLoop::current()->RunUntilIdle();
+}
+
+// If a frame has an invalid header, then the connection is closed and
+// subsequent frames must not trigger events.
+TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 11},
- NOT_FINAL_CHUNK, "HELLO"},
- {{NO_HEADER}, FINAL_CHUNK, " WORLD"}};
+ static const InitFrame frames[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
set_stream(stream.Pass());
{
InSequence s;
@@ -1375,7 +1575,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) {
set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
// We use this checkpoint object to verify that the quota update comes after
// the write.
- MockFunction<void(int)> checkpoint;
+ Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
@@ -1396,7 +1596,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) {
// Verify that our quota actually is refreshed when we are told it is.
TEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) {
set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream));
- MockFunction<void(int)> checkpoint;
+ Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
@@ -1444,7 +1644,7 @@ TEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) {
// If a write fails, the channel is dropped.
TEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) {
set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream));
- MockFunction<void(int)> checkpoint;
+ Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
@@ -1501,10 +1701,29 @@ TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 0},
- FINAL_CHUNK, ""}};
- stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+ stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
+ ERR_CONNECTION_CLOSED);
+ set_stream(stream.Pass());
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
+ EXPECT_CALL(*event_interface_, OnFlowControl(_));
+ EXPECT_CALL(*event_interface_, OnClosingHandshake());
+ EXPECT_CALL(*event_interface_,
+ OnDropChannel(kWebSocketErrorNoStatusReceived, _));
+
+ CreateChannelAndConnectSuccessfully();
+}
+
+// A version of the above test with NULL payload.
+TEST_F(WebSocketChannelEventInterfaceTest,
+ CloseWithNullPayloadGivesStatus1005) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, NULL}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
ERR_CONNECTION_CLOSED);
set_stream(stream.Pass());
@@ -1517,16 +1736,113 @@ TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
CreateChannelAndConnectSuccessfully();
}
+// If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then
+// kWebSocketErrorProtocolError must be sent to the renderer.
+TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
+ ERR_WS_PROTOCOL_ERROR);
+ set_stream(stream.Pass());
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
+ EXPECT_CALL(*event_interface_, OnFlowControl(_));
+
+ EXPECT_CALL(*event_interface_,
+ OnDropChannel(kWebSocketErrorProtocolError, _));
+
+ CreateChannelAndConnectSuccessfully();
+}
+
+// Async version of above test.
+TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
+ ERR_WS_PROTOCOL_ERROR);
+ set_stream(stream.Pass());
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
+ EXPECT_CALL(*event_interface_, OnFlowControl(_));
+
+ EXPECT_CALL(*event_interface_,
+ OnDropChannel(kWebSocketErrorProtocolError, _));
+
+ CreateChannelAndConnectSuccessfully();
+ base::MessageLoop::current()->RunUntilIdle();
+}
+
+// The closing handshake times out and sends an OnDropChannel event if no
+// response to the client Close message is received.
+TEST_F(WebSocketChannelEventInterfaceTest,
+ ClientInitiatedClosingHandshakeTimesOut) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
+ ERR_IO_PENDING);
+ set_stream(stream.Pass());
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
+ EXPECT_CALL(*event_interface_, OnFlowControl(_));
+ // This checkpoint object verifies that the OnDropChannel message comes after
+ // the timeout.
+ Checkpoint checkpoint;
+ TestClosure completion;
+ {
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(*event_interface_,
+ OnDropChannel(kWebSocketErrorAbnormalClosure, _))
+ .WillOnce(InvokeClosureReturnDeleted(completion.closure()));
+ }
+ CreateChannelAndConnectSuccessfully();
+ // OneShotTimer is not very friendly to testing; there is no apparent way to
+ // set an expectation on it. Instead the tests need to infer that the timeout
+ // was fired by the behaviour of the WebSocketChannel object.
+ channel_->SetClosingHandshakeTimeoutForTesting(
+ TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
+ channel_->StartClosingHandshake(kWebSocketNormalClosure, "");
+ checkpoint.Call(1);
+ completion.WaitForResult();
+}
+
+// The closing handshake times out and sends an OnDropChannel event if a Close
+// message is received but the connection isn't closed by the remote host.
+TEST_F(WebSocketChannelEventInterfaceTest,
+ ServerInitiatedClosingHandshakeTimesOut) {
+ scoped_ptr<ReadableFakeWebSocketStream> stream(
+ new ReadableFakeWebSocketStream);
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
+ set_stream(stream.Pass());
+ EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
+ EXPECT_CALL(*event_interface_, OnFlowControl(_));
+ Checkpoint checkpoint;
+ TestClosure completion;
+ {
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(*event_interface_, OnClosingHandshake());
+ EXPECT_CALL(*event_interface_,
+ OnDropChannel(kWebSocketErrorAbnormalClosure, _))
+ .WillOnce(InvokeClosureReturnDeleted(completion.closure()));
+ }
+ CreateChannelAndConnectSuccessfully();
+ channel_->SetClosingHandshakeTimeoutForTesting(
+ TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
+ checkpoint.Call(1);
+ completion.WaitForResult();
+}
+
// RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
// WebSocketChannel actually only sets the mask bit in the header, it doesn't
// perform masking itself (not all transports actually use masking).
TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 13},
- FINAL_CHUNK, "NEEDS MASKING"}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
+ MASKED, "NEEDS MASKING"}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1537,12 +1853,12 @@ TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
// RFC6455 5.5.1 "The application MUST NOT send any more data frames after
// sending a Close frame."
TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 9},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1554,17 +1870,17 @@ TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
// RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
// send a Close frame, the endpoint MUST send a Close frame in response."
TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 7},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
- .WillOnce(ReturnChunks(&chunks))
+ .WillOnce(ReturnFrames(&frames))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1573,29 +1889,29 @@ TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
// The converse of the above case; after sending a Close frame, we should not
// send another one.
TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 7},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
+ static const InitFrame frames_init[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
// We store the parameters that were passed to ReadFrames() so that we can
// call them explicitly later.
CompletionCallback read_callback;
- ScopedVector<WebSocketFrameChunk>* frame_chunks = NULL;
+ ScopedVector<WebSocketFrame>* frames = NULL;
// Use a checkpoint to make the ordering of events clearer.
- MockFunction<void(int)> checkpoint;
+ Checkpoint checkpoint;
{
InSequence s;
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
- .WillOnce(DoAll(SaveArg<0>(&frame_chunks),
+ .WillOnce(DoAll(SaveArg<0>(&frames),
SaveArg<1>(&read_callback),
Return(ERR_IO_PENDING)));
EXPECT_CALL(checkpoint, Call(1));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
@@ -1610,28 +1926,74 @@ TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close");
checkpoint.Call(2);
- *frame_chunks = CreateFrameChunkVector(chunks);
+ *frames = CreateFrameVector(frames_init);
read_callback.Run(OK);
checkpoint.Call(3);
}
+// Invalid close status codes should not be sent on the network.
+TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) {
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Error")}};
+
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(Return(ERR_IO_PENDING));
+
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
+
+ CreateChannelAndConnectSuccessfully();
+ channel_->StartClosingHandshake(999, "");
+}
+
+// A Close frame with a reason longer than 123 bytes cannot be sent on the
+// network.
+TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) {
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Error")}};
+
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(Return(ERR_IO_PENDING));
+
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
+
+ CreateChannelAndConnectSuccessfully();
+ channel_->StartClosingHandshake(1000, std::string(124, 'A'));
+}
+
// We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no
// status in the Close message from the other side. Code 1005 is not allowed to
// appear on the wire, so we should not echo it back. See test
// CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
// correctly generated internally.
TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 0},
- FINAL_CHUNK, ""}};
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 0},
- FINAL_CHUNK, ""}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(ReturnFrames(&frames))
+ .WillRepeatedly(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+ .WillOnce(Return(OK));
+
+ CreateChannelAndConnectSuccessfully();
+}
+
+TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) {
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, NULL}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
- .WillOnce(ReturnChunks(&chunks))
+ .WillOnce(ReturnFrames(&frames))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1643,58 +2005,74 @@ TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
// "Application data" as found in the message body of the Ping frame being
// replied to."
TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 16},
- FINAL_CHUNK, "Application data"}};
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, 16},
- FINAL_CHUNK, "Application data"}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
+ NOT_MASKED, "Application data"}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
+ MASKED, "Application data"}};
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(ReturnFrames(&frames))
+ .WillRepeatedly(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+ .WillOnce(Return(OK));
+
+ CreateChannelAndConnectSuccessfully();
+}
+
+// A ping with a NULL payload should be responded to with a Pong with an empty
+// payload.
+TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithEmptyPong) {
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, NULL}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, ""}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
- .WillOnce(ReturnChunks(&chunks))
+ .WillOnce(ReturnFrames(&frames))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
}
TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 16},
- FINAL_CHUNK, "Application data"}};
- static const InitFrameChunk expected1[] = {
- {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 6},
- FINAL_CHUNK, "Hello "}};
- static const InitFrameChunk expected2[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, 16},
- FINAL_CHUNK, "Application data"}};
- static const InitFrameChunk expected3[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, MASKED, 5},
- FINAL_CHUNK, "World"}};
- ScopedVector<WebSocketFrameChunk>* read_chunks;
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
+ NOT_MASKED, "Application data"}};
+ static const InitFrame expected1[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
+ static const InitFrame expected2[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
+ MASKED, "Application data"}};
+ static const InitFrame expected3[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+ MASKED, "World"}};
+ ScopedVector<WebSocketFrame>* read_frames;
CompletionCallback read_callback;
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
- .WillOnce(DoAll(SaveArg<0>(&read_chunks),
+ .WillOnce(DoAll(SaveArg<0>(&read_frames),
SaveArg<1>(&read_callback),
Return(ERR_IO_PENDING)))
.WillRepeatedly(Return(ERR_IO_PENDING));
{
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
.WillOnce(Return(OK));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
.WillOnce(Return(OK));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected3), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
.WillOnce(Return(OK));
}
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
- *read_chunks = CreateFrameChunkVector(chunks);
+ *read_frames = CreateFrameVector(frames);
read_callback.Run(OK);
channel_->SendFrame(
true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World"));
@@ -1703,24 +2081,22 @@ TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
// WriteFrames() may not be called until the previous write has completed.
// WebSocketChannel must buffer writes that happen in the meantime.
TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
- static const InitFrameChunk expected1[] = {
- {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 6},
- FINAL_CHUNK, "Hello "}};
- static const InitFrameChunk expected2[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 5}, FINAL_CHUNK,
- "World"}};
+ static const InitFrame expected1[] = {
+ {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
+ static const InitFrame expected2[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
CompletionCallback write_callback;
- MockFunction<void(int)> checkpoint;
+ Checkpoint checkpoint;
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
{
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
.WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
EXPECT_CALL(checkpoint, Call(2));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
.WillOnce(Return(ERR_IO_PENDING));
EXPECT_CALL(checkpoint, Call(3));
}
@@ -1741,27 +2117,22 @@ TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
// important to get good throughput in the "many small messages" case.
TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
static const char input_letters[] = "Hello";
- static const InitFrameChunk expected1[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
- "H"}};
- static const InitFrameChunk expected2[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
- "e"},
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
- "l"},
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
- "l"},
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
- "o"}};
+ static const InitFrame expected1[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}};
+ static const InitFrame expected2[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
CompletionCallback write_callback;
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
{
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
.WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
.WillOnce(Return(ERR_IO_PENDING));
}
@@ -1781,12 +2152,12 @@ TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
// even be using a different extension which uses that code to mean something
// else.
TEST_F(WebSocketChannelStreamTest, MuxErrorIsNotSentToStream) {
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 16},
- FINAL_CHUNK, CLOSE_DATA(GOING_AWAY, "Internal Error")}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(GOING_AWAY, "Internal Error")}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close());
@@ -1800,45 +2171,41 @@ TEST_F(WebSocketChannelStreamTest, MuxErrorIsNotSentToStream) {
// protocol also has Binary frames and those need to be 8-bit clean. For the
// sake of completeness, this test verifies that they are.
TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
- ScopedVector<WebSocketFrameChunk>* frame_chunks = NULL;
+ ScopedVector<WebSocketFrame>* frames = NULL;
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
- .WillOnce(DoAll(SaveArg<0>(&frame_chunks), Return(ERR_IO_PENDING)));
+ .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
CreateChannelAndConnectSuccessfully();
channel_->SendFrame(
true,
WebSocketFrameHeader::kOpCodeBinary,
std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize));
- ASSERT_TRUE(frame_chunks != NULL);
- ASSERT_EQ(1U, frame_chunks->size());
- const WebSocketFrameChunk* out_chunk = (*frame_chunks)[0];
- ASSERT_TRUE(out_chunk->header);
- EXPECT_EQ(kBinaryBlobSize, out_chunk->header->payload_length);
- ASSERT_TRUE(out_chunk->data);
- EXPECT_EQ(kBinaryBlobSize, static_cast<size_t>(out_chunk->data->size()));
- EXPECT_EQ(0, memcmp(kBinaryBlob, out_chunk->data->data(), kBinaryBlobSize));
+ ASSERT_TRUE(frames != NULL);
+ ASSERT_EQ(1U, frames->size());
+ const WebSocketFrame* out_frame = (*frames)[0];
+ EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length);
+ ASSERT_TRUE(out_frame->data);
+ EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->data->data(), kBinaryBlobSize));
}
// Test the read path for 8-bit cleanliness as well.
TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
- scoped_ptr<WebSocketFrameHeader> frame_header(
- new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeBinary));
- frame_header->final = true;
- frame_header->payload_length = kBinaryBlobSize;
- scoped_ptr<WebSocketFrameChunk> frame_chunk(new WebSocketFrameChunk);
- frame_chunk->header = frame_header.Pass();
- frame_chunk->final_chunk = true;
- frame_chunk->data = new IOBufferWithSize(kBinaryBlobSize);
- memcpy(frame_chunk->data->data(), kBinaryBlob, kBinaryBlobSize);
- ScopedVector<WebSocketFrameChunk> chunks;
- chunks.push_back(frame_chunk.release());
+ scoped_ptr<WebSocketFrame> frame(
+ new WebSocketFrame(WebSocketFrameHeader::kOpCodeBinary));
+ WebSocketFrameHeader& frame_header = frame->header;
+ frame_header.final = true;
+ frame_header.payload_length = kBinaryBlobSize;
+ frame->data = new IOBuffer(kBinaryBlobSize);
+ memcpy(frame->data->data(), kBinaryBlob, kBinaryBlobSize);
+ ScopedVector<WebSocketFrame> frames;
+ frames.push_back(frame.release());
scoped_ptr<ReadableFakeWebSocketStream> stream(
new ReadableFakeWebSocketStream);
stream->PrepareRawReadFrames(
- ReadableFakeWebSocketStream::SYNC, OK, chunks.Pass());
+ ReadableFakeWebSocketStream::SYNC, OK, frames.Pass());
set_stream(stream.Pass());
EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
EXPECT_CALL(*event_interface_, OnFlowControl(_));
@@ -1856,17 +2223,17 @@ TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
// but the current implementation fails the connection. Since a Close has
// already been sent, this just means closing the connection.
TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
- static const InitFrameChunk chunks[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 4},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 9},
- FINAL_CHUNK, "Ping body"}};
- static const InitFrameChunk expected[] = {
- {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 4},
- FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
+ NOT_MASKED, "Ping body"}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
- .WillOnce(ReturnChunks(&chunks))
+ .WillOnce(ReturnFrames(&frames))
.WillRepeatedly(Return(ERR_IO_PENDING));
{
// We only need to verify the relative order of WriteFrames() and
@@ -1874,7 +2241,7 @@ TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
// frame before calling ReadFrames() again, but that is an implementation
// detail and better not to consider required behaviour.
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
}
@@ -1882,5 +2249,138 @@ TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
CreateChannelAndConnectSuccessfully();
}
+// A protocol error from the remote server should result in a close frame with
+// status 1002, followed by the connection closing.
+TEST_F(WebSocketChannelStreamTest, ProtocolError) {
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+ .WillOnce(Return(OK));
+ EXPECT_CALL(*mock_stream_, Close());
+
+ CreateChannelAndConnectSuccessfully();
+}
+
+// Set the closing handshake timeout to a very tiny value before connecting.
+class WebSocketChannelStreamTimeoutTest : public WebSocketChannelStreamTest {
+ protected:
+ WebSocketChannelStreamTimeoutTest() {}
+
+ virtual void CreateChannelAndConnectSuccessfully() OVERRIDE {
+ set_stream(mock_stream_.Pass());
+ CreateChannelAndConnect();
+ channel_->SetClosingHandshakeTimeoutForTesting(
+ TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
+ connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+ }
+};
+
+// In this case the server initiates the closing handshake with a Close
+// message. WebSocketChannel responds with a matching Close message, and waits
+// for the server to close the TCP/IP connection. The server never closes the
+// connection, so the closing handshake times out and WebSocketChannel closes
+// the connection itself.
+TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) {
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(ReturnFrames(&frames))
+ .WillRepeatedly(Return(ERR_IO_PENDING));
+ Checkpoint checkpoint;
+ TestClosure completion;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+ .WillOnce(Return(OK));
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(*mock_stream_, Close())
+ .WillOnce(InvokeClosure(completion.closure()));
+ }
+
+ CreateChannelAndConnectSuccessfully();
+ checkpoint.Call(1);
+ completion.WaitForResult();
+}
+
+// In this case the client initiates the closing handshake by sending a Close
+// message. WebSocketChannel waits for a Close message in response from the
+// server. The server never responds to the Close message, so the closing
+// handshake times out and WebSocketChannel closes the connection.
+TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) {
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillRepeatedly(Return(ERR_IO_PENDING));
+ TestClosure completion;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+ .WillOnce(Return(OK));
+ EXPECT_CALL(*mock_stream_, Close())
+ .WillOnce(InvokeClosure(completion.closure()));
+ }
+
+ CreateChannelAndConnectSuccessfully();
+ channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK");
+ completion.WaitForResult();
+}
+
+// In this case the client initiates the closing handshake and the server
+// responds with a matching Close message. WebSocketChannel waits for the server
+// to close the TCP/IP connection, but it never does. The closing handshake
+// times out and WebSocketChannel closes the connection.
+TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) {
+ static const InitFrame expected[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ static const InitFrame frames[] = {
+ {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
+ NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
+ EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+ TestClosure completion;
+ ScopedVector<WebSocketFrame>* read_frames = NULL;
+ CompletionCallback read_callback;
+ {
+ InSequence s;
+ // Copy the arguments to ReadFrames so that the test can call the callback
+ // after it has send the close message.
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(DoAll(SaveArg<0>(&read_frames),
+ SaveArg<1>(&read_callback),
+ Return(ERR_IO_PENDING)));
+ // The first real event that happens is the client sending the Close
+ // message.
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+ .WillOnce(Return(OK));
+ // The |read_frames| callback is called (from this test case) at this
+ // point. ReadFrames is called again by WebSocketChannel, waiting for
+ // ERR_CONNECTION_CLOSED.
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce(Return(ERR_IO_PENDING));
+ // The timeout happens and so WebSocketChannel closes the stream.
+ EXPECT_CALL(*mock_stream_, Close())
+ .WillOnce(InvokeClosure(completion.closure()));
+ }
+
+ CreateChannelAndConnectSuccessfully();
+ channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK");
+ ASSERT_TRUE(read_frames);
+ // Provide the "Close" message from the server.
+ *read_frames = CreateFrameVector(frames);
+ read_callback.Run(OK);
+ completion.WaitForResult();
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/websockets/websocket_deflate_predictor.h b/chromium/net/websockets/websocket_deflate_predictor.h
new file mode 100644
index 00000000000..c786d805b56
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_predictor.h
@@ -0,0 +1,58 @@
+// 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_WEBSOCKETS_WEBSOCKET_DEFLATE_PREDICTOR_H_
+#define NET_WEBSOCKETS_WEBSOCKET_DEFLATE_PREDICTOR_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "net/base/net_export.h"
+
+namespace net {
+
+struct WebSocketFrame;
+
+// WebSocketDeflatePredictor is an interface class used for judging whether
+// a WebSocketDeflateStream should compress a message or not.
+class NET_EXPORT_PRIVATE WebSocketDeflatePredictor {
+ public:
+ enum Result {
+ // Deflate and send the message.
+ DEFLATE,
+ // Do not deflate and send the original message.
+ DO_NOT_DEFLATE,
+ // Try compressing the message and send the smaller one of the original
+ // and the compressed message.
+ // Returning this result implies that the deflater is running on
+ // DoNotTakeOverContext mode and the entire message is visible.
+ TRY_DEFLATE,
+ };
+
+ virtual ~WebSocketDeflatePredictor() {}
+
+ // Predicts and returns whether the deflater should deflate the message
+ // which begins with |frames[frame_index]| or not.
+ // |frames[(frame_index + 1):]| consists of future frames if any.
+ // |frames[frame_index]| must be the first frame of a data message,
+ // but future frames may contain control message frames.
+ // |frames[frame_index]| cannot be recorded yet and all preceding
+ // data frames have to be already recorded when this method is called.
+ virtual Result Predict(const ScopedVector<WebSocketFrame>& frames,
+ size_t frame_index) = 0;
+
+ // Records frame data for future prediction.
+ // Only data frames should be recorded. Do not pass control frames' data.
+ // All input data frames for the stream must be recorded in order.
+ virtual void RecordInputDataFrame(const WebSocketFrame* frame) = 0;
+
+ // Records frame data for future prediction.
+ // Only data frames should be recorded. Do not pass control frames' data.
+ // All data frames written by the stream must be recorded in order
+ // regardless of whether they are compressed or not.
+ virtual void RecordWrittenDataFrame(const WebSocketFrame* frame) = 0;
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_DEFLATE_PREDICTOR_H_
diff --git a/chromium/net/websockets/websocket_deflate_predictor_impl.cc b/chromium/net/websockets/websocket_deflate_predictor_impl.cc
new file mode 100644
index 00000000000..0d1a5c20258
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_predictor_impl.cc
@@ -0,0 +1,23 @@
+// 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/websockets/websocket_deflate_predictor_impl.h"
+
+namespace net {
+
+typedef WebSocketDeflatePredictor::Result Result;
+
+Result WebSocketDeflatePredictorImpl::Predict(
+ const ScopedVector<WebSocketFrame>& frames,
+ size_t frame_index) {
+ return DEFLATE;
+}
+
+void WebSocketDeflatePredictorImpl::RecordInputDataFrame(
+ const WebSocketFrame* frame) {}
+
+void WebSocketDeflatePredictorImpl::RecordWrittenDataFrame(
+ const WebSocketFrame* frame) {}
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_deflate_predictor_impl.h b/chromium/net/websockets/websocket_deflate_predictor_impl.h
new file mode 100644
index 00000000000..88a919cc025
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_predictor_impl.h
@@ -0,0 +1,31 @@
+// 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_WEBSOCKETS_WEBSOCKET_DEFLATE_PREDICTOR_IMPL_H_
+#define NET_WEBSOCKETS_WEBSOCKET_DEFLATE_PREDICTOR_IMPL_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_vector.h"
+#include "net/base/net_export.h"
+#include "net/websockets/websocket_deflate_predictor.h"
+
+namespace net {
+
+struct WebSocketFrame;
+
+class NET_EXPORT_PRIVATE WebSocketDeflatePredictorImpl
+ : public WebSocketDeflatePredictor {
+ public:
+ virtual ~WebSocketDeflatePredictorImpl() {}
+
+ virtual Result Predict(const ScopedVector<WebSocketFrame>& frames,
+ size_t frame_index) OVERRIDE;
+ virtual void RecordInputDataFrame(const WebSocketFrame* frame) OVERRIDE;
+ virtual void RecordWrittenDataFrame(const WebSocketFrame* frame) OVERRIDE;
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_DEFLATE_PREDICTOR_IMPL_H_
diff --git a/chromium/net/websockets/websocket_deflate_predictor_impl_test.cc b/chromium/net/websockets/websocket_deflate_predictor_impl_test.cc
new file mode 100644
index 00000000000..79c54e10d06
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_predictor_impl_test.cc
@@ -0,0 +1,29 @@
+// 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/websockets/websocket_deflate_predictor_impl.h"
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "net/websockets/websocket_frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+typedef WebSocketDeflatePredictor::Result Result;
+
+TEST(WebSocketDeflatePredictorImpl, Predict) {
+ WebSocketDeflatePredictorImpl predictor;
+ ScopedVector<WebSocketFrame> frames;
+ frames.push_back(new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
+ Result result = predictor.Predict(frames, 0);
+
+ EXPECT_EQ(WebSocketDeflatePredictor::DEFLATE, result);
+}
+
+} // namespace
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_deflate_stream.cc b/chromium/net/websockets/websocket_deflate_stream.cc
new file mode 100644
index 00000000000..601670d373b
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_stream.cc
@@ -0,0 +1,372 @@
+// 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/websockets/websocket_deflate_stream.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/websockets/websocket_deflate_predictor.h"
+#include "net/websockets/websocket_deflater.h"
+#include "net/websockets/websocket_errors.h"
+#include "net/websockets/websocket_frame.h"
+#include "net/websockets/websocket_inflater.h"
+#include "net/websockets/websocket_stream.h"
+
+class GURL;
+
+namespace net {
+
+namespace {
+
+const int kWindowBits = 15;
+const size_t kChunkSize = 4 * 1024;
+
+} // namespace
+
+WebSocketDeflateStream::WebSocketDeflateStream(
+ scoped_ptr<WebSocketStream> stream,
+ WebSocketDeflater::ContextTakeOverMode mode,
+ scoped_ptr<WebSocketDeflatePredictor> predictor)
+ : stream_(stream.Pass()),
+ deflater_(mode),
+ inflater_(kChunkSize, kChunkSize),
+ reading_state_(NOT_READING),
+ writing_state_(NOT_WRITING),
+ current_reading_opcode_(WebSocketFrameHeader::kOpCodeText),
+ current_writing_opcode_(WebSocketFrameHeader::kOpCodeText),
+ predictor_(predictor.Pass()) {
+ DCHECK(stream_);
+ deflater_.Initialize(kWindowBits);
+ inflater_.Initialize(kWindowBits);
+}
+
+WebSocketDeflateStream::~WebSocketDeflateStream() {}
+
+int WebSocketDeflateStream::ReadFrames(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
+ CompletionCallback callback_to_pass =
+ base::Bind(&WebSocketDeflateStream::OnReadComplete,
+ base::Unretained(this),
+ base::Unretained(frames),
+ callback);
+ int result = stream_->ReadFrames(frames, callback_to_pass);
+ if (result < 0)
+ return result;
+ DCHECK_EQ(OK, result);
+ return InflateAndReadIfNecessary(frames, callback_to_pass);
+}
+
+int WebSocketDeflateStream::WriteFrames(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
+ int result = Deflate(frames);
+ if (result != OK)
+ return result;
+ if (frames->empty())
+ return OK;
+ return stream_->WriteFrames(frames, callback);
+}
+
+void WebSocketDeflateStream::Close() { stream_->Close(); }
+
+std::string WebSocketDeflateStream::GetSubProtocol() const {
+ return stream_->GetSubProtocol();
+}
+
+std::string WebSocketDeflateStream::GetExtensions() const {
+ return stream_->GetExtensions();
+}
+
+void WebSocketDeflateStream::OnReadComplete(
+ ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback,
+ int result) {
+ if (result != OK) {
+ frames->clear();
+ callback.Run(result);
+ return;
+ }
+
+ int r = InflateAndReadIfNecessary(frames, callback);
+ if (r != ERR_IO_PENDING)
+ callback.Run(r);
+}
+
+int WebSocketDeflateStream::Deflate(ScopedVector<WebSocketFrame>* frames) {
+ ScopedVector<WebSocketFrame> frames_to_write;
+ // Store frames of the currently processed message if writing_state_ equals to
+ // WRITING_POSSIBLY_COMPRESSED_MESSAGE.
+ ScopedVector<WebSocketFrame> frames_of_message;
+ for (size_t i = 0; i < frames->size(); ++i) {
+ DCHECK(!(*frames)[i]->header.reserved1);
+ if (!WebSocketFrameHeader::IsKnownDataOpCode((*frames)[i]->header.opcode)) {
+ frames_to_write.push_back((*frames)[i]);
+ (*frames)[i] = NULL;
+ continue;
+ }
+ if (writing_state_ == NOT_WRITING)
+ OnMessageStart(*frames, i);
+
+ scoped_ptr<WebSocketFrame> frame((*frames)[i]);
+ (*frames)[i] = NULL;
+ predictor_->RecordInputDataFrame(frame.get());
+
+ if (writing_state_ == WRITING_UNCOMPRESSED_MESSAGE) {
+ if (frame->header.final)
+ writing_state_ = NOT_WRITING;
+ predictor_->RecordWrittenDataFrame(frame.get());
+ frames_to_write.push_back(frame.release());
+ current_writing_opcode_ = WebSocketFrameHeader::kOpCodeContinuation;
+ } else {
+ if (frame->data && !deflater_.AddBytes(frame->data->data(),
+ frame->header.payload_length)) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "deflater_.AddBytes() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ if (frame->header.final && !deflater_.Finish()) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "deflater_.Finish() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+
+ if (writing_state_ == WRITING_COMPRESSED_MESSAGE) {
+ if (deflater_.CurrentOutputSize() >= kChunkSize ||
+ frame->header.final) {
+ int result = AppendCompressedFrame(frame->header, &frames_to_write);
+ if (result != OK)
+ return result;
+ }
+ if (frame->header.final)
+ writing_state_ = NOT_WRITING;
+ } else {
+ DCHECK_EQ(WRITING_POSSIBLY_COMPRESSED_MESSAGE, writing_state_);
+ bool final = frame->header.final;
+ frames_of_message.push_back(frame.release());
+ if (final) {
+ int result = AppendPossiblyCompressedMessage(&frames_of_message,
+ &frames_to_write);
+ if (result != OK)
+ return result;
+ frames_of_message.clear();
+ writing_state_ = NOT_WRITING;
+ }
+ }
+ }
+ }
+ DCHECK_NE(WRITING_POSSIBLY_COMPRESSED_MESSAGE, writing_state_);
+ frames->swap(frames_to_write);
+ return OK;
+}
+
+void WebSocketDeflateStream::OnMessageStart(
+ const ScopedVector<WebSocketFrame>& frames, size_t index) {
+ WebSocketFrame* frame = frames[index];
+ current_writing_opcode_ = frame->header.opcode;
+ DCHECK(current_writing_opcode_ == WebSocketFrameHeader::kOpCodeText ||
+ current_writing_opcode_ == WebSocketFrameHeader::kOpCodeBinary);
+ WebSocketDeflatePredictor::Result prediction =
+ predictor_->Predict(frames, index);
+
+ switch (prediction) {
+ case WebSocketDeflatePredictor::DEFLATE:
+ writing_state_ = WRITING_COMPRESSED_MESSAGE;
+ return;
+ case WebSocketDeflatePredictor::DO_NOT_DEFLATE:
+ writing_state_ = WRITING_UNCOMPRESSED_MESSAGE;
+ return;
+ case WebSocketDeflatePredictor::TRY_DEFLATE:
+ writing_state_ = WRITING_POSSIBLY_COMPRESSED_MESSAGE;
+ return;
+ }
+ NOTREACHED();
+}
+
+int WebSocketDeflateStream::AppendCompressedFrame(
+ const WebSocketFrameHeader& header,
+ ScopedVector<WebSocketFrame>* frames_to_write) {
+ const WebSocketFrameHeader::OpCode opcode = current_writing_opcode_;
+ scoped_refptr<IOBufferWithSize> compressed_payload =
+ deflater_.GetOutput(deflater_.CurrentOutputSize());
+ if (!compressed_payload) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "deflater_.GetOutput() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ scoped_ptr<WebSocketFrame> compressed(new WebSocketFrame(opcode));
+ compressed->header.CopyFrom(header);
+ compressed->header.opcode = opcode;
+ compressed->header.final = header.final;
+ compressed->header.reserved1 =
+ (opcode != WebSocketFrameHeader::kOpCodeContinuation);
+ compressed->data = compressed_payload;
+ compressed->header.payload_length = compressed_payload->size();
+
+ current_writing_opcode_ = WebSocketFrameHeader::kOpCodeContinuation;
+ predictor_->RecordWrittenDataFrame(compressed.get());
+ frames_to_write->push_back(compressed.release());
+ return OK;
+}
+
+int WebSocketDeflateStream::AppendPossiblyCompressedMessage(
+ ScopedVector<WebSocketFrame>* frames,
+ ScopedVector<WebSocketFrame>* frames_to_write) {
+ DCHECK(!frames->empty());
+
+ const WebSocketFrameHeader::OpCode opcode = current_writing_opcode_;
+ scoped_refptr<IOBufferWithSize> compressed_payload =
+ deflater_.GetOutput(deflater_.CurrentOutputSize());
+ if (!compressed_payload) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "deflater_.GetOutput() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+
+ uint64 original_payload_length = 0;
+ for (size_t i = 0; i < frames->size(); ++i) {
+ WebSocketFrame* frame = (*frames)[i];
+ // Asserts checking that frames represent one whole data message.
+ DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode));
+ DCHECK_EQ(i == 0,
+ WebSocketFrameHeader::kOpCodeContinuation !=
+ frame->header.opcode);
+ DCHECK_EQ(i == frames->size() - 1, frame->header.final);
+ original_payload_length += frame->header.payload_length;
+ }
+ if (original_payload_length <=
+ static_cast<uint64>(compressed_payload->size())) {
+ // Compression is not effective. Use the original frames.
+ for (size_t i = 0; i < frames->size(); ++i) {
+ WebSocketFrame* frame = (*frames)[i];
+ frames_to_write->push_back(frame);
+ predictor_->RecordWrittenDataFrame(frame);
+ (*frames)[i] = NULL;
+ }
+ frames->weak_clear();
+ return OK;
+ }
+ scoped_ptr<WebSocketFrame> compressed(new WebSocketFrame(opcode));
+ compressed->header.CopyFrom((*frames)[0]->header);
+ compressed->header.opcode = opcode;
+ compressed->header.final = true;
+ compressed->header.reserved1 = true;
+ compressed->data = compressed_payload;
+ compressed->header.payload_length = compressed_payload->size();
+
+ predictor_->RecordWrittenDataFrame(compressed.get());
+ frames_to_write->push_back(compressed.release());
+ return OK;
+}
+
+int WebSocketDeflateStream::Inflate(ScopedVector<WebSocketFrame>* frames) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ ScopedVector<WebSocketFrame> frames_passed;
+ frames->swap(frames_passed);
+ for (size_t i = 0; i < frames_passed.size(); ++i) {
+ scoped_ptr<WebSocketFrame> frame(frames_passed[i]);
+ frames_passed[i] = NULL;
+ if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
+ frames_to_output.push_back(frame.release());
+ continue;
+ }
+
+ if (reading_state_ == NOT_READING) {
+ if (frame->header.reserved1)
+ reading_state_ = READING_COMPRESSED_MESSAGE;
+ else
+ reading_state_ = READING_UNCOMPRESSED_MESSAGE;
+ current_reading_opcode_ = frame->header.opcode;
+ } else {
+ if (frame->header.reserved1) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "Receiving a non-first frame with RSV1 flag set.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ }
+
+ if (reading_state_ == READING_UNCOMPRESSED_MESSAGE) {
+ if (frame->header.final)
+ reading_state_ = NOT_READING;
+ current_reading_opcode_ = WebSocketFrameHeader::kOpCodeContinuation;
+ frames_to_output.push_back(frame.release());
+ } else {
+ DCHECK_EQ(reading_state_, READING_COMPRESSED_MESSAGE);
+ if (frame->data && !inflater_.AddBytes(frame->data->data(),
+ frame->header.payload_length)) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "inflater_.AddBytes() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ if (frame->header.final) {
+ if (!inflater_.Finish()) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "inflater_.Finish() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ }
+ // TODO(yhirano): Many frames can be generated by the inflater and
+ // memory consumption can grow.
+ // We could avoid it, but avoiding it makes this class much more
+ // complicated.
+ while (inflater_.CurrentOutputSize() >= kChunkSize ||
+ frame->header.final) {
+ size_t size = std::min(kChunkSize, inflater_.CurrentOutputSize());
+ scoped_ptr<WebSocketFrame> inflated(
+ new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
+ scoped_refptr<IOBufferWithSize> data = inflater_.GetOutput(size);
+ bool is_final = !inflater_.CurrentOutputSize();
+ // |is_final| can't be true if |frame->header.final| is false.
+ DCHECK(!(is_final && !frame->header.final));
+ if (!data) {
+ DVLOG(1) << "WebSocket protocol error. "
+ << "inflater_.GetOutput() returns an error.";
+ return ERR_WS_PROTOCOL_ERROR;
+ }
+ inflated->header.CopyFrom(frame->header);
+ inflated->header.opcode = current_reading_opcode_;
+ inflated->header.final = is_final;
+ inflated->header.reserved1 = false;
+ inflated->data = data;
+ inflated->header.payload_length = data->size();
+
+ frames_to_output.push_back(inflated.release());
+ current_reading_opcode_ = WebSocketFrameHeader::kOpCodeContinuation;
+ if (is_final)
+ break;
+ }
+ if (frame->header.final)
+ reading_state_ = NOT_READING;
+ }
+ }
+ frames->swap(frames_to_output);
+ return frames->empty() ? ERR_IO_PENDING : OK;
+}
+
+int WebSocketDeflateStream::InflateAndReadIfNecessary(
+ ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
+ int result = Inflate(frames);
+ while (result == ERR_IO_PENDING) {
+ DCHECK(frames->empty());
+ result = stream_->ReadFrames(frames, callback);
+ if (result < 0)
+ break;
+ DCHECK_EQ(OK, result);
+ DCHECK(!frames->empty());
+ result = Inflate(frames);
+ }
+ if (result < 0)
+ frames->clear();
+ return result;
+}
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_deflate_stream.h b/chromium/net/websockets/websocket_deflate_stream.h
new file mode 100644
index 00000000000..a7859446f6a
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_stream.h
@@ -0,0 +1,103 @@
+// 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_WEBSOCKETS_WEBSOCKET_DEFLATE_STREAM_H_
+#define NET_WEBSOCKETS_WEBSOCKET_DEFLATE_STREAM_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_export.h"
+#include "net/websockets/websocket_deflater.h"
+#include "net/websockets/websocket_frame.h"
+#include "net/websockets/websocket_inflater.h"
+#include "net/websockets/websocket_stream.h"
+
+class GURL;
+
+namespace net {
+
+class WebSocketDeflatePredictor;
+
+// WebSocketDeflateStream is a WebSocketStream subclass.
+// WebSocketDeflateStream is for permessage-deflate WebSocket extension[1].
+//
+// WebSocketDeflateStream::ReadFrames and WriteFrames may change frame
+// boundary. In particular, if a control frame is placed in the middle of
+// data message frames, the control frame can overtake data frames.
+// Say there are frames df1, df2 and cf, df1 and df2 are frames of a
+// data message and cf is a control message frame. cf may arrive first and
+// data frames may follow cf.
+// Note that message boundary will be preserved, i.e. if the last frame of
+// a message m1 is read / written before the last frame of a message m2,
+// WebSocketDeflateStream will respect the order.
+//
+// [1]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-12
+class NET_EXPORT_PRIVATE WebSocketDeflateStream : public WebSocketStream {
+ public:
+ WebSocketDeflateStream(scoped_ptr<WebSocketStream> stream,
+ WebSocketDeflater::ContextTakeOverMode mode,
+ scoped_ptr<WebSocketDeflatePredictor> predictor);
+ virtual ~WebSocketDeflateStream();
+
+ // WebSocketStream functions.
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual std::string GetSubProtocol() const OVERRIDE;
+ virtual std::string GetExtensions() const OVERRIDE;
+
+ private:
+ enum ReadingState {
+ READING_COMPRESSED_MESSAGE,
+ READING_UNCOMPRESSED_MESSAGE,
+ NOT_READING,
+ };
+
+ enum WritingState {
+ WRITING_COMPRESSED_MESSAGE,
+ WRITING_UNCOMPRESSED_MESSAGE,
+ WRITING_POSSIBLY_COMPRESSED_MESSAGE,
+ NOT_WRITING,
+ };
+
+ void OnReadComplete(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback,
+ int result);
+
+ // This function deflates |frames| and stores the result to |frames| itself.
+ int Deflate(ScopedVector<WebSocketFrame>* frames);
+ void OnMessageStart(const ScopedVector<WebSocketFrame>& frames, size_t index);
+ int AppendCompressedFrame(const WebSocketFrameHeader& header,
+ ScopedVector<WebSocketFrame>* frames_to_write);
+ int AppendPossiblyCompressedMessage(
+ ScopedVector<WebSocketFrame>* frames,
+ ScopedVector<WebSocketFrame>* frames_to_write);
+
+ // This function inflates |frames| and stores the result to |frames| itself.
+ int Inflate(ScopedVector<WebSocketFrame>* frames);
+
+ int InflateAndReadIfNecessary(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback);
+
+ const scoped_ptr<WebSocketStream> stream_;
+ WebSocketDeflater deflater_;
+ WebSocketInflater inflater_;
+ ReadingState reading_state_;
+ WritingState writing_state_;
+ WebSocketFrameHeader::OpCode current_reading_opcode_;
+ WebSocketFrameHeader::OpCode current_writing_opcode_;
+ scoped_ptr<WebSocketDeflatePredictor> predictor_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketDeflateStream);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_DEFLATE_STREAM_H_
diff --git a/chromium/net/websockets/websocket_deflate_stream_test.cc b/chromium/net/websockets/websocket_deflate_stream_test.cc
new file mode 100644
index 00000000000..1775962dce1
--- /dev/null
+++ b/chromium/net/websockets/websocket_deflate_stream_test.cc
@@ -0,0 +1,1206 @@
+// 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/websockets/websocket_deflate_stream.h"
+
+#include <stdint.h>
+#include <deque>
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "net/base/completion_callback.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/websockets/websocket_deflate_predictor.h"
+#include "net/websockets/websocket_deflater.h"
+#include "net/websockets/websocket_frame.h"
+#include "net/websockets/websocket_inflater.h"
+#include "net/websockets/websocket_stream.h"
+#include "net/websockets/websocket_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+namespace {
+
+typedef ::testing::MockFunction<void(int)> MockCallback; // NOLINT
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+
+typedef uint32_t FrameFlag;
+const FrameFlag kNoFlag = 0;
+const FrameFlag kFinal = 1;
+const FrameFlag kReserved1 = 2;
+// We don't define values for other flags because we don't need them.
+
+// The value must equal to the value of the corresponding
+// constant in websocket_deflate_stream.cc
+const size_t kChunkSize = 4 * 1024;
+const int kWindowBits = 15;
+
+scoped_refptr<IOBuffer> ToIOBuffer(const std::string& s) {
+ scoped_refptr<IOBuffer> buffer = new IOBuffer(s.size());
+ memcpy(buffer->data(), s.data(), s.size());
+ return buffer;
+}
+
+std::string ToString(IOBufferWithSize* buffer) {
+ return std::string(buffer->data(), buffer->size());
+}
+
+std::string ToString(const scoped_refptr<IOBufferWithSize>& buffer) {
+ return ToString(buffer.get());
+}
+
+std::string ToString(IOBuffer* buffer, size_t size) {
+ return std::string(buffer->data(), size);
+}
+
+std::string ToString(const scoped_refptr<IOBuffer>& buffer, size_t size) {
+ return ToString(buffer.get(), size);
+}
+
+std::string ToString(const WebSocketFrame* frame) {
+ return frame->data ? ToString(frame->data, frame->header.payload_length) : "";
+}
+
+void AppendTo(ScopedVector<WebSocketFrame>* frames,
+ WebSocketFrameHeader::OpCode opcode,
+ FrameFlag flag,
+ const std::string& data) {
+ scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode));
+ frame->header.final = (flag & kFinal);
+ frame->header.reserved1 = (flag & kReserved1);
+ frame->data = ToIOBuffer(data);
+ frame->header.payload_length = data.size();
+ frames->push_back(frame.release());
+}
+
+void AppendTo(ScopedVector<WebSocketFrame>* frames,
+ WebSocketFrameHeader::OpCode opcode,
+ FrameFlag flag) {
+ scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode));
+ frame->header.final = (flag & kFinal);
+ frame->header.reserved1 = (flag & kReserved1);
+ frames->push_back(frame.release());
+}
+
+class MockWebSocketStream : public WebSocketStream {
+ public:
+ MOCK_METHOD2(ReadFrames, int(ScopedVector<WebSocketFrame>*,
+ const CompletionCallback&));
+ MOCK_METHOD2(WriteFrames, int(ScopedVector<WebSocketFrame>*,
+ const CompletionCallback&));
+ MOCK_METHOD0(Close, void());
+ MOCK_CONST_METHOD0(GetSubProtocol, std::string());
+ MOCK_CONST_METHOD0(GetExtensions, std::string());
+};
+
+// This mock class relies on some assumptions.
+// - RecordInputDataFrame is called after the corresponding WriteFrames
+// call.
+// - RecordWrittenDataFrame is called before writing the frame.
+class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor {
+ public:
+ WebSocketDeflatePredictorMock() : result_(DEFLATE) {}
+ virtual ~WebSocketDeflatePredictorMock() {
+ // Verify whether all expectaions are consumed.
+ if (!frames_to_be_input_.empty()) {
+ ADD_FAILURE() << "There are missing frames to be input.";
+ return;
+ }
+ if (!frames_written_.empty()) {
+ ADD_FAILURE() << "There are extra written frames.";
+ return;
+ }
+ }
+
+ // WebSocketDeflatePredictor functions.
+ virtual Result Predict(const ScopedVector<WebSocketFrame>& frames,
+ size_t frame_index) OVERRIDE {
+ return result_;
+ }
+ virtual void RecordInputDataFrame(const WebSocketFrame* frame) OVERRIDE {
+ if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
+ ADD_FAILURE() << "Control frames should not be recorded.";
+ return;
+ }
+ if (frame->header.reserved1) {
+ ADD_FAILURE() << "Input frame may not be compressed.";
+ return;
+ }
+ if (frames_to_be_input_.empty()) {
+ ADD_FAILURE() << "Unexpected input data frame";
+ return;
+ }
+ if (frame != frames_to_be_input_.front()) {
+ ADD_FAILURE() << "Input data frame does not match the expectation.";
+ return;
+ }
+ frames_to_be_input_.pop_front();
+ }
+ virtual void RecordWrittenDataFrame(const WebSocketFrame* frame) OVERRIDE {
+ if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) {
+ ADD_FAILURE() << "Control frames should not be recorded.";
+ return;
+ }
+ frames_written_.push_back(frame);
+ }
+
+ // Sets |result_| for the |Predict| return value.
+ void set_result(Result result) { result_ = result; }
+
+ // Adds |frame| as an expectation of future |RecordInputDataFrame| call.
+ void AddFrameToBeInput(const WebSocketFrame* frame) {
+ if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode))
+ return;
+ frames_to_be_input_.push_back(frame);
+ }
+ // Verifies that |frame| is recorded in order.
+ void VerifySentFrame(const WebSocketFrame* frame) {
+ if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode))
+ return;
+ if (frames_written_.empty()) {
+ ADD_FAILURE() << "There are missing frames to be written.";
+ return;
+ }
+ if (frame != frames_written_.front()) {
+ ADD_FAILURE() << "Written data frame does not match the expectation.";
+ return;
+ }
+ frames_written_.pop_front();
+ }
+ void AddFramesToBeInput(const ScopedVector<WebSocketFrame>& frames) {
+ for (size_t i = 0; i < frames.size(); ++i)
+ AddFrameToBeInput(frames[i]);
+ }
+ void VerifySentFrames(const ScopedVector<WebSocketFrame>& frames) {
+ for (size_t i = 0; i < frames.size(); ++i)
+ VerifySentFrame(frames[i]);
+ }
+ // Call this method in order to disable checks in the destructor when
+ // WriteFrames fails.
+ void Clear() {
+ frames_to_be_input_.clear();
+ frames_written_.clear();
+ }
+
+ private:
+ Result result_;
+ // Data frames which will be recorded by |RecordInputFrames|.
+ // Pushed by |AddFrameToBeInput| and popped and verified by
+ // |RecordInputFrames|.
+ std::deque<const WebSocketFrame*> frames_to_be_input_;
+ // Data frames recorded by |RecordWrittenFrames|.
+ // Pushed by |RecordWrittenFrames| and popped and verified by
+ // |VerifySentFrame|.
+ std::deque<const WebSocketFrame*> frames_written_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock);
+};
+
+class WebSocketDeflateStreamTest : public ::testing::Test {
+ public:
+ WebSocketDeflateStreamTest()
+ : mock_stream_(NULL) {
+ mock_stream_ = new testing::StrictMock<MockWebSocketStream>;
+ predictor_ = new WebSocketDeflatePredictorMock;
+ deflate_stream_.reset(new WebSocketDeflateStream(
+ scoped_ptr<WebSocketStream>(mock_stream_),
+ WebSocketDeflater::TAKE_OVER_CONTEXT,
+ scoped_ptr<WebSocketDeflatePredictor>(predictor_)));
+ }
+ virtual ~WebSocketDeflateStreamTest() {}
+
+ protected:
+ scoped_ptr<WebSocketDeflateStream> deflate_stream_;
+ // Owned by |deflate_stream_|.
+ MockWebSocketStream* mock_stream_;
+ // Owned by |deflate_stream_|.
+ WebSocketDeflatePredictorMock* predictor_;
+};
+
+// Since WebSocketDeflater with DoNotTakeOverContext is well tested at
+// websocket_deflater_test.cc, we have only a few tests for this configuration
+// here.
+class WebSocketDeflateStreamWithDoNotTakeOverContextTest
+ : public ::testing::Test {
+ public:
+ WebSocketDeflateStreamWithDoNotTakeOverContextTest()
+ : mock_stream_(NULL) {
+ mock_stream_ = new testing::StrictMock<MockWebSocketStream>;
+ predictor_ = new WebSocketDeflatePredictorMock;
+ deflate_stream_.reset(new WebSocketDeflateStream(
+ scoped_ptr<WebSocketStream>(mock_stream_),
+ WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT,
+ scoped_ptr<WebSocketDeflatePredictor>(predictor_)));
+ }
+ virtual ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() {}
+
+ protected:
+ scoped_ptr<WebSocketDeflateStream> deflate_stream_;
+ // |mock_stream_| will be deleted when |deflate_stream_| is destroyed.
+ MockWebSocketStream* mock_stream_;
+ // |predictor_| will be deleted when |deflate_stream_| is destroyed.
+ WebSocketDeflatePredictorMock* predictor_;
+};
+
+// ReadFrameStub is a stub for WebSocketStream::ReadFrames.
+// It returns |result_| and |frames_to_output_| to the caller and
+// saves parameters to |frames_passed_| and |callback_|.
+class ReadFramesStub {
+ public:
+ explicit ReadFramesStub(int result) : result_(result) {}
+
+ ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output)
+ : result_(result) {
+ frames_to_output_.swap(*frames_to_output);
+ }
+
+ int Call(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
+ DCHECK(frames->empty());
+ frames_passed_ = frames;
+ callback_ = callback;
+ frames->swap(frames_to_output_);
+ return result_;
+ }
+
+ int result() const { return result_; }
+ const CompletionCallback callback() const { return callback_; }
+ ScopedVector<WebSocketFrame>* frames_passed() {
+ return frames_passed_;
+ }
+
+ private:
+ int result_;
+ CompletionCallback callback_;
+ ScopedVector<WebSocketFrame> frames_to_output_;
+ ScopedVector<WebSocketFrame>* frames_passed_;
+};
+
+// WriteFramesStub is a stub for WebSocketStream::WriteFrames.
+// It returns |result_| and |frames_| to the caller and
+// saves |callback| parameter to |callback_|.
+class WriteFramesStub {
+ public:
+ explicit WriteFramesStub(WebSocketDeflatePredictorMock* predictor,
+ int result)
+ : result_(result), predictor_(predictor) {}
+
+ int Call(ScopedVector<WebSocketFrame>* frames,
+ const CompletionCallback& callback) {
+ frames_.insert(frames_.end(), frames->begin(), frames->end());
+ frames->weak_clear();
+ callback_ = callback;
+ predictor_->VerifySentFrames(frames_);
+ return result_;
+ }
+
+ int result() const { return result_; }
+ const CompletionCallback callback() const { return callback_; }
+ ScopedVector<WebSocketFrame>* frames() { return &frames_; }
+
+ private:
+ int result_;
+ CompletionCallback callback_;
+ ScopedVector<WebSocketFrame> frames_;
+ WebSocketDeflatePredictorMock* predictor_;
+};
+
+TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) {
+ ScopedVector<WebSocketFrame> frames;
+ CompletionCallback callback;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Return(ERR_FAILED));
+ }
+ EXPECT_EQ(ERR_FAILED, deflate_stream_->ReadFrames(&frames, callback));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameImmediately) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "hello");
+ ReadFramesStub stub(OK, &frames_to_output);
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ CompletionCallback callback;
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) {
+ ReadFramesStub stub(ERR_IO_PENDING);
+ ScopedVector<WebSocketFrame> frames;
+ MockCallback mock_callback, checkpoint;
+ CompletionCallback callback =
+ base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(mock_callback, Call(OK));
+ }
+ ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(0u, frames.size());
+
+ checkpoint.Call(0);
+
+ AppendTo(stub.frames_passed(),
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "hello");
+ stub.callback().Run(OK);
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) {
+ ReadFramesStub stub(ERR_IO_PENDING);
+ ScopedVector<WebSocketFrame> frames;
+ MockCallback mock_callback, checkpoint;
+ CompletionCallback callback =
+ base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(mock_callback, Call(ERR_FAILED));
+ }
+ ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(0u, frames.size());
+
+ checkpoint.Call(0);
+
+ AppendTo(stub.frames_passed(),
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "hello");
+ stub.callback().Run(ERR_FAILED);
+ ASSERT_EQ(0u, frames.size());
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameImmediately) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("Hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) {
+ ReadFramesStub stub(ERR_IO_PENDING);
+ MockCallback mock_callback, checkpoint;
+ CompletionCallback callback =
+ base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ ScopedVector<WebSocketFrame> frames;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(mock_callback, Call(OK));
+ }
+ ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
+
+ checkpoint.Call(0);
+
+ AppendTo(stub.frames_passed(),
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ stub.callback().Run(OK);
+
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("Hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest,
+ ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ const std::string data1("\xf2", 1);
+ const std::string data2("\x48\xcd\xc9\xc9\x07\x00", 6);
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kReserved1,
+ data1);
+ ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING);
+ MockCallback mock_callback, checkpoint;
+ CompletionCallback callback =
+ base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub1, &ReadFramesStub::Call))
+ .WillOnce(Invoke(&stub2, &ReadFramesStub::Call));
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(mock_callback, Call(OK));
+ }
+ ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(0u, frames.size());
+
+ AppendTo(stub2.frames_passed(),
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ data2);
+
+ checkpoint.Call(0);
+ stub2.callback().Run(OK);
+
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("Hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadInvalidCompressedPayload) {
+ const std::string data("\xf2\x48\xcdINVALID", 10);
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ data);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
+ deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(0u, frames.size());
+}
+
+TEST_F(WebSocketDeflateStreamTest, MergeMultipleFramesInReadFrames) {
+ const std::string data1("\xf2\x48\xcd", 3);
+ const std::string data2("\xc9\xc9\x07\x00", 4);
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kReserved1,
+ data1);
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeContinuation,
+ kFinal,
+ data2);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("Hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadUncompressedEmptyFrames) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kNoFlag);
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeContinuation,
+ kFinal);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(2u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_FALSE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("", ToString(frames[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames[1]->header.opcode);
+ EXPECT_TRUE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ("", ToString(frames[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadCompressedEmptyFrames) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kReserved1,
+ std::string("\x02\x00", 1));
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeContinuation,
+ kFinal);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest,
+ ReadCompressedFrameFollowedByEmptyFrame) {
+ const std::string data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kReserved1,
+ data);
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeContinuation,
+ kFinal);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(1u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("Hello", ToString(frames[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadControlFrameBetweenDataFrames) {
+ const std::string data1("\xf2\x48\xcd", 3);
+ const std::string data2("\xc9\xc9\x07\x00", 4);
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kReserved1,
+ data1);
+ AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodePing, kFinal);
+ AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodeText, kFinal, data2);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(2u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
+ EXPECT_TRUE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ("Hello", ToString(frames[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, SplitToMultipleFramesInReadFrames) {
+ WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
+ deflater.Initialize(kWindowBits);
+ const size_t kSize = kChunkSize * 3;
+ const std::string original_data(kSize, 'a');
+ deflater.AddBytes(original_data.data(), original_data.size());
+ deflater.Finish();
+
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeBinary,
+ kFinal | kReserved1,
+ ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
+
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(3u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
+ EXPECT_FALSE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames[1]->header.opcode);
+ EXPECT_FALSE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[1]->header.payload_length));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames[2]->header.opcode);
+ EXPECT_TRUE(frames[2]->header.final);
+ EXPECT_FALSE(frames[2]->header.reserved1);
+ EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[2]->header.payload_length));
+ EXPECT_EQ(original_data,
+ ToString(frames[0]) + ToString(frames[1]) + ToString(frames[2]));
+}
+
+TEST_F(WebSocketDeflateStreamTest,
+ Reserved1TurnsOnDuringReadingCompressedContinuationFrame) {
+ const std::string data1("\xf2\x48\xcd", 3);
+ const std::string data2("\xc9\xc9\x07\x00", 4);
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kReserved1,
+ data1);
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeContinuation,
+ kFinal | kReserved1,
+ data2);
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
+ deflate_stream_->ReadFrames(&frames, callback));
+}
+
+TEST_F(WebSocketDeflateStreamTest,
+ Reserved1TurnsOnDuringReadingUncompressedContinuationFrame) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kNoFlag,
+ "hello");
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeContinuation,
+ kFinal | kReserved1,
+ "world");
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
+ deflate_stream_->ReadFrames(&frames, callback));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ std::string(
+ "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13));
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ std::string("\x4a\x86\x33\x8d\x00\x00", 6));
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(2u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("compressed1", ToString(frames[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
+ EXPECT_TRUE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ("compressed2", ToString(frames[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, ReadUncompressedMessages) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "uncompressed1");
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "uncompressed2");
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(2u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("uncompressed1", ToString(frames[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
+ EXPECT_TRUE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ("uncompressed2", ToString(frames[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest,
+ ReadCompressedMessageThenUncompressedMessage) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ std::string(
+ "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "uncompressed");
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(2u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("compressed", ToString(frames[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
+ EXPECT_TRUE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ("uncompressed", ToString(frames[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest,
+ ReadUncompressedMessageThenCompressedMessage) {
+ ScopedVector<WebSocketFrame> frames_to_output;
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal,
+ "uncompressed");
+ AppendTo(&frames_to_output,
+ WebSocketFrameHeader::kOpCodeText,
+ kFinal | kReserved1,
+ std::string(
+ "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
+ ReadFramesStub stub(OK, &frames_to_output);
+ CompletionCallback callback;
+ ScopedVector<WebSocketFrame> frames;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback));
+ ASSERT_EQ(2u, frames.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
+ EXPECT_TRUE(frames[0]->header.final);
+ EXPECT_FALSE(frames[0]->header.reserved1);
+ EXPECT_EQ("uncompressed", ToString(frames[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode);
+ EXPECT_TRUE(frames[1]->header.final);
+ EXPECT_FALSE(frames[1]->header.reserved1);
+ EXPECT_EQ("compressed", ToString(frames[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteEmpty) {
+ ScopedVector<WebSocketFrame> frames;
+ CompletionCallback callback;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0);
+ }
+ EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) {
+ ScopedVector<WebSocketFrame> frames;
+ CompletionCallback callback;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Return(ERR_FAILED));
+ }
+
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello");
+ predictor_->AddFramesToBeInput(frames);
+ EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback));
+ predictor_->Clear();
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) {
+ ScopedVector<WebSocketFrame> frames;
+ CompletionCallback callback;
+ WriteFramesStub stub(predictor_, OK);
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
+ predictor_->AddFramesToBeInput(frames);
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(1u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_TRUE(frames_passed[0]->header.final);
+ EXPECT_TRUE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
+ ToString(frames_passed[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) {
+ WriteFramesStub stub(predictor_, ERR_IO_PENDING);
+ MockCallback mock_callback, checkpoint;
+ CompletionCallback callback =
+ base::Bind(&MockCallback::Call, base::Unretained(&mock_callback));
+ ScopedVector<WebSocketFrame> frames;
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ EXPECT_CALL(checkpoint, Call(0));
+ EXPECT_CALL(mock_callback, Call(OK));
+ }
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
+ predictor_->AddFramesToBeInput(frames);
+ ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback));
+
+ checkpoint.Call(0);
+ stub.callback().Run(OK);
+
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(1u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_TRUE(frames_passed[0]->header.final);
+ EXPECT_TRUE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
+ ToString(frames_passed[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteControlFrameBetweenDataFrames) {
+ ScopedVector<WebSocketFrame> frames;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "Hel");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodePing, kFinal);
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo");
+ predictor_->AddFramesToBeInput(frames);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(2u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames_passed[0]->header.opcode);
+ EXPECT_TRUE(frames_passed[0]->header.final);
+ EXPECT_FALSE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
+ EXPECT_TRUE(frames_passed[1]->header.final);
+ EXPECT_TRUE(frames_passed[1]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
+ ToString(frames_passed[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteEmptyMessage) {
+ ScopedVector<WebSocketFrame> frames;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal);
+ predictor_->AddFramesToBeInput(frames);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(1u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_TRUE(frames_passed[0]->header.final);
+ EXPECT_TRUE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ(std::string("\x02\x00", 2), ToString(frames_passed[0]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteUncompressedMessage) {
+ ScopedVector<WebSocketFrame> frames;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAA");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA");
+ predictor_->AddFramesToBeInput(frames);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+
+ predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(2u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_FALSE(frames_passed[0]->header.final);
+ EXPECT_FALSE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ("AAAA", ToString(frames_passed[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames_passed[1]->header.opcode);
+ EXPECT_TRUE(frames_passed[1]->header.final);
+ EXPECT_FALSE(frames_passed[1]->header.reserved1);
+ EXPECT_EQ("AAA", ToString(frames_passed[1]));
+}
+
+TEST_F(WebSocketDeflateStreamTest, LargeDeflatedFramesShouldBeSplit) {
+ WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
+ LinearCongruentialGenerator lcg(133);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+ const size_t size = 1024;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+ .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ScopedVector<WebSocketFrame> total_compressed_frames;
+
+ deflater.Initialize(kWindowBits);
+ while (true) {
+ bool is_final = (total_compressed_frames.size() >= 2);
+ ScopedVector<WebSocketFrame> frames;
+ std::string data;
+ for (size_t i = 0; i < size; ++i)
+ data += static_cast<char>(lcg.Generate());
+ deflater.AddBytes(data.data(), data.size());
+ FrameFlag flag = is_final ? kFinal : kNoFlag;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data);
+ predictor_->AddFramesToBeInput(frames);
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ total_compressed_frames.insert(total_compressed_frames.end(),
+ stub.frames()->begin(),
+ stub.frames()->end());
+ stub.frames()->weak_clear();
+ if (is_final)
+ break;
+ }
+ deflater.Finish();
+ std::string total_deflated;
+ for (size_t i = 0; i < total_compressed_frames.size(); ++i) {
+ WebSocketFrame* frame = total_compressed_frames[i];
+ const WebSocketFrameHeader& header = frame->header;
+ if (i > 0) {
+ EXPECT_EQ(header.kOpCodeContinuation, header.opcode);
+ EXPECT_FALSE(header.reserved1);
+ } else {
+ EXPECT_EQ(header.kOpCodeBinary, header.opcode);
+ EXPECT_TRUE(header.reserved1);
+ }
+ const bool is_final_frame = (i + 1 == total_compressed_frames.size());
+ EXPECT_EQ(is_final_frame, header.final);
+ if (!is_final_frame)
+ EXPECT_GT(header.payload_length, 0ul);
+ total_deflated += ToString(frame);
+ }
+ EXPECT_EQ(total_deflated,
+ ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
+}
+
+TEST_F(WebSocketDeflateStreamTest, WriteMultipleMessages) {
+ ScopedVector<WebSocketFrame> frames;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
+ predictor_->AddFramesToBeInput(frames);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(2u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_TRUE(frames_passed[0]->header.final);
+ EXPECT_TRUE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
+ ToString(frames_passed[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
+ EXPECT_TRUE(frames_passed[1]->header.final);
+ EXPECT_TRUE(frames_passed[1]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed[1]));
+}
+
+TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
+ WriteMultipleMessages) {
+ ScopedVector<WebSocketFrame> frames;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
+ predictor_->AddFramesToBeInput(frames);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(2u, frames_passed.size());
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_TRUE(frames_passed[0]->header.final);
+ EXPECT_TRUE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
+ ToString(frames_passed[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode);
+ EXPECT_TRUE(frames_passed[1]->header.final);
+ EXPECT_TRUE(frames_passed[1]->header.reserved1);
+ EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7),
+ ToString(frames_passed[1]));
+}
+
+// In order to check the stream works correctly for multiple
+// "PossiblyCompressedMessage"s, we test various messages at one test case.
+TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest,
+ WritePossiblyCompressMessages) {
+ ScopedVector<WebSocketFrame> frames;
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "He");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "llo");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAAAAAAAA");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AA");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "XX");
+ AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY");
+ predictor_->AddFramesToBeInput(frames);
+ WriteFramesStub stub(predictor_, OK);
+ CompletionCallback callback;
+ predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE);
+
+ {
+ InSequence s;
+ EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+ .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
+ }
+ ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback));
+ const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames();
+ ASSERT_EQ(5u, frames_passed.size());
+
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode);
+ EXPECT_FALSE(frames_passed[0]->header.final);
+ EXPECT_FALSE(frames_passed[0]->header.reserved1);
+ EXPECT_EQ("He", ToString(frames_passed[0]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames_passed[1]->header.opcode);
+ EXPECT_TRUE(frames_passed[1]->header.final);
+ EXPECT_FALSE(frames_passed[1]->header.reserved1);
+ EXPECT_EQ("llo", ToString(frames_passed[1]));
+
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[2]->header.opcode);
+ EXPECT_TRUE(frames_passed[2]->header.final);
+ EXPECT_TRUE(frames_passed[2]->header.reserved1);
+ EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6),
+ ToString(frames_passed[2]));
+
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[3]->header.opcode);
+ EXPECT_FALSE(frames_passed[3]->header.final);
+ EXPECT_FALSE(frames_passed[3]->header.reserved1);
+ EXPECT_EQ("XX", ToString(frames_passed[3]));
+ EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
+ frames_passed[4]->header.opcode);
+ EXPECT_TRUE(frames_passed[4]->header.final);
+ EXPECT_FALSE(frames_passed[4]->header.reserved1);
+ EXPECT_EQ("YY", ToString(frames_passed[4]));
+}
+
+} // namespace
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_deflater.cc b/chromium/net/websockets/websocket_deflater.cc
index c5a4e6a31f1..41d13e86870 100644
--- a/chromium/net/websockets/websocket_deflater.cc
+++ b/chromium/net/websockets/websocket_deflater.cc
@@ -120,7 +120,7 @@ int WebSocketDeflater::Deflate(int flush) {
stream_->avail_out = fixed_buffer_.size();
result = deflate(stream_.get(), flush);
size_t size = fixed_buffer_.size() - stream_->avail_out;
- buffer_.insert(buffer_.end(), &fixed_buffer_[0], &fixed_buffer_[size]);
+ buffer_.insert(buffer_.end(), &fixed_buffer_[0], &fixed_buffer_[0] + size);
} while (result == Z_OK);
return result;
}
diff --git a/chromium/net/websockets/websocket_event_interface.h b/chromium/net/websockets/websocket_event_interface.h
index 7eb54bf8b15..baba88ce012 100644
--- a/chromium/net/websockets/websocket_event_interface.h
+++ b/chromium/net/websockets/websocket_event_interface.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/compiler_specific.h" // for WARN_UNUSED_RESULT
#include "net/base/net_export.h"
namespace net {
@@ -18,35 +19,41 @@ namespace net {
class NET_EXPORT WebSocketEventInterface {
public:
typedef int WebSocketMessageType;
+
+ // Any event can cause the Channel to be deleted. The Channel needs to avoid
+ // doing further processing in this case. It does not need to do cleanup, as
+ // cleanup will already have been done as a result of the deletion.
+ enum ChannelState {
+ CHANNEL_ALIVE,
+ CHANNEL_DELETED
+ };
+
virtual ~WebSocketEventInterface() {}
// Called in response to an AddChannelRequest. This generally means that a
// response has been received from the remote server, but the response might
// have been generated internally. If |fail| is true, the channel cannot be
- // used and it is valid to delete the WebSocketChannel from within this
- // callback.
- virtual void OnAddChannelResponse(
+ // used and should be deleted, returning CHANNEL_DELETED.
+ virtual ChannelState OnAddChannelResponse(
bool fail,
- const std::string& selected_subprotocol) = 0;
+ const std::string& selected_subprotocol) WARN_UNUSED_RESULT = 0;
// Called when a data frame has been received from the remote host and needs
- // to be forwarded to the renderer process. It is not safe to delete the
- // WebSocketChannel object from within this callback.
- virtual void OnDataFrame(bool fin,
- WebSocketMessageType type,
- const std::vector<char>& data) = 0;
+ // to be forwarded to the renderer process.
+ virtual ChannelState OnDataFrame(
+ bool fin,
+ WebSocketMessageType type,
+ const std::vector<char>& data) WARN_UNUSED_RESULT = 0;
// Called to provide more send quota for this channel to the renderer
// process. Currently the quota units are always bytes of message body
- // data. In future it might depend on the type of multiplexing in use. It is
- // not safe to delete the WebSocketChannel from within this callback.
- virtual void OnFlowControl(int64 quota) = 0;
+ // data. In future it might depend on the type of multiplexing in use.
+ virtual ChannelState OnFlowControl(int64 quota) WARN_UNUSED_RESULT = 0;
// Called when the remote server has Started the WebSocket Closing
// Handshake. The client should not attempt to send any more messages after
// receiving this message. It will be followed by OnDropChannel() when the
- // closing handshake is complete. It is not safe to delete the
- // WebSocketChannel from within this callback.
- virtual void OnClosingHandshake() = 0;
+ // closing handshake is complete.
+ virtual ChannelState OnClosingHandshake() WARN_UNUSED_RESULT = 0;
// Called when the channel has been dropped, either due to a network close, a
// network error, or a protocol error. This may or may not be preceeded by a
@@ -59,10 +66,10 @@ class NET_EXPORT WebSocketEventInterface {
// The channel should not be used again after OnDropChannel() has been
// called.
//
- // It is not safe to delete the WebSocketChannel from within this
- // callback. It is recommended to delete the channel after returning to the
- // event loop.
- virtual void OnDropChannel(uint16 code, const std::string& reason) = 0;
+ // This method returns a ChannelState for consistency, but all implementations
+ // must delete the Channel and return CHANNEL_DELETED.
+ virtual ChannelState OnDropChannel(uint16 code, const std::string& reason)
+ WARN_UNUSED_RESULT = 0;
protected:
WebSocketEventInterface() {}
diff --git a/chromium/net/websockets/websocket_frame.cc b/chromium/net/websockets/websocket_frame.cc
index f05b5b76152..763712a6f57 100644
--- a/chromium/net/websockets/websocket_frame.cc
+++ b/chromium/net/websockets/websocket_frame.cc
@@ -41,18 +41,27 @@ inline void MaskWebSocketFramePayloadByBytes(
namespace net {
-scoped_ptr<WebSocketFrameHeader> WebSocketFrameHeader::Clone() {
+scoped_ptr<WebSocketFrameHeader> WebSocketFrameHeader::Clone() const {
scoped_ptr<WebSocketFrameHeader> ret(new WebSocketFrameHeader(opcode));
- ret->final = final;
- ret->reserved1 = reserved1;
- ret->reserved2 = reserved2;
- ret->reserved3 = reserved3;
- ret->opcode = opcode;
- ret->masked = masked;
- ret->payload_length = payload_length;
+ ret->CopyFrom(*this);
return ret.Pass();
}
+void WebSocketFrameHeader::CopyFrom(const WebSocketFrameHeader& source) {
+ final = source.final;
+ reserved1 = source.reserved1;
+ reserved2 = source.reserved2;
+ reserved3 = source.reserved3;
+ opcode = source.opcode;
+ masked = source.masked;
+ payload_length = source.payload_length;
+}
+
+WebSocketFrame::WebSocketFrame(WebSocketFrameHeader::OpCode opcode)
+ : header(opcode) {}
+
+WebSocketFrame::~WebSocketFrame() {}
+
WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) {}
WebSocketFrameChunk::~WebSocketFrameChunk() {}
@@ -195,7 +204,7 @@ void MaskWebSocketFramePayload(const WebSocketMaskingKey& masking_key,
// Create a version of the mask which is rotated by the appropriate offset
// for our alignment. The "trick" here is that 0 XORed with the mask will
// give the value of the mask for the appropriate byte.
- char realigned_mask[kMaskingKeyLength] = { 0 };
+ char realigned_mask[kMaskingKeyLength] = {};
MaskWebSocketFramePayloadByBytes(
masking_key,
(frame_offset + aligned_begin - data) % kMaskingKeyLength,
diff --git a/chromium/net/websockets/websocket_frame.h b/chromium/net/websockets/websocket_frame.h
index 8c04f7dce44..c9d8b976926 100644
--- a/chromium/net/websockets/websocket_frame.h
+++ b/chromium/net/websockets/websocket_frame.h
@@ -14,6 +14,7 @@
namespace net {
+class IOBuffer;
class IOBufferWithSize;
// Represents a WebSocket frame header.
@@ -69,7 +70,10 @@ struct NET_EXPORT WebSocketFrameHeader {
payload_length(0) {}
// Create a clone of this object on the heap.
- scoped_ptr<WebSocketFrameHeader> Clone();
+ scoped_ptr<WebSocketFrameHeader> Clone() const;
+
+ // Overwrite this object with the fields from |source|.
+ void CopyFrom(const WebSocketFrameHeader& source);
// Members below correspond to each item in WebSocket frame header.
// See <http://tools.ietf.org/html/rfc6455#section-5.2> for details.
@@ -85,16 +89,32 @@ struct NET_EXPORT WebSocketFrameHeader {
DISALLOW_COPY_AND_ASSIGN(WebSocketFrameHeader);
};
-// Contains payload data of part of a WebSocket frame.
+// Contains an entire WebSocket frame including payload. This is used by APIs
+// that are not concerned about retaining the original frame boundaries (because
+// frames may need to be split in order for the data to fit in memory).
+struct NET_EXPORT_PRIVATE WebSocketFrame {
+ // A frame must always have an opcode, so this parameter is compulsory.
+ explicit WebSocketFrame(WebSocketFrameHeader::OpCode opcode);
+ ~WebSocketFrame();
+
+ // |header| is always present.
+ WebSocketFrameHeader header;
+
+ // |data| is always unmasked even if the frame is masked. The size of |data|
+ // is given by |header.payload_length|.
+ scoped_refptr<IOBuffer> data;
+};
+
+// Structure describing one chunk of a WebSocket frame.
//
-// Payload of a WebSocket frame may be divided into multiple chunks.
+// The payload of a WebSocket frame may be divided into multiple chunks.
// You need to look at |final_chunk| member variable to detect the end of a
// series of chunk objects of a WebSocket frame.
//
-// Frame dissection is necessary to handle WebSocket frame stream containing
-// abritrarily large frames in the browser process. Because the server may send
-// a huge frame that doesn't fit in the memory, we cannot store the entire
-// payload data in the memory.
+// Frame dissection is necessary to handle frames that are too large to store in
+// the browser memory without losing information about the frame boundaries. In
+// practice, most code does not need to worry about the original frame
+// boundaries and can use the WebSocketFrame type declared above.
//
// Users of this struct should treat WebSocket frames as a data stream; it's
// important to keep the frame data flowing, especially in the browser process.
diff --git a/chromium/net/websockets/websocket_handshake_constants.cc b/chromium/net/websockets/websocket_handshake_constants.cc
index 357b1349ae9..dc670aa3636 100644
--- a/chromium/net/websockets/websocket_handshake_constants.cc
+++ b/chromium/net/websockets/websocket_handshake_constants.cc
@@ -17,6 +17,8 @@ const char* const kSecWebSocketKey = "Sec-WebSocket-Key";
const char* const kSecWebSocketAccept = "Sec-WebSocket-Accept";
const char* const kSecWebSocketVersion = "Sec-WebSocket-Version";
+const char* const kSupportedVersion = "13";
+
const char* const kUpgrade = "Upgrade";
const char* const kWebSocketGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
diff --git a/chromium/net/websockets/websocket_handshake_constants.h b/chromium/net/websockets/websocket_handshake_constants.h
index 0cf67a8ac7f..43d3efda0f8 100644
--- a/chromium/net/websockets/websocket_handshake_constants.h
+++ b/chromium/net/websockets/websocket_handshake_constants.h
@@ -42,6 +42,11 @@ extern const char* const kSecWebSocketAccept;
// "Sec-WebSocket-Version"
extern const char* const kSecWebSocketVersion;
+// This implementation only supports one version of the WebSocket protocol,
+// "13", as specified in RFC6455. If support for multiple versions is added in
+// future, it will probably no longer be worth having a constant for this.
+extern const char* const kSupportedVersion;
+
// "Upgrade"
extern const char* const kUpgrade;
diff --git a/chromium/net/websockets/websocket_handshake_handler.cc b/chromium/net/websockets/websocket_handshake_handler.cc
index e5b66418afe..787dde682e7 100644
--- a/chromium/net/websockets/websocket_handshake_handler.cc
+++ b/chromium/net/websockets/websocket_handshake_handler.cc
@@ -7,7 +7,6 @@
#include <limits>
#include "base/base64.h"
-#include "base/md5.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
@@ -23,25 +22,23 @@
namespace net {
namespace {
-const size_t kRequestKey3Size = 8U;
-const size_t kResponseKeySize = 16U;
-
-// First version that introduced new WebSocket handshake which does not
-// require sending "key3" or "response key" data after headers.
-const int kMinVersionOfHybiNewHandshake = 4;
+const int kVersionHeaderValueForRFC6455 = 13;
+// Splits |handshake_message| into Status-Line or Request-Line (including CRLF)
+// and headers (excluding 2nd CRLF of double CRLFs at the end of a handshake
+// response).
void ParseHandshakeHeader(
const char* handshake_message, int len,
- std::string* status_line,
+ std::string* request_line,
std::string* headers) {
size_t i = base::StringPiece(handshake_message, len).find_first_of("\r\n");
if (i == base::StringPiece::npos) {
- *status_line = std::string(handshake_message, len);
+ *request_line = std::string(handshake_message, len);
*headers = "";
return;
}
- // |status_line| includes \r\n.
- *status_line = std::string(handshake_message, i + 2);
+ // |request_line| includes \r\n.
+ *request_line = std::string(handshake_message, i + 2);
int header_len = len - (i + 2) - 2;
if (header_len > 0) {
@@ -115,19 +112,21 @@ std::string FilterHeaders(
return filtered_headers;
}
-int GetVersionFromRequest(const std::string& request_headers) {
+bool CheckVersionInRequest(const std::string& request_headers) {
std::vector<std::string> values;
- const char* const headers_to_get[2] = {
- websockets::kSecWebSocketVersionLowercase, "sec-websocket-draft"};
- FetchHeaders(request_headers, headers_to_get, 2, &values);
+ const char* const headers_to_get[1] = {
+ websockets::kSecWebSocketVersionLowercase};
+ FetchHeaders(request_headers, headers_to_get, 1, &values);
DCHECK_LE(values.size(), 1U);
if (values.empty())
- return 0;
+ return false;
+
int version;
bool conversion_success = base::StringToInt(values[0], &version);
- DCHECK(conversion_success);
- DCHECK_GE(version, 1);
- return version;
+ if (!conversion_success)
+ return false;
+
+ return version == kVersionHeaderValueForRFC6455;
}
// Append a header to a string. Equivalent to
@@ -152,44 +151,9 @@ void AppendHeader(const base::StringPiece& header,
} // namespace
-namespace internal {
-
-void GetKeyNumber(const std::string& key, std::string* challenge) {
- uint32 key_number = 0;
- uint32 spaces = 0;
- for (size_t i = 0; i < key.size(); ++i) {
- if (isdigit(key[i])) {
- // key_number should not overflow. (it comes from
- // WebCore/websockets/WebSocketHandshake.cpp).
- // Trust, but verify.
- DCHECK_GE((std::numeric_limits<uint32>::max() - (key[i] - '0')) / 10,
- key_number) << "Supplied key would overflow";
- key_number = key_number * 10 + key[i] - '0';
- } else if (key[i] == ' ') {
- ++spaces;
- }
- }
- DCHECK_NE(0u, spaces) << "Key must contain at least one space";
- if (spaces == 0)
- return;
- DCHECK_EQ(0u, key_number % spaces) << "Key number must be an integral "
- << "multiple of the number of spaces";
- key_number /= spaces;
-
- char part[4];
- for (int i = 0; i < 4; i++) {
- part[3 - i] = key_number & 0xFF;
- key_number >>= 8;
- }
- challenge->append(part, 4);
-}
-
-} // namespace internal
-
WebSocketHandshakeRequestHandler::WebSocketHandshakeRequestHandler()
: original_length_(0),
- raw_length_(0),
- protocol_version_(-1) {}
+ raw_length_(0) {}
bool WebSocketHandshakeRequestHandler::ParseRequest(
const char* data, int length) {
@@ -202,32 +166,15 @@ bool WebSocketHandshakeRequestHandler::ParseRequest(
ParseHandshakeHeader(input.data(),
input_header_length,
- &status_line_,
+ &request_line_,
&headers_);
- // WebSocket protocol drafts hixie-76 (hybi-00), hybi-01, 02 and 03 require
- // the clients to send key3 after the handshake request header fields.
- // Hybi-04 and later drafts, on the other hand, no longer have key3
- // in the handshake format.
- protocol_version_ = GetVersionFromRequest(headers_);
- DCHECK_GE(protocol_version_, 0);
- if (protocol_version_ >= kMinVersionOfHybiNewHandshake) {
- key3_ = "";
- original_length_ = input_header_length;
- return true;
- }
-
- if (input_header_length + kRequestKey3Size > input.size())
+ if (!CheckVersionInRequest(headers_)) {
+ NOTREACHED();
return false;
+ }
- // Assumes WebKit doesn't send any data after handshake request message
- // until handshake is finished.
- // Thus, |key3_| is part of handshake message, and not in part
- // of WebSocket frame stream.
- DCHECK_EQ(kRequestKey3Size, input.size() - input_header_length);
- key3_ = std::string(input.data() + input_header_length,
- input.size() - input_header_length);
- original_length_ = input.size();
+ original_length_ = input_header_length;
return true;
}
@@ -253,9 +200,9 @@ HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo(
const GURL& url, std::string* challenge) {
HttpRequestInfo request_info;
request_info.url = url;
- size_t method_end = base::StringPiece(status_line_).find_first_of(" ");
+ size_t method_end = base::StringPiece(request_line_).find_first_of(" ");
if (method_end != base::StringPiece::npos)
- request_info.method = std::string(status_line_.data(), method_end);
+ request_info.method = std::string(request_line_.data(), method_end);
request_info.extra_headers.Clear();
request_info.extra_headers.AddHeadersFromString(headers_);
@@ -263,31 +210,12 @@ HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo(
request_info.extra_headers.RemoveHeader(websockets::kUpgrade);
request_info.extra_headers.RemoveHeader(HttpRequestHeaders::kConnection);
- if (protocol_version_ >= kMinVersionOfHybiNewHandshake) {
- std::string key;
- bool header_present = request_info.extra_headers.GetHeader(
- websockets::kSecWebSocketKey, &key);
- DCHECK(header_present);
- request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey);
- *challenge = key;
- } else {
- challenge->clear();
- std::string key;
- bool header_present =
- request_info.extra_headers.GetHeader("Sec-WebSocket-Key1", &key);
- DCHECK(header_present);
- request_info.extra_headers.RemoveHeader("Sec-WebSocket-Key1");
- internal::GetKeyNumber(key, challenge);
-
- header_present =
- request_info.extra_headers.GetHeader("Sec-WebSocket-Key2", &key);
- DCHECK(header_present);
- request_info.extra_headers.RemoveHeader("Sec-WebSocket-Key2");
- internal::GetKeyNumber(key, challenge);
-
- challenge->append(key3_);
- }
-
+ std::string key;
+ bool header_present = request_info.extra_headers.GetHeader(
+ websockets::kSecWebSocketKey, &key);
+ DCHECK(header_present);
+ request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey);
+ *challenge = key;
return request_info;
}
@@ -300,13 +228,11 @@ bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
// For details, see WebSocket Layering over SPDY/3 Draft 8.
if (spdy_protocol_version <= 2) {
(*headers)["path"] = url.path();
- (*headers)["version"] =
- base::StringPrintf("%s%d", "WebSocket/", protocol_version_);
+ (*headers)["version"] = "WebSocket/13";
(*headers)["scheme"] = url.scheme();
} else {
(*headers)[":path"] = url.path();
- (*headers)[":version"] =
- base::StringPrintf("%s%d", "WebSocket/", protocol_version_);
+ (*headers)[":version"] = "WebSocket/13";
(*headers)[":scheme"] = url.scheme();
}
@@ -366,11 +292,10 @@ bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
}
std::string WebSocketHandshakeRequestHandler::GetRawRequest() {
- DCHECK(!status_line_.empty());
+ DCHECK(!request_line_.empty());
DCHECK(!headers_.empty());
- // The following works on both hybi-04 and older handshake,
- // because |key3_| is guaranteed to be empty if the handshake was hybi-04's.
- std::string raw_request = status_line_ + headers_ + "\r\n" + key3_;
+
+ std::string raw_request = request_line_ + headers_ + "\r\n";
raw_length_ = raw_request.size();
return raw_request;
}
@@ -380,34 +305,18 @@ size_t WebSocketHandshakeRequestHandler::raw_length() const {
return raw_length_;
}
-int WebSocketHandshakeRequestHandler::protocol_version() const {
- DCHECK_GE(protocol_version_, 0);
- return protocol_version_;
-}
-
WebSocketHandshakeResponseHandler::WebSocketHandshakeResponseHandler()
- : original_header_length_(0),
- protocol_version_(0) {}
+ : original_header_length_(0) {}
WebSocketHandshakeResponseHandler::~WebSocketHandshakeResponseHandler() {}
-int WebSocketHandshakeResponseHandler::protocol_version() const {
- DCHECK_GE(protocol_version_, 0);
- return protocol_version_;
-}
-
-void WebSocketHandshakeResponseHandler::set_protocol_version(
- int protocol_version) {
- DCHECK_GE(protocol_version, 0);
- protocol_version_ = protocol_version;
-}
-
size_t WebSocketHandshakeResponseHandler::ParseRawResponse(
const char* data, int length) {
DCHECK_GT(length, 0);
if (HasResponse()) {
DCHECK(!status_line_.empty());
// headers_ might be empty for wrong response from server.
+
return 0;
}
@@ -428,14 +337,21 @@ size_t WebSocketHandshakeResponseHandler::ParseRawResponse(
DCHECK_GE(original_header_length_, header_size);
header_separator_ = std::string(original_.data() + header_size,
original_header_length_ - header_size);
- key_ = std::string(original_.data() + original_header_length_,
- GetResponseKeySize());
- return original_header_length_ + GetResponseKeySize() - old_original_length;
+ return original_header_length_ - old_original_length;
}
bool WebSocketHandshakeResponseHandler::HasResponse() const {
return original_header_length_ > 0 &&
- original_header_length_ + GetResponseKeySize() <= original_.size();
+ static_cast<size_t>(original_header_length_) <= original_.size();
+}
+
+void ComputeSecWebSocketAccept(const std::string& key,
+ std::string* accept) {
+ DCHECK(accept);
+
+ std::string hash =
+ base::SHA1HashString(key + websockets::kWebSocketGuid);
+ base::Base64Encode(hash, accept);
}
bool WebSocketHandshakeResponseHandler::ParseResponseInfo(
@@ -448,24 +364,18 @@ bool WebSocketHandshakeResponseHandler::ParseResponseInfo(
std::string response_message;
response_message = response_info.headers->GetStatusLine();
response_message += "\r\n";
- if (protocol_version_ >= kMinVersionOfHybiNewHandshake)
- AppendHeader(websockets::kUpgrade,
- websockets::kWebSocketLowercase,
- &response_message);
- else
- AppendHeader(websockets::kUpgrade, "WebSocket", &response_message);
+
+ AppendHeader(websockets::kUpgrade,
+ websockets::kWebSocketLowercase,
+ &response_message);
+
AppendHeader(
HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message);
- if (protocol_version_ >= kMinVersionOfHybiNewHandshake) {
- std::string hash =
- base::SHA1HashString(challenge + websockets::kWebSocketGuid);
- std::string websocket_accept;
- bool encode_success = base::Base64Encode(hash, &websocket_accept);
- DCHECK(encode_success);
- AppendHeader(
- websockets::kSecWebSocketAccept, websocket_accept, &response_message);
- }
+ std::string websocket_accept;
+ ComputeSecWebSocketAccept(challenge, &websocket_accept);
+ AppendHeader(
+ websockets::kSecWebSocketAccept, websocket_accept, &response_message);
void* iter = NULL;
std::string name;
@@ -475,14 +385,6 @@ bool WebSocketHandshakeResponseHandler::ParseResponseInfo(
}
response_message += "\r\n";
- if (protocol_version_ < kMinVersionOfHybiNewHandshake) {
- base::MD5Digest digest;
- base::MD5Sum(challenge.data(), challenge.size(), &digest);
-
- const char* digest_data = reinterpret_cast<char*>(digest.a);
- response_message.append(digest_data, sizeof(digest.a));
- }
-
return ParseRawResponse(response_message.data(),
response_message.size()) == response_message.size();
}
@@ -502,8 +404,7 @@ bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
std::string hash =
base::SHA1HashString(challenge + websockets::kWebSocketGuid);
std::string websocket_accept;
- bool encode_success = base::Base64Encode(hash, &websocket_accept);
- DCHECK(encode_success);
+ base::Base64Encode(hash, &websocket_accept);
std::string response_message = base::StringPrintf(
"%s %s\r\n", websockets::kHttpProtocolVersion, status->second.c_str());
@@ -583,23 +484,15 @@ void WebSocketHandshakeResponseHandler::RemoveHeaders(
std::string WebSocketHandshakeResponseHandler::GetRawResponse() const {
DCHECK(HasResponse());
- return std::string(original_.data(),
- original_header_length_ + GetResponseKeySize());
+ return original_.substr(0, original_header_length_);
}
std::string WebSocketHandshakeResponseHandler::GetResponse() {
DCHECK(HasResponse());
DCHECK(!status_line_.empty());
// headers_ might be empty for wrong response from server.
- DCHECK_EQ(GetResponseKeySize(), key_.size());
- return status_line_ + headers_ + header_separator_ + key_;
-}
-
-size_t WebSocketHandshakeResponseHandler::GetResponseKeySize() const {
- if (protocol_version_ >= kMinVersionOfHybiNewHandshake)
- return 0;
- return kResponseKeySize;
+ return status_line_ + headers_ + header_separator_;
}
} // namespace net
diff --git a/chromium/net/websockets/websocket_handshake_handler.h b/chromium/net/websockets/websocket_handshake_handler.h
index 14c0fcec4cc..73af66d0aaa 100644
--- a/chromium/net/websockets/websocket_handshake_handler.h
+++ b/chromium/net/websockets/websocket_handshake_handler.h
@@ -10,21 +10,6 @@
// cookies to the renderer process, so handles HttpOnly cookies in
// browser process.
//
-// The classes below support two styles of handshake: handshake based
-// on hixie-76 draft and one based on hybi-04 draft. The critical difference
-// between these two is how they pass challenge and response values. Hixie-76
-// based handshake appends a few bytes of binary data after header fields of
-// handshake request and response. These data are called "key3" (for request)
-// or "response key" (for response). On the other hand, handshake based on
-// hybi-04 and later drafts put challenge and response values into handshake
-// header fields, thus we do not need to send or receive extra bytes after
-// handshake headers.
-//
-// While we are working on updating WebSocket implementation in WebKit to
-// conform to the latest protocol draft, we need to accept both styles of
-// handshake. After we land the protocol changes in WebKit, we will be able to
-// drop codes handling old-style handshake.
-
#ifndef NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
@@ -38,6 +23,9 @@
namespace net {
+void ComputeSecWebSocketAccept(const std::string& key,
+ std::string* accept);
+
class NET_EXPORT_PRIVATE WebSocketHandshakeRequestHandler {
public:
WebSocketHandshakeRequestHandler();
@@ -58,10 +46,8 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeRequestHandler {
void RemoveHeaders(const char* const headers_to_remove[],
size_t headers_to_remove_len);
- // Gets request info to open WebSocket connection.
- // Fills challenge data (concatenation of key1, 2 and 3 for hybi-03 and
- // earlier, or Sec-WebSocket-Key header value for hybi-04 and later)
- // in |challenge|.
+ // Gets request info to open WebSocket connection and fills challenge data in
+ // |challenge|.
HttpRequestInfo GetRequestInfo(const GURL& url, std::string* challenge);
// Gets request as SpdyHeaderBlock.
// Also, fills challenge data in |challenge|.
@@ -75,19 +61,11 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeRequestHandler {
// Calling raw_length is valid only after GetRawRequest() call.
size_t raw_length() const;
- // Returns the value of Sec-WebSocket-Version or Sec-WebSocket-Draft header
- // (the latter is an old name of the former). Returns 0 if both headers were
- // absent, which means the handshake was based on hybi-00 (= hixie-76).
- // Should only be called after the handshake has been parsed.
- int protocol_version() const;
-
private:
- std::string status_line_;
+ std::string request_line_;
std::string headers_;
- std::string key3_;
int original_length_;
int raw_length_;
- int protocol_version_; // "-1" means we haven't parsed the handshake yet.
DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeRequestHandler);
};
@@ -97,17 +75,11 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeResponseHandler {
WebSocketHandshakeResponseHandler();
~WebSocketHandshakeResponseHandler();
- // Set WebSocket protocol version before parsing the response.
- // Default is 0 (hybi-00, which is same as hixie-76).
- int protocol_version() const;
- void set_protocol_version(int protocol_version);
-
// Parses WebSocket handshake response from WebSocket server.
// Returns number of bytes in |data| used for WebSocket handshake response
- // message, including response key. If it already got whole WebSocket
- // handshake response message, returns zero. In other words,
- // [data + returned value, data + length) will be WebSocket frame data
- // after handshake response message.
+ // message. If it already got whole WebSocket handshake response message,
+ // returns zero. In other words, [data + returned value, data + length) will
+ // be WebSocket frame data after handshake response message.
// TODO(ukai): fail fast when response gives wrong status code.
size_t ParseRawResponse(const char* data, int length);
// Returns true if it already parses full handshake response message.
@@ -135,37 +107,18 @@ class NET_EXPORT_PRIVATE WebSocketHandshakeResponseHandler {
std::string GetResponse();
private:
- // Returns the length of response key. This function will return 0
- // if the specified WebSocket protocol version does not require
- // sending response key.
- size_t GetResponseKeySize() const;
-
+ // Original bytes input by using ParseRawResponse().
std::string original_;
+ // Number of bytes actually used for the handshake response in |original_|.
int original_header_length_;
+
std::string status_line_;
std::string headers_;
std::string header_separator_;
- std::string key_;
- int protocol_version_;
DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeResponseHandler);
};
-namespace internal {
-
-// Private Functions (Exposed for Unit Testing) -------------------------------
-
-// Gets a key number from |key| and appends the number to |challenge|.
-// The key number (/part_N/) is extracted as step per 4.-8. in
-// "5.2. Sending the server's opening handshake" of
-// http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-00.txt
-// TODO(ricea): Remove this when we remove support for pre-RFC6455 versions of
-// WebSockets.
-void NET_EXPORT_PRIVATE GetKeyNumber(const std::string& key,
- std::string* challenge);
-
-} // namespace internal
-
} // namespace net
#endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_HANDLER_H_
diff --git a/chromium/net/websockets/websocket_handshake_handler_spdy_test.cc b/chromium/net/websockets/websocket_handshake_handler_spdy_test.cc
index ebab9a8cf59..a825dcdfede 100644
--- a/chromium/net/websockets/websocket_handshake_handler_spdy_test.cc
+++ b/chromium/net/websockets/websocket_handshake_handler_spdy_test.cc
@@ -28,7 +28,8 @@ class WebSocketHandshakeHandlerSpdyTest
INSTANTIATE_TEST_CASE_P(
NextProto,
WebSocketHandshakeHandlerSpdyTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponse) {
@@ -48,7 +49,6 @@ TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponse) {
EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(13, request_handler.protocol_version());
GURL url("ws://example.com/demo");
std::string challenge;
@@ -85,7 +85,6 @@ TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponse) {
spdy_util_.SetHeader("sec-websocket-extensions", "foo", &headers);
WebSocketHandshakeResponseHandler response_handler;
- response_handler.set_protocol_version(13);
EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(
headers, challenge, spdy_util_.spdy_version()));
EXPECT_TRUE(response_handler.HasResponse());
@@ -122,7 +121,6 @@ TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponseWithCookies) {
EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(13, request_handler.protocol_version());
GURL url("ws://example.com/demo");
std::string challenge;
@@ -166,7 +164,6 @@ TEST_P(WebSocketHandshakeHandlerSpdyTest, RequestResponseWithCookies) {
WebSocketHandshakeResponseHandler response_handler;
- response_handler.set_protocol_version(13);
EXPECT_TRUE(response_handler.ParseResponseHeaderBlock(
headers, challenge, spdy_util_.spdy_version()));
EXPECT_TRUE(response_handler.HasResponse());
diff --git a/chromium/net/websockets/websocket_handshake_handler_test.cc b/chromium/net/websockets/websocket_handshake_handler_test.cc
index 4c1b15578ee..e59a982bf16 100644
--- a/chromium/net/websockets/websocket_handshake_handler_test.cc
+++ b/chromium/net/websockets/websocket_handshake_handler_test.cc
@@ -26,46 +26,6 @@ const char* const kSetCookieHeaders[] = {
"set-cookie", "set-cookie2"
};
-// A test fixture to simplify tests for GetKeyNumber().
-class WebSocketHandshakeGetKeyNumberTest : public ::testing::Test {
- protected:
- static const char kExampleFromDraftKey1[];
-
- // The object is default-initialised with an empty challenge and the example
- // key from draft-ietf-hybi-thewebsocketprotocol-00. These can be changed
- // using set_challenge() and set_key().
- WebSocketHandshakeGetKeyNumberTest()
- : challenge_(), key_(kExampleFromDraftKey1) {}
-
- // A convenience wrapper for the function under test which automatically
- // passes in the arguments stored in the object.
- void GetKeyNumber() { ::net::internal::GetKeyNumber(key_, &challenge_); }
-
- // Read current challenge.
- const std::string& challenge() const { return challenge_; }
-
- // Overwrite challenge.
- void set_challenge(const std::string& challenge) { challenge_ = challenge; }
-
- // Reset the challenge to be empty.
- void reset_challenge() { challenge_.clear(); }
-
- // Change key.
- void set_key(const std::string& key) { key_ = key; }
-
- private:
- std::string challenge_;
- std::string key_;
-};
-
-const char WebSocketHandshakeGetKeyNumberTest::kExampleFromDraftKey1[] =
- "3e6b263 4 17 80";
-
-// A version of the above fixture for death tests.
-class WebSocketHandshakeGetKeyNumberDeathTest
- : public WebSocketHandshakeGetKeyNumberTest {
-};
-
} // namespace
namespace net {
@@ -76,41 +36,16 @@ TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequest) {
static const char kHandshakeRequestMessage[] =
"GET /demo HTTP/1.1\r\n"
"Host: example.com\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Upgrade: WebSocket\r\n"
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
- "Origin: http://example.com\r\n"
- "\r\n"
- "^n:ds[4U";
-
- EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(0, handler.protocol_version());
-
- handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
-
- EXPECT_EQ(kHandshakeRequestMessage, handler.GetRawRequest());
-}
-
-TEST(WebSocketHandshakeRequestHandlerTest, SimpleRequestHybi06Handshake) {
- WebSocketHandshakeRequestHandler handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Origin: http://example.com\r\n"
"Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 6\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
"\r\n";
EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(6, handler.protocol_version());
handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
@@ -123,61 +58,17 @@ TEST(WebSocketHandshakeRequestHandlerTest, ReplaceRequestCookies) {
static const char kHandshakeRequestMessage[] =
"GET /demo HTTP/1.1\r\n"
"Host: example.com\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Upgrade: WebSocket\r\n"
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
- "Origin: http://example.com\r\n"
- "Cookie: WK-websocket-test=1\r\n"
- "\r\n"
- "^n:ds[4U";
-
- EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(0, handler.protocol_version());
-
- handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
-
- handler.AppendHeaderIfMissing("Cookie",
- "WK-websocket-test=1; "
- "WK-websocket-test-httponly=1");
-
- static const char kHandshakeRequestExpectedMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Upgrade: WebSocket\r\n"
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
- "Origin: http://example.com\r\n"
- "Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
- "\r\n"
- "^n:ds[4U";
-
- EXPECT_EQ(kHandshakeRequestExpectedMessage, handler.GetRawRequest());
-}
-
-TEST(WebSocketHandshakeRequestHandlerTest,
- ReplaceRequestCookiesHybi06Handshake) {
- WebSocketHandshakeRequestHandler handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Origin: http://example.com\r\n"
"Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 6\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
"Cookie: WK-websocket-test=1\r\n"
"\r\n";
EXPECT_TRUE(handler.ParseRequest(kHandshakeRequestMessage,
strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(6, handler.protocol_version());
handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
@@ -193,7 +84,7 @@ TEST(WebSocketHandshakeRequestHandlerTest,
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Origin: http://example.com\r\n"
"Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 6\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
"Cookie: WK-websocket-test=1; WK-websocket-test-httponly=1\r\n"
"\r\n";
@@ -202,32 +93,6 @@ TEST(WebSocketHandshakeRequestHandlerTest,
TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponse) {
WebSocketHandshakeResponseHandler handler;
- EXPECT_EQ(0, handler.protocol_version());
-
- static const char kHandshakeResponseMessage[] =
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Location: ws://example.com/demo\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n"
- "8jKS'y:G*Co,Wxa-";
-
- EXPECT_EQ(strlen(kHandshakeResponseMessage),
- handler.ParseRawResponse(kHandshakeResponseMessage,
- strlen(kHandshakeResponseMessage)));
- EXPECT_TRUE(handler.HasResponse());
-
- handler.RemoveHeaders(kCookieHeaders, arraysize(kCookieHeaders));
-
- EXPECT_EQ(kHandshakeResponseMessage, handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponseHybi06Handshake) {
- WebSocketHandshakeResponseHandler handler;
- handler.set_protocol_version(6);
- EXPECT_EQ(6, handler.protocol_version());
static const char kHandshakeResponseMessage[] =
"HTTP/1.1 101 Switching Protocols\r\n"
@@ -249,49 +114,6 @@ TEST(WebSocketHandshakeResponseHandlerTest, SimpleResponseHybi06Handshake) {
TEST(WebSocketHandshakeResponseHandlerTest, ReplaceResponseCookies) {
WebSocketHandshakeResponseHandler handler;
- EXPECT_EQ(0, handler.protocol_version());
-
- static const char kHandshakeResponseMessage[] =
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Location: ws://example.com/demo\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Set-Cookie: WK-websocket-test-1\r\n"
- "Set-Cookie: WK-websocket-test-httponly=1; HttpOnly\r\n"
- "\r\n"
- "8jKS'y:G*Co,Wxa-";
-
- EXPECT_EQ(strlen(kHandshakeResponseMessage),
- handler.ParseRawResponse(kHandshakeResponseMessage,
- strlen(kHandshakeResponseMessage)));
- EXPECT_TRUE(handler.HasResponse());
- std::vector<std::string> cookies;
- handler.GetHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders), &cookies);
- ASSERT_EQ(2U, cookies.size());
- EXPECT_EQ("WK-websocket-test-1", cookies[0]);
- EXPECT_EQ("WK-websocket-test-httponly=1; HttpOnly", cookies[1]);
- handler.RemoveHeaders(kSetCookieHeaders, arraysize(kSetCookieHeaders));
-
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Location: ws://example.com/demo\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n"
- "8jKS'y:G*Co,Wxa-";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeResponseHandlerTest,
- ReplaceResponseCookiesHybi06Handshake) {
- WebSocketHandshakeResponseHandler handler;
- handler.set_protocol_version(6);
- EXPECT_EQ(6, handler.protocol_version());
static const char kHandshakeResponseMessage[] =
"HTTP/1.1 101 Switching Protocols\r\n"
@@ -329,20 +151,18 @@ TEST(WebSocketHandshakeResponseHandlerTest, BadResponse) {
WebSocketHandshakeResponseHandler handler;
static const char kBadMessage[] = "\n\n\r\net-Location: w";
- EXPECT_EQ(strlen(kBadMessage),
- handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
+ EXPECT_EQ(2U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
EXPECT_TRUE(handler.HasResponse());
- EXPECT_EQ(kBadMessage, handler.GetResponse());
+ EXPECT_EQ("\n\n", handler.GetResponse());
}
TEST(WebSocketHandshakeResponseHandlerTest, BadResponse2) {
WebSocketHandshakeResponseHandler handler;
static const char kBadMessage[] = "\n\r\n\r\net-Location: w";
- EXPECT_EQ(strlen(kBadMessage),
- handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
+ EXPECT_EQ(3U, handler.ParseRawResponse(kBadMessage, strlen(kBadMessage)));
EXPECT_TRUE(handler.HasResponse());
- EXPECT_EQ(kBadMessage, handler.GetResponse());
+ EXPECT_EQ("\n\r\n", handler.GetResponse());
}
TEST(WebSocketHandshakeHandlerTest, HttpRequestResponse) {
@@ -351,101 +171,16 @@ TEST(WebSocketHandshakeHandlerTest, HttpRequestResponse) {
static const char kHandshakeRequestMessage[] =
"GET /demo HTTP/1.1\r\n"
"Host: example.com\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "Upgrade: WebSocket\r\n"
- "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"
- "Origin: http://example.com\r\n"
- "\r\n"
- "^n:ds[4U";
-
- EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
- strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(0, request_handler.protocol_version());
-
- GURL url("ws://example.com/demo");
- std::string challenge;
- const HttpRequestInfo& request_info =
- request_handler.GetRequestInfo(url, &challenge);
-
- EXPECT_EQ(url, request_info.url);
- EXPECT_EQ("GET", request_info.method);
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Upgrade"));
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Connection"));
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key1"));
- EXPECT_FALSE(request_info.extra_headers.HasHeader("Sec-WebSocket-Key2"));
- std::string value;
- EXPECT_TRUE(request_info.extra_headers.GetHeader("Host", &value));
- EXPECT_EQ("example.com", value);
- EXPECT_TRUE(request_info.extra_headers.GetHeader("Origin", &value));
- EXPECT_EQ("http://example.com", value);
- EXPECT_TRUE(request_info.extra_headers.GetHeader("Sec-WebSocket-Protocol",
- &value));
- EXPECT_EQ("sample", value);
-
- const char expected_challenge[] = "\x31\x6e\x41\x13\x0f\x7e\xd6\x3c^n:ds[4U";
-
- EXPECT_EQ(expected_challenge, challenge);
-
- static const char kHandshakeResponseHeader[] =
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Location: ws://example.com/demo\r\n"
- "Sec-WebSocket-Protocol: sample\r\n";
-
- std::string raw_headers =
- HttpUtil::AssembleRawHeaders(kHandshakeResponseHeader,
- strlen(kHandshakeResponseHeader));
- HttpResponseInfo response_info;
- response_info.headers = new HttpResponseHeaders(raw_headers);
-
- EXPECT_TRUE(StartsWithASCII(response_info.headers->GetStatusLine(),
- "HTTP/1.1 101 ", false));
- EXPECT_FALSE(response_info.headers->HasHeader("Upgrade"));
- EXPECT_FALSE(response_info.headers->HasHeader("Connection"));
- EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Origin",
- "http://example.com"));
- EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Location",
- "ws://example.com/demo"));
- EXPECT_TRUE(response_info.headers->HasHeaderValue("Sec-WebSocket-Protocol",
- "sample"));
-
- WebSocketHandshakeResponseHandler response_handler;
- EXPECT_EQ(0, response_handler.protocol_version());
- EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
- EXPECT_TRUE(response_handler.HasResponse());
-
- static const char kHandshakeResponseExpectedMessage[] =
- "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
- "Upgrade: WebSocket\r\n"
- "Connection: Upgrade\r\n"
- "Sec-WebSocket-Origin: http://example.com\r\n"
- "Sec-WebSocket-Location: ws://example.com/demo\r\n"
- "Sec-WebSocket-Protocol: sample\r\n"
- "\r\n"
- "8jKS'y:G*Co,Wxa-";
-
- EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
-}
-
-TEST(WebSocketHandshakeHandlerTest, HttpRequestResponseHybi06Handshake) {
- WebSocketHandshakeRequestHandler request_handler;
-
- static const char kHandshakeRequestMessage[] =
- "GET /demo HTTP/1.1\r\n"
- "Host: example.com\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Origin: http://example.com\r\n"
"Sec-WebSocket-Protocol: sample\r\n"
- "Sec-WebSocket-Version: 6\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
"\r\n";
EXPECT_TRUE(request_handler.ParseRequest(kHandshakeRequestMessage,
strlen(kHandshakeRequestMessage)));
- EXPECT_EQ(6, request_handler.protocol_version());
GURL url("ws://example.com/demo");
std::string challenge;
@@ -488,8 +223,6 @@ TEST(WebSocketHandshakeHandlerTest, HttpRequestResponseHybi06Handshake) {
"sample"));
WebSocketHandshakeResponseHandler response_handler;
- response_handler.set_protocol_version(request_handler.protocol_version());
- EXPECT_EQ(6, response_handler.protocol_version());
EXPECT_TRUE(response_handler.ParseResponseInfo(response_info, challenge));
EXPECT_TRUE(response_handler.HasResponse());
@@ -505,79 +238,4 @@ TEST(WebSocketHandshakeHandlerTest, HttpRequestResponseHybi06Handshake) {
EXPECT_EQ(kHandshakeResponseExpectedMessage, response_handler.GetResponse());
}
-TEST_F(WebSocketHandshakeGetKeyNumberTest, AppendsToString) {
- set_challenge("hello");
- GetKeyNumber();
- EXPECT_EQ("hello", challenge().substr(0, 5));
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberTest, AppendsFourBytes) {
- set_challenge("hello");
- set_key("1 1");
- GetKeyNumber();
- EXPECT_EQ(9u, challenge().length());
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberTest, IsBigEndian) {
- set_key(base::StringPrintf("%u ", 0x61626364));
- GetKeyNumber();
- EXPECT_EQ("abcd", challenge());
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberTest, IgnoresLetters) {
- set_key("1b 1");
- GetKeyNumber();
- char expected_response[] = { 0, 0, 0, 11 };
- EXPECT_EQ(std::string(expected_response, 4), challenge());
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberTest, DividesBySpaces) {
- set_key("1 2");
- GetKeyNumber();
- EXPECT_EQ(12, challenge()[3]);
- reset_challenge();
- set_key("1 2");
- GetKeyNumber();
- EXPECT_EQ(6, challenge()[3]);
- reset_challenge();
- set_key(" 1 2");
- GetKeyNumber();
- EXPECT_EQ(4, challenge()[3]);
- reset_challenge();
- set_key(" 1 2 ");
- GetKeyNumber();
- EXPECT_EQ(3, challenge()[3]);
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberTest, MatchesExampleFromDraft) {
- set_key("3e6b263 4 17 80");
- GetKeyNumber();
- char expected_response[] = { 0x36, 0x09, 0x65, 0x65 };
- EXPECT_EQ(std::string(expected_response, 4), challenge());
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberTest, Maximum32bitInteger) {
- set_key("4294967295 ");
- GetKeyNumber();
- char expected_response[] = { '\xFF', '\xFF', '\xFF', '\xFF' };
- EXPECT_EQ(std::string(expected_response, 4), challenge());
-}
-
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-TEST_F(WebSocketHandshakeGetKeyNumberDeathTest, ThirtyThreeBitIntegerNoGood) {
- set_key(" 4294967296");
- EXPECT_DEBUG_DEATH(GetKeyNumber(), "overflow");
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberDeathTest, NoSpacesNoGood) {
- set_key("11");
- EXPECT_DEBUG_DEATH(GetKeyNumber(), "space");
-}
-
-TEST_F(WebSocketHandshakeGetKeyNumberDeathTest, MustBeIntegralMultiple) {
- set_key("1 1");
- EXPECT_DEBUG_DEATH(GetKeyNumber(), "spaces");
-}
-#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-
} // namespace net
diff --git a/chromium/net/websockets/websocket_handshake_stream_base.h b/chromium/net/websockets/websocket_handshake_stream_base.h
new file mode 100644
index 00000000000..71d8321824f
--- /dev/null
+++ b/chromium/net/websockets/websocket_handshake_stream_base.h
@@ -0,0 +1,77 @@
+// 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_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
+#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
+
+// This file is included from net/http files.
+// Since net/http can be built without linking net/websockets code,
+// this file must not introduce any link-time dependencies on websockets.
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/supports_user_data.h"
+#include "net/http/http_stream_base.h"
+#include "net/url_request/websocket_handshake_userdata_key.h"
+#include "net/websockets/websocket_stream.h"
+
+namespace net {
+
+class ClientSocketHandle;
+class SpdySession;
+
+// WebSocketHandshakeStreamBase is the base class of
+// WebSocketBasicHandshakeStream. net/http code uses this interface to handle
+// WebSocketBasicHandshakeStream when it needs to be treated differently from
+// HttpStreamBase.
+class NET_EXPORT WebSocketHandshakeStreamBase : public HttpStreamBase {
+ public:
+ // An object that stores data needed for the creation of a
+ // WebSocketBasicHandshakeStream object. A new CreateHelper is used for each
+ // WebSocket connection.
+ class NET_EXPORT_PRIVATE CreateHelper : public base::SupportsUserData::Data {
+ public:
+ // Returns a key to use to lookup this object in a URLRequest object. It is
+ // different from any other key that is supplied to
+ // URLRequest::SetUserData().
+ static const void* DataKey() { return kWebSocketHandshakeUserDataKey; }
+
+ virtual ~CreateHelper() {}
+
+ // Create a WebSocketBasicHandshakeStream. This is called after the
+ // underlying connection has been established but before any handshake data
+ // has been transferred. This can be called more than once in the case that
+ // HTTP authentication is needed.
+ virtual WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) = 0;
+
+ // Create a WebSocketSpdyHandshakeStream (unimplemented as of October 2013)
+ virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
+ const base::WeakPtr<SpdySession>& session,
+ bool use_relative_url) = 0;
+ };
+
+ // This has to have an inline implementation so that the net/url_request/
+ // tests do not fail on iOS.
+ virtual ~WebSocketHandshakeStreamBase() {}
+
+ // After the handshake has completed, this method creates a WebSocketStream
+ // (of the appropriate type) from the WebSocketHandshakeStreamBase object.
+ // The WebSocketHandshakeStreamBase object is unusable after Upgrade() has
+ // been called.
+ virtual scoped_ptr<WebSocketStream> Upgrade() = 0;
+
+ protected:
+ // As with the destructor, this must be inline.
+ WebSocketHandshakeStreamBase() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeStreamBase);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_BASE_H_
diff --git a/chromium/net/websockets/websocket_handshake_stream_create_helper.cc b/chromium/net/websockets/websocket_handshake_stream_create_helper.cc
new file mode 100644
index 00000000000..8f1060c4868
--- /dev/null
+++ b/chromium/net/websockets/websocket_handshake_stream_create_helper.cc
@@ -0,0 +1,43 @@
+// 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/websockets/websocket_handshake_stream_create_helper.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/spdy/spdy_session.h"
+#include "net/websockets/websocket_basic_handshake_stream.h"
+
+namespace net {
+
+WebSocketHandshakeStreamCreateHelper::WebSocketHandshakeStreamCreateHelper(
+ const std::vector<std::string>& requested_subprotocols)
+ : requested_subprotocols_(requested_subprotocols),
+ stream_(NULL) {}
+
+WebSocketHandshakeStreamCreateHelper::~WebSocketHandshakeStreamCreateHelper() {}
+
+WebSocketHandshakeStreamBase*
+WebSocketHandshakeStreamCreateHelper::CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) {
+ return stream_ =
+ new WebSocketBasicHandshakeStream(connection.Pass(),
+ using_proxy,
+ requested_subprotocols_,
+ std::vector<std::string>());
+}
+
+// TODO(ricea): Create a WebSocketSpdyHandshakeStream. crbug.com/323852
+WebSocketHandshakeStreamBase*
+WebSocketHandshakeStreamCreateHelper::CreateSpdyStream(
+ const base::WeakPtr<SpdySession>& session,
+ bool use_relative_url) {
+ NOTREACHED() << "Not implemented";
+ return NULL;
+}
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_handshake_stream_create_helper.h b/chromium/net/websockets/websocket_handshake_stream_create_helper.h
new file mode 100644
index 00000000000..31be2313ff7
--- /dev/null
+++ b/chromium/net/websockets/websocket_handshake_stream_create_helper.h
@@ -0,0 +1,61 @@
+// 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_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_CREATE_HELPER_H_
+#define NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_CREATE_HELPER_H_
+
+#include <string>
+#include <vector>
+
+#include "net/base/net_export.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
+
+namespace net {
+
+// Implementation of WebSocketHandshakeStreamBase::CreateHelper. This class is
+// used in the implementation of WebSocketStream::CreateAndConnectStream() and
+// is not intended to be used by itself.
+//
+// Holds the information needed to construct a
+// WebSocketBasicHandshakeStreamBase.
+class NET_EXPORT_PRIVATE WebSocketHandshakeStreamCreateHelper
+ : public WebSocketHandshakeStreamBase::CreateHelper {
+ public:
+ explicit WebSocketHandshakeStreamCreateHelper(
+ const std::vector<std::string>& requested_subprotocols);
+
+ virtual ~WebSocketHandshakeStreamCreateHelper();
+
+ // WebSocketHandshakeStreamBase::CreateHelper methods
+
+ // Create a WebSocketBasicHandshakeStream.
+ virtual WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) OVERRIDE;
+
+ // Unimplemented as of November 2013.
+ virtual WebSocketHandshakeStreamBase* CreateSpdyStream(
+ const base::WeakPtr<SpdySession>& session,
+ bool use_relative_url) OVERRIDE;
+
+ // Return the WebSocketHandshakeStreamBase object that we created. In the case
+ // where CreateBasicStream() was called more than once, returns the most
+ // recent stream, which will be the one on which the handshake succeeded.
+ WebSocketHandshakeStreamBase* stream() { return stream_; }
+
+ private:
+ const std::vector<std::string> requested_subprotocols_;
+
+ // This is owned by the caller of CreateBaseStream() or
+ // CreateSpdyStream(). Both the stream and this object will be destroyed
+ // during the destruction of the URLRequest object associated with the
+ // handshake.
+ WebSocketHandshakeStreamBase* stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketHandshakeStreamCreateHelper);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_HANDSHAKE_STREAM_CREATE_HELPER_H_
diff --git a/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc b/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
new file mode 100644
index 00000000000..7566edf6174
--- /dev/null
+++ b/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -0,0 +1,145 @@
+// 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/websockets/websocket_handshake_stream_create_helper.h"
+
+#include "net/base/completion_callback.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_request_info.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/socket_test_util.h"
+#include "net/websockets/websocket_basic_handshake_stream.h"
+#include "net/websockets/websocket_stream.h"
+#include "net/websockets/websocket_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+namespace {
+
+// This class encapsulates the details of creating a mock ClientSocketHandle.
+class MockClientSocketHandleFactory {
+ public:
+ MockClientSocketHandleFactory()
+ : histograms_("a"),
+ pool_(1, 1, &histograms_, socket_factory_maker_.factory()) {}
+
+ // The created socket expects |expect_written| to be written to the socket,
+ // and will respond with |return_to_read|. The test will fail if the expected
+ // text is not written, or if all the bytes are not read.
+ scoped_ptr<ClientSocketHandle> CreateClientSocketHandle(
+ const std::string& expect_written,
+ 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());
+ return socket_handle.Pass();
+ }
+
+ private:
+ WebSocketDeterministicMockClientSocketFactoryMaker socket_factory_maker_;
+ ClientSocketPoolHistograms histograms_;
+ MockTransportClientSocketPool pool_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockClientSocketHandleFactory);
+};
+
+class WebSocketHandshakeStreamCreateHelperTest : public ::testing::Test {
+ protected:
+ scoped_ptr<WebSocketStream> CreateAndInitializeStream(
+ const std::string& socket_url,
+ const std::string& socket_path,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin,
+ const std::string& extra_request_headers,
+ const std::string& extra_response_headers) {
+ WebSocketHandshakeStreamCreateHelper create_helper(sub_protocols);
+
+ scoped_ptr<ClientSocketHandle> socket_handle =
+ socket_handle_factory_.CreateClientSocketHandle(
+ WebSocketStandardRequest(
+ socket_path, origin, extra_request_headers),
+ WebSocketStandardResponse(extra_response_headers));
+
+ scoped_ptr<WebSocketHandshakeStreamBase> handshake(
+ create_helper.CreateBasicStream(socket_handle.Pass(), false));
+
+ // If in future the implementation type returned by CreateBasicStream()
+ // changes, this static_cast will be wrong. However, in that case the test
+ // will fail and AddressSanitizer should identify the issue.
+ static_cast<WebSocketBasicHandshakeStream*>(handshake.get())
+ ->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ==");
+
+ HttpRequestInfo request_info;
+ request_info.url = GURL(socket_url);
+ request_info.method = "GET";
+ request_info.load_flags = LOAD_DISABLE_CACHE | LOAD_DO_NOT_PROMPT_FOR_LOGIN;
+ int rv = handshake->InitializeStream(
+ &request_info, DEFAULT_PRIORITY, BoundNetLog(), CompletionCallback());
+ EXPECT_EQ(OK, rv);
+
+ HttpRequestHeaders headers;
+ headers.SetHeader("Host", "localhost");
+ headers.SetHeader("Connection", "Upgrade");
+ headers.SetHeader("Upgrade", "websocket");
+ headers.SetHeader("Origin", origin);
+ headers.SetHeader("Sec-WebSocket-Version", "13");
+ headers.SetHeader("User-Agent", "");
+ headers.SetHeader("Accept-Encoding", "gzip,deflate");
+ headers.SetHeader("Accept-Language", "en-us,fr");
+
+ HttpResponseInfo response;
+ TestCompletionCallback dummy;
+
+ rv = handshake->SendRequest(headers, &response, dummy.callback());
+
+ EXPECT_EQ(OK, rv);
+
+ rv = handshake->ReadResponseHeaders(dummy.callback());
+ EXPECT_EQ(OK, rv);
+ EXPECT_EQ(101, response.headers->response_code());
+ EXPECT_TRUE(response.headers->HasHeaderValue("Connection", "Upgrade"));
+ EXPECT_TRUE(response.headers->HasHeaderValue("Upgrade", "websocket"));
+ return handshake->Upgrade();
+ }
+
+ MockClientSocketHandleFactory socket_handle_factory_;
+};
+
+// Confirm that the basic case works as expected.
+TEST_F(WebSocketHandshakeStreamCreateHelperTest, BasicStream) {
+ scoped_ptr<WebSocketStream> stream =
+ CreateAndInitializeStream("ws://localhost/", "/",
+ std::vector<std::string>(), "http://localhost/",
+ "", "");
+ EXPECT_EQ("", stream->GetExtensions());
+ EXPECT_EQ("", stream->GetSubProtocol());
+}
+
+// Verify that the sub-protocols are passed through.
+TEST_F(WebSocketHandshakeStreamCreateHelperTest, SubProtocols) {
+ std::vector<std::string> sub_protocols;
+ sub_protocols.push_back("chat");
+ sub_protocols.push_back("superchat");
+ scoped_ptr<WebSocketStream> stream =
+ CreateAndInitializeStream("ws://localhost/", "/",
+ sub_protocols, "http://localhost/",
+ "Sec-WebSocket-Protocol: chat, superchat\r\n",
+ "Sec-WebSocket-Protocol: superchat\r\n");
+ EXPECT_EQ("superchat", stream->GetSubProtocol());
+}
+
+// TODO(ricea): Test extensions once they are implemented.
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/websockets/websocket_inflater.cc b/chromium/net/websockets/websocket_inflater.cc
new file mode 100644
index 00000000000..6f468223ce5
--- /dev/null
+++ b/chromium/net/websockets/websocket_inflater.cc
@@ -0,0 +1,283 @@
+// 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/websockets/websocket_inflater.h"
+
+#include <algorithm>
+#include <deque>
+#include <vector>
+
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "third_party/zlib/zlib.h"
+
+namespace net {
+
+namespace {
+
+class ShrinkableIOBufferWithSize : public IOBufferWithSize {
+ public:
+ explicit ShrinkableIOBufferWithSize(int size)
+ : IOBufferWithSize(size) {}
+
+ void Shrink(int new_size) {
+ DCHECK_LE(new_size, size_);
+ size_ = new_size;
+ }
+
+ private:
+ virtual ~ShrinkableIOBufferWithSize() {}
+};
+
+} // namespace
+
+WebSocketInflater::WebSocketInflater()
+ : input_queue_(kDefaultInputIOBufferCapacity),
+ output_buffer_(kDefaultBufferCapacity) {}
+
+WebSocketInflater::WebSocketInflater(size_t input_queue_capacity,
+ size_t output_buffer_capacity)
+ : input_queue_(input_queue_capacity),
+ output_buffer_(output_buffer_capacity) {
+ DCHECK_GT(input_queue_capacity, 0u);
+ DCHECK_GT(output_buffer_capacity, 0u);
+}
+
+bool WebSocketInflater::Initialize(int window_bits) {
+ DCHECK_LE(8, window_bits);
+ DCHECK_GE(15, window_bits);
+ stream_.reset(new z_stream);
+ memset(stream_.get(), 0, sizeof(*stream_));
+ int result = inflateInit2(stream_.get(), -window_bits);
+ if (result != Z_OK) {
+ inflateEnd(stream_.get());
+ stream_.reset();
+ return false;
+ }
+ return true;
+}
+
+WebSocketInflater::~WebSocketInflater() {
+ if (stream_) {
+ inflateEnd(stream_.get());
+ stream_.reset();
+ }
+}
+
+bool WebSocketInflater::AddBytes(const char* data, size_t size) {
+ if (!size)
+ return true;
+
+ if (!input_queue_.IsEmpty()) {
+ // choked
+ input_queue_.Push(data, size);
+ return true;
+ }
+
+ int result = InflateWithFlush(data, size);
+ if (stream_->avail_in > 0)
+ input_queue_.Push(&data[size - stream_->avail_in], stream_->avail_in);
+
+ return result == Z_OK || result == Z_BUF_ERROR;
+}
+
+bool WebSocketInflater::Finish() {
+ return AddBytes("\x00\x00\xff\xff", 4);
+}
+
+scoped_refptr<IOBufferWithSize> WebSocketInflater::GetOutput(size_t size) {
+ scoped_refptr<ShrinkableIOBufferWithSize> buffer =
+ new ShrinkableIOBufferWithSize(size);
+ size_t num_bytes_copied = 0;
+
+ while (num_bytes_copied < size && output_buffer_.Size() > 0) {
+ size_t num_bytes_to_copy =
+ std::min(output_buffer_.Size(), size - num_bytes_copied);
+ output_buffer_.Read(&buffer->data()[num_bytes_copied], num_bytes_to_copy);
+ num_bytes_copied += num_bytes_to_copy;
+ int result = InflateChokedInput();
+ if (result != Z_OK && result != Z_BUF_ERROR)
+ return NULL;
+ }
+ buffer->Shrink(num_bytes_copied);
+ return buffer;
+}
+
+int WebSocketInflater::InflateWithFlush(const char* next_in, size_t avail_in) {
+ int result = Inflate(next_in, avail_in, Z_NO_FLUSH);
+ if (result != Z_OK && result != Z_BUF_ERROR)
+ return result;
+
+ if (CurrentOutputSize() > 0)
+ return result;
+ // CurrentOutputSize() == 0 means there is no data to be output,
+ // so we should make sure it by using Z_SYNC_FLUSH.
+ return Inflate(reinterpret_cast<const char*>(stream_->next_in),
+ stream_->avail_in,
+ Z_SYNC_FLUSH);
+}
+
+int WebSocketInflater::Inflate(const char* next_in,
+ size_t avail_in,
+ int flush) {
+ stream_->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(next_in));
+ stream_->avail_in = avail_in;
+
+ int result = Z_BUF_ERROR;
+ do {
+ std::pair<char*, size_t> tail = output_buffer_.GetTail();
+ if (!tail.second)
+ break;
+
+ stream_->next_out = reinterpret_cast<Bytef*>(tail.first);
+ stream_->avail_out = tail.second;
+ result = inflate(stream_.get(), flush);
+ output_buffer_.AdvanceTail(tail.second - stream_->avail_out);
+ if (result == Z_STREAM_END) {
+ // Received a block with BFINAL set to 1. Reset the decompression state.
+ result = inflateReset(stream_.get());
+ } else if (tail.second == stream_->avail_out) {
+ break;
+ }
+ } while (result == Z_OK || result == Z_BUF_ERROR);
+ return result;
+}
+
+int WebSocketInflater::InflateChokedInput() {
+ if (input_queue_.IsEmpty())
+ return InflateWithFlush(NULL, 0);
+
+ int result = Z_BUF_ERROR;
+ while (!input_queue_.IsEmpty()) {
+ std::pair<char*, size_t> top = input_queue_.Top();
+
+ result = InflateWithFlush(top.first, top.second);
+ input_queue_.Consume(top.second - stream_->avail_in);
+
+ if (result != Z_OK && result != Z_BUF_ERROR)
+ return result;
+
+ if (stream_->avail_in > 0) {
+ // There are some data which are not consumed.
+ break;
+ }
+ }
+ return result;
+}
+
+WebSocketInflater::OutputBuffer::OutputBuffer(size_t capacity)
+ : capacity_(capacity),
+ buffer_(capacity_ + 1), // 1 for sentinel
+ head_(0),
+ tail_(0) {}
+
+WebSocketInflater::OutputBuffer::~OutputBuffer() {}
+
+size_t WebSocketInflater::OutputBuffer::Size() const {
+ return (tail_ + buffer_.size() - head_) % buffer_.size();
+}
+
+std::pair<char*, size_t> WebSocketInflater::OutputBuffer::GetTail() {
+ DCHECK_LT(tail_, buffer_.size());
+ return std::make_pair(&buffer_[tail_],
+ std::min(capacity_ - Size(), buffer_.size() - tail_));
+}
+
+void WebSocketInflater::OutputBuffer::Read(char* dest, size_t size) {
+ DCHECK_LE(size, Size());
+
+ size_t num_bytes_copied = 0;
+ if (tail_ < head_) {
+ size_t num_bytes_to_copy = std::min(size, buffer_.size() - head_);
+ DCHECK_LT(head_, buffer_.size());
+ memcpy(&dest[num_bytes_copied], &buffer_[head_], num_bytes_to_copy);
+ AdvanceHead(num_bytes_to_copy);
+ num_bytes_copied += num_bytes_to_copy;
+ }
+
+ if (num_bytes_copied == size)
+ return;
+ DCHECK_LE(head_, tail_);
+ size_t num_bytes_to_copy = size - num_bytes_copied;
+ DCHECK_LE(num_bytes_to_copy, tail_ - head_);
+ DCHECK_LT(head_, buffer_.size());
+ memcpy(&dest[num_bytes_copied], &buffer_[head_], num_bytes_to_copy);
+ AdvanceHead(num_bytes_to_copy);
+ num_bytes_copied += num_bytes_to_copy;
+ DCHECK_EQ(size, num_bytes_copied);
+ return;
+}
+
+void WebSocketInflater::OutputBuffer::AdvanceHead(size_t advance) {
+ DCHECK_LE(advance, Size());
+ head_ = (head_ + advance) % buffer_.size();
+}
+
+void WebSocketInflater::OutputBuffer::AdvanceTail(size_t advance) {
+ DCHECK_LE(advance + Size(), capacity_);
+ tail_ = (tail_ + advance) % buffer_.size();
+}
+
+WebSocketInflater::InputQueue::InputQueue(size_t capacity)
+ : capacity_(capacity), head_of_first_buffer_(0), tail_of_last_buffer_(0) {}
+
+WebSocketInflater::InputQueue::~InputQueue() {}
+
+std::pair<char*, size_t> WebSocketInflater::InputQueue::Top() {
+ DCHECK(!IsEmpty());
+ if (buffers_.size() == 1) {
+ return std::make_pair(&buffers_.front()->data()[head_of_first_buffer_],
+ tail_of_last_buffer_ - head_of_first_buffer_);
+ }
+ return std::make_pair(&buffers_.front()->data()[head_of_first_buffer_],
+ capacity_ - head_of_first_buffer_);
+}
+
+void WebSocketInflater::InputQueue::Push(const char* data, size_t size) {
+ if (!size)
+ return;
+
+ size_t num_copied_bytes = 0;
+ if (!IsEmpty())
+ num_copied_bytes += PushToLastBuffer(data, size);
+
+ while (num_copied_bytes < size) {
+ DCHECK(IsEmpty() || tail_of_last_buffer_ == capacity_);
+
+ buffers_.push_back(new IOBufferWithSize(capacity_));
+ tail_of_last_buffer_ = 0;
+ num_copied_bytes +=
+ PushToLastBuffer(&data[num_copied_bytes], size - num_copied_bytes);
+ }
+}
+
+void WebSocketInflater::InputQueue::Consume(size_t size) {
+ DCHECK(!IsEmpty());
+ DCHECK_LE(size + head_of_first_buffer_, capacity_);
+
+ head_of_first_buffer_ += size;
+ if (head_of_first_buffer_ == capacity_) {
+ buffers_.pop_front();
+ head_of_first_buffer_ = 0;
+ }
+ if (buffers_.size() == 1 && head_of_first_buffer_ == tail_of_last_buffer_) {
+ buffers_.pop_front();
+ head_of_first_buffer_ = 0;
+ tail_of_last_buffer_ = 0;
+ }
+}
+
+size_t WebSocketInflater::InputQueue::PushToLastBuffer(const char* data,
+ size_t size) {
+ DCHECK(!IsEmpty());
+ size_t num_bytes_to_copy = std::min(size, capacity_ - tail_of_last_buffer_);
+ if (!num_bytes_to_copy)
+ return 0;
+ IOBufferWithSize* buffer = buffers_.back().get();
+ memcpy(&buffer->data()[tail_of_last_buffer_], data, num_bytes_to_copy);
+ tail_of_last_buffer_ += num_bytes_to_copy;
+ return num_bytes_to_copy;
+}
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_inflater.h b/chromium/net/websockets/websocket_inflater.h
new file mode 100644
index 00000000000..e57317f5334
--- /dev/null
+++ b/chromium/net/websockets/websocket_inflater.h
@@ -0,0 +1,130 @@
+// 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_WEBSOCKETS_WEBSOCKET_INFLATER_H_
+#define NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
+
+#include <deque>
+#include <utility>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/net_export.h"
+
+extern "C" struct z_stream_s;
+
+namespace net {
+
+class IOBufferWithSize;
+
+// WebSocketInflater uncompresses data compressed by DEFLATE algorithm.
+class NET_EXPORT_PRIVATE WebSocketInflater {
+ public:
+ WebSocketInflater();
+ // |input_queue_capacity| is a capacity for each contiguous block in the
+ // input queue. The input queue can grow without limit.
+ WebSocketInflater(size_t input_queue_capacity, size_t output_buffer_capacity);
+ ~WebSocketInflater();
+
+ // Returns true if there is no error.
+ // |window_bits| must be between 8 and 15 (both inclusive).
+ // This function must be called exactly once before calling any of the
+ // following functions.
+ bool Initialize(int window_bits);
+
+ // Adds bytes to |stream_|.
+ // Returns true if there is no error.
+ // If the size of the output data reaches the capacity of the output buffer,
+ // the following input data will be "choked", i.e. stored in the input queue,
+ // staying compressed.
+ bool AddBytes(const char* data, size_t size);
+
+ // Flushes the input.
+ // Returns true if there is no error.
+ bool Finish();
+
+ // Returns up to |size| bytes of the decompressed output.
+ // Returns null if there is an inflation error.
+ // The returned bytes will be dropped from the current output and never be
+ // returned again.
+ // If some input data is choked, calling this function may restart the
+ // inflation process.
+ // This means that even if you call |Finish()| and call |GetOutput()| with
+ // size = |CurrentOutputSize()|, the inflater may have some remaining data.
+ // To confirm the inflater emptiness, you should check whether
+ // |CurrentOutputSize()| is zero.
+ scoped_refptr<IOBufferWithSize> GetOutput(size_t size);
+
+ // Returns the size of the current inflated output.
+ size_t CurrentOutputSize() const { return output_buffer_.Size(); }
+
+ static const size_t kDefaultBufferCapacity = 512;
+ static const size_t kDefaultInputIOBufferCapacity = 512;
+
+ private:
+ // Ring buffer with fixed capacity.
+ class OutputBuffer {
+ public:
+ explicit OutputBuffer(size_t capacity);
+ ~OutputBuffer();
+
+ size_t Size() const;
+ // Returns (tail pointer, availabe size).
+ // A user can push data to the queue by writing the data to
+ // the area returned by this function and calling AdvanceTail.
+ std::pair<char*, size_t> GetTail();
+ void Read(char* dest, size_t size);
+ void AdvanceTail(size_t advance);
+
+ private:
+ void AdvanceHead(size_t advance);
+
+ const size_t capacity_;
+ std::vector<char> buffer_;
+ size_t head_;
+ size_t tail_;
+ };
+
+ class InputQueue {
+ public:
+ // |capacity| is used for the capacity of each IOBuffer in this queue.
+ // this queue itself can grow without limit.
+ explicit InputQueue(size_t capacity);
+ ~InputQueue();
+
+ // Returns (data pointer, size), the first component of unconsumed data.
+ // The type of data pointer is non-const because |inflate| function
+ // requires so.
+ std::pair<char*, size_t> Top();
+ bool IsEmpty() const { return buffers_.empty(); }
+ void Push(const char* data, size_t size);
+ // Consumes the topmost |size| bytes.
+ // |size| must be less than or equal to the first buffer size.
+ void Consume(size_t size);
+
+ private:
+ size_t PushToLastBuffer(const char* data, size_t size);
+
+ const size_t capacity_;
+ size_t head_of_first_buffer_;
+ size_t tail_of_last_buffer_;
+ std::deque<scoped_refptr<IOBufferWithSize> > buffers_;
+ };
+
+ int InflateWithFlush(const char* next_in, size_t avail_in);
+ int Inflate(const char* next_in, size_t avail_in, int flush);
+ int InflateChokedInput();
+
+ scoped_ptr<z_stream_s> stream_;
+ InputQueue input_queue_;
+ OutputBuffer output_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketInflater);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_INFLATER_H_
diff --git a/chromium/net/websockets/websocket_inflater_test.cc b/chromium/net/websockets/websocket_inflater_test.cc
new file mode 100644
index 00000000000..139e90112b7
--- /dev/null
+++ b/chromium/net/websockets/websocket_inflater_test.cc
@@ -0,0 +1,224 @@
+// 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/websockets/websocket_inflater.h"
+
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "net/base/io_buffer.h"
+#include "net/websockets/websocket_deflater.h"
+#include "net/websockets/websocket_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+namespace {
+
+std::string ToString(IOBufferWithSize* buffer) {
+ return std::string(buffer->data(), buffer->size());
+}
+
+TEST(WebSocketInflaterTest, Construct) {
+ WebSocketInflater inflater;
+ ASSERT_TRUE(inflater.Initialize(15));
+
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+}
+
+TEST(WebSocketInflaterTest, InflateHelloTakeOverContext) {
+ WebSocketInflater inflater;
+ ASSERT_TRUE(inflater.Initialize(15));
+ scoped_refptr<IOBufferWithSize> actual1, actual2;
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ actual1 = inflater.GetOutput(inflater.CurrentOutputSize());
+ ASSERT_TRUE(actual1);
+ EXPECT_EQ("Hello", ToString(actual1.get()));
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5));
+ ASSERT_TRUE(inflater.Finish());
+ actual2 = inflater.GetOutput(inflater.CurrentOutputSize());
+ ASSERT_TRUE(actual2);
+ EXPECT_EQ("Hello", ToString(actual2.get()));
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+}
+
+TEST(WebSocketInflaterTest, InflateHelloSmallCapacity) {
+ WebSocketInflater inflater(1, 1);
+ ASSERT_TRUE(inflater.Initialize(15));
+ std::string actual;
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ for (size_t i = 0; i < 5; ++i) {
+ ASSERT_EQ(1u, inflater.CurrentOutputSize());
+ scoped_refptr<IOBufferWithSize> buffer = inflater.GetOutput(1);
+ ASSERT_TRUE(buffer);
+ ASSERT_EQ(1, buffer->size());
+ actual += ToString(buffer.get());
+ }
+ EXPECT_EQ("Hello", actual);
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+}
+
+TEST(WebSocketInflaterTest, InflateHelloSmallCapacityGetTotalOutput) {
+ WebSocketInflater inflater(1, 1);
+ ASSERT_TRUE(inflater.Initialize(15));
+ scoped_refptr<IOBufferWithSize> actual;
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ ASSERT_EQ(1u, inflater.CurrentOutputSize());
+ actual = inflater.GetOutput(1024);
+ EXPECT_EQ("Hello", ToString(actual));
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+}
+
+TEST(WebSocketInflaterTest, InflateInvalidData) {
+ WebSocketInflater inflater;
+ ASSERT_TRUE(inflater.Initialize(15));
+ EXPECT_FALSE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16));
+}
+
+TEST(WebSocketInflaterTest, ChokedInvalidData) {
+ WebSocketInflater inflater(1, 1);
+ ASSERT_TRUE(inflater.Initialize(15));
+
+ EXPECT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16));
+ EXPECT_TRUE(inflater.Finish());
+ EXPECT_EQ(1u, inflater.CurrentOutputSize());
+ EXPECT_FALSE(inflater.GetOutput(1024));
+}
+
+TEST(WebSocketInflaterTest, MultipleAddBytesCalls) {
+ WebSocketInflater inflater;
+ ASSERT_TRUE(inflater.Initialize(15));
+ std::string input("\xf2\x48\xcd\xc9\xc9\x07\x00", 7);
+ scoped_refptr<IOBufferWithSize> actual;
+
+ for (size_t i = 0; i < input.size(); ++i) {
+ ASSERT_TRUE(inflater.AddBytes(&input[i], 1));
+ }
+ ASSERT_TRUE(inflater.Finish());
+ actual = inflater.GetOutput(5);
+ ASSERT_TRUE(actual);
+ EXPECT_EQ("Hello", ToString(actual.get()));
+}
+
+TEST(WebSocketInflaterTest, Reset) {
+ WebSocketInflater inflater;
+ ASSERT_TRUE(inflater.Initialize(15));
+ scoped_refptr<IOBufferWithSize> actual1, actual2;
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ actual1 = inflater.GetOutput(inflater.CurrentOutputSize());
+ ASSERT_TRUE(actual1);
+ EXPECT_EQ("Hello", ToString(actual1.get()));
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+
+ // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0]
+ ASSERT_TRUE(inflater.AddBytes("\x01", 1));
+ ASSERT_TRUE(inflater.Finish());
+ ASSERT_EQ(0u, inflater.CurrentOutputSize());
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ actual2 = inflater.GetOutput(inflater.CurrentOutputSize());
+ ASSERT_TRUE(actual2);
+ EXPECT_EQ("Hello", ToString(actual2.get()));
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+}
+
+TEST(WebSocketInflaterTest, ResetAndLostContext) {
+ WebSocketInflater inflater;
+ scoped_refptr<IOBufferWithSize> actual1, actual2;
+ ASSERT_TRUE(inflater.Initialize(15));
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ actual1 = inflater.GetOutput(inflater.CurrentOutputSize());
+ ASSERT_TRUE(actual1);
+ EXPECT_EQ("Hello", ToString(actual1.get()));
+ EXPECT_EQ(0u, inflater.CurrentOutputSize());
+
+ // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0]
+ ASSERT_TRUE(inflater.AddBytes("\x01", 1));
+ ASSERT_TRUE(inflater.Finish());
+ ASSERT_EQ(0u, inflater.CurrentOutputSize());
+
+ // The context is already reset.
+ ASSERT_FALSE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5));
+}
+
+TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutput) {
+ WebSocketInflater inflater;
+ scoped_refptr<IOBufferWithSize> actual1, actual2;
+ ASSERT_TRUE(inflater.Initialize(15));
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ EXPECT_EQ(5u, inflater.CurrentOutputSize());
+
+ // This is a test for detecting memory leaks with valgrind.
+}
+
+TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutputChoked) {
+ WebSocketInflater inflater(1, 1);
+ scoped_refptr<IOBufferWithSize> actual1, actual2;
+ ASSERT_TRUE(inflater.Initialize(15));
+
+ ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
+ ASSERT_TRUE(inflater.Finish());
+ EXPECT_EQ(1u, inflater.CurrentOutputSize());
+
+ // This is a test for detecting memory leaks with valgrind.
+}
+
+TEST(WebSocketInflaterTest, LargeRandomDeflateInflate) {
+ const size_t size = 64 * 1024;
+ LinearCongruentialGenerator generator(133);
+ std::vector<char> input;
+ std::vector<char> output;
+ scoped_refptr<IOBufferWithSize> compressed;
+
+ WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
+ ASSERT_TRUE(deflater.Initialize(8));
+ WebSocketInflater inflater(256, 256);
+ ASSERT_TRUE(inflater.Initialize(8));
+
+ for (size_t i = 0; i < size; ++i)
+ input.push_back(static_cast<char>(generator.Generate()));
+
+ ASSERT_TRUE(deflater.AddBytes(&input[0], input.size()));
+ ASSERT_TRUE(deflater.Finish());
+
+ compressed = deflater.GetOutput(deflater.CurrentOutputSize());
+
+ ASSERT_TRUE(compressed);
+ ASSERT_EQ(0u, deflater.CurrentOutputSize());
+
+ ASSERT_TRUE(inflater.AddBytes(compressed->data(), compressed->size()));
+ ASSERT_TRUE(inflater.Finish());
+
+ while (inflater.CurrentOutputSize() > 0) {
+ scoped_refptr<IOBufferWithSize> uncompressed =
+ inflater.GetOutput(inflater.CurrentOutputSize());
+ ASSERT_TRUE(uncompressed);
+ output.insert(output.end(),
+ uncompressed->data(),
+ uncompressed->data() + uncompressed->size());
+ }
+
+ EXPECT_EQ(output, input);
+}
+
+} // unnamed namespace
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_job.cc b/chromium/net/websockets/websocket_job.cc
index 50d121837ac..b0f5be8bf3f 100644
--- a/chromium/net/websockets/websocket_job.cc
+++ b/chromium/net/websockets/websocket_job.cc
@@ -358,9 +358,6 @@ bool WebSocketJob::SendHandshakeRequest(const char* data, int len) {
if (!handshake_request_->ParseRequest(data, len))
return false;
- // handshake message is completed.
- handshake_response_->set_protocol_version(
- handshake_request_->protocol_version());
AddCookieHeaderAndSend();
return true;
}
diff --git a/chromium/net/websockets/websocket_job_test.cc b/chromium/net/websockets/websocket_job_test.cc
index 434796dbcbc..bdbae709eb9 100644
--- a/chromium/net/websockets/websocket_job_test.cc
+++ b/chromium/net/websockets/websocket_job_test.cc
@@ -597,7 +597,8 @@ void WebSocketJobTest::TestSlowHandshake() {
INSTANTIATE_TEST_CASE_P(
NextProto,
WebSocketJobTest,
- testing::Values(kProtoSPDY2, kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
+ testing::Values(kProtoDeprecatedSPDY2,
+ kProtoSPDY3, kProtoSPDY31, kProtoSPDY4a2,
kProtoHTTP2Draft04));
TEST_P(WebSocketJobTest, DelayedCookies) {
diff --git a/chromium/net/websockets/websocket_stream.cc b/chromium/net/websockets/websocket_stream.cc
index b2d316bb2ae..e81c24e706e 100644
--- a/chromium/net/websockets/websocket_stream.cc
+++ b/chromium/net/websockets/websocket_stream.cc
@@ -5,8 +5,156 @@
#include "net/websockets/websocket_stream.h"
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/http/http_request_headers.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/websockets/websocket_errors.h"
+#include "net/websockets/websocket_handshake_constants.h"
+#include "net/websockets/websocket_handshake_stream_base.h"
+#include "net/websockets/websocket_handshake_stream_create_helper.h"
+#include "net/websockets/websocket_test_util.h"
+#include "url/gurl.h"
namespace net {
+namespace {
+
+class StreamRequestImpl;
+
+class Delegate : public URLRequest::Delegate {
+ public:
+ explicit Delegate(StreamRequestImpl* owner) : owner_(owner) {}
+ virtual ~Delegate() {}
+
+ // Implementation of URLRequest::Delegate methods.
+ virtual void OnResponseStarted(URLRequest* request) OVERRIDE;
+
+ virtual void OnAuthRequired(URLRequest* request,
+ AuthChallengeInfo* auth_info) OVERRIDE;
+
+ virtual void OnCertificateRequested(URLRequest* request,
+ SSLCertRequestInfo* cert_request_info)
+ OVERRIDE;
+
+ virtual void OnSSLCertificateError(URLRequest* request,
+ const SSLInfo& ssl_info,
+ bool fatal) OVERRIDE;
+
+ virtual void OnReadCompleted(URLRequest* request, int bytes_read) OVERRIDE;
+
+ private:
+ StreamRequestImpl* owner_;
+};
+
+class StreamRequestImpl : public WebSocketStreamRequest {
+ public:
+ StreamRequestImpl(
+ const GURL& url,
+ const URLRequestContext* context,
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate,
+ WebSocketHandshakeStreamCreateHelper* create_helper)
+ : delegate_(new Delegate(this)),
+ url_request_(url, DEFAULT_PRIORITY, delegate_.get(), context),
+ connect_delegate_(connect_delegate.Pass()),
+ create_helper_(create_helper) {}
+
+ // Destroying this object destroys the URLRequest, which cancels the request
+ // and so terminates the handshake if it is incomplete.
+ virtual ~StreamRequestImpl() {}
+
+ URLRequest* url_request() { return &url_request_; }
+
+ void PerformUpgrade() {
+ connect_delegate_->OnSuccess(create_helper_->stream()->Upgrade());
+ }
+
+ void ReportFailure() {
+ connect_delegate_->OnFailure(kWebSocketErrorAbnormalClosure);
+ }
+
+ private:
+ // |delegate_| needs to be declared before |url_request_| so that it gets
+ // initialised first.
+ scoped_ptr<Delegate> delegate_;
+
+ // Deleting the StreamRequestImpl object deletes this URLRequest object,
+ // cancelling the whole connection.
+ URLRequest url_request_;
+
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate_;
+
+ // Owned by the URLRequest.
+ WebSocketHandshakeStreamCreateHelper* create_helper_;
+};
+
+void Delegate::OnResponseStarted(URLRequest* request) {
+ switch (request->GetResponseCode()) {
+ case HTTP_SWITCHING_PROTOCOLS:
+ owner_->PerformUpgrade();
+ return;
+
+ case HTTP_UNAUTHORIZED:
+ case HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ return;
+
+ default:
+ owner_->ReportFailure();
+ }
+}
+
+void Delegate::OnAuthRequired(URLRequest* request,
+ AuthChallengeInfo* auth_info) {
+ request->CancelAuth();
+}
+
+void Delegate::OnCertificateRequested(URLRequest* request,
+ SSLCertRequestInfo* cert_request_info) {
+ request->ContinueWithCertificate(NULL);
+}
+
+void Delegate::OnSSLCertificateError(URLRequest* request,
+ const SSLInfo& ssl_info,
+ bool fatal) {
+ request->Cancel();
+}
+
+void Delegate::OnReadCompleted(URLRequest* request, int bytes_read) {
+ NOTREACHED();
+}
+
+// Internal implementation of CreateAndConnectStream and
+// CreateAndConnectStreamForTesting.
+scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamWithCreateHelper(
+ const GURL& socket_url,
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
+ const GURL& origin,
+ URLRequestContext* url_request_context,
+ const BoundNetLog& net_log,
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
+ scoped_ptr<StreamRequestImpl> request(
+ new StreamRequestImpl(socket_url,
+ url_request_context,
+ connect_delegate.Pass(),
+ create_helper.get()));
+ HttpRequestHeaders headers;
+ headers.SetHeader(websockets::kUpgrade, websockets::kWebSocketLowercase);
+ headers.SetHeader(HttpRequestHeaders::kConnection, websockets::kUpgrade);
+ headers.SetHeader(HttpRequestHeaders::kOrigin, origin.spec());
+ // TODO(ricea): Move the version number to websocket_handshake_constants.h
+ headers.SetHeader(websockets::kSecWebSocketVersion,
+ websockets::kSupportedVersion);
+ request->url_request()->SetExtraRequestHeaders(headers);
+ request->url_request()->SetUserData(
+ WebSocketHandshakeStreamBase::CreateHelper::DataKey(),
+ create_helper.release());
+ request->url_request()->SetLoadFlags(LOAD_DISABLE_CACHE |
+ LOAD_DO_NOT_PROMPT_FOR_LOGIN);
+ request->url_request()->Start();
+ return request.PassAs<WebSocketStreamRequest>();
+}
+
+} // namespace
WebSocketStreamRequest::~WebSocketStreamRequest() {}
@@ -15,7 +163,6 @@ WebSocketStream::~WebSocketStream() {}
WebSocketStream::ConnectDelegate::~ConnectDelegate() {}
-// Placeholder until the real implementation is ready.
scoped_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream(
const GURL& socket_url,
const std::vector<std::string>& requested_subprotocols,
@@ -23,10 +170,30 @@ scoped_ptr<WebSocketStreamRequest> WebSocketStream::CreateAndConnectStream(
URLRequestContext* url_request_context,
const BoundNetLog& net_log,
scoped_ptr<ConnectDelegate> connect_delegate) {
- NOTIMPLEMENTED();
- return make_scoped_ptr(new WebSocketStreamRequest());
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper(
+ new WebSocketHandshakeStreamCreateHelper(requested_subprotocols));
+ return CreateAndConnectStreamWithCreateHelper(socket_url,
+ create_helper.Pass(),
+ origin,
+ url_request_context,
+ net_log,
+ connect_delegate.Pass());
}
-WebSocketStream* WebSocketStream::AsWebSocketStream() { return this; }
+// This is declared in websocket_test_util.h.
+scoped_ptr<WebSocketStreamRequest> CreateAndConnectStreamForTesting(
+ const GURL& socket_url,
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
+ const GURL& origin,
+ URLRequestContext* url_request_context,
+ const BoundNetLog& net_log,
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) {
+ return CreateAndConnectStreamWithCreateHelper(socket_url,
+ create_helper.Pass(),
+ origin,
+ url_request_context,
+ net_log,
+ connect_delegate.Pass());
+}
} // namespace net
diff --git a/chromium/net/websockets/websocket_stream.h b/chromium/net/websockets/websocket_stream.h
index 4885bbe7295..c08f8dc39b7 100644
--- a/chromium/net/websockets/websocket_stream.h
+++ b/chromium/net/websockets/websocket_stream.h
@@ -14,17 +14,14 @@
#include "base/memory/scoped_vector.h"
#include "net/base/completion_callback.h"
#include "net/base/net_export.h"
-#include "net/websockets/websocket_stream_base.h"
class GURL;
namespace net {
class BoundNetLog;
-class HttpRequestHeaders;
-class HttpResponseInfo;
class URLRequestContext;
-struct WebSocketFrameChunk;
+struct WebSocketFrame;
// WebSocketStreamRequest is the caller's handle to the process of creation of a
// WebSocketStream. Deleting the object before the OnSuccess or OnFailure
@@ -49,11 +46,11 @@ class NET_EXPORT_PRIVATE WebSocketStreamRequest {
// |callback| will be called when the operation is finished. Non-null |callback|
// must be provided to these functions.
-class NET_EXPORT_PRIVATE WebSocketStream : public WebSocketStreamBase {
+class NET_EXPORT_PRIVATE WebSocketStream {
public:
// A concrete object derived from ConnectDelegate is supplied by the caller to
// CreateAndConnectStream() to receive the result of the connection.
- class ConnectDelegate {
+ class NET_EXPORT_PRIVATE ConnectDelegate {
public:
virtual ~ConnectDelegate();
// Called on successful connection. The parameter is an object derived from
@@ -91,10 +88,10 @@ class NET_EXPORT_PRIVATE WebSocketStream : public WebSocketStreamBase {
virtual ~WebSocketStream();
// Reads WebSocket frame data. This operation finishes when new frame data
- // becomes available. Each frame message might be chopped off in the middle
- // as specified in the description of the WebSocketFrameChunk struct.
- // |frame_chunks| remains owned by the caller and must be valid until the
- // operation completes or Close() is called. |frame_chunks| must be empty on
+ // becomes available.
+ //
+ // |frames| remains owned by the caller and must be valid until the
+ // operation completes or Close() is called. |frames| must be empty on
// calling.
//
// This function should not be called while the previous call of ReadFrames()
@@ -102,20 +99,18 @@ class NET_EXPORT_PRIVATE WebSocketStream : public WebSocketStreamBase {
//
// Returns net::OK or one of the net::ERR_* codes.
//
- // frame_chunks->size() >= 1 if the result is OK.
+ // frames->size() >= 1 if the result is OK.
//
- // A frame with an incomplete header will never be inserted into
- // |frame_chunks|. If the currently available bytes of a new frame do not form
- // a complete frame header, then the implementation will buffer them until all
- // the fields in the WebSocketFrameHeader object can be filled. If
- // ReadFrames() is freshly called in this situation, it will return
- // ERR_IO_PENDING exactly as if no data was available.
+ // Only frames with complete header information are inserted into |frames|. If
+ // the currently available bytes of a new frame do not form a complete frame
+ // header, then the implementation will buffer them until all the fields in
+ // the WebSocketFrameHeader object can be filled. If ReadFrames() is freshly
+ // called in this situation, it will return ERR_IO_PENDING exactly as if no
+ // data was available.
//
- // Every WebSocketFrameChunk in the vector except the first and last is
- // guaranteed to be a complete frame. The first chunk may be the final part
- // of the previous frame. The last chunk may be the first part of a new
- // frame. If there is only one chunk, then it may consist of data from the
- // middle part of a frame.
+ // Original frame boundaries are not preserved. In particular, if only part of
+ // a frame is available, then the frame will be split, and the available data
+ // will be returned immediately.
//
// When the socket is closed on the remote side, this method will return
// ERR_CONNECTION_CLOSED. It will not return OK with an empty vector.
@@ -124,33 +119,34 @@ class NET_EXPORT_PRIVATE WebSocketStream : public WebSocketStreamBase {
// ReadFrames may discard the incomplete frame. Since the renderer will
// discard any incomplete messages when the connection is closed, this makes
// no difference to the overall semantics.
- virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ //
+ // Implementations of ReadFrames() must be able to handle being deleted during
+ // the execution of callback.Run(). In practice this means that the method
+ // calling callback.Run() (and any calling methods in the same object) must
+ // return immediately without any further method calls or access to member
+ // variables. Implementors should write test(s) for this case.
+ virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) = 0;
- // Writes WebSocket frame data. |frame_chunks| must only contain complete
- // frames. Every chunk must have a non-NULL |header| and the |final_chunk|
- // boolean set to true.
- //
- // The |frame_chunks| pointer must remain valid until the operation completes
- // or Close() is called. WriteFrames() will modify the contents of
- // |frame_chunks| in the process of sending the message. After WriteFrames()
- // has completed it is safe to clear and then re-use the vector, but other
- // than that the caller should make no assumptions about its contents.
+ // Writes WebSocket frame data.
//
- // This function should not be called while a previous call to WriteFrames()
- // on the same stream is pending.
+ // |frames| must be valid until the operation completes or Close() is called.
//
- // Frame boundaries may not be preserved. Frames may be split or
- // coalesced. Message boundaries are preserved (as required by WebSocket API
- // semantics).
+ // This function must not be called while a previous call of WriteFrames() is
+ // still pending.
//
// This method will only return OK if all frames were written completely.
// Otherwise it will return an appropriate net error code.
- virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
+ //
+ // The callback implementation is permitted to delete this
+ // object. Implementations of WriteFrames() should be robust against
+ // this. This generally means returning to the event loop immediately after
+ // calling the callback.
+ virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
const CompletionCallback& callback) = 0;
// Closes the stream. All pending I/O operations (if any) are cancelled
- // at this point, so |frame_chunks| can be freed.
+ // at this point, so |frames| can be freed.
virtual void Close() = 0;
// The subprotocol that was negotiated for the stream. If no protocol was
@@ -168,40 +164,6 @@ class NET_EXPORT_PRIVATE WebSocketStream : public WebSocketStreamBase {
// extensions were negotiated, the empty string is returned.
virtual std::string GetExtensions() const = 0;
- // TODO(yutak): Add following interfaces:
- // - RenewStreamForAuth for authentication (is this necessary?)
- // - GetSSLInfo, GetSSLCertRequestInfo for SSL
-
- // WebSocketStreamBase derived functions
- virtual WebSocketStream* AsWebSocketStream() OVERRIDE;
-
- ////////////////////////////////////////////////////////////////////////////
- // Methods used during the stream handshake. These must not be called once a
- // WebSocket protocol stream has been established (ie. after the
- // SuccessCallback or FailureCallback has been called.)
-
- // Writes WebSocket handshake request to the underlying socket. Must be called
- // before ReadHandshakeResponse().
- //
- // |callback| will only be called if this method returns ERR_IO_PENDING.
- //
- // |response_info| must remain valid until the callback from
- // ReadHandshakeResponse has been called.
- //
- // TODO(ricea): This function is only used during the handshake and is
- // probably only applicable to certain subclasses of WebSocketStream. Move it
- // somewhere else? Also applies to ReadHandshakeResponse.
- virtual int SendHandshakeRequest(const GURL& url,
- const HttpRequestHeaders& headers,
- HttpResponseInfo* response_info,
- const CompletionCallback& callback) = 0;
-
- // Reads WebSocket handshake response from the underlying socket. Must be
- // called after SendHandshakeRequest() completes.
- //
- // |callback| will only be called if this method returns ERR_IO_PENDING.
- virtual int ReadHandshakeResponse(const CompletionCallback& callback) = 0;
-
protected:
WebSocketStream();
diff --git a/chromium/net/websockets/websocket_stream_base.h b/chromium/net/websockets/websocket_stream_base.h
deleted file mode 100644
index dc863d20001..00000000000
--- a/chromium/net/websockets/websocket_stream_base.h
+++ /dev/null
@@ -1,55 +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_WEBSOCKETS_WEBSOCKET_STREAM_BASE_H_
-#define NET_WEBSOCKETS_WEBSOCKET_STREAM_BASE_H_
-
-// This file is included from net/http files.
-// Since net/http can be built without linking net/websockets code,
-// this file should not depend on net/websockets.
-
-#include <base/basictypes.h>
-
-namespace net {
-
-class ClientSocketHandle;
-class SpdySession;
-class WebSocketStream;
-
-// WebSocketStreamBase is the base class of WebSocketStream.
-// net/http code uses this interface to handle WebSocketStream.
-class NET_EXPORT WebSocketStreamBase {
- public:
- class Factory {
- public:
- virtual ~Factory() {}
-
- // Create a WebSocketBasicStream.
- // This function (or the returned object) takes the ownership
- // of |connection|.
- virtual WebSocketStreamBase* CreateBasicStream(
- ClientSocketHandle* connection,
- bool using_proxy) = 0;
-
- // Create a WebSocketSpdyStream.
- virtual WebSocketStreamBase* CreateSpdyStream(
- const base::WeakPtr<SpdySession>& session,
- bool use_relative_url) = 0;
- };
-
- virtual ~WebSocketStreamBase() {}
-
- // Return this object as a WebSocketStream.
- virtual WebSocketStream* AsWebSocketStream() = 0;
-
- protected:
- WebSocketStreamBase() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WebSocketStreamBase);
-};
-
-} // namespace net
-
-#endif // NET_WEBSOCKETS_WEBSOCKET_STREAM_BASE_H_
diff --git a/chromium/net/websockets/websocket_stream_test.cc b/chromium/net/websockets/websocket_stream_test.cc
new file mode 100644
index 00000000000..3e11a95ac1c
--- /dev/null
+++ b/chromium/net/websockets/websocket_stream_test.cc
@@ -0,0 +1,515 @@
+// 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/websockets/websocket_stream.h"
+
+#include <string>
+#include <vector>
+
+#include "base/run_loop.h"
+#include "net/base/net_errors.h"
+#include "net/socket/client_socket_handle.h"
+#include "net/socket/socket_test_util.h"
+#include "net/url_request/url_request_test_util.h"
+#include "net/websockets/websocket_basic_handshake_stream.h"
+#include "net/websockets/websocket_handshake_stream_create_helper.h"
+#include "net/websockets/websocket_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace net {
+namespace {
+
+// A sub-class of WebSocketHandshakeStreamCreateHelper which always sets a
+// deterministic key to use in the WebSocket handshake.
+class DeterministicKeyWebSocketHandshakeStreamCreateHelper
+ : public WebSocketHandshakeStreamCreateHelper {
+ public:
+ DeterministicKeyWebSocketHandshakeStreamCreateHelper(
+ const std::vector<std::string>& requested_subprotocols)
+ : WebSocketHandshakeStreamCreateHelper(requested_subprotocols) {}
+
+ virtual WebSocketHandshakeStreamBase* CreateBasicStream(
+ scoped_ptr<ClientSocketHandle> connection,
+ bool using_proxy) OVERRIDE {
+ WebSocketHandshakeStreamCreateHelper::CreateBasicStream(connection.Pass(),
+ using_proxy);
+ // This will break in an obvious way if the type created by
+ // CreateBasicStream() changes.
+ static_cast<WebSocketBasicHandshakeStream*>(stream())
+ ->SetWebSocketKeyForTesting("dGhlIHNhbXBsZSBub25jZQ==");
+ return stream();
+ }
+};
+
+class WebSocketStreamCreateTest : public ::testing::Test {
+ protected:
+ WebSocketStreamCreateTest() : websocket_error_(0) {}
+
+ void CreateAndConnectCustomResponse(
+ const std::string& socket_url,
+ const std::string& socket_path,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin,
+ const std::string& extra_request_headers,
+ const std::string& response_body) {
+ url_request_context_host_.SetExpectations(
+ WebSocketStandardRequest(socket_path, origin, extra_request_headers),
+ response_body);
+ CreateAndConnectStream(socket_url, sub_protocols, origin);
+ }
+
+ // |extra_request_headers| and |extra_response_headers| must end in "\r\n" or
+ // errors like "Unable to perform synchronous IO while stopped" will occur.
+ void CreateAndConnectStandard(const std::string& socket_url,
+ const std::string& socket_path,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin,
+ const std::string& extra_request_headers,
+ const std::string& extra_response_headers) {
+ CreateAndConnectCustomResponse(
+ socket_url,
+ socket_path,
+ sub_protocols,
+ origin,
+ extra_request_headers,
+ WebSocketStandardResponse(extra_response_headers));
+ }
+
+ void CreateAndConnectRawExpectations(
+ const std::string& socket_url,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin,
+ scoped_ptr<DeterministicSocketData> socket_data) {
+ url_request_context_host_.SetRawExpectations(socket_data.Pass());
+ CreateAndConnectStream(socket_url, sub_protocols, origin);
+ }
+
+ // A wrapper for CreateAndConnectStreamForTesting that knows about our default
+ // parameters.
+ void CreateAndConnectStream(const std::string& socket_url,
+ const std::vector<std::string>& sub_protocols,
+ const std::string& origin) {
+ stream_request_ = ::net::CreateAndConnectStreamForTesting(
+ GURL(socket_url),
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper>(
+ new DeterministicKeyWebSocketHandshakeStreamCreateHelper(
+ sub_protocols)),
+ GURL(origin),
+ url_request_context_host_.GetURLRequestContext(),
+ BoundNetLog(),
+ scoped_ptr<WebSocketStream::ConnectDelegate>(
+ new TestConnectDelegate(this)));
+ }
+
+ static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
+
+ // A simple function to make the tests more readable. Creates an empty vector.
+ static std::vector<std::string> NoSubProtocols() {
+ return std::vector<std::string>();
+ }
+
+ uint16 error() const { return websocket_error_; }
+
+ class TestConnectDelegate : public WebSocketStream::ConnectDelegate {
+ public:
+ TestConnectDelegate(WebSocketStreamCreateTest* owner) : owner_(owner) {}
+
+ virtual void OnSuccess(scoped_ptr<WebSocketStream> stream) OVERRIDE {
+ stream.swap(owner_->stream_);
+ }
+
+ virtual void OnFailure(uint16 websocket_error) OVERRIDE {
+ owner_->websocket_error_ = websocket_error;
+ }
+
+ private:
+ WebSocketStreamCreateTest* owner_;
+ };
+
+ WebSocketTestURLRequestContextHost url_request_context_host_;
+ scoped_ptr<WebSocketStreamRequest> stream_request_;
+ // Only set if the connection succeeded.
+ scoped_ptr<WebSocketStream> stream_;
+ // Only set if the connection failed. 0 otherwise.
+ uint16 websocket_error_;
+};
+
+// Confirm that the basic case works as expected.
+TEST_F(WebSocketStreamCreateTest, SimpleSuccess) {
+ CreateAndConnectStandard(
+ "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", "");
+ RunUntilIdle();
+ EXPECT_TRUE(stream_);
+}
+
+// Confirm that the stream isn't established until the message loop runs.
+TEST_F(WebSocketStreamCreateTest, NeedsToRunLoop) {
+ CreateAndConnectStandard(
+ "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", "");
+ EXPECT_FALSE(stream_);
+}
+
+// Check the path is used.
+TEST_F(WebSocketStreamCreateTest, PathIsUsed) {
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ "");
+ RunUntilIdle();
+ EXPECT_TRUE(stream_);
+}
+
+// Check that the origin is used.
+TEST_F(WebSocketStreamCreateTest, OriginIsUsed) {
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ NoSubProtocols(),
+ "http://google.com/",
+ "",
+ "");
+ RunUntilIdle();
+ EXPECT_TRUE(stream_);
+}
+
+// Check that sub-protocols are sent and parsed.
+TEST_F(WebSocketStreamCreateTest, SubProtocolIsUsed) {
+ std::vector<std::string> sub_protocols;
+ sub_protocols.push_back("chatv11.chromium.org");
+ sub_protocols.push_back("chatv20.chromium.org");
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ sub_protocols,
+ "http://google.com/",
+ "Sec-WebSocket-Protocol: chatv11.chromium.org, "
+ "chatv20.chromium.org\r\n",
+ "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n");
+ RunUntilIdle();
+ EXPECT_TRUE(stream_);
+ EXPECT_EQ("chatv20.chromium.org", stream_->GetSubProtocol());
+}
+
+// Unsolicited sub-protocols are rejected.
+TEST_F(WebSocketStreamCreateTest, UnsolicitedSubProtocol) {
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ NoSubProtocols(),
+ "http://google.com/",
+ "",
+ "Sec-WebSocket-Protocol: chatv20.chromium.org\r\n");
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+ EXPECT_EQ(1006, error());
+}
+
+// Missing sub-protocol response is rejected.
+TEST_F(WebSocketStreamCreateTest, UnacceptedSubProtocol) {
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ std::vector<std::string>(1, "chat.example.com"),
+ "http://localhost/",
+ "Sec-WebSocket-Protocol: chat.example.com\r\n",
+ "");
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+ EXPECT_EQ(1006, error());
+}
+
+// Only one sub-protocol can be accepted.
+TEST_F(WebSocketStreamCreateTest, MultipleSubProtocolsInResponse) {
+ std::vector<std::string> sub_protocols;
+ sub_protocols.push_back("chatv11.chromium.org");
+ sub_protocols.push_back("chatv20.chromium.org");
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ sub_protocols,
+ "http://google.com/",
+ "Sec-WebSocket-Protocol: chatv11.chromium.org, "
+ "chatv20.chromium.org\r\n",
+ "Sec-WebSocket-Protocol: chatv11.chromium.org, "
+ "chatv20.chromium.org\r\n");
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+ EXPECT_EQ(1006, error());
+}
+
+// Unknown extension in the response is rejected
+TEST_F(WebSocketStreamCreateTest, UnknownExtension) {
+ CreateAndConnectStandard("ws://localhost/testing_path",
+ "/testing_path",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ "Sec-WebSocket-Extensions: x-unknown-extension\r\n");
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+ EXPECT_EQ(1006, error());
+}
+
+// Additional Sec-WebSocket-Accept headers should be rejected.
+TEST_F(WebSocketStreamCreateTest, DoubleAccept) {
+ CreateAndConnectStandard(
+ "ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n");
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+ EXPECT_EQ(1006, error());
+}
+
+// Response code 200 must be rejected.
+TEST_F(WebSocketStreamCreateTest, InvalidStatusCode) {
+ static const char kInvalidStatusCodeResponse[] =
+ "HTTP/1.1 200 OK\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kInvalidStatusCodeResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Redirects are not followed (according to the WHATWG WebSocket API, which
+// overrides RFC6455 for browser applications).
+TEST_F(WebSocketStreamCreateTest, RedirectsRejected) {
+ static const char kRedirectResponse[] =
+ "HTTP/1.1 302 Moved Temporarily\r\n"
+ "Content-Type: text/html\r\n"
+ "Content-Length: 34\r\n"
+ "Connection: keep-alive\r\n"
+ "Location: ws://localhost/other\r\n"
+ "\r\n"
+ "<title>Moved</title><h1>Moved</h1>";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kRedirectResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Malformed responses should be rejected. HttpStreamParser will accept just
+// about any garbage in the middle of the headers. To make it give up, the junk
+// has to be at the start of the response. Even then, it just gets treated as an
+// HTTP/0.9 response.
+TEST_F(WebSocketStreamCreateTest, MalformedResponse) {
+ static const char kMalformedResponse[] =
+ "220 mx.google.com ESMTP\r\n"
+ "HTTP/1.1 101 OK\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kMalformedResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Upgrade header must be present.
+TEST_F(WebSocketStreamCreateTest, MissingUpgradeHeader) {
+ static const char kMissingUpgradeResponse[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kMissingUpgradeResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// There must only be one upgrade header.
+TEST_F(WebSocketStreamCreateTest, DoubleUpgradeHeader) {
+ CreateAndConnectStandard(
+ "ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "", "Upgrade: HTTP/2.0\r\n");
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Connection header must be present.
+TEST_F(WebSocketStreamCreateTest, MissingConnectionHeader) {
+ static const char kMissingConnectionResponse[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kMissingConnectionResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Connection header is permitted to contain other tokens.
+TEST_F(WebSocketStreamCreateTest, AdditionalTokenInConnectionHeader) {
+ static const char kAdditionalConnectionTokenResponse[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade, Keep-Alive\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kAdditionalConnectionTokenResponse);
+ RunUntilIdle();
+ EXPECT_TRUE(stream_);
+}
+
+// Sec-WebSocket-Accept header must be present.
+TEST_F(WebSocketStreamCreateTest, MissingSecWebSocketAccept) {
+ static const char kMissingAcceptResponse[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kMissingAcceptResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Sec-WebSocket-Accept header must match the key that was sent.
+TEST_F(WebSocketStreamCreateTest, WrongSecWebSocketAccept) {
+ static const char kIncorrectAcceptResponse[] =
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: x/byyPZ2tOFvJCGkkugcKvqhhPk=\r\n"
+ "\r\n";
+ CreateAndConnectCustomResponse("ws://localhost/",
+ "/",
+ NoSubProtocols(),
+ "http://localhost/",
+ "",
+ kIncorrectAcceptResponse);
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Cancellation works.
+TEST_F(WebSocketStreamCreateTest, Cancellation) {
+ CreateAndConnectStandard(
+ "ws://localhost/", "/", NoSubProtocols(), "http://localhost/", "", "");
+ stream_request_.reset();
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+}
+
+// Connect failure must look just like negotiation failure.
+TEST_F(WebSocketStreamCreateTest, ConnectionFailure) {
+ scoped_ptr<DeterministicSocketData> socket_data(
+ new DeterministicSocketData(NULL, 0, NULL, 0));
+ socket_data->set_connect_data(
+ MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
+ CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
+ "http://localhost/", socket_data.Pass());
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Connect timeout must look just like any other failure.
+TEST_F(WebSocketStreamCreateTest, ConnectionTimeout) {
+ scoped_ptr<DeterministicSocketData> socket_data(
+ new DeterministicSocketData(NULL, 0, NULL, 0));
+ socket_data->set_connect_data(
+ MockConnect(ASYNC, ERR_CONNECTION_TIMED_OUT));
+ CreateAndConnectRawExpectations("ws://localhost/", NoSubProtocols(),
+ "http://localhost/", socket_data.Pass());
+ RunUntilIdle();
+ EXPECT_EQ(1006, error());
+}
+
+// Cancellation during connect works.
+TEST_F(WebSocketStreamCreateTest, CancellationDuringConnect) {
+ scoped_ptr<DeterministicSocketData> socket_data(
+ new DeterministicSocketData(NULL, 0, NULL, 0));
+ socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
+ CreateAndConnectRawExpectations("ws://localhost/",
+ NoSubProtocols(),
+ "http://localhost/",
+ socket_data.Pass());
+ stream_request_.reset();
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+}
+
+// Cancellation during write of the request headers works.
+TEST_F(WebSocketStreamCreateTest, CancellationDuringWrite) {
+ // We seem to need at least two operations in order to use SetStop().
+ MockWrite writes[] = {MockWrite(ASYNC, 0, "GET / HTTP/"),
+ MockWrite(ASYNC, 1, "1.1\r\n")};
+ // We keep a copy of the pointer so that we can call RunFor() on it later.
+ DeterministicSocketData* socket_data(
+ new DeterministicSocketData(NULL, 0, writes, arraysize(writes)));
+ socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ socket_data->SetStop(1);
+ CreateAndConnectRawExpectations("ws://localhost/",
+ NoSubProtocols(),
+ "http://localhost/",
+ make_scoped_ptr(socket_data));
+ socket_data->Run();
+ stream_request_.reset();
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+}
+
+// Cancellation during read of the response headers works.
+TEST_F(WebSocketStreamCreateTest, CancellationDuringRead) {
+ std::string request = WebSocketStandardRequest("/", "http://localhost/", "");
+ MockWrite writes[] = {MockWrite(ASYNC, 0, request.c_str())};
+ MockRead reads[] = {
+ MockRead(ASYNC, 1, "HTTP/1.1 101 Switching Protocols\r\nUpgr"),
+ };
+ DeterministicSocketData* socket_data(new DeterministicSocketData(
+ reads, arraysize(reads), writes, arraysize(writes)));
+ socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ socket_data->SetStop(1);
+ CreateAndConnectRawExpectations("ws://localhost/",
+ NoSubProtocols(),
+ "http://localhost/",
+ make_scoped_ptr(socket_data));
+ socket_data->Run();
+ stream_request_.reset();
+ RunUntilIdle();
+ EXPECT_FALSE(stream_);
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/websockets/websocket_test_util.cc b/chromium/net/websockets/websocket_test_util.cc
new file mode 100644
index 00000000000..55113c6f15c
--- /dev/null
+++ b/chromium/net/websockets/websocket_test_util.cc
@@ -0,0 +1,125 @@
+// 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/websockets/websocket_test_util.h"
+
+#include "base/basictypes.h"
+#include "base/strings/stringprintf.h"
+#include "net/socket/socket_test_util.h"
+
+namespace net {
+
+namespace {
+const uint64 kA =
+ (static_cast<uint64>(0x5851f42d) << 32) + static_cast<uint64>(0x4c957f2d);
+const uint64 kC = 12345;
+const uint64 kM = static_cast<uint64>(1) << 48;
+
+} // namespace
+
+LinearCongruentialGenerator::LinearCongruentialGenerator(uint32 seed)
+ : current_(seed) {}
+
+uint32 LinearCongruentialGenerator::Generate() {
+ uint64 result = current_;
+ current_ = (current_ * kA + kC) % kM;
+ return static_cast<uint32>(result >> 16);
+}
+
+std::string WebSocketStandardRequest(const std::string& path,
+ const std::string& origin,
+ const std::string& extra_headers) {
+ // Unrelated changes in net/http may change the order and default-values of
+ // HTTP headers, causing WebSocket tests to fail. It is safe to update this
+ // string in that case.
+ return base::StringPrintf(
+ "GET %s HTTP/1.1\r\n"
+ "Host: localhost\r\n"
+ "Connection: Upgrade\r\n"
+ "Upgrade: websocket\r\n"
+ "Origin: %s\r\n"
+ "Sec-WebSocket-Version: 13\r\n"
+ "User-Agent:\r\n"
+ "Accept-Encoding: gzip,deflate\r\n"
+ "Accept-Language: en-us,fr\r\n"
+ "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
+ "%s\r\n",
+ path.c_str(),
+ origin.c_str(),
+ extra_headers.c_str());
+}
+
+std::string WebSocketStandardResponse(const std::string& extra_headers) {
+ return base::StringPrintf(
+ "HTTP/1.1 101 Switching Protocols\r\n"
+ "Upgrade: websocket\r\n"
+ "Connection: Upgrade\r\n"
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
+ "%s\r\n",
+ extra_headers.c_str());
+}
+
+struct WebSocketDeterministicMockClientSocketFactoryMaker::Detail {
+ std::string expect_written;
+ std::string return_to_read;
+ MockRead read;
+ MockWrite write;
+ scoped_ptr<DeterministicSocketData> data;
+ DeterministicMockClientSocketFactory factory;
+};
+
+WebSocketDeterministicMockClientSocketFactoryMaker::
+ WebSocketDeterministicMockClientSocketFactoryMaker()
+ : detail_(new Detail) {}
+
+WebSocketDeterministicMockClientSocketFactoryMaker::
+ ~WebSocketDeterministicMockClientSocketFactoryMaker() {}
+
+DeterministicMockClientSocketFactory*
+WebSocketDeterministicMockClientSocketFactoryMaker::factory() {
+ return &detail_->factory;
+}
+
+void WebSocketDeterministicMockClientSocketFactoryMaker::SetExpectations(
+ const std::string& expect_written,
+ const std::string& return_to_read) {
+ // We need to extend the lifetime of these strings.
+ detail_->expect_written = expect_written;
+ detail_->return_to_read = return_to_read;
+ detail_->write = MockWrite(SYNCHRONOUS, 0, detail_->expect_written.c_str());
+ detail_->read = MockRead(SYNCHRONOUS, 1, detail_->return_to_read.c_str());
+ scoped_ptr<DeterministicSocketData> socket_data(
+ new DeterministicSocketData(&detail_->read, 1, &detail_->write, 1));
+ socket_data->set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ socket_data->SetStop(2);
+ SetRawExpectations(socket_data.Pass());
+}
+
+void WebSocketDeterministicMockClientSocketFactoryMaker::SetRawExpectations(
+ scoped_ptr<DeterministicSocketData> socket_data) {
+ detail_->data = socket_data.Pass();
+ detail_->factory.AddSocketDataProvider(detail_->data.get());
+}
+
+WebSocketTestURLRequestContextHost::WebSocketTestURLRequestContextHost()
+ : url_request_context_(true) {
+ url_request_context_.set_client_socket_factory(maker_.factory());
+}
+
+WebSocketTestURLRequestContextHost::~WebSocketTestURLRequestContextHost() {}
+
+void WebSocketTestURLRequestContextHost::SetRawExpectations(
+ scoped_ptr<DeterministicSocketData> socket_data) {
+ maker_.SetRawExpectations(socket_data.Pass());
+}
+
+TestURLRequestContext*
+WebSocketTestURLRequestContextHost::GetURLRequestContext() {
+ url_request_context_.Init();
+ // A Network Delegate is required to make the URLRequest::Delegate work.
+ url_request_context_.set_network_delegate(&network_delegate_);
+ return &url_request_context_;
+}
+
+} // namespace net
diff --git a/chromium/net/websockets/websocket_test_util.h b/chromium/net/websockets/websocket_test_util.h
new file mode 100644
index 00000000000..71b2ce668c8
--- /dev/null
+++ b/chromium/net/websockets/websocket_test_util.h
@@ -0,0 +1,114 @@
+// 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_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_
+#define NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/url_request/url_request_test_util.h"
+#include "net/websockets/websocket_stream.h"
+
+class GURL;
+
+namespace net {
+
+class BoundNetLog;
+class DeterministicSocketData;
+class URLRequestContext;
+class WebSocketHandshakeStreamCreateHelper;
+class DeterministicMockClientSocketFactory;
+
+class LinearCongruentialGenerator {
+ public:
+ explicit LinearCongruentialGenerator(uint32 seed);
+ uint32 Generate();
+
+ private:
+ uint64 current_;
+};
+
+// Alternate version of WebSocketStream::CreateAndConnectStream() for testing
+// use only. The difference is the use of a |create_helper| argument in place of
+// |requested_subprotocols|. Implemented in websocket_stream.cc.
+NET_EXPORT_PRIVATE extern scoped_ptr<WebSocketStreamRequest>
+ CreateAndConnectStreamForTesting(
+ const GURL& socket_url,
+ scoped_ptr<WebSocketHandshakeStreamCreateHelper> create_helper,
+ const GURL& origin,
+ URLRequestContext* url_request_context,
+ const BoundNetLog& net_log,
+ scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate);
+
+// Generates a standard WebSocket handshake request. The challenge key used is
+// "dGhlIHNhbXBsZSBub25jZQ==". Each header in |extra_headers| must be terminated
+// with "\r\n".
+extern std::string WebSocketStandardRequest(const std::string& path,
+ const std::string& origin,
+ const std::string& extra_headers);
+
+// A response with the appropriate accept header to match the above challenge
+// key. Each header in |extra_headers| must be terminated with "\r\n".
+extern std::string WebSocketStandardResponse(const std::string& extra_headers);
+
+// This class provides a convenient way to construct a
+// DeterministicMockClientSocketFactory for WebSocket tests.
+class WebSocketDeterministicMockClientSocketFactoryMaker {
+ public:
+ WebSocketDeterministicMockClientSocketFactoryMaker();
+ ~WebSocketDeterministicMockClientSocketFactoryMaker();
+
+ // The socket created by the factory will expect |expect_written| to be
+ // written to the socket, and will respond with |return_to_read|. The test
+ // will fail if the expected text is not written, or all the bytes are not
+ // read.
+ void SetExpectations(const std::string& expect_written,
+ const std::string& return_to_read);
+
+ // A low-level interface to permit arbitrary expectations to be set.
+ void SetRawExpectations(scoped_ptr<DeterministicSocketData> socket_data);
+
+ // Call to get a pointer to the factory, which remains owned by this object.
+ DeterministicMockClientSocketFactory* factory();
+
+ private:
+ struct Detail;
+ scoped_ptr<Detail> detail_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketDeterministicMockClientSocketFactoryMaker);
+};
+
+// This class encapsulates the details of creating a
+// TestURLRequestContext that returns mock ClientSocketHandles that do what is
+// required by the tests.
+struct WebSocketTestURLRequestContextHost {
+ public:
+ WebSocketTestURLRequestContextHost();
+ ~WebSocketTestURLRequestContextHost();
+
+ void SetExpectations(const std::string& expect_written,
+ const std::string& return_to_read) {
+ maker_.SetExpectations(expect_written, return_to_read);
+ }
+
+ void SetRawExpectations(scoped_ptr<DeterministicSocketData> socket_data);
+
+ // Call after calling one of SetExpections() or SetRawExpectations(). The
+ // returned pointer remains owned by this object. This should only be called
+ // once.
+ TestURLRequestContext* GetURLRequestContext();
+
+ private:
+ WebSocketDeterministicMockClientSocketFactoryMaker maker_;
+ TestURLRequestContext url_request_context_;
+ TestNetworkDelegate network_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketTestURLRequestContextHost);
+};
+
+} // namespace net
+
+#endif // NET_WEBSOCKETS_WEBSOCKET_TEST_UTIL_H_