// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed 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 com.google.devtools.build.lib.bazel.repository.downloader;

import com.google.common.base.Ascii;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteStreams;
import com.google.common.math.IntMath;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.util.Sleeper;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.WillClose;

/**
 * Class for establishing connections to HTTP servers for downloading files.
 *
 * <p>This class must be used in conjunction with {@link HttpConnectorMultiplexer}.
 *
 * <p>Instances are thread safe and can be reused.
 */
@ThreadSafe
class HttpConnector {

  private static final int MAX_RETRIES = 8;
  private static final int MAX_REDIRECTS = 40;
  private static final int MIN_RETRY_DELAY_MS = 100;
  private static final int MIN_CONNECT_TIMEOUT_MS = 1000;
  private static final int MAX_CONNECT_TIMEOUT_MS = 10000;
  private static final int READ_TIMEOUT_MS = 20000;
  private static final ImmutableSet<String> COMPRESSED_EXTENSIONS =
      ImmutableSet.of("bz2", "gz", "jar", "tgz", "war", "xz", "zip");

  private final Locale locale;
  private final EventHandler eventHandler;
  private final ProxyHelper proxyHelper;
  private final Sleeper sleeper;
  private final float timeoutScaling;

  HttpConnector(
      Locale locale,
      EventHandler eventHandler,
      ProxyHelper proxyHelper,
      Sleeper sleeper,
      float timeoutScaling) {
    this.locale = locale;
    this.eventHandler = eventHandler;
    this.proxyHelper = proxyHelper;
    this.sleeper = sleeper;
    this.timeoutScaling = timeoutScaling;
  }

  HttpConnector(
      Locale locale, EventHandler eventHandler, ProxyHelper proxyHelper, Sleeper sleeper) {
    this(locale, eventHandler, proxyHelper, sleeper, 1.0f);
  }

  private int scale(int unscaled) {
    return Math.round(unscaled * timeoutScaling);
  }

