/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package java.net;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import libcore.net.http.HttpEngine;

/**
 * An {@link URLConnection} for HTTP (<a
 * href="http://tools.ietf.org/html/rfc2616">RFC 2616</a>) used to send and
 * receive data over the web. Data may be of any type and length. This class may
 * be used to send and receive streaming data whose length is not known in
 * advance.
 *
 * <p>Uses of this class follow a pattern:
 * <ol>
 *   <li>Obtain a new {@code HttpURLConnection} by calling {@link
 *       URL#openConnection() URL.openConnection()} and casting the result to
 *       {@code HttpURLConnection}.
 *   <li>Prepare the request. The primary property of a request is its URI.
 *       Request headers may also include metadata such as credentials, preferred
 *       content types, and session cookies.
 *   <li>Optionally upload a request body. Instances must be configured with
 *       {@link #setDoOutput(boolean) setDoOutput(true)} if they include a
 *       request body. Transmit data by writing to the stream returned by {@link
 *       #getOutputStream()}.
 *   <li>Read the response. Response headers typically include metadata such as
 *       the response body's content type and length, modified dates and session
 *       cookies. The response body may be read from the stream returned by {@link
 *       #getInputStream()}. If the response has no body, that method returns an
 *       empty stream.
 *   <li>Disconnect. Once the response body has been read, the {@code
 *       HttpURLConnection} should be closed by calling {@link #disconnect()}.
 *       Disconnecting releases the resources held by a connection so they may
 *       be closed or reused.
 * </ol>
 *
 * <p>For example, to retrieve the webpage at {@code http://www.android.com/}:
 * <pre>   {@code
 *   URL url = new URL("http://www.android.com/");
 *   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
 *   try {
 *     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
 *     readStream(in);
 *   } finally {
 *     urlConnection.disconnect();
 *   }
 * }</pre>
 *
 * <h3>Secure Communication with HTTPS</h3>

 * Calling {@link URL#openConnection()} on a URL with the "https"
 * scheme will return an {@code HttpsURLConnection}, which allows for
 * overriding the default {@link javax.net.ssl.HostnameVerifier
 * HostnameVerifier} and {@link javax.net.ssl.SSLSocketFactory
 * SSLSocketFactory}. An application-supplied {@code SSLSocketFactory}
 * created from an {@link javax.net.ssl.SSLContext SSLContext} can
 * provide a custom {@link javax.net.ssl.X509TrustManager
 * X509TrustManager} for verifying certificate chains and a custom
 * {@link javax.net.ssl.X509KeyManager X509KeyManager} for supplying
 * client certificates. See {@link javax.net.ssl.HttpsURLConnection
 * HttpsURLConnection} for more details.
 *
 * <h3>Response Handling</h3>
 * {@code HttpURLConnection} will follow up to five HTTP redirects. It will
 * follow redirects from one origin server to another. This implementation
 * doesn't follow redirects from HTTPS to HTTP or vice versa.
 *
 * <p>If the HTTP response indicates that an error occurred, {@link
 * #getInputStream()} will throw an {@link IOException}. Use {@link
 * #getErrorStream()} to read the error response. The headers can be read in
 * the normal way using {@link #getHeaderFields()},
 *
 * <h3>Posting Content</h3>
 * To upload data to a web server, configure the connection for output using
 * {@link #setDoOutput(boolean) setDoOutput(true)}.
 *
 * <p>For best performance, you should call either {@link
 * #setFixedLengthStreamingMode(int)} when the body length is known in advance,
 * or {@link #setChunkedStreamingMode(int)} when it is not. Otherwise {@code
 * HttpURLConnection} will be forced to buffer the complete request body in
 * memory before it is transmitted, wasting (and possibly exhausting) heap and
 * increasing latency.
 *
 * <p>For example, to perform an upload: <pre>   {@code
 *   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
 *   try {
 *     urlConnection.setDoOutput(true);
 *     urlConnection.setChunkedStreamingMode(0);
 *
 *     OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
 *     writeStream(out);
 *
 *     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
 *     readStream(in);
 *   } finally {
 *     urlConnection.disconnect();
 *   }
 * }</pre>
 *
 * <h3>Performance</h3>
 * The input and output streams returned by this class are <strong>not
 * buffered</strong>. Most callers should wrap the returned streams with {@link
 * java.io.BufferedInputStream BufferedInputStream} or {@link
 * java.io.BufferedOutputStream BufferedOutputStream}. Callers that do only bulk
 * reads or writes may omit buffering.
 *
 * <p>When transferring large amounts of data to or from a server, use streams
 * to limit how much data is in memory at once. Unless you need the entire
 * body to be in memory at once, process it as a stream (rather than storing
 * the complete body as a single byte array or string).
 *
 * <p>To reduce latency, this class may reuse the same underlying {@code Socket}
 * for multiple request/response pairs. As a result, HTTP connections may be
 * held open longer than necessary. Calls to {@link #disconnect()} may return
 * the socket to a pool of connected sockets. This behavior can be disabled by
 * setting the "http.keepAlive" system property to "false" before issuing any
 * HTTP requests. The "http.maxConnections" property may be used to control how
 * many idle connections to each server will be held.
 *
 * <p>By default, this implementation of {@code HttpURLConnection} requests that
 * servers use gzip compression. Since {@link #getContentLength()} returns the
 * number of bytes transmitted, you cannot use that method to predict how many
 * bytes can be read from {@link #getInputStream()}. Instead, read that stream
 * until it is exhausted: when {@link InputStream#read} returns -1. Gzip
 * compression can be disabled by setting the acceptable encodings in the
 * request header: <pre>   {@code
 *   urlConnection.setRequestProperty("Accept-Encoding", "identity");
 * }</pre>
 *
 * <h3>Handling Network Sign-On</h3>
 * Some Wi-Fi networks block Internet access until the user clicks through a
 * sign-on page. Such sign-on pages are typically presented by using HTTP
 * redirects. You can use {@link #getURL()} to test if your connection has been
 * unexpectedly redirected. This check is not valid until <strong>after</strong>
 * the response headers have been received, which you can trigger by calling
 * {@link #getHeaderFields()} or {@link #getInputStream()}. For example, to
 * check that a response was not redirected to an unexpected host:
 * <pre>   {@code
 *   HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
 *   try {
 *     InputStream in = new BufferedInputStream(urlConnection.getInputStream());
 *     if (!url.getHost().equals(urlConnection.getURL().getHost())) {
 *       // we were redirected! Kick the user out to the browser to sign on?
 *     }
 *     ...
 *   } finally {
 *     urlConnection.disconnect();
 *   }
 * }</pre>
 *
 * <h3>HTTP Authentication</h3>
 * {@code HttpURLConnection} supports <a
 * href="http://www.ietf.org/rfc/rfc2617">HTTP basic authentication</a>. Use
 * {@link Authenticator} to set the VM-wide authentication handler:
 * <pre>   {@code
 *   Authenticator.setDefault(new Authenticator() {
 *     protected PasswordAuthentication getPasswordAuthentication() {
 *       return new PasswordAuthentication(username, password.toCharArray());
 *     }
 *   });
 * }</pre>
 * Unless paired with HTTPS, this is <strong>not</strong> a secure mechanism for
 * user authentication. In particular, the username, password, request and
 * response are all transmitted over the network without encryption.
 *
 * <h3>Sessions with Cookies</h3>
 * To establish and maintain a potentially long-lived session between client
 * and server, {@code HttpURLConnection} includes an extensible cookie manager.
 * Enable VM-wide cookie management using {@link CookieHandler} and {@link
 * CookieManager}: <pre>   {@code
 *   CookieManager cookieManager = new CookieManager();
 *   CookieHandler.setDefault(cookieManager);
 * }</pre>
 * By default, {@code CookieManager} accepts cookies from the <a
 * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html">origin
 * server</a> only. Two other policies are included: {@link
 * CookiePolicy#ACCEPT_ALL} and {@link CookiePolicy#ACCEPT_NONE}. Implement
 * {@link CookiePolicy} to define a custom policy.
 *
 * <p>The default {@code CookieManager} keeps all accepted cookies in memory. It
 * will forget these cookies when the VM exits. Implement {@link CookieStore} to
 * define a custom cookie store.
 *
 * <p>In addition to the cookies set by HTTP responses, you may set cookies
 * programmatically. To be included in HTTP request headers, cookies must have
 * the domain and path properties set.
 *
 * <p>By default, new instances of {@code HttpCookie} work only with servers
 * that support <a href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</a>
 * cookies. Many web servers support only the older specification, <a
 * href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</a>. For compatibility
 * with the most web servers, set the cookie version to 0.
 *
 * <p>For example, to receive {@code www.twitter.com} in French: <pre>   {@code
 *   HttpCookie cookie = new HttpCookie("lang", "fr");
 *   cookie.setDomain("twitter.com");
 *   cookie.setPath("/");
 *   cookie.setVersion(0);
 *   cookieManager.getCookieStore().add(new URI("http://twitter.com/"), cookie);
 * }</pre>
 *
 * <h3>HTTP Methods</h3>
 * <p>{@code HttpURLConnection} uses the {@code GET} method by default. It will
 * use {@code POST} if {@link #setDoOutput setDoOutput(true)} has been called.
 * Other HTTP methods ({@code OPTIONS}, {@code HEAD}, {@code PUT}, {@code
 * DELETE} and {@code TRACE}) can be used with {@link #setRequestMethod}.
 *
 * <h3>Proxies</h3>
 * By default, this class will connect directly to the <a
 * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec1.html">origin
 * server</a>. It can also connect via an {@link Proxy.Type#HTTP HTTP} or {@link
 * Proxy.Type#SOCKS SOCKS} proxy. To use a proxy, use {@link
 * URL#openConnection(Proxy) URL.openConnection(Proxy)} when creating the
 * connection.
 *
 * <h3>IPv6 Support</h3>
 * <p>This class includes transparent support for IPv6. For hosts with both IPv4
 * and IPv6 addresses, it will attempt to connect to each of a host's addresses
 * until a connection is established.
 *
 * <h3>Response Caching</h3>
 * <p>{@code HttpURLConnection} supports a VM-wide HTTP response cache.
 * Implement {@link ResponseCache} and use {@link ResponseCache#setDefault} to
 * install a custom cache. Implementing this API is onerous: correct
 * implementations should follow all caching rules defined by <a
 * href="http://tools.ietf.org/html/rfc2616#section-13">Section 13 of RFC
 * 2616</a>.
 *
 * <p>Each instance of {@code HttpURLConnection} may be used for one
 * request/response pair. Instances of this class are not thread safe.
 */
public abstract class HttpURLConnection extends URLConnection {

    /**
     * The subset of HTTP methods that the user may select via {@link
     * #setRequestMethod(String)}.
     */
    private static final String[] PERMITTED_USER_METHODS = {
            HttpEngine.OPTIONS,
            HttpEngine.GET,
            HttpEngine.HEAD,
            HttpEngine.POST,
            HttpEngine.PUT,
            HttpEngine.DELETE,
            HttpEngine.TRACE
            // Note: we don't allow users to specify "CONNECT"
    };

    /**
     * The HTTP request method of this {@code HttpURLConnection}. The default
     * value is {@code "GET"}.
     */
    protected String method = HttpEngine.GET;

    /**
     * The status code of the response obtained from the HTTP request. The
     * default value is {@code -1}.
     * <p>
     * <li>1xx: Informational</li>
     * <li>2xx: Success</li>
     * <li>3xx: Relocation/Redirection</li>
     * <li>4xx: Client Error</li>
     * <li>5xx: Server Error</li>
     */
    protected int responseCode = -1;

    /**
     * The HTTP response message which corresponds to the response code.
     */
    protected String responseMessage;

    /**
     * Flag to define whether the protocol will automatically follow redirects
     * or not. The default value is {@code true}.
     */
    protected boolean instanceFollowRedirects = followRedirects;

    private static boolean followRedirects = true;

    /**
     * If the HTTP chunked encoding is enabled this parameter defines the
     * chunk-length. Default value is {@code -1} that means the chunked encoding
     * mode is disabled.
     */
    protected int chunkLength = -1;

    /**
     * If using HTTP fixed-length streaming mode this parameter defines the
     * fixed length of content. Default value is {@code -1} that means the
     * fixed-length streaming mode is disabled.
     */
    protected int fixedContentLength = -1;

    // 2XX: generally "OK"
    // 3XX: relocation/redirect
    // 4XX: client error
    // 5XX: server error
    /**
     * Numeric status code, 202: Accepted
     */
    public static final int HTTP_ACCEPTED = 202;

    /**
     * Numeric status code, 502: Bad Gateway
     */
    public static final int HTTP_BAD_GATEWAY = 502;

    /**
     * Numeric status code, 405: Bad Method
     */
    public static final int HTTP_BAD_METHOD = 405;

    /**
     * Numeric status code, 400: Bad Request
     */
    public static final int HTTP_BAD_REQUEST = 400;

    /**
     * Numeric status code, 408: Client Timeout
     */
    public static final int HTTP_CLIENT_TIMEOUT = 408;

    /**
     * Numeric status code, 409: Conflict
     */
    public static final int HTTP_CONFLICT = 409;

