| Index: net/test/android/javatests/src/org/chromium/net/test/TestServerBuilder.java
|
| diff --git a/net/test/android/javatests/src/org/chromium/net/test/TestServerBuilder.java b/net/test/android/javatests/src/org/chromium/net/test/TestServerBuilder.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3b52ab14d06e314570a674e4e5d44ab878dea59c
|
| --- /dev/null
|
| +++ b/net/test/android/javatests/src/org/chromium/net/test/TestServerBuilder.java
|
| @@ -0,0 +1,341 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.net.test;
|
| +
|
| +import android.util.Log;
|
| +
|
| +import org.json.JSONArray;
|
| +import org.json.JSONException;
|
| +import org.json.JSONObject;
|
| +
|
| +import java.util.ArrayList;
|
| +import java.util.Collections;
|
| +import java.util.HashSet;
|
| +import java.util.Iterator;
|
| +import java.util.List;
|
| +import java.util.Set;
|
| +import java.util.regex.Pattern;
|
| +
|
| +/** Creates instances of BaseTestServer.
|
| + *
|
| + * This will eventually create instances of:
|
| + * - FtpTestServer
|
| + * - HttpTestServer
|
| + * - TcpEchoTestServer
|
| + * - UdpEchoTestServer
|
| + * - WebsocketTestServer
|
| + * depending on the parameters passed to the constructor.
|
| + */
|
| +class TestServerBuilder {
|
| + private static final String TAG = "TestServerBuilder";
|
| +
|
| + private static final Pattern SWITCH_PREFIX_RE = Pattern.compile("--");
|
| + private static final Pattern SWITCH_VALUE_SEPARATOR_RE = Pattern.compile("=");
|
| +
|
| + private static final Set<String> OCSP_RESPONSES;
|
| + private static final Set<String> SSL_BULK_CIPHERS;
|
| + private static final Set<String> SSL_CLIENT_CERT_TYPES;
|
| + private static final Set<String> SSL_KEY_EXCHANGE_ALGORITHMS;
|
| + private static final Set<String> TLS_INTOLERANCE_TYPES;
|
| + static {
|
| + HashSet<String> ocspResponses = new HashSet<String>();
|
| + ocspResponses.add("ok");
|
| + ocspResponses.add("revoked");
|
| + ocspResponses.add("invalid");
|
| + OCSP_RESPONSES = Collections.unmodifiableSet(ocspResponses);
|
| +
|
| + HashSet<String> sslBulkCiphers = new HashSet<String>();
|
| + sslBulkCiphers.add("aes256");
|
| + sslBulkCiphers.add("aes128");
|
| + sslBulkCiphers.add("3des");
|
| + sslBulkCiphers.add("rc4");
|
| + SSL_BULK_CIPHERS = Collections.unmodifiableSet(sslBulkCiphers);
|
| +
|
| + HashSet<String> sslClientCertTypes = new HashSet<String>();
|
| + sslClientCertTypes.add("rsa_sign");
|
| + sslClientCertTypes.add("dss_sign");
|
| + sslClientCertTypes.add("ecdsa_sign");
|
| + SSL_CLIENT_CERT_TYPES = Collections.unmodifiableSet(sslClientCertTypes);
|
| +
|
| + HashSet<String> sslKeyExchangeAlgorithms = new HashSet<String>();
|
| + sslKeyExchangeAlgorithms.add("rsa");
|
| + sslKeyExchangeAlgorithms.add("dhe_rsa");
|
| + SSL_KEY_EXCHANGE_ALGORITHMS = Collections.unmodifiableSet(sslKeyExchangeAlgorithms);
|
| +
|
| + HashSet<String> tlsIntoleranceTypes = new HashSet<String>();
|
| + tlsIntoleranceTypes.add("alert");
|
| + tlsIntoleranceTypes.add("close");
|
| + tlsIntoleranceTypes.add("reset");
|
| + TLS_INTOLERANCE_TYPES = Collections.unmodifiableSet(tlsIntoleranceTypes);
|
| + }
|
| +
|
| + private enum TlsIntolerant {
|
| + MIN(0),
|
| +
|
| + TOLERATE_ALL(0),
|
| + ABORT_ALL(1),
|
| + ABORT_1_1_AND_ABOVE(2),
|
| + ABORT_1_2_AND_ABOVE(3),
|
| +
|
| + MAX(3);
|
| +
|
| + private TlsIntolerant(int value) {
|
| + mValue = value;
|
| + }
|
| +
|
| + public int value() {
|
| + return mValue;
|
| + }
|
| +
|
| + private final int mValue;
|
| + }
|
| +
|
| + private enum ServerType {
|
| + HTTP,
|
| + FTP,
|
| + TCP_ECHO,
|
| + UDP_ECHO,
|
| + BASIC_AUTH_PROXY,
|
| + WEBSOCKET,
|
| + }
|
| +
|
| + // The path to the file containing the certificate and private key that the server should use,
|
| + // in PEM format.
|
| + private String mCertAndKeyFile;
|
| +
|
| + // Directory from which the server should read data files.
|
| + private String mDataDir;
|
| +
|
| + // If true, the server should disable the TLS session cache. Defaults to false.
|
| + private boolean mDisableSessionCache;
|
| +
|
| + // Root URL for files served. Defaults to "/files/"
|
| + private String mFileRootUrl = "/files/";
|
| +
|
| + // Hostname or IP the server should listen on and accept connections from.
|
| + // Defaults to "127.0.0.1"
|
| + private String mHost = "127.0.0.1";
|
| +
|
| + // If true, the server should use HTTPS.
|
| + private boolean mHttps;
|
| +
|
| + // If true, log to the logcat.
|
| + private boolean mLogToConsole;
|
| +
|
| + // Type of OCSP response generated. Defaults to "ok".
|
| + private String mOcsp = "ok";
|
| +
|
| + // Port to be used by the server.
|
| + private int mPort;
|
| +
|
| + // Type of server to build.
|
| + private ServerType mServerType = ServerType.HTTP;
|
| +
|
| + // The bulk encryption algorithms that should be accepted by the server.
|
| + // Defaults to "aes256", "aes128", "3des", "rc4"
|
| + private List<String> mSslBulkCiphers;
|
| +
|
| + // If true, the server should require SSL client authentication on every connection.
|
| + // Defaults to false.
|
| + private boolean mSslClientAuth;
|
| +
|
| + // The CA names that should be included in the client certificate requests.
|
| + private List<String> mSslClientCas;
|
| +
|
| + // The certificate_types that should be included in the client certificate request.
|
| + // Defaults to "rsa_sign"
|
| + private List<String> mSslClientCertTypes;
|
| +
|
| + // The key exchange algorithms that should be accepted by the server.
|
| + // Defaults to "rsa", "dhe_rsa"
|
| + private List<String> mSslKeyExchanges;
|
| +
|
| + /** Create a TestServerBuilder.
|
| + *
|
| + * @param json The server configuration. Determines the type of server spawned and the specific
|
| + * configuration thereof.
|
| + */
|
| + public TestServerBuilder(JSONObject json) throws JSONException {
|
| + mSslBulkCiphers = new ArrayList<String>(SSL_BULK_CIPHERS);
|
| + mSslClientCas = new ArrayList<String>();
|
| + mSslClientCertTypes = new ArrayList<String>();
|
| + mSslClientCertTypes.add("rsa_sign");
|
| + mSslKeyExchanges = new ArrayList<String>(SSL_KEY_EXCHANGE_ALGORITHMS);
|
| +
|
| + parse(json);
|
| + }
|
| +
|
| + /** Create a BaseTestServer.
|
| + *
|
| + * @return An instance of BaseTestServer.
|
| + */
|
| + public BaseTestServer build() {
|
| + Log.i(TAG, "building with: " + toString());
|
| +
|
| + // TODO(jbudorick): Implement this in a subsequent CL.
|
| + throw new UnsupportedOperationException(
|
| + "TestServerBuilder.build() hasn't been implemented yet.");
|
| + }
|
| +
|
| + private void parse(JSONObject json) throws JSONException {
|
| + Iterator<String> keyIter = json.keys();
|
| + while (keyIter.hasNext()) {
|
| + String key = keyIter.next();
|
| + Log.i(TAG, "Received key: " + key);
|
| + switch (key) {
|
| + case "cert-and-key-file":
|
| + mCertAndKeyFile = json.getString(key);
|
| + break;
|
| + case "data-dir":
|
| + mDataDir = json.getString(key);
|
| + break;
|
| + case "disable-session-cache":
|
| + mDisableSessionCache = true;
|
| + break;
|
| + case "host":
|
| + mHost = json.getString(key);
|
| + break;
|
| + case "https":
|
| + mHttps = true;
|
| + break;
|
| + case "log-to-console":
|
| + mLogToConsole = true;
|
| + break;
|
| + case "port":
|
| + mPort = json.getInt(key);
|
| + break;
|
| + case "server-type":
|
| + parseServerType(json.getString(key));
|
| + break;
|
| + case "ssl-client-auth":
|
| + mSslClientAuth = true;
|
| + break;
|
| + case "ssl-client-ca":
|
| + mSslClientCas = jsonArrayAsStringList(json.getJSONArray(key));
|
| + break;
|
| + case "ssl-key-exchange":
|
| + mSslKeyExchanges = jsonArrayAsStringList(json.getJSONArray(key));
|
| + if (SSL_KEY_EXCHANGE_ALGORITHMS.containsAll(mSslKeyExchanges)) {
|
| + mSslKeyExchanges.removeAll(SSL_KEY_EXCHANGE_ALGORITHMS);
|
| + throw new JSONException("invalid values provided for ssl-key-exchange: "
|
| + + mSslKeyExchanges.toString());
|
| + }
|
| + break;
|
| + default:
|
| + Log.e(TAG, "Unrecognized command-line flag: " + key);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| +
|
| + private void parseServerType(String serverType) throws JSONException {
|
| + switch (serverType) {
|
| + case "http":
|
| + mServerType = ServerType.HTTP;
|
| + break;
|
| + case "ftp":
|
| + mServerType = ServerType.FTP;
|
| + break;
|
| + case "tcp-echo":
|
| + mServerType = ServerType.TCP_ECHO;
|
| + break;
|
| + case "udp-echo":
|
| + mServerType = ServerType.UDP_ECHO;
|
| + break;
|
| + case "basic-auth-proxy":
|
| + mServerType = ServerType.BASIC_AUTH_PROXY;
|
| + break;
|
| + case "websocket":
|
| + mServerType = ServerType.WEBSOCKET;
|
| + break;
|
| + default:
|
| + throw new JSONException("Unrecognized server-type value: \"" + serverType + "\"");
|
| + }
|
| + }
|
| +
|
| + private static List<String> jsonArrayAsStringList(JSONArray jsonArray) throws JSONException {
|
| + List<String> result = new ArrayList<String>(jsonArray.length());
|
| + for (int i = 0; i < jsonArray.length(); ++i) {
|
| + result.set(i, jsonArray.getString(i));
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + public String toString() {
|
| + StringBuilder resultBuilder = new StringBuilder("{");
|
| + resultBuilder.append(formatString("mCertAndKeyFile", mCertAndKeyFile));
|
| + resultBuilder.append(formatString("mDataDir", mDataDir));
|
| + resultBuilder.append(formatBoolean("mDisableSessionCache", mDisableSessionCache));
|
| + resultBuilder.append(formatString("mFileRootUrl", mFileRootUrl));
|
| + resultBuilder.append(formatString("mHost", mHost));
|
| + resultBuilder.append(formatBoolean("mHttps", mHttps));
|
| + resultBuilder.append(formatBoolean("mLogToConsole", mLogToConsole));
|
| + resultBuilder.append(formatString("mOcsp", mOcsp));
|
| + resultBuilder.append(formatInt("mPort", mPort));
|
| + resultBuilder.append(formatServerType("mServerType", mServerType));
|
| + resultBuilder.append(formatList("mSslBulkCiphers", mSslBulkCiphers));
|
| + resultBuilder.append(formatBoolean("mSslClientAuth", mSslClientAuth));
|
| + resultBuilder.append(formatList("mSslClientCas", mSslClientCas));
|
| + resultBuilder.append(formatList("mSslClientCertTypes", mSslClientCertTypes));
|
| + resultBuilder.append(formatList("mSslKeyExchanges", mSslKeyExchanges));
|
| + resultBuilder.append("}");
|
| + return resultBuilder.toString();
|
| + }
|
| +
|
| + private String formatString(String label, String value) {
|
| + return "\"" + label + "\": \"" + formatString(value) + "\",";
|
| + }
|
| +
|
| + private String formatString(String value) {
|
| + return value != null ? value : "null";
|
| + }
|
| +
|
| + private String formatInt(String label, int value) {
|
| + return "\"" + label + "\": \"" + Integer.toString(value) + "\",";
|
| + }
|
| +
|
| + private String formatBoolean(String label, boolean value) {
|
| + return "\"" + label + "\": \"" + Boolean.toString(value) + "\",";
|
| + }
|
| +
|
| + private String formatList(String label, List<String> value) {
|
| + StringBuilder resultBuilder = new StringBuilder("\"");
|
| + resultBuilder.append(label).append("\": [");
|
| + for (String s : value) {
|
| + resultBuilder.append("\"").append(formatString(s)).append("\",");
|
| + }
|
| + resultBuilder.append("],");
|
| + return resultBuilder.toString();
|
| + }
|
| +
|
| + private String formatServerType(String label, ServerType serverType) {
|
| + String result = "\"mServerType\": \"";
|
| + switch (serverType) {
|
| + case HTTP:
|
| + result += "HTTP";
|
| + break;
|
| + case FTP:
|
| + result += "FTP";
|
| + break;
|
| + case TCP_ECHO:
|
| + result += "TCP_ECHO";
|
| + break;
|
| + case UDP_ECHO:
|
| + result += "UDP_ECHO";
|
| + break;
|
| + case BASIC_AUTH_PROXY:
|
| + result += "BASIC_AUTH_PROXY";
|
| + break;
|
| + case WEBSOCKET:
|
| + result += "WEBSOCKET";
|
| + break;
|
| + default:
|
| + result += "???";
|
| + break;
|
| + }
|
| + result += "\",";
|
| + return result;
|
| + }
|
| +}
|
|
|