  URLConnection connect(
      URL originalUrl, ImmutableMap<String, String> requestHeaders)
          throws IOException {

    if (Thread.interrupted()) {
      throw new InterruptedIOException();
    }
    URL url = originalUrl;
    if (HttpUtils.isProtocol(url, "file")) {
      return url.openConnection();
    }
    List<Throwable> suppressions = new ArrayList<>();
    int retries = 0;
    int redirects = 0;
    int connectTimeout = scale(MIN_CONNECT_TIMEOUT_MS);
    while (true) {
      HttpURLConnection connection = null;
      try {
        connection = (HttpURLConnection)
            url.openConnection(proxyHelper.createProxyIfNeeded(url));
        boolean isAlreadyCompressed =
            COMPRESSED_EXTENSIONS.contains(HttpUtils.getExtension(url.getPath()))
                || COMPRESSED_EXTENSIONS.contains(HttpUtils.getExtension(originalUrl.getPath()));
        connection.setInstanceFollowRedirects(false);
        for (Map.Entry<String, String> entry : requestHeaders.entrySet()) {
          if (isAlreadyCompressed && Ascii.equalsIgnoreCase(entry.getKey(), "Accept-Encoding")) {
            // We're not going to ask for compression if we're downloading a file that already
            // appears to be compressed.
            continue;
          }
          connection.addRequestProperty(entry.getKey(), entry.getValue());
        }
        connection.setConnectTimeout(connectTimeout);
        // The read timeout is always large because it stays in effect after this method.
        connection.setReadTimeout(scale(READ_TIMEOUT_MS));
        // Java tries to abstract HTTP error responses for us. We don't want that. So we're going
        // to try and undo any IOException that doesn't appear to be a legitimate I/O exception.
        int code;
        try {
          connection.connect();
          code = connection.getResponseCode();
        } catch (FileNotFoundException ignored) {
          code = connection.getResponseCode();
        } catch (UnknownHostException e) {
          String message = "Unknown host: " + e.getMessage();
          eventHandler.handle(Event.progress(message));
          throw new UnrecoverableHttpException(message);
        } catch (IllegalArgumentException e) {
          // This will happen if the user does something like specify a port greater than 2^16-1.
          throw new UnrecoverableHttpException(e.getMessage());
        } catch (IOException e) {
          // Some HTTP error status codes are converted to IOExceptions, which we can only
          // disambiguate from other IOExceptions by checking the exception message. We need to be
          // careful because some exceptions (e.g., SocketTimeoutException) may have a null message.
          if (e.getMessage() == null || !e.getMessage().startsWith("Server returned")) {
            throw e;
          }
          code = connection.getResponseCode();
        }
        // 206 means partial content and only happens if caller specified Range. See RFC7233 § 4.1.
        if (code == 200 || code == 206) {
          return connection;
        } else if (code == 301 || code == 302 || code == 303 || code == 307) {
          readAllBytesAndClose(connection.getInputStream());
          if (++redirects == MAX_REDIRECTS) {
            eventHandler.handle(Event.progress("Redirect loop detected in " + originalUrl));
            throw new UnrecoverableHttpException("Redirect loop detected");
          }
          url = HttpUtils.getLocation(connection);
          if (code == 301) {
            originalUrl = url;
          }
        } else if (code == 403) {
          // jart@ has noticed BitBucket + Amazon AWS downloads frequently flake with this code.
          throw new IOException(describeHttpResponse(connection));
        } else if (code == 408) {
          // The 408 (Request Timeout) status code indicates that the server did not receive a
          // complete request message within the time that it was prepared to wait. Server SHOULD
          // send the "close" connection option (Section 6.1 of [RFC7230]) in the response, since
          // 408 implies that the server has decided to close the connection rather than continue
          // waiting.  If the client has an outstanding request in transit, the client MAY repeat
          // that request on a new connection. Quoth RFC7231 § 6.5.7
          throw new IOException(describeHttpResponse(connection));
        } else if (code < 500          // 4xx means client seems to have erred quoth RFC7231 § 6.5
                    || code == 501     // Server doesn't support function quoth RFC7231 § 6.6.2
                    || code == 502     // Host not configured on server cf. RFC7231 § 6.6.3
                    || code == 505) {  // Server refuses to support version quoth RFC7231 § 6.6.6
          // This is a permanent error so we're not going to retry.
          readAllBytesAndClose(connection.getErrorStream());
          throw new UnrecoverableHttpException(describeHttpResponse(connection));
        } else {
          // However we will retry on some 5xx errors, particularly 500 and 503.
          throw new IOException(describeHttpResponse(connection));
        }
      } catch (UnrecoverableHttpException e) {
        throw e;
      } catch (IllegalArgumentException e) {
        throw new UnrecoverableHttpException(e.getMessage());
      } catch (SocketTimeoutException e) {
        // SocketTimeoutExceptions are InterruptedExceptions; however they do not signify
        // an external interruption, but simply a failed download due to some server timing
        // out. So rethrow them as ordinary IOExceptions.
        throw new IOException(e.getMessage(), e);
      } catch (IOException e) {
        if (connection != null) {
          // If we got here, it means we might not have consumed the entire payload of the
          // response, if any. So we're going to force this socket to disconnect and not be
          // reused. This is particularly important if multiple threads end up establishing
          // connections to multiple mirrors simultaneously for a large file. We don't want to
          // download that large file twice.
          connection.disconnect();
        }
        // We don't respect the Retry-After header (RFC7231 § 7.1.3) because it's rarely used and
        // tends to be too conservative when it is. We're already being good citizens by using
        // exponential backoff. Furthermore RFC law didn't use the magic word "MUST".
        int timeout = IntMath.pow(2, retries) * MIN_RETRY_DELAY_MS;
        if (e instanceof SocketTimeoutException) {
          eventHandler.handle(Event.progress("Timeout connecting to " + url));
          connectTimeout = Math.min(connectTimeout * 2, scale(MAX_CONNECT_TIMEOUT_MS));
          // If we got connect timeout, we're already doing exponential backoff, so no point
          // in sleeping too.
          timeout = 1;
        } else if (e instanceof InterruptedIOException) {
          // Please note that SocketTimeoutException is a subtype of InterruptedIOException.
          throw e;
        }
        if (++retries == MAX_RETRIES) {
          if (!(e instanceof SocketTimeoutException)) {
            eventHandler
                .handle(Event.progress(format("Error connecting to %s: %s", url, e.getMessage())));
          }
          for (Throwable suppressed : suppressions) {
            e.addSuppressed(suppressed);
          }
          throw e;
        }
        // Java 7 allows us to create a tree of all errors that led to the ultimate failure.
        suppressions.add(e);
        eventHandler.handle(
            Event.progress(format("Failed to connect to %s trying again in %,dms", url, timeout)));
        url = originalUrl;
        try {
          sleeper.sleepMillis(timeout);
        } catch (InterruptedException translated) {
          throw new InterruptedIOException();
        }
      } catch (RuntimeException e) {
        if (connection != null) {
          connection.disconnect();
        }
        eventHandler.handle(Event.progress(format("Unknown error connecting to %s: %s", url, e)));
        throw e;
      }
    }
  }

  private String describeHttpResponse(HttpURLConnection connection) throws IOException {
    return format(
        "%s returned %d %s",
        connection.getRequestMethod(),
        connection.getResponseCode(),
        Strings.nullToEmpty(connection.getResponseMessage()));
  }

  private String format(String format, Object... args) {
    return String.format(locale, format, args);
  }

  // Exhausts all bytes in an HTTP to make it easier for Java infrastructure to reuse sockets.
  private static void readAllBytesAndClose(
      @WillClose @Nullable InputStream stream)
          throws IOException {
    if (stream != null) {
      ByteStreams.exhaust(stream);
      stream.close();
    }
  }
}
