summaryrefslogtreecommitdiffstats
path: root/net/test/test_server.h
blob: 8affc12b91ca32d138ea4f76327419aa77bee982 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_TEST_TEST_SERVER_H_
#define NET_TEST_TEST_SERVER_H_
#pragma once

#include <string>
#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"

#if defined(OS_WIN)
#include "base/scoped_handle_win.h"
#endif

#if defined(USE_NSS)
#include "base/ref_counted.h"
#include "net/base/x509_certificate.h"
#endif

class CommandLine;
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:
  enum Type {
    TYPE_FTP,
    TYPE_HTTP,
    TYPE_HTTPS,
  };

  // 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 { return host_port_pair_; }
  std::string GetScheme() const;
  bool GetAddressList(AddressList* address_list) const WARN_UNUSED_RESULT;

  GURL GetURL(const std::string& path);

  GURL GetURLWithUser(const std::string& path,
                      const std::string& user);

  GURL GetURLWithUserAndPassword(const std::string& path,
                                 const std::string& user,
                                 const std::string& password);

 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;

  // Returns path to the root certificate.
  FilePath GetRootCertificatePath();

  // Returns false if our test root certificate is not trusted.
  bool CheckCATrusted() WARN_UNUSED_RESULT;

  // 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_;

  // Handle of the Python process running the test server.
  base::ProcessHandle process_handle_;

#if defined(OS_WIN)
  // JobObject used to clean up orphaned child processes.
  ScopedHandle job_handle_;

  // The pipe file handle we read from.
  ScopedHandle child_read_fd_;

  // The pipe file handle the child and we write to.
  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_;

#if defined(USE_NSS)
  scoped_refptr<X509Certificate> cert_;
#endif

  Type type_;

  DISALLOW_COPY_AND_ASSIGN(TestServer);
};

}  // namespace net

#endif  // NET_TEST_TEST_SERVER_H_