    /**
     * Numeric status code, 201: Created
     */
    public static final int HTTP_CREATED = 201;

    /**
     * Numeric status code, 413: Entity too large
     */
    public static final int HTTP_ENTITY_TOO_LARGE = 413;

    /**
     * Numeric status code, 403: Forbidden
     */
    public static final int HTTP_FORBIDDEN = 403;

    /**
     * Numeric status code, 504: Gateway timeout
     */
    public static final int HTTP_GATEWAY_TIMEOUT = 504;

    /**
     * Numeric status code, 410: Gone
     */
    public static final int HTTP_GONE = 410;

    /**
     * Numeric status code, 500: Internal error
     */
    public static final int HTTP_INTERNAL_ERROR = 500;

    /**
     * Numeric status code, 411: Length required
     */
    public static final int HTTP_LENGTH_REQUIRED = 411;

    /**
     * Numeric status code, 301 Moved permanently
     */
    public static final int HTTP_MOVED_PERM = 301;

    /**
     * Numeric status code, 302: Moved temporarily
     */
    public static final int HTTP_MOVED_TEMP = 302;

    /**
     * Numeric status code, 300: Multiple choices
     */
    public static final int HTTP_MULT_CHOICE = 300;

    /**
     * Numeric status code, 204: No content
     */
    public static final int HTTP_NO_CONTENT = 204;

    /**
     * Numeric status code, 406: Not acceptable
     */
    public static final int HTTP_NOT_ACCEPTABLE = 406;

    /**
     * Numeric status code, 203: Not authoritative
     */
    public static final int HTTP_NOT_AUTHORITATIVE = 203;

    /**
     * Numeric status code, 404: Not found
     */
    public static final int HTTP_NOT_FOUND = 404;

    /**
     * Numeric status code, 501: Not implemented
     */
    public static final int HTTP_NOT_IMPLEMENTED = 501;

    /**
     * Numeric status code, 304: Not modified
     */
    public static final int HTTP_NOT_MODIFIED = 304;

    /**
     * Numeric status code, 200: OK
     */
    public static final int HTTP_OK = 200;

    /**
     * Numeric status code, 206: Partial
     */
    public static final int HTTP_PARTIAL = 206;

    /**
     * Numeric status code, 402: Payment required
     */
    public static final int HTTP_PAYMENT_REQUIRED = 402;

    /**
     * Numeric status code, 412: Precondition failed
     */
    public static final int HTTP_PRECON_FAILED = 412;

    /**
     * Numeric status code, 407: Proxy authentication required
     */
    public static final int HTTP_PROXY_AUTH = 407;

    /**
     * Numeric status code, 414: Request too long
     */
    public static final int HTTP_REQ_TOO_LONG = 414;

    /**
     * Numeric status code, 205: Reset
     */
    public static final int HTTP_RESET = 205;

    /**
     * Numeric status code, 303: See other
     */
    public static final int HTTP_SEE_OTHER = 303;

    /**
     * Numeric status code, 500: Internal error
     *
     * @deprecated Use {@link #HTTP_INTERNAL_ERROR}
     */
    @Deprecated
    public static final int HTTP_SERVER_ERROR = 500;

    /**
     * Numeric status code, 305: Use proxy.
     *
     * <p>Like Firefox and Chrome, this class doesn't honor this response code.
     * Other implementations respond to this status code by retrying the request
     * using the HTTP proxy named by the response's Location header field.
     */
    public static final int HTTP_USE_PROXY = 305;

