1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_TEST_TEST_SERVER_H_
6#define NET_TEST_TEST_SERVER_H_
7#pragma once
8
9#include <string>
10#include <utility>
11#include <vector>
12
13#include "build/build_config.h"
14
15#include "base/compiler_specific.h"
16#include "base/file_path.h"
17#include "base/file_util.h"
18#include "base/process_util.h"
19#include "net/base/host_port_pair.h"
20#include "net/base/net_util.h"
21
22#if defined(OS_WIN)
23#include "base/win/scoped_handle.h"
24#endif
25
26class CommandLine;
27class DictionaryValue;
28class GURL;
29
30namespace net {
31
32class AddressList;
33
34// This object bounds the lifetime of an external python-based HTTP/FTP server
35// that can provide various responses useful for testing.
36class TestServer {
37 public:
38  typedef std::pair<std::string, std::string> StringPair;
39
40  enum Type {
41    TYPE_FTP,
42    TYPE_HTTP,
43    TYPE_HTTPS,
44    TYPE_SYNC,
45  };
46
47  // Container for various options to control how the HTTPS server is
48  // initialized.
49  struct HTTPSOptions {
50    enum ServerCertificate {
51      CERT_OK,
52      CERT_MISMATCHED_NAME,
53      CERT_EXPIRED,
54    };
55
56    // Bitmask of bulk encryption algorithms that the test server supports
57    // and that can be selectively enabled or disabled.
58    enum BulkCipher {
59      // Special value used to indicate that any algorithm the server supports
60      // is acceptable. Preferred over explicitly OR-ing all ciphers.
61      BULK_CIPHER_ANY    = 0,
62
63      BULK_CIPHER_RC4    = (1 << 0),
64      BULK_CIPHER_AES128 = (1 << 1),
65      BULK_CIPHER_AES256 = (1 << 2),
66
67      // NOTE: 3DES support in the Python test server has external
68      // dependencies and not be available on all machines. Clients may not
69      // be able to connect if only 3DES is specified.
70      BULK_CIPHER_3DES   = (1 << 3),
71    };
72
73    // Initialize a new HTTPSOptions using CERT_OK as the certificate.
74    HTTPSOptions();
75
76    // Initialize a new HTTPSOptions that will use the specified certificate.
77    explicit HTTPSOptions(ServerCertificate cert);
78    ~HTTPSOptions();
79
80    // Returns the relative filename of the file that contains the
81    // |server_certificate|.
82    FilePath GetCertificateFile() const;
83
84    // The certificate to use when serving requests.
85    ServerCertificate server_certificate;
86
87    // True if a CertificateRequest should be sent to the client during
88    // handshaking.
89    bool request_client_certificate;
90
91    // If |request_client_certificate| is true, an optional list of files,
92    // each containing a single, PEM-encoded X.509 certificates. The subject
93    // from each certificate will be added to the certificate_authorities
94    // field of the CertificateRequest.
95    std::vector<FilePath> client_authorities;
96
97    // A bitwise-OR of BulkCipher that should be used by the
98    // HTTPS server, or BULK_CIPHER_ANY to indicate that all implemented
99    // ciphers are acceptable.
100    int bulk_ciphers;
101  };
102
103  TestServer(Type type, const FilePath& document_root);
104
105  // Initialize a HTTPS TestServer with a specific set of HTTPSOptions.
106  TestServer(const HTTPSOptions& https_options,
107             const FilePath& document_root);
108
109  ~TestServer();
110
111  bool Start() WARN_UNUSED_RESULT;
112
113  // Stop the server started by Start().
114  bool Stop();
115
116  const FilePath& document_root() const { return document_root_; }
117  const HostPortPair& host_port_pair() const;
118  const DictionaryValue& server_data() const;
119  std::string GetScheme() const;
120  bool GetAddressList(AddressList* address_list) const WARN_UNUSED_RESULT;
121
122  GURL GetURL(const std::string& path) const;
123
124  GURL GetURLWithUser(const std::string& path,
125                      const std::string& user) const;
126
127  GURL GetURLWithUserAndPassword(const std::string& path,
128                                 const std::string& user,
129                                 const std::string& password) const;
130
131  static bool GetFilePathWithReplacements(
132      const std::string& original_path,
133      const std::vector<StringPair>& text_to_replace,
134      std::string* replacement_path);
135
136 private:
137  void Init(const FilePath& document_root);
138
139  // Modify PYTHONPATH to contain libraries we need.
140  bool SetPythonPath() WARN_UNUSED_RESULT;
141
142  // Launches the Python test server. Returns true on success.
143  bool LaunchPython(const FilePath& testserver_path) WARN_UNUSED_RESULT;
144
145  // Waits for the server to start. Returns true on success.
146  bool WaitToStart() WARN_UNUSED_RESULT;
147
148  // Parses the server data read from the test server.  Returns true
149  // on success.
150  bool ParseServerData(const std::string& server_data) WARN_UNUSED_RESULT;
151
152  // Returns path to the root certificate.
153  FilePath GetRootCertificatePath() const;
154
155  // Load the test root cert, if it hasn't been loaded yet.
156  bool LoadTestRootCert() WARN_UNUSED_RESULT;
157
158  // Add the command line arguments for the Python test server to
159  // |command_line|. Return true on success.
160  bool AddCommandLineArguments(CommandLine* command_line) const;
161
162  // Document root of the test server.
163  FilePath document_root_;
164
165  // Directory that contains the SSL certificates.
166  FilePath certificates_dir_;
167
168  // Address the test server listens on.
169  HostPortPair host_port_pair_;
170
171  // Holds the data sent from the server (e.g., port number).
172  scoped_ptr<DictionaryValue> server_data_;
173
174  // Handle of the Python process running the test server.
175  base::ProcessHandle process_handle_;
176
177  scoped_ptr<net::ScopedPortException> allowed_port_;
178
179#if defined(OS_WIN)
180  // JobObject used to clean up orphaned child processes.
181  base::win::ScopedHandle job_handle_;
182
183  // The pipe file handle we read from.
184  base::win::ScopedHandle child_read_fd_;
185
186  // The pipe file handle the child and we write to.
187  base::win::ScopedHandle child_write_fd_;
188#endif
189
190#if defined(OS_POSIX)
191  // The file descriptor the child writes to when it starts.
192  int child_fd_;
193  file_util::ScopedFD child_fd_closer_;
194#endif
195
196  // If |type_| is TYPE_HTTPS, the TLS settings to use for the test server.
197  HTTPSOptions https_options_;
198
199  Type type_;
200
201  // Has the server been started?
202  bool started_;
203
204  DISALLOW_COPY_AND_ASSIGN(TestServer);
205};
206
207}  // namespace net
208
209#endif  // NET_TEST_TEST_SERVER_H_
210