All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.whispersystems.textsecure.internal.websocket.OkHttpClientWrapper Maven / Gradle / Ivy

The newest version!
package org.whispersystems.textsecure.internal.websocket;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.internal.ws.WebSocket;
import com.squareup.okhttp.internal.ws.WebSocketListener;

import org.whispersystems.libaxolotl.logging.Log;
import org.whispersystems.textsecure.api.push.TrustStore;
import org.whispersystems.textsecure.api.util.CredentialsProvider;
import org.whispersystems.textsecure.internal.util.BlacklistingTrustManager;
import org.whispersystems.textsecure.internal.util.Util;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;

import okio.Buffer;
import okio.BufferedSource;

public class OkHttpClientWrapper implements WebSocketListener {

  private static final String TAG = OkHttpClientWrapper.class.getSimpleName();

  private final String                 uri;
  private final TrustStore             trustStore;
  private final CredentialsProvider    credentialsProvider;
  private final WebSocketEventListener listener;
  private final String                 userAgent;

  private WebSocket webSocket;
  private boolean   closed;
  private boolean   connected;

  public OkHttpClientWrapper(String uri, TrustStore trustStore,
                             CredentialsProvider credentialsProvider,
                             String userAgent,
                             WebSocketEventListener listener)
  {
    Log.w(TAG, "Connecting to: " + uri);

    this.uri                 = uri;
    this.trustStore          = trustStore;
    this.credentialsProvider = credentialsProvider;
    this.userAgent           = userAgent;
    this.listener            = listener;
  }

  public void connect(final int timeout, final TimeUnit timeUnit) {
    new Thread() {
      @Override
      public void run() {
        int attempt = 0;

        while ((webSocket = newSocket(timeout, timeUnit)) != null) {
          try {
            Response response = webSocket.connect(OkHttpClientWrapper.this);

            if (response.code() == 101) {
              synchronized (OkHttpClientWrapper.this) {
                if (closed) webSocket.close(1000, "OK");
                else        connected = true;
              }

              listener.onConnected();
              return;
            }

            Log.w(TAG, "WebSocket Response: " + response.code());
          } catch (IOException e) {
            Log.w(TAG, e);
          }

          Util.sleep(Math.min(++attempt * 200, TimeUnit.SECONDS.toMillis(15)));
        }
      }
    }.start();
  }

  public synchronized void disconnect() {
    Log.w(TAG, "Calling disconnect()...");
    try {
      closed = true;
      if (webSocket != null && connected) {
        webSocket.close(1000, "OK");
      }
    } catch (IOException e) {
      Log.w(TAG, e);
    }
  }

  public void sendMessage(byte[] message) throws IOException {
    webSocket.sendMessage(WebSocket.PayloadType.BINARY, new Buffer().write(message));
  }

  @Override
  public void onMessage(BufferedSource payload, WebSocket.PayloadType type) throws IOException {
    Log.w(TAG, "onMessage: " + type);
    if (type.equals(WebSocket.PayloadType.BINARY)) {
      listener.onMessage(payload.readByteArray());
    }

    payload.close();
  }

  @Override
  public void onClose(int code, String reason) {
    Log.w(TAG, String.format("onClose(%d, %s)", code, reason));
    listener.onClose();
  }

  @Override
  public void onFailure(IOException e) {
    Log.w(TAG, e);
    listener.onClose();
  }

  private synchronized WebSocket newSocket(int timeout, TimeUnit unit) {
    if (closed) return null;

    String       filledUri    = String.format(uri, credentialsProvider.getUser(), credentialsProvider.getPassword());
    OkHttpClient okHttpClient = new OkHttpClient();

    okHttpClient.setSslSocketFactory(createTlsSocketFactory(trustStore));
    okHttpClient.setReadTimeout(timeout, unit);
    okHttpClient.setConnectTimeout(timeout, unit);

    Request.Builder requestBuilder = new Request.Builder().url(filledUri);

    if (userAgent != null) {
      requestBuilder.addHeader("X-Signal-Agent", userAgent);
    }

    return WebSocket.newWebSocket(okHttpClient, requestBuilder.build());
  }

  private SSLSocketFactory createTlsSocketFactory(TrustStore trustStore) {
    try {
      SSLContext context = SSLContext.getInstance("TLS");
      context.init(null, BlacklistingTrustManager.createFor(trustStore), null);

      return context.getSocketFactory();
    } catch (NoSuchAlgorithmException | KeyManagementException e) {
      throw new AssertionError(e);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy