protected CloseableHttpClient constructHttpClient() throws IOException {
    RequestConfig config =
        RequestConfig.custom()
            .setConnectTimeout(20 * 1000)
            .setConnectionRequestTimeout(20 * 1000)
            .setSocketTimeout(20 * 1000)
            .setMaxRedirects(20)
            .build();

    URL mmsc = new URL(apn.getMmsc());
    CredentialsProvider credsProvider = new BasicCredentialsProvider();

    if (apn.hasAuthentication()) {
      credsProvider.setCredentials(
          new AuthScope(
              mmsc.getHost(), mmsc.getPort() > -1 ? mmsc.getPort() : mmsc.getDefaultPort()),
          new UsernamePasswordCredentials(apn.getUsername(), apn.getPassword()));
    }

    return HttpClients.custom()
        .setConnectionReuseStrategy(new NoConnectionReuseStrategyHC4())
        .setRedirectStrategy(new LaxRedirectStrategy())
        .setUserAgent("Android-Mms/2.0")
        .setConnectionManager(new BasicHttpClientConnectionManager())
        .setDefaultRequestConfig(config)
        .setDefaultCredentialsProvider(credsProvider)
        .build();
  }
  protected byte[] execute(HttpUriRequest request) throws IOException {
    Log.w(TAG, "connecting to " + apn.getMmsc());

    CloseableHttpClient client = null;
    CloseableHttpResponse response = null;
    try {
      client = constructHttpClient();
      response = client.execute(request);

      Log.w(TAG, "* response code: " + response.getStatusLine());

      if (response.getStatusLine().getStatusCode() == 200) {
        return parseResponse(response.getEntity().getContent());
      }
    } catch (NullPointerException npe) {
      // TODO determine root cause
      // see: https://github.com/WhisperSystems/Signal-Android/issues/4379
      throw new IOException(npe);
    } finally {
      if (response != null) response.close();
      if (client != null) client.close();
    }

    throw new IOException("unhandled response code");
  }
  protected byte[] makeRequest(boolean useProxy) throws IOException {
    Log.w(TAG, "connecting to " + apn.getMmsc() + (useProxy ? " using proxy" : ""));

    HttpUriRequest request;
    CloseableHttpClient client = null;
    CloseableHttpResponse response = null;
    try {
      request = constructRequest(useProxy);
      client = constructHttpClient();
      response = client.execute(request);

      Log.w(TAG, "* response code: " + response.getStatusLine());

      if (response.getStatusLine().getStatusCode() == 200) {
        return parseResponse(response.getEntity().getContent());
      }
    } finally {
      if (response != null) response.close();
      if (client != null) client.close();
    }

    throw new IOException("unhandled response code");
  }