    /**
     * Numeric status code, 401: Unauthorized
     */
    public static final int HTTP_UNAUTHORIZED = 401;

    /**
     * Numeric status code, 415: Unsupported type
     */
    public static final int HTTP_UNSUPPORTED_TYPE = 415;

    /**
     * Numeric status code, 503: Unavailable
     */
    public static final int HTTP_UNAVAILABLE = 503;

    /**
     * Numeric status code, 505: Version not supported
     */
    public static final int HTTP_VERSION = 505;

    /**
     * Constructs a new {@code HttpURLConnection} instance pointing to the
     * resource specified by the {@code url}.
     *
     * @param url
     *            the URL of this connection.
     * @see URL
     * @see URLConnection
     */
    protected HttpURLConnection(URL url) {
        super(url);
    }

    /**
     * Closes the connection to the HTTP server.
     *
     * @see URLConnection#connect()
     * @see URLConnection#connected
     */
    public abstract void disconnect();

    /**
     * Returns an input stream from the server in the case of an error such as
     * the requested file has not been found on the remote server. This stream
     * can be used to read the data the server will send back.
     *
     * @return the error input stream returned by the server.
     */
    public InputStream getErrorStream() {
        return null;
    }

    /**
     * Returns the value of {@code followRedirects} which indicates if this
     * connection follows a different URL redirected by the server. It is
     * enabled by default.
     *
     * @return the value of the flag.
     * @see #setFollowRedirects
     */
    public static boolean getFollowRedirects() {
        return followRedirects;
    }

    /**
     * Returns the permission object (in this case {@code SocketPermission})
     * with the host and the port number as the target name and {@code
     * "resolve, connect"} as the action list. If the port number of this URL
     * instance is lower than {@code 0} the port will be set to {@code 80}.
     *
     * @return the permission object required for this connection.
     * @throws IOException
     *             if an IO exception occurs during the creation of the
     *             permission object.
     */
    @Override
    public java.security.Permission getPermission() throws IOException {
        int port = url.getPort();
        if (port < 0) {
            port = 80;
        }
        return new SocketPermission(url.getHost() + ":" + port,
                "connect, resolve");
    }

    /**
     * Returns the request method which will be used to make the request to the
     * remote HTTP server. All possible methods of this HTTP implementation is
     * listed in the class definition.
     *
     * @return the request method string.
     * @see #method
     * @see #setRequestMethod
     */
    public String getRequestMethod() {
        return method;
    }

    /**
     * Returns the response code returned by the remote HTTP server.
     *
     * @return the response code, -1 if no valid response code.
     * @throws IOException
     *             if there is an IO error during the retrieval.
     * @see #getResponseMessage
     */
    public int getResponseCode() throws IOException {
        // Call getInputStream() first since getHeaderField() doesn't return
        // exceptions
        getInputStream();
        String response = getHeaderField(0);
        if (response == null) {
            return -1;
        }
        response = response.trim();
        int mark = response.indexOf(" ") + 1;
        if (mark == 0) {
            return -1;
        }
        int last = mark + 3;
        if (last > response.length()) {
            last = response.length();
        }
        responseCode = Integer.parseInt(response.substring(mark, last));
        if (last + 1 <= response.length()) {
            responseMessage = response.substring(last + 1);
        }
        return responseCode;
    }

    /**
     * Returns the response message returned by the remote HTTP server.
     *
     * @return the response message. {@code null} if no such response exists.
     * @throws IOException
     *             if there is an error during the retrieval.
     * @see #getResponseCode()
     */
    public String getResponseMessage() throws IOException {
        if (responseMessage != null) {
            return responseMessage;
        }
        getResponseCode();
        return responseMessage;
    }

    /**
     * Sets the flag of whether this connection will follow redirects returned
     * by the remote server.
     *
     * @param auto
     *            the value to enable or disable this option.
     */
    public static void setFollowRedirects(boolean auto) {
        followRedirects = auto;
    }

