// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_TEST_TEST_SERVER_H_ #define NET_TEST_TEST_SERVER_H_ #pragma once #include <string> #include <utility> #include <vector> #include "build/build_config.h" #include "base/compiler_specific.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/process_util.h" #include "net/base/host_port_pair.h" #include "net/base/net_util.h" #if defined(OS_WIN) #include "base/win/scoped_handle.h" #endif class CommandLine; class DictionaryValue; class GURL; namespace net { class AddressList; // This object bounds the lifetime of an external python-based HTTP/FTP server // that can provide various responses useful for testing. class TestServer { public: typedef std::pair<std::string, std::string> StringPair; enum Type { TYPE_FTP, TYPE_HTTP, TYPE_HTTPS, TYPE_SYNC, }; // Container for various options to control how the HTTPS server is // initialized. struct HTTPSOptions { enum ServerCertificate { CERT_OK, CERT_MISMATCHED_NAME, CERT_EXPIRED, }; // Bitmask of bulk encryption algorithms that the test server supports // and that can be selectively enabled or disabled. enum BulkCipher { // Special value used to indicate that any algorithm the server supports // is acceptable. Preferred over explicitly OR-ing all ciphers. BULK_CIPHER_ANY = 0, BULK_CIPHER_RC4 = (1 << 0), BULK_CIPHER_AES128 = (1 << 1), BULK_CIPHER_AES256 = (1 << 2), // NOTE: 3DES support in the Python test server has external // dependencies and not be available on all machines. Clients may not // be able to connect if only 3DES is specified. BULK_CIPHER_3DES = (1 << 3), }; // Initialize a new HTTPSOptions using CERT_OK as the certificate. HTTPSOptions(); // Initialize a new HTTPSOptions that will use the specified certificate. explicit HTTPSOptions(ServerCertificate cert); ~HTTPSOptions(); // Returns the relative filename of the file that contains the // |server_certificate|. FilePath GetCertificateFile() const; // The certificate to use when serving requests. ServerCertificate server_certificate; // True if a CertificateRequest should be sent to the client during // handshaking. bool request_client_certificate; // If |request_client_certificate| is true, an optional list of files, // each containing a single, PEM-encoded X.509 certificates. The subject // from each certificate will be added to the certificate_authorities // field of the CertificateRequest. std::vector<FilePath> client_authorities; // A bitwise-OR of BulkCipher that should be used by the // HTTPS server, or BULK_CIPHER_ANY to indicate that all implemented // ciphers are acceptable. int bulk_ciphers; }; TestServer(Type type, const FilePath& document_root); // Initialize a HTTPS TestServer with a specific set of HTTPSOptions. TestServer(const HTTPSOptions& https_options, const FilePath& document_root); ~TestServer(); bool Start() WARN_UNUSED_RESULT; // Stop the server started by Start(). bool Stop(); const FilePath& document_root() const { return document_root_; } const HostPortPair& host_port_pair() const; const DictionaryValue& server_data() const; std::string GetScheme() const; bool GetAddressList(AddressList* address_list) const WARN_UNUSED_RESULT; GURL GetURL(const std::string& path) const; GURL GetURLWithUser(const std::string& path, const std::string& user) const; GURL GetURLWithUserAndPassword(const std::string& path, const std::string& user, const std::string& password) const; static bool GetFilePathWithReplacements( const std::string& original_path, const std::vector<StringPair>& text_to_replace, std::string* replacement_path); private: void Init(const FilePath& document_root); // Modify PYTHONPATH to contain libraries we need. bool SetPythonPath() WARN_UNUSED_RESULT; // Launches the Python test server. Returns true on success. bool LaunchPython(const FilePath& testserver_path) WARN_UNUSED_RESULT; // Waits for the server to start. Returns true on success. bool WaitToStart() WARN_UNUSED_RESULT; // Parses the server data read from the test server. Returns true // on success. bool ParseServerData(const std::string& server_data) WARN_UNUSED_RESULT; // Returns path to the root certificate. FilePath GetRootCertificatePath() const; // Load the test root cert, if it hasn't been loaded yet. bool LoadTestRootCert() WARN_UNUSED_RESULT; // Add the command line arguments for the Python test server to // |command_line|. Return true on success. bool AddCommandLineArguments(CommandLine* command_line) const; // Document root of the test server. FilePath document_root_; // Directory that contains the SSL certificates. FilePath certificates_dir_; // Address the test server listens on. HostPortPair host_port_pair_; // Holds the data sent from the server (e.g., port number). scoped_ptr<DictionaryValue> server_data_; // Handle of the Python process running the test server. base::ProcessHandle process_handle_; scoped_ptr<net::ScopedPortException> allowed_port_; #if defined(OS_WIN) // JobObject used to clean up orphaned child processes. base::win::ScopedHandle job_handle_; // The pipe file handle we read from. base::win::ScopedHandle child_read_fd_; // The pipe file handle the child and we write to. base::win::ScopedHandle child_write_fd_; #endif #if defined(OS_POSIX) // The file descriptor the child writes to when it starts. int child_fd_; file_util::ScopedFD child_fd_closer_; #endif // If |type_| is TYPE_HTTPS, the TLS settings to use for the test server. HTTPSOptions https_options_; Type type_; // Has the server been started? bool started_; DISALLOW_COPY_AND_ASSIGN(TestServer); }; } // namespace net #endif // NET_TEST_TEST_SERVER_H_