    /**
     * Sets the request command which will be sent to the remote HTTP server.
     * This method can only be called before the connection is made.
     *
     * @param method
     *            the string representing the method to be used.
     * @throws ProtocolException
     *             if this is called after connected, or the method is not
     *             supported by this HTTP implementation.
     * @see #getRequestMethod()
     * @see #method
     */
    public void setRequestMethod(String method) throws ProtocolException {
        if (connected) {
            throw new ProtocolException("Connection already established");
        }
        for (String permittedUserMethod : PERMITTED_USER_METHODS) {
            if (permittedUserMethod.equals(method)) {
                // if there is a supported method that matches the desired
                // method, then set the current method and return
                this.method = permittedUserMethod;
                return;
            }
        }
        // if none matches, then throw ProtocolException
        throw new ProtocolException("Unknown method '" + method + "'; must be one of " +
                Arrays.toString(PERMITTED_USER_METHODS));
    }

    /**
     * Returns whether this connection uses a proxy server or not.
     *
     * @return {@code true} if this connection passes a proxy server, false
     *         otherwise.
     */
    public abstract boolean usingProxy();

    /**
     * Returns the encoding used to transmit the response body over the network.
     * This is null or "identity" if the content was not encoded, or "gzip" if
     * the body was gzip compressed. Most callers will be more interested in the
     * {@link #getContentType() content type}, which may also include the
     * content's character encoding.
     */
    @Override public String getContentEncoding() {
        return super.getContentEncoding(); // overridden for Javadoc only
    }

    /**
     * Returns whether this connection follows redirects.
     *
     * @return {@code true} if this connection follows redirects, false
     *         otherwise.
     */
    public boolean getInstanceFollowRedirects() {
        return instanceFollowRedirects;
    }

    /**
     * Sets whether this connection follows redirects.
     *
     * @param followRedirects
     *            {@code true} if this connection will follows redirects, false
     *            otherwise.
     */
    public void setInstanceFollowRedirects(boolean followRedirects) {
        instanceFollowRedirects = followRedirects;
    }

    /**
     * Returns the date value in milliseconds since {@code 01.01.1970, 00:00h}
     * corresponding to the header field {@code field}. The {@code defaultValue}
     * will be returned if no such field can be found in the response header.
     *
     * @param field
     *            the header field name.
     * @param defaultValue
     *            the default value to use if the specified header field wont be
     *            found.
     * @return the header field represented in milliseconds since January 1,
     *         1970 GMT.
     */
    @Override
    public long getHeaderFieldDate(String field, long defaultValue) {
        return super.getHeaderFieldDate(field, defaultValue);
    }

    /**
     * If the length of a HTTP request body is known ahead, sets fixed length to
     * enable streaming without buffering. Sets after connection will cause an
     * exception.
     *
     * @see #setChunkedStreamingMode
     * @param contentLength
     *            the fixed length of the HTTP request body.
     * @throws IllegalStateException
     *             if already connected or another mode already set.
     * @throws IllegalArgumentException
     *             if {@code contentLength} is less than zero.
     */
    public void setFixedLengthStreamingMode(int contentLength) {
        if (super.connected) {
            throw new IllegalStateException("Already connected");
        }
        if (chunkLength > 0) {
            throw new IllegalStateException("Already in chunked mode");
        }
        if (contentLength < 0) {
            throw new IllegalArgumentException("contentLength < 0");
        }
        this.fixedContentLength = contentLength;
    }

    /**
     * Stream a request body whose length is not known in advance. Old HTTP/1.0
     * only servers may not support this mode.
     *
     * <p>When HTTP chunked encoding is used, the stream is divided into
     * chunks, each prefixed with a header containing the chunk's size. Setting
     * a large chunk length requires a large internal buffer, potentially
     * wasting memory. Setting a small chunk length increases the number of
     * bytes that must be transmitted because of the header on every chunk.
     * Most caller should use {@code 0} to get the system default.
     *
     * @see #setFixedLengthStreamingMode
     * @param chunkLength the length to use, or {@code 0} for the default chunk
     *     length.
     * @throws IllegalStateException if already connected or another mode
     *     already set.
     */
    public void setChunkedStreamingMode(int chunkLength) {
        if (super.connected) {
            throw new IllegalStateException("Already connected");
        }
        if (fixedContentLength >= 0) {
            throw new IllegalStateException("Already in fixed-length mode");
        }
        if (chunkLength <= 0) {
            this.chunkLength = HttpEngine.DEFAULT_CHUNK_LENGTH;
        } else {
            this.chunkLength = chunkLength;
        }
    }
}
