diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5e368ad096..08fe5c696e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -229,6 +229,7 @@
+
.
+ */
+package textsecure;
+
+option java_package = "org.whispersystems.textsecure.internal.websocket";
+option java_outer_classname = "WebSocketProtos";
+
+message WebSocketRequestMessage {
+ optional string verb = 1;
+ optional string path = 2;
+ optional bytes body = 3;
+ optional uint64 id = 4;
+}
+
+message WebSocketResponseMessage {
+ optional uint64 id = 1;
+ optional uint32 status = 2;
+ optional string message = 3;
+ optional bytes body = 4;
+}
+
+message WebSocketMessage {
+ enum Type {
+ UNKNOWN = 0;
+ REQUEST = 1;
+ RESPONSE = 2;
+ }
+
+ optional Type type = 1;
+ optional WebSocketRequestMessage request = 2;
+ optional WebSocketResponseMessage response = 3;
+}
\ No newline at end of file
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java
index acd27015f0..4d2afb37ef 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java
@@ -30,6 +30,7 @@ import org.whispersystems.textsecure.api.push.SignedPreKeyEntity;
import org.whispersystems.textsecure.api.push.TrustStore;
import org.whispersystems.textsecure.internal.crypto.ProvisioningCipher;
import org.whispersystems.textsecure.internal.push.PushServiceSocket;
+import org.whispersystems.textsecure.internal.util.StaticCredentialsProvider;
import java.io.IOException;
import java.util.List;
@@ -45,7 +46,7 @@ public class TextSecureAccountManager {
public TextSecureAccountManager(String url, TrustStore trustStore,
String user, String password)
{
- this.pushServiceSocket = new PushServiceSocket(url, trustStore, user, password);
+ this.pushServiceSocket = new PushServiceSocket(url, trustStore, new StaticCredentialsProvider(user, password, null));
this.user = user;
}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessagePipe.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessagePipe.java
new file mode 100644
index 0000000000..64a7f7408c
--- /dev/null
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessagePipe.java
@@ -0,0 +1,87 @@
+package org.whispersystems.textsecure.api;
+
+import org.whispersystems.libaxolotl.InvalidVersionException;
+import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
+import org.whispersystems.textsecure.api.util.CredentialsProvider;
+import org.whispersystems.textsecure.internal.websocket.WebSocketConnection;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage;
+import static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage;
+
+public class TextSecureMessagePipe {
+
+ private final WebSocketConnection websocket;
+ private final CredentialsProvider credentialsProvider;
+
+ public TextSecureMessagePipe(WebSocketConnection websocket, CredentialsProvider credentialsProvider) {
+ this.websocket = websocket;
+ this.credentialsProvider = credentialsProvider;
+
+ this.websocket.connect();
+ }
+
+ public TextSecureEnvelope read(long timeout, TimeUnit unit)
+ throws InvalidVersionException, IOException, TimeoutException
+ {
+ return read(timeout, unit, new NullMessagePipeCallback());
+ }
+
+ public TextSecureEnvelope read(long timeout, TimeUnit unit, MessagePipeCallback callback)
+ throws TimeoutException, IOException, InvalidVersionException
+ {
+ while (true) {
+ WebSocketRequestMessage request = websocket.readRequest(unit.toMillis(timeout));
+ WebSocketResponseMessage response = createWebSocketResponse(request);
+
+ try {
+ if (isTextSecureEnvelope(request)) {
+ TextSecureEnvelope envelope = new TextSecureEnvelope(request.getBody().toByteArray(),
+ credentialsProvider.getSignalingKey());
+
+ callback.onMessage(envelope);
+ return envelope;
+ }
+ } finally {
+ websocket.sendResponse(response);
+ }
+ }
+ }
+
+ public void shutdown() throws IOException {
+ websocket.disconnect();
+ }
+
+ private boolean isTextSecureEnvelope(WebSocketRequestMessage message) {
+ return "PUT".equals(message.getVerb()) && "/api/v1/message".equals(message.getPath());
+ }
+
+ private WebSocketResponseMessage createWebSocketResponse(WebSocketRequestMessage request) {
+ if (isTextSecureEnvelope(request)) {
+ return WebSocketResponseMessage.newBuilder()
+ .setId(request.getId())
+ .setStatus(200)
+ .setMessage("OK")
+ .build();
+ } else {
+ return WebSocketResponseMessage.newBuilder()
+ .setId(request.getId())
+ .setStatus(400)
+ .setMessage("Unknown")
+ .build();
+ }
+ }
+
+ public static interface MessagePipeCallback {
+ public void onMessage(TextSecureEnvelope envelope);
+ }
+
+ private static class NullMessagePipeCallback implements MessagePipeCallback {
+ @Override
+ public void onMessage(TextSecureEnvelope envelope) {}
+ }
+
+}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java
index 221a32e27b..a7e30be72a 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageReceiver.java
@@ -17,23 +17,43 @@
package org.whispersystems.textsecure.api;
import org.whispersystems.libaxolotl.InvalidMessageException;
+import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.textsecure.api.crypto.AttachmentCipherInputStream;
import org.whispersystems.textsecure.api.messages.TextSecureAttachmentPointer;
+import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
import org.whispersystems.textsecure.api.push.TrustStore;
+import org.whispersystems.textsecure.api.util.CredentialsProvider;
import org.whispersystems.textsecure.internal.push.PushServiceSocket;
+import org.whispersystems.textsecure.internal.util.StaticCredentialsProvider;
+import org.whispersystems.textsecure.internal.websocket.WebSocketConnection;
+import org.whispersystems.textsecure.internal.websocket.WebSocketProtos;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage;
public class TextSecureMessageReceiver {
- private final PushServiceSocket socket;
+ private final PushServiceSocket socket;
+ private final TrustStore trustStore;
+ private final String url;
+ private final CredentialsProvider credentialsProvider;
public TextSecureMessageReceiver(String url, TrustStore trustStore,
- String user, String password)
+ String user, String password, String signalingKey)
{
- this.socket = new PushServiceSocket(url, trustStore, user, password);
+ this(url, trustStore, new StaticCredentialsProvider(user, password, signalingKey));
+ }
+
+ public TextSecureMessageReceiver(String url, TrustStore trustStore, CredentialsProvider credentials) {
+ this.url = url;
+ this.trustStore = trustStore;
+ this.credentialsProvider = credentials;
+ this.socket = new PushServiceSocket(url, trustStore, credentials);
}
public InputStream retrieveAttachment(TextSecureAttachmentPointer pointer, File destination)
@@ -43,4 +63,9 @@ public class TextSecureMessageReceiver {
return new AttachmentCipherInputStream(destination, pointer.getKey());
}
+ public TextSecureMessagePipe createMessagePipe() {
+ WebSocketConnection webSocket = new WebSocketConnection(url, trustStore, credentialsProvider);
+ return new TextSecureMessagePipe(webSocket, credentialsProvider);
+ }
+
}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageSender.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageSender.java
index c033e94dd3..1fed694abd 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageSender.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureMessageSender.java
@@ -47,6 +47,7 @@ import org.whispersystems.textsecure.api.push.exceptions.UnregisteredUserExcepti
import org.whispersystems.textsecure.api.push.exceptions.EncapsulatedExceptions;
import org.whispersystems.textsecure.internal.push.exceptions.MismatchedDevicesException;
import org.whispersystems.textsecure.internal.push.exceptions.StaleDevicesException;
+import org.whispersystems.textsecure.internal.util.StaticCredentialsProvider;
import org.whispersystems.textsecure.internal.util.Util;
import java.io.IOException;
@@ -72,7 +73,7 @@ public class TextSecureMessageSender {
long userId, AxolotlStore store,
Optional eventListener)
{
- this.socket = new PushServiceSocket(url, trustStore, user, password);
+ this.socket = new PushServiceSocket(url, trustStore, new StaticCredentialsProvider(user, password, null));
this.store = store;
this.syncAddress = new PushAddress(userId, user, null);
this.eventListener = eventListener;
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/messages/TextSecureEnvelope.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/messages/TextSecureEnvelope.java
index a796f1a062..09876d00fc 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/messages/TextSecureEnvelope.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/messages/TextSecureEnvelope.java
@@ -59,8 +59,12 @@ public class TextSecureEnvelope {
public TextSecureEnvelope(String message, String signalingKey)
throws IOException, InvalidVersionException
{
- byte[] ciphertext = Base64.decode(message);
+ this(Base64.decode(message), signalingKey);
+ }
+ public TextSecureEnvelope(byte[] ciphertext, String signalingKey)
+ throws InvalidVersionException, IOException
+ {
if (ciphertext.length < VERSION_LENGTH || ciphertext[VERSION_OFFSET] != SUPPORTED_VERSION)
throw new InvalidVersionException("Unsupported version!");
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/util/CredentialsProvider.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/util/CredentialsProvider.java
new file mode 100644
index 0000000000..baa745adee
--- /dev/null
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/util/CredentialsProvider.java
@@ -0,0 +1,7 @@
+package org.whispersystems.textsecure.api.util;
+
+public interface CredentialsProvider {
+ public String getUser();
+ public String getPassword();
+ public String getSignalingKey();
+}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java
index 142dad4955..b303e99415 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java
@@ -27,23 +27,24 @@ import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.libaxolotl.state.PreKeyBundle;
import org.whispersystems.libaxolotl.state.PreKeyRecord;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
-import org.whispersystems.textsecure.api.push.PushAddress;
import org.whispersystems.textsecure.api.crypto.AttachmentCipherOutputStream;
import org.whispersystems.textsecure.api.push.ContactTokenDetails;
+import org.whispersystems.textsecure.api.push.PushAddress;
import org.whispersystems.textsecure.api.push.SignedPreKeyEntity;
import org.whispersystems.textsecure.api.push.TrustStore;
-import org.whispersystems.textsecure.api.push.exceptions.UnregisteredUserException;
-import org.whispersystems.textsecure.internal.push.exceptions.MismatchedDevicesException;
-import org.whispersystems.textsecure.internal.push.exceptions.StaleDevicesException;
-import org.whispersystems.textsecure.internal.util.Base64;
-import org.whispersystems.textsecure.internal.util.Util;
import org.whispersystems.textsecure.api.push.exceptions.AuthorizationFailedException;
import org.whispersystems.textsecure.api.push.exceptions.ExpectationFailedException;
import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException;
import org.whispersystems.textsecure.api.push.exceptions.NotFoundException;
import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException;
import org.whispersystems.textsecure.api.push.exceptions.RateLimitException;
+import org.whispersystems.textsecure.api.push.exceptions.UnregisteredUserException;
+import org.whispersystems.textsecure.api.util.CredentialsProvider;
+import org.whispersystems.textsecure.internal.push.exceptions.MismatchedDevicesException;
+import org.whispersystems.textsecure.internal.push.exceptions.StaleDevicesException;
+import org.whispersystems.textsecure.internal.util.Base64;
import org.whispersystems.textsecure.internal.util.BlacklistingTrustManager;
+import org.whispersystems.textsecure.internal.util.Util;
import java.io.File;
import java.io.FileOutputStream;
@@ -54,10 +55,7 @@ import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -65,7 +63,6 @@ import java.util.Set;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
/**
*
@@ -96,23 +93,20 @@ public class PushServiceSocket {
private static final boolean ENFORCE_SSL = true;
- private final String serviceUrl;
- private final String localNumber;
- private final String password;
- private final TrustManager[] trustManagers;
+ private final String serviceUrl;
+ private final TrustManager[] trustManagers;
+ private final CredentialsProvider credentialsProvider;
- public PushServiceSocket(String serviceUrl, TrustStore trustStore,
- String localNumber, String password)
+ public PushServiceSocket(String serviceUrl, TrustStore trustStore, CredentialsProvider credentialsProvider)
{
- this.serviceUrl = serviceUrl;
- this.localNumber = localNumber;
- this.password = password;
- this.trustManagers = initializeTrustManager(trustStore);
+ this.serviceUrl = serviceUrl;
+ this.credentialsProvider = credentialsProvider;
+ this.trustManagers = BlacklistingTrustManager.createFor(trustStore);
}
public void createAccount(boolean voice) throws IOException {
String path = voice ? CREATE_ACCOUNT_VOICE_PATH : CREATE_ACCOUNT_SMS_PATH;
- makeRequest(String.format(path, localNumber), "GET", null);
+ makeRequest(String.format(path, credentialsProvider.getUser()), "GET", null);
}
public void verifyAccount(String verificationCode, String signalingKey,
@@ -145,7 +139,7 @@ public class PushServiceSocket {
}
public void registerGcmId(String gcmRegistrationId) throws IOException {
- GcmRegistrationId registration = new GcmRegistrationId(gcmRegistrationId);
+ GcmRegistrationId registration = new GcmRegistrationId(gcmRegistrationId, true);
makeRequest(REGISTER_GCM_PATH, "PUT", new Gson().toJson(registration));
}
@@ -510,7 +504,7 @@ public class PushServiceSocket {
connection.setRequestMethod(method);
connection.setRequestProperty("Content-Type", "application/json");
- if (password != null) {
+ if (credentialsProvider.getPassword() != null) {
connection.setRequestProperty("Authorization", getAuthorizationHeader());
}
@@ -539,35 +533,21 @@ public class PushServiceSocket {
private String getAuthorizationHeader() {
try {
- return "Basic " + Base64.encodeBytes((localNumber + ":" + password).getBytes("UTF-8"));
+ return "Basic " + Base64.encodeBytes((credentialsProvider.getUser() + ":" + credentialsProvider.getPassword()).getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
- private TrustManager[] initializeTrustManager(TrustStore trustStore) {
- try {
- InputStream keyStoreInputStream = trustStore.getKeyStoreInputStream();
- KeyStore keyStore = KeyStore.getInstance("BKS");
-
- keyStore.load(keyStoreInputStream, trustStore.getKeyStorePassword().toCharArray());
-
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
- trustManagerFactory.init(keyStore);
-
- return BlacklistingTrustManager.createFor(trustManagerFactory.getTrustManagers());
- } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException kse) {
- throw new AssertionError(kse);
- }
- }
-
private static class GcmRegistrationId {
private String gcmRegistrationId;
+ private boolean webSocketChannel;
public GcmRegistrationId() {}
- public GcmRegistrationId(String gcmRegistrationId) {
+ public GcmRegistrationId(String gcmRegistrationId, boolean webSocketChannel) {
this.gcmRegistrationId = gcmRegistrationId;
+ this.webSocketChannel = webSocketChannel;
}
}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/BlacklistingTrustManager.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/BlacklistingTrustManager.java
index 4c5b47defa..42a5ec92c4 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/BlacklistingTrustManager.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/BlacklistingTrustManager.java
@@ -16,13 +16,21 @@
*/
package org.whispersystems.textsecure.internal.util;
+import org.whispersystems.textsecure.api.push.TrustStore;
+
+import java.io.IOException;
+import java.io.InputStream;
import java.math.BigInteger;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.LinkedList;
import java.util.List;
import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
/**
@@ -51,6 +59,22 @@ public class BlacklistingTrustManager implements X509TrustManager {
throw new AssertionError("No X509 Trust Managers!");
}
+ public static TrustManager[] createFor(TrustStore trustStore) {
+ try {
+ InputStream keyStoreInputStream = trustStore.getKeyStoreInputStream();
+ KeyStore keyStore = KeyStore.getInstance("BKS");
+
+ keyStore.load(keyStoreInputStream, trustStore.getKeyStorePassword().toCharArray());
+
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
+ trustManagerFactory.init(keyStore);
+
+ return BlacklistingTrustManager.createFor(trustManagerFactory.getTrustManagers());
+ } catch (KeyStoreException | CertificateException | IOException | NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
private final X509TrustManager trustManager;
public BlacklistingTrustManager(X509TrustManager trustManager) {
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/StaticCredentialsProvider.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/StaticCredentialsProvider.java
new file mode 100644
index 0000000000..281086d2b5
--- /dev/null
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/StaticCredentialsProvider.java
@@ -0,0 +1,31 @@
+package org.whispersystems.textsecure.internal.util;
+
+import org.whispersystems.textsecure.api.util.CredentialsProvider;
+
+public class StaticCredentialsProvider implements CredentialsProvider {
+
+ private final String user;
+ private final String password;
+ private final String signalingKey;
+
+ public StaticCredentialsProvider(String user, String password, String signalingKey) {
+ this.user = user;
+ this.password = password;
+ this.signalingKey = signalingKey;
+ }
+
+ @Override
+ public String getUser() {
+ return user;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public String getSignalingKey() {
+ return signalingKey;
+ }
+}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/Util.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/Util.java
index 63eb5b7174..51e89c9a8f 100644
--- a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/Util.java
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/util/Util.java
@@ -102,4 +102,20 @@ public class Util {
out.close();
}
+ public static void sleep(long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ public static void wait(Object lock, long millis) {
+ try {
+ lock.wait(millis);
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/websocket/WebSocketConnection.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/websocket/WebSocketConnection.java
new file mode 100644
index 0000000000..87ceb8c300
--- /dev/null
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/websocket/WebSocketConnection.java
@@ -0,0 +1,292 @@
+package org.whispersystems.textsecure.internal.websocket;
+
+import android.util.Log;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+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.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.LinkedList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+
+import okio.Buffer;
+import okio.BufferedSource;
+
+import static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage;
+import static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage;
+import static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage;
+
+public class WebSocketConnection {
+
+ private static final String TAG = WebSocketConnection.class.getSimpleName();
+
+ private final LinkedList incomingRequests = new LinkedList<>();
+
+ private final String wsUri;
+ private final TrustStore trustStore;
+ private final CredentialsProvider credentialsProvider;
+
+ private Client client;
+ private KeepAliveSender keepAliveSender;
+
+ public WebSocketConnection(String httpUri, TrustStore trustStore, CredentialsProvider credentialsProvider) {
+ this.trustStore = trustStore;
+ this.credentialsProvider = credentialsProvider;
+ this.wsUri = httpUri.replace("https://", "wss://")
+ .replace("http://", "ws://") + "/v1/websocket/?login=%s&password=%s";
+ }
+
+ public synchronized void connect() {
+ Log.w(TAG, "WSC connect()...");
+
+ if (client == null) {
+ client = new Client(wsUri, trustStore, credentialsProvider);
+ client.connect();
+ }
+ }
+
+ public synchronized void disconnect() throws IOException {
+ Log.w(TAG, "WSC disconnect()...");
+
+ if (client != null) {
+ client.disconnect();
+ client = null;
+ }
+
+ if (keepAliveSender != null) {
+ keepAliveSender.shutdown();
+ keepAliveSender = null;
+ }
+ }
+
+ public synchronized WebSocketRequestMessage readRequest(long timeoutMillis)
+ throws TimeoutException, IOException
+ {
+ if (client == null) {
+ throw new IOException("Connection closed!");
+ }
+
+ long startTime = System.currentTimeMillis();
+
+ while (client != null && incomingRequests.isEmpty() && elapsedTime(startTime) < timeoutMillis) {
+ Util.wait(this, Math.max(1, timeoutMillis - elapsedTime(startTime)));
+ }
+
+ if (incomingRequests.isEmpty() && client == null) throw new IOException("Connection closed!");
+ else if (incomingRequests.isEmpty()) throw new TimeoutException("Timeout exceeded");
+ else return incomingRequests.removeFirst();
+ }
+
+ public synchronized void sendResponse(WebSocketResponseMessage response) throws IOException {
+ if (client == null) {
+ throw new IOException("Connection closed!");
+ }
+
+ WebSocketMessage message = WebSocketMessage.newBuilder()
+ .setType(WebSocketMessage.Type.RESPONSE)
+ .setResponse(response)
+ .build();
+
+ client.sendMessage(message.toByteArray());
+ }
+
+ private synchronized void sendKeepAlive() throws IOException {
+ if (keepAliveSender != null) {
+ client.sendMessage(WebSocketMessage.newBuilder()
+ .setType(WebSocketMessage.Type.REQUEST)
+ .setRequest(WebSocketRequestMessage.newBuilder()
+ .setId(System.currentTimeMillis())
+ .setPath("/v1/keepalive")
+ .setVerb("GET")
+ .build()).build()
+ .toByteArray());
+ }
+ }
+
+ private synchronized void onMessage(byte[] payload) {
+ Log.w(TAG, "WSC onMessage()");
+ try {
+ WebSocketMessage message = WebSocketMessage.parseFrom(payload);
+
+ Log.w(TAG, "Message Type: " + message.getType().getNumber());
+
+ if (message.getType().getNumber() == WebSocketMessage.Type.REQUEST_VALUE) {
+ incomingRequests.add(message.getRequest());
+ }
+
+ notifyAll();
+ } catch (InvalidProtocolBufferException e) {
+ Log.w(TAG, e);
+ }
+ }
+
+ private synchronized void onClose() {
+ Log.w(TAG, "onClose()...");
+
+ if (client != null) {
+ client = null;
+ connect();
+ }
+
+ if (keepAliveSender != null) {
+ keepAliveSender.shutdown();
+ keepAliveSender = null;
+ }
+
+ notifyAll();
+ }
+
+ private synchronized void onConnected() {
+ if (client != null) {
+ keepAliveSender = new KeepAliveSender();
+ keepAliveSender.start();
+ }
+ }
+
+ private long elapsedTime(long startTime) {
+ return System.currentTimeMillis() - startTime;
+ }
+
+ private class Client implements WebSocketListener {
+
+ private final String uri;
+ private final TrustStore trustStore;
+ private final CredentialsProvider credentialsProvider;
+
+ private WebSocket webSocket;
+ private boolean closed;
+
+ public Client(String uri, TrustStore trustStore, CredentialsProvider credentialsProvider) {
+ Log.w(TAG, "Connecting to: " + uri);
+
+ this.uri = uri;
+ this.trustStore = trustStore;
+ this.credentialsProvider = credentialsProvider;
+ }
+
+ public void connect() {
+ new Thread() {
+ @Override
+ public void run() {
+ int attempt = 0;
+
+ while (newSocket()) {
+ try {
+ Response response = webSocket.connect(Client.this);
+
+ if (response.code() == 101) {
+ 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) {
+ 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)) {
+ WebSocketConnection.this.onMessage(payload.readByteArray());
+ }
+
+ payload.close();
+ }
+
+ @Override
+ public void onClose(int code, String reason) {
+ Log.w(TAG, String.format("onClose(%d, %s)", code, reason));
+ WebSocketConnection.this.onClose();
+ }
+
+ @Override
+ public void onFailure(IOException e) {
+ Log.w(TAG, e);
+ WebSocketConnection.this.onClose();
+ }
+
+ private synchronized boolean newSocket() {
+ if (closed) return false;
+
+ String filledUri = String.format(uri, credentialsProvider.getUser(), credentialsProvider.getPassword());
+ SSLSocketFactory socketFactory = createTlsSocketFactory(trustStore);
+
+ this.webSocket = WebSocket.newWebSocket(new OkHttpClient().setSslSocketFactory(socketFactory),
+ new Request.Builder().url(filledUri).build());
+
+ return true;
+ }
+
+ 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);
+ }
+ }
+ }
+
+ private class KeepAliveSender extends Thread {
+
+ private AtomicBoolean stop = new AtomicBoolean(false);
+
+ public void run() {
+ while (!stop.get()) {
+ try {
+ Thread.sleep(TimeUnit.SECONDS.toMillis(15));
+
+ Log.w(TAG, "Sending keep alive...");
+ sendKeepAlive();
+ } catch (Throwable e) {
+ Log.w(TAG, e);
+ }
+ }
+ }
+
+ public void shutdown() {
+ stop.set(true);
+ }
+ }
+}
diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/websocket/WebSocketProtos.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/websocket/WebSocketProtos.java
new file mode 100644
index 0000000000..8e0a0f28f1
--- /dev/null
+++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/websocket/WebSocketProtos.java
@@ -0,0 +1,2471 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: WebSocketResources.proto
+
+package org.whispersystems.textsecure.internal.websocket;
+
+public final class WebSocketProtos {
+ private WebSocketProtos() {}
+ public static void registerAllExtensions(
+ com.google.protobuf.ExtensionRegistry registry) {
+ }
+ public interface WebSocketRequestMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional string verb = 1;
+ /**
+ * optional string verb = 1;
+ */
+ boolean hasVerb();
+ /**
+ * optional string verb = 1;
+ */
+ java.lang.String getVerb();
+ /**
+ * optional string verb = 1;
+ */
+ com.google.protobuf.ByteString
+ getVerbBytes();
+
+ // optional string path = 2;
+ /**
+ * optional string path = 2;
+ */
+ boolean hasPath();
+ /**
+ * optional string path = 2;
+ */
+ java.lang.String getPath();
+ /**
+ * optional string path = 2;
+ */
+ com.google.protobuf.ByteString
+ getPathBytes();
+
+ // optional bytes body = 3;
+ /**
+ * optional bytes body = 3;
+ */
+ boolean hasBody();
+ /**
+ * optional bytes body = 3;
+ */
+ com.google.protobuf.ByteString getBody();
+
+ // optional uint64 id = 4;
+ /**
+ * optional uint64 id = 4;
+ */
+ boolean hasId();
+ /**
+ * optional uint64 id = 4;
+ */
+ long getId();
+ }
+ /**
+ * Protobuf type {@code textsecure.WebSocketRequestMessage}
+ */
+ public static final class WebSocketRequestMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements WebSocketRequestMessageOrBuilder {
+ // Use WebSocketRequestMessage.newBuilder() to construct.
+ private WebSocketRequestMessage(com.google.protobuf.GeneratedMessage.Builder> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private WebSocketRequestMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final WebSocketRequestMessage defaultInstance;
+ public static WebSocketRequestMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public WebSocketRequestMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private WebSocketRequestMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 10: {
+ bitField0_ |= 0x00000001;
+ verb_ = input.readBytes();
+ break;
+ }
+ case 18: {
+ bitField0_ |= 0x00000002;
+ path_ = input.readBytes();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ body_ = input.readBytes();
+ break;
+ }
+ case 32: {
+ bitField0_ |= 0x00000008;
+ id_ = input.readUInt64();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketRequestMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketRequestMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.class, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ public WebSocketRequestMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new WebSocketRequestMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional string verb = 1;
+ public static final int VERB_FIELD_NUMBER = 1;
+ private java.lang.Object verb_;
+ /**
+ * optional string verb = 1;
+ */
+ public boolean hasVerb() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public java.lang.String getVerb() {
+ java.lang.Object ref = verb_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ verb_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public com.google.protobuf.ByteString
+ getVerbBytes() {
+ java.lang.Object ref = verb_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ verb_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional string path = 2;
+ public static final int PATH_FIELD_NUMBER = 2;
+ private java.lang.Object path_;
+ /**
+ * optional string path = 2;
+ */
+ public boolean hasPath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * optional string path = 2;
+ */
+ public java.lang.String getPath() {
+ java.lang.Object ref = path_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ path_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ * optional string path = 2;
+ */
+ public com.google.protobuf.ByteString
+ getPathBytes() {
+ java.lang.Object ref = path_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ path_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional bytes body = 3;
+ public static final int BODY_FIELD_NUMBER = 3;
+ private com.google.protobuf.ByteString body_;
+ /**
+ * optional bytes body = 3;
+ */
+ public boolean hasBody() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * optional bytes body = 3;
+ */
+ public com.google.protobuf.ByteString getBody() {
+ return body_;
+ }
+
+ // optional uint64 id = 4;
+ public static final int ID_FIELD_NUMBER = 4;
+ private long id_;
+ /**
+ * optional uint64 id = 4;
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * optional uint64 id = 4;
+ */
+ public long getId() {
+ return id_;
+ }
+
+ private void initFields() {
+ verb_ = "";
+ path_ = "";
+ body_ = com.google.protobuf.ByteString.EMPTY;
+ id_ = 0L;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeBytes(1, getVerbBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeBytes(2, getPathBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, body_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeUInt64(4, id_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(1, getVerbBytes());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(2, getPathBytes());
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, body_);
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(4, id_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.WebSocketRequestMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder
+ implements org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketRequestMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketRequestMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.class, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ verb_ = "";
+ bitField0_ = (bitField0_ & ~0x00000001);
+ path_ = "";
+ bitField0_ = (bitField0_ & ~0x00000002);
+ body_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000004);
+ id_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketRequestMessage_descriptor;
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage getDefaultInstanceForType() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage build() {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage buildPartial() {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage result = new org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.verb_ = verb_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.path_ = path_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.body_ = body_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.id_ = id_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage) {
+ return mergeFrom((org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage other) {
+ if (other == org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance()) return this;
+ if (other.hasVerb()) {
+ bitField0_ |= 0x00000001;
+ verb_ = other.verb_;
+ onChanged();
+ }
+ if (other.hasPath()) {
+ bitField0_ |= 0x00000002;
+ path_ = other.path_;
+ onChanged();
+ }
+ if (other.hasBody()) {
+ setBody(other.getBody());
+ }
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional string verb = 1;
+ private java.lang.Object verb_ = "";
+ /**
+ * optional string verb = 1;
+ */
+ public boolean hasVerb() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public java.lang.String getVerb() {
+ java.lang.Object ref = verb_;
+ if (!(ref instanceof java.lang.String)) {
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ verb_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public com.google.protobuf.ByteString
+ getVerbBytes() {
+ java.lang.Object ref = verb_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ verb_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public Builder setVerb(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ verb_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public Builder clearVerb() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ verb_ = getDefaultInstance().getVerb();
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string verb = 1;
+ */
+ public Builder setVerbBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ verb_ = value;
+ onChanged();
+ return this;
+ }
+
+ // optional string path = 2;
+ private java.lang.Object path_ = "";
+ /**
+ * optional string path = 2;
+ */
+ public boolean hasPath() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * optional string path = 2;
+ */
+ public java.lang.String getPath() {
+ java.lang.Object ref = path_;
+ if (!(ref instanceof java.lang.String)) {
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ path_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string path = 2;
+ */
+ public com.google.protobuf.ByteString
+ getPathBytes() {
+ java.lang.Object ref = path_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ path_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string path = 2;
+ */
+ public Builder setPath(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ path_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string path = 2;
+ */
+ public Builder clearPath() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ path_ = getDefaultInstance().getPath();
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string path = 2;
+ */
+ public Builder setPathBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000002;
+ path_ = value;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes body = 3;
+ private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * optional bytes body = 3;
+ */
+ public boolean hasBody() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * optional bytes body = 3;
+ */
+ public com.google.protobuf.ByteString getBody() {
+ return body_;
+ }
+ /**
+ * optional bytes body = 3;
+ */
+ public Builder setBody(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ body_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional bytes body = 3;
+ */
+ public Builder clearBody() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ body_ = getDefaultInstance().getBody();
+ onChanged();
+ return this;
+ }
+
+ // optional uint64 id = 4;
+ private long id_ ;
+ /**
+ * optional uint64 id = 4;
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * optional uint64 id = 4;
+ */
+ public long getId() {
+ return id_;
+ }
+ /**
+ * optional uint64 id = 4;
+ */
+ public Builder setId(long value) {
+ bitField0_ |= 0x00000008;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional uint64 id = 4;
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ id_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.WebSocketRequestMessage)
+ }
+
+ static {
+ defaultInstance = new WebSocketRequestMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.WebSocketRequestMessage)
+ }
+
+ public interface WebSocketResponseMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional uint64 id = 1;
+ /**
+ * optional uint64 id = 1;
+ */
+ boolean hasId();
+ /**
+ * optional uint64 id = 1;
+ */
+ long getId();
+
+ // optional uint32 status = 2;
+ /**
+ * optional uint32 status = 2;
+ */
+ boolean hasStatus();
+ /**
+ * optional uint32 status = 2;
+ */
+ int getStatus();
+
+ // optional string message = 3;
+ /**
+ * optional string message = 3;
+ */
+ boolean hasMessage();
+ /**
+ * optional string message = 3;
+ */
+ java.lang.String getMessage();
+ /**
+ * optional string message = 3;
+ */
+ com.google.protobuf.ByteString
+ getMessageBytes();
+
+ // optional bytes body = 4;
+ /**
+ * optional bytes body = 4;
+ */
+ boolean hasBody();
+ /**
+ * optional bytes body = 4;
+ */
+ com.google.protobuf.ByteString getBody();
+ }
+ /**
+ * Protobuf type {@code textsecure.WebSocketResponseMessage}
+ */
+ public static final class WebSocketResponseMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements WebSocketResponseMessageOrBuilder {
+ // Use WebSocketResponseMessage.newBuilder() to construct.
+ private WebSocketResponseMessage(com.google.protobuf.GeneratedMessage.Builder> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private WebSocketResponseMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final WebSocketResponseMessage defaultInstance;
+ public static WebSocketResponseMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public WebSocketResponseMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private WebSocketResponseMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ bitField0_ |= 0x00000001;
+ id_ = input.readUInt64();
+ break;
+ }
+ case 16: {
+ bitField0_ |= 0x00000002;
+ status_ = input.readUInt32();
+ break;
+ }
+ case 26: {
+ bitField0_ |= 0x00000004;
+ message_ = input.readBytes();
+ break;
+ }
+ case 34: {
+ bitField0_ |= 0x00000008;
+ body_ = input.readBytes();
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketResponseMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketResponseMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.class, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ public WebSocketResponseMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new WebSocketResponseMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ private int bitField0_;
+ // optional uint64 id = 1;
+ public static final int ID_FIELD_NUMBER = 1;
+ private long id_;
+ /**
+ * optional uint64 id = 1;
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * optional uint64 id = 1;
+ */
+ public long getId() {
+ return id_;
+ }
+
+ // optional uint32 status = 2;
+ public static final int STATUS_FIELD_NUMBER = 2;
+ private int status_;
+ /**
+ * optional uint32 status = 2;
+ */
+ public boolean hasStatus() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * optional uint32 status = 2;
+ */
+ public int getStatus() {
+ return status_;
+ }
+
+ // optional string message = 3;
+ public static final int MESSAGE_FIELD_NUMBER = 3;
+ private java.lang.Object message_;
+ /**
+ * optional string message = 3;
+ */
+ public boolean hasMessage() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * optional string message = 3;
+ */
+ public java.lang.String getMessage() {
+ java.lang.Object ref = message_;
+ if (ref instanceof java.lang.String) {
+ return (java.lang.String) ref;
+ } else {
+ com.google.protobuf.ByteString bs =
+ (com.google.protobuf.ByteString) ref;
+ java.lang.String s = bs.toStringUtf8();
+ if (bs.isValidUtf8()) {
+ message_ = s;
+ }
+ return s;
+ }
+ }
+ /**
+ * optional string message = 3;
+ */
+ public com.google.protobuf.ByteString
+ getMessageBytes() {
+ java.lang.Object ref = message_;
+ if (ref instanceof java.lang.String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ message_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+
+ // optional bytes body = 4;
+ public static final int BODY_FIELD_NUMBER = 4;
+ private com.google.protobuf.ByteString body_;
+ /**
+ * optional bytes body = 4;
+ */
+ public boolean hasBody() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * optional bytes body = 4;
+ */
+ public com.google.protobuf.ByteString getBody() {
+ return body_;
+ }
+
+ private void initFields() {
+ id_ = 0L;
+ status_ = 0;
+ message_ = "";
+ body_ = com.google.protobuf.ByteString.EMPTY;
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeUInt64(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeUInt32(2, status_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeBytes(3, getMessageBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ output.writeBytes(4, body_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt64Size(1, id_);
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeUInt32Size(2, status_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(3, getMessageBytes());
+ }
+ if (((bitField0_ & 0x00000008) == 0x00000008)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeBytesSize(4, body_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.WebSocketResponseMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder
+ implements org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketResponseMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketResponseMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.class, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ id_ = 0L;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ status_ = 0;
+ bitField0_ = (bitField0_ & ~0x00000002);
+ message_ = "";
+ bitField0_ = (bitField0_ & ~0x00000004);
+ body_ = com.google.protobuf.ByteString.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000008);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketResponseMessage_descriptor;
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage getDefaultInstanceForType() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage build() {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage buildPartial() {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage result = new org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.id_ = id_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ result.status_ = status_;
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ result.message_ = message_;
+ if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+ to_bitField0_ |= 0x00000008;
+ }
+ result.body_ = body_;
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage) {
+ return mergeFrom((org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage other) {
+ if (other == org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance()) return this;
+ if (other.hasId()) {
+ setId(other.getId());
+ }
+ if (other.hasStatus()) {
+ setStatus(other.getStatus());
+ }
+ if (other.hasMessage()) {
+ bitField0_ |= 0x00000004;
+ message_ = other.message_;
+ onChanged();
+ }
+ if (other.hasBody()) {
+ setBody(other.getBody());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional uint64 id = 1;
+ private long id_ ;
+ /**
+ * optional uint64 id = 1;
+ */
+ public boolean hasId() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * optional uint64 id = 1;
+ */
+ public long getId() {
+ return id_;
+ }
+ /**
+ * optional uint64 id = 1;
+ */
+ public Builder setId(long value) {
+ bitField0_ |= 0x00000001;
+ id_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional uint64 id = 1;
+ */
+ public Builder clearId() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ id_ = 0L;
+ onChanged();
+ return this;
+ }
+
+ // optional uint32 status = 2;
+ private int status_ ;
+ /**
+ * optional uint32 status = 2;
+ */
+ public boolean hasStatus() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * optional uint32 status = 2;
+ */
+ public int getStatus() {
+ return status_;
+ }
+ /**
+ * optional uint32 status = 2;
+ */
+ public Builder setStatus(int value) {
+ bitField0_ |= 0x00000002;
+ status_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional uint32 status = 2;
+ */
+ public Builder clearStatus() {
+ bitField0_ = (bitField0_ & ~0x00000002);
+ status_ = 0;
+ onChanged();
+ return this;
+ }
+
+ // optional string message = 3;
+ private java.lang.Object message_ = "";
+ /**
+ * optional string message = 3;
+ */
+ public boolean hasMessage() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * optional string message = 3;
+ */
+ public java.lang.String getMessage() {
+ java.lang.Object ref = message_;
+ if (!(ref instanceof java.lang.String)) {
+ java.lang.String s = ((com.google.protobuf.ByteString) ref)
+ .toStringUtf8();
+ message_ = s;
+ return s;
+ } else {
+ return (java.lang.String) ref;
+ }
+ }
+ /**
+ * optional string message = 3;
+ */
+ public com.google.protobuf.ByteString
+ getMessageBytes() {
+ java.lang.Object ref = message_;
+ if (ref instanceof String) {
+ com.google.protobuf.ByteString b =
+ com.google.protobuf.ByteString.copyFromUtf8(
+ (java.lang.String) ref);
+ message_ = b;
+ return b;
+ } else {
+ return (com.google.protobuf.ByteString) ref;
+ }
+ }
+ /**
+ * optional string message = 3;
+ */
+ public Builder setMessage(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ message_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string message = 3;
+ */
+ public Builder clearMessage() {
+ bitField0_ = (bitField0_ & ~0x00000004);
+ message_ = getDefaultInstance().getMessage();
+ onChanged();
+ return this;
+ }
+ /**
+ * optional string message = 3;
+ */
+ public Builder setMessageBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000004;
+ message_ = value;
+ onChanged();
+ return this;
+ }
+
+ // optional bytes body = 4;
+ private com.google.protobuf.ByteString body_ = com.google.protobuf.ByteString.EMPTY;
+ /**
+ * optional bytes body = 4;
+ */
+ public boolean hasBody() {
+ return ((bitField0_ & 0x00000008) == 0x00000008);
+ }
+ /**
+ * optional bytes body = 4;
+ */
+ public com.google.protobuf.ByteString getBody() {
+ return body_;
+ }
+ /**
+ * optional bytes body = 4;
+ */
+ public Builder setBody(com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000008;
+ body_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional bytes body = 4;
+ */
+ public Builder clearBody() {
+ bitField0_ = (bitField0_ & ~0x00000008);
+ body_ = getDefaultInstance().getBody();
+ onChanged();
+ return this;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.WebSocketResponseMessage)
+ }
+
+ static {
+ defaultInstance = new WebSocketResponseMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.WebSocketResponseMessage)
+ }
+
+ public interface WebSocketMessageOrBuilder
+ extends com.google.protobuf.MessageOrBuilder {
+
+ // optional .textsecure.WebSocketMessage.Type type = 1;
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ boolean hasType();
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type getType();
+
+ // optional .textsecure.WebSocketRequestMessage request = 2;
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ boolean hasRequest();
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage getRequest();
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder getRequestOrBuilder();
+
+ // optional .textsecure.WebSocketResponseMessage response = 3;
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ boolean hasResponse();
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage getResponse();
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder getResponseOrBuilder();
+ }
+ /**
+ * Protobuf type {@code textsecure.WebSocketMessage}
+ */
+ public static final class WebSocketMessage extends
+ com.google.protobuf.GeneratedMessage
+ implements WebSocketMessageOrBuilder {
+ // Use WebSocketMessage.newBuilder() to construct.
+ private WebSocketMessage(com.google.protobuf.GeneratedMessage.Builder> builder) {
+ super(builder);
+ this.unknownFields = builder.getUnknownFields();
+ }
+ private WebSocketMessage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+ private static final WebSocketMessage defaultInstance;
+ public static WebSocketMessage getDefaultInstance() {
+ return defaultInstance;
+ }
+
+ public WebSocketMessage getDefaultInstanceForType() {
+ return defaultInstance;
+ }
+
+ private final com.google.protobuf.UnknownFieldSet unknownFields;
+ @java.lang.Override
+ public final com.google.protobuf.UnknownFieldSet
+ getUnknownFields() {
+ return this.unknownFields;
+ }
+ private WebSocketMessage(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ initFields();
+ int mutable_bitField0_ = 0;
+ com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+ com.google.protobuf.UnknownFieldSet.newBuilder();
+ try {
+ boolean done = false;
+ while (!done) {
+ int tag = input.readTag();
+ switch (tag) {
+ case 0:
+ done = true;
+ break;
+ default: {
+ if (!parseUnknownField(input, unknownFields,
+ extensionRegistry, tag)) {
+ done = true;
+ }
+ break;
+ }
+ case 8: {
+ int rawValue = input.readEnum();
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type value = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type.valueOf(rawValue);
+ if (value == null) {
+ unknownFields.mergeVarintField(1, rawValue);
+ } else {
+ bitField0_ |= 0x00000001;
+ type_ = value;
+ }
+ break;
+ }
+ case 18: {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ subBuilder = request_.toBuilder();
+ }
+ request_ = input.readMessage(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(request_);
+ request_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000002;
+ break;
+ }
+ case 26: {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder subBuilder = null;
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ subBuilder = response_.toBuilder();
+ }
+ response_ = input.readMessage(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.PARSER, extensionRegistry);
+ if (subBuilder != null) {
+ subBuilder.mergeFrom(response_);
+ response_ = subBuilder.buildPartial();
+ }
+ bitField0_ |= 0x00000004;
+ break;
+ }
+ }
+ }
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ throw e.setUnfinishedMessage(this);
+ } catch (java.io.IOException e) {
+ throw new com.google.protobuf.InvalidProtocolBufferException(
+ e.getMessage()).setUnfinishedMessage(this);
+ } finally {
+ this.unknownFields = unknownFields.build();
+ makeExtensionsImmutable();
+ }
+ }
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.class, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Builder.class);
+ }
+
+ public static com.google.protobuf.Parser PARSER =
+ new com.google.protobuf.AbstractParser() {
+ public WebSocketMessage parsePartialFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return new WebSocketMessage(input, extensionRegistry);
+ }
+ };
+
+ @java.lang.Override
+ public com.google.protobuf.Parser getParserForType() {
+ return PARSER;
+ }
+
+ /**
+ * Protobuf enum {@code textsecure.WebSocketMessage.Type}
+ */
+ public enum Type
+ implements com.google.protobuf.ProtocolMessageEnum {
+ /**
+ * UNKNOWN = 0;
+ */
+ UNKNOWN(0, 0),
+ /**
+ * REQUEST = 1;
+ */
+ REQUEST(1, 1),
+ /**
+ * RESPONSE = 2;
+ */
+ RESPONSE(2, 2),
+ ;
+
+ /**
+ * UNKNOWN = 0;
+ */
+ public static final int UNKNOWN_VALUE = 0;
+ /**
+ * REQUEST = 1;
+ */
+ public static final int REQUEST_VALUE = 1;
+ /**
+ * RESPONSE = 2;
+ */
+ public static final int RESPONSE_VALUE = 2;
+
+
+ public final int getNumber() { return value; }
+
+ public static Type valueOf(int value) {
+ switch (value) {
+ case 0: return UNKNOWN;
+ case 1: return REQUEST;
+ case 2: return RESPONSE;
+ default: return null;
+ }
+ }
+
+ public static com.google.protobuf.Internal.EnumLiteMap
+ internalGetValueMap() {
+ return internalValueMap;
+ }
+ private static com.google.protobuf.Internal.EnumLiteMap
+ internalValueMap =
+ new com.google.protobuf.Internal.EnumLiteMap() {
+ public Type findValueByNumber(int number) {
+ return Type.valueOf(number);
+ }
+ };
+
+ public final com.google.protobuf.Descriptors.EnumValueDescriptor
+ getValueDescriptor() {
+ return getDescriptor().getValues().get(index);
+ }
+ public final com.google.protobuf.Descriptors.EnumDescriptor
+ getDescriptorForType() {
+ return getDescriptor();
+ }
+ public static final com.google.protobuf.Descriptors.EnumDescriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.getDescriptor().getEnumTypes().get(0);
+ }
+
+ private static final Type[] VALUES = values();
+
+ public static Type valueOf(
+ com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+ if (desc.getType() != getDescriptor()) {
+ throw new java.lang.IllegalArgumentException(
+ "EnumValueDescriptor is not for this type.");
+ }
+ return VALUES[desc.getIndex()];
+ }
+
+ private final int index;
+ private final int value;
+
+ private Type(int index, int value) {
+ this.index = index;
+ this.value = value;
+ }
+
+ // @@protoc_insertion_point(enum_scope:textsecure.WebSocketMessage.Type)
+ }
+
+ private int bitField0_;
+ // optional .textsecure.WebSocketMessage.Type type = 1;
+ public static final int TYPE_FIELD_NUMBER = 1;
+ private org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type type_;
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type getType() {
+ return type_;
+ }
+
+ // optional .textsecure.WebSocketRequestMessage request = 2;
+ public static final int REQUEST_FIELD_NUMBER = 2;
+ private org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage request_;
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public boolean hasRequest() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage getRequest() {
+ return request_;
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder getRequestOrBuilder() {
+ return request_;
+ }
+
+ // optional .textsecure.WebSocketResponseMessage response = 3;
+ public static final int RESPONSE_FIELD_NUMBER = 3;
+ private org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage response_;
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public boolean hasResponse() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage getResponse() {
+ return response_;
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder getResponseOrBuilder() {
+ return response_;
+ }
+
+ private void initFields() {
+ type_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type.UNKNOWN;
+ request_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance();
+ response_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance();
+ }
+ private byte memoizedIsInitialized = -1;
+ public final boolean isInitialized() {
+ byte isInitialized = memoizedIsInitialized;
+ if (isInitialized != -1) return isInitialized == 1;
+
+ memoizedIsInitialized = 1;
+ return true;
+ }
+
+ public void writeTo(com.google.protobuf.CodedOutputStream output)
+ throws java.io.IOException {
+ getSerializedSize();
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ output.writeEnum(1, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ output.writeMessage(2, request_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ output.writeMessage(3, response_);
+ }
+ getUnknownFields().writeTo(output);
+ }
+
+ private int memoizedSerializedSize = -1;
+ public int getSerializedSize() {
+ int size = memoizedSerializedSize;
+ if (size != -1) return size;
+
+ size = 0;
+ if (((bitField0_ & 0x00000001) == 0x00000001)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeEnumSize(1, type_.getNumber());
+ }
+ if (((bitField0_ & 0x00000002) == 0x00000002)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(2, request_);
+ }
+ if (((bitField0_ & 0x00000004) == 0x00000004)) {
+ size += com.google.protobuf.CodedOutputStream
+ .computeMessageSize(3, response_);
+ }
+ size += getUnknownFields().getSerializedSize();
+ memoizedSerializedSize = size;
+ return size;
+ }
+
+ private static final long serialVersionUID = 0L;
+ @java.lang.Override
+ protected java.lang.Object writeReplace()
+ throws java.io.ObjectStreamException {
+ return super.writeReplace();
+ }
+
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(
+ com.google.protobuf.ByteString data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(
+ com.google.protobuf.ByteString data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(byte[] data)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(
+ byte[] data,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws com.google.protobuf.InvalidProtocolBufferException {
+ return PARSER.parseFrom(data, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseDelimitedFrom(java.io.InputStream input)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseDelimitedFrom(
+ java.io.InputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseDelimitedFrom(input, extensionRegistry);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(
+ com.google.protobuf.CodedInputStream input)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input);
+ }
+ public static org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parseFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ return PARSER.parseFrom(input, extensionRegistry);
+ }
+
+ public static Builder newBuilder() { return Builder.create(); }
+ public Builder newBuilderForType() { return newBuilder(); }
+ public static Builder newBuilder(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage prototype) {
+ return newBuilder().mergeFrom(prototype);
+ }
+ public Builder toBuilder() { return newBuilder(this); }
+
+ @java.lang.Override
+ protected Builder newBuilderForType(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ Builder builder = new Builder(parent);
+ return builder;
+ }
+ /**
+ * Protobuf type {@code textsecure.WebSocketMessage}
+ */
+ public static final class Builder extends
+ com.google.protobuf.GeneratedMessage.Builder
+ implements org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessageOrBuilder {
+ public static final com.google.protobuf.Descriptors.Descriptor
+ getDescriptor() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketMessage_descriptor;
+ }
+
+ protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internalGetFieldAccessorTable() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketMessage_fieldAccessorTable
+ .ensureFieldAccessorsInitialized(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.class, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Builder.class);
+ }
+
+ // Construct using org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.newBuilder()
+ private Builder() {
+ maybeForceBuilderInitialization();
+ }
+
+ private Builder(
+ com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+ super(parent);
+ maybeForceBuilderInitialization();
+ }
+ private void maybeForceBuilderInitialization() {
+ if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+ getRequestFieldBuilder();
+ getResponseFieldBuilder();
+ }
+ }
+ private static Builder create() {
+ return new Builder();
+ }
+
+ public Builder clear() {
+ super.clear();
+ type_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type.UNKNOWN;
+ bitField0_ = (bitField0_ & ~0x00000001);
+ if (requestBuilder_ == null) {
+ request_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance();
+ } else {
+ requestBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000002);
+ if (responseBuilder_ == null) {
+ response_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance();
+ } else {
+ responseBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+
+ public Builder clone() {
+ return create().mergeFrom(buildPartial());
+ }
+
+ public com.google.protobuf.Descriptors.Descriptor
+ getDescriptorForType() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.internal_static_textsecure_WebSocketMessage_descriptor;
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage getDefaultInstanceForType() {
+ return org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.getDefaultInstance();
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage build() {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage result = buildPartial();
+ if (!result.isInitialized()) {
+ throw newUninitializedMessageException(result);
+ }
+ return result;
+ }
+
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage buildPartial() {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage result = new org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage(this);
+ int from_bitField0_ = bitField0_;
+ int to_bitField0_ = 0;
+ if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+ to_bitField0_ |= 0x00000001;
+ }
+ result.type_ = type_;
+ if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+ to_bitField0_ |= 0x00000002;
+ }
+ if (requestBuilder_ == null) {
+ result.request_ = request_;
+ } else {
+ result.request_ = requestBuilder_.build();
+ }
+ if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+ to_bitField0_ |= 0x00000004;
+ }
+ if (responseBuilder_ == null) {
+ result.response_ = response_;
+ } else {
+ result.response_ = responseBuilder_.build();
+ }
+ result.bitField0_ = to_bitField0_;
+ onBuilt();
+ return result;
+ }
+
+ public Builder mergeFrom(com.google.protobuf.Message other) {
+ if (other instanceof org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage) {
+ return mergeFrom((org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage)other);
+ } else {
+ super.mergeFrom(other);
+ return this;
+ }
+ }
+
+ public Builder mergeFrom(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage other) {
+ if (other == org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.getDefaultInstance()) return this;
+ if (other.hasType()) {
+ setType(other.getType());
+ }
+ if (other.hasRequest()) {
+ mergeRequest(other.getRequest());
+ }
+ if (other.hasResponse()) {
+ mergeResponse(other.getResponse());
+ }
+ this.mergeUnknownFields(other.getUnknownFields());
+ return this;
+ }
+
+ public final boolean isInitialized() {
+ return true;
+ }
+
+ public Builder mergeFrom(
+ com.google.protobuf.CodedInputStream input,
+ com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+ throws java.io.IOException {
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage parsedMessage = null;
+ try {
+ parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+ } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+ parsedMessage = (org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage) e.getUnfinishedMessage();
+ throw e;
+ } finally {
+ if (parsedMessage != null) {
+ mergeFrom(parsedMessage);
+ }
+ }
+ return this;
+ }
+ private int bitField0_;
+
+ // optional .textsecure.WebSocketMessage.Type type = 1;
+ private org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type type_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type.UNKNOWN;
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ public boolean hasType() {
+ return ((bitField0_ & 0x00000001) == 0x00000001);
+ }
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type getType() {
+ return type_;
+ }
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ public Builder setType(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ bitField0_ |= 0x00000001;
+ type_ = value;
+ onChanged();
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketMessage.Type type = 1;
+ */
+ public Builder clearType() {
+ bitField0_ = (bitField0_ & ~0x00000001);
+ type_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketMessage.Type.UNKNOWN;
+ onChanged();
+ return this;
+ }
+
+ // optional .textsecure.WebSocketRequestMessage request = 2;
+ private org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage request_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder> requestBuilder_;
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public boolean hasRequest() {
+ return ((bitField0_ & 0x00000002) == 0x00000002);
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage getRequest() {
+ if (requestBuilder_ == null) {
+ return request_;
+ } else {
+ return requestBuilder_.getMessage();
+ }
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public Builder setRequest(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage value) {
+ if (requestBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ request_ = value;
+ onChanged();
+ } else {
+ requestBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public Builder setRequest(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder builderForValue) {
+ if (requestBuilder_ == null) {
+ request_ = builderForValue.build();
+ onChanged();
+ } else {
+ requestBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public Builder mergeRequest(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage value) {
+ if (requestBuilder_ == null) {
+ if (((bitField0_ & 0x00000002) == 0x00000002) &&
+ request_ != org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance()) {
+ request_ =
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.newBuilder(request_).mergeFrom(value).buildPartial();
+ } else {
+ request_ = value;
+ }
+ onChanged();
+ } else {
+ requestBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000002;
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public Builder clearRequest() {
+ if (requestBuilder_ == null) {
+ request_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.getDefaultInstance();
+ onChanged();
+ } else {
+ requestBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000002);
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder getRequestBuilder() {
+ bitField0_ |= 0x00000002;
+ onChanged();
+ return getRequestFieldBuilder().getBuilder();
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder getRequestOrBuilder() {
+ if (requestBuilder_ != null) {
+ return requestBuilder_.getMessageOrBuilder();
+ } else {
+ return request_;
+ }
+ }
+ /**
+ * optional .textsecure.WebSocketRequestMessage request = 2;
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder>
+ getRequestFieldBuilder() {
+ if (requestBuilder_ == null) {
+ requestBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessage.Builder, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketRequestMessageOrBuilder>(
+ request_,
+ getParentForChildren(),
+ isClean());
+ request_ = null;
+ }
+ return requestBuilder_;
+ }
+
+ // optional .textsecure.WebSocketResponseMessage response = 3;
+ private org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage response_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance();
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder> responseBuilder_;
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public boolean hasResponse() {
+ return ((bitField0_ & 0x00000004) == 0x00000004);
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage getResponse() {
+ if (responseBuilder_ == null) {
+ return response_;
+ } else {
+ return responseBuilder_.getMessage();
+ }
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public Builder setResponse(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage value) {
+ if (responseBuilder_ == null) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ response_ = value;
+ onChanged();
+ } else {
+ responseBuilder_.setMessage(value);
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public Builder setResponse(
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder builderForValue) {
+ if (responseBuilder_ == null) {
+ response_ = builderForValue.build();
+ onChanged();
+ } else {
+ responseBuilder_.setMessage(builderForValue.build());
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public Builder mergeResponse(org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage value) {
+ if (responseBuilder_ == null) {
+ if (((bitField0_ & 0x00000004) == 0x00000004) &&
+ response_ != org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance()) {
+ response_ =
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.newBuilder(response_).mergeFrom(value).buildPartial();
+ } else {
+ response_ = value;
+ }
+ onChanged();
+ } else {
+ responseBuilder_.mergeFrom(value);
+ }
+ bitField0_ |= 0x00000004;
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public Builder clearResponse() {
+ if (responseBuilder_ == null) {
+ response_ = org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.getDefaultInstance();
+ onChanged();
+ } else {
+ responseBuilder_.clear();
+ }
+ bitField0_ = (bitField0_ & ~0x00000004);
+ return this;
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder getResponseBuilder() {
+ bitField0_ |= 0x00000004;
+ onChanged();
+ return getResponseFieldBuilder().getBuilder();
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ public org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder getResponseOrBuilder() {
+ if (responseBuilder_ != null) {
+ return responseBuilder_.getMessageOrBuilder();
+ } else {
+ return response_;
+ }
+ }
+ /**
+ * optional .textsecure.WebSocketResponseMessage response = 3;
+ */
+ private com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder>
+ getResponseFieldBuilder() {
+ if (responseBuilder_ == null) {
+ responseBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+ org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessage.Builder, org.whispersystems.textsecure.internal.websocket.WebSocketProtos.WebSocketResponseMessageOrBuilder>(
+ response_,
+ getParentForChildren(),
+ isClean());
+ response_ = null;
+ }
+ return responseBuilder_;
+ }
+
+ // @@protoc_insertion_point(builder_scope:textsecure.WebSocketMessage)
+ }
+
+ static {
+ defaultInstance = new WebSocketMessage(true);
+ defaultInstance.initFields();
+ }
+
+ // @@protoc_insertion_point(class_scope:textsecure.WebSocketMessage)
+ }
+
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_WebSocketRequestMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_WebSocketRequestMessage_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_WebSocketResponseMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_WebSocketResponseMessage_fieldAccessorTable;
+ private static com.google.protobuf.Descriptors.Descriptor
+ internal_static_textsecure_WebSocketMessage_descriptor;
+ private static
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable
+ internal_static_textsecure_WebSocketMessage_fieldAccessorTable;
+
+ public static com.google.protobuf.Descriptors.FileDescriptor
+ getDescriptor() {
+ return descriptor;
+ }
+ private static com.google.protobuf.Descriptors.FileDescriptor
+ descriptor;
+ static {
+ java.lang.String[] descriptorData = {
+ "\n\030WebSocketResources.proto\022\ntextsecure\"O" +
+ "\n\027WebSocketRequestMessage\022\014\n\004verb\030\001 \001(\t\022" +
+ "\014\n\004path\030\002 \001(\t\022\014\n\004body\030\003 \001(\014\022\n\n\002id\030\004 \001(\004\"" +
+ "U\n\030WebSocketResponseMessage\022\n\n\002id\030\001 \001(\004\022" +
+ "\016\n\006status\030\002 \001(\r\022\017\n\007message\030\003 \001(\t\022\014\n\004body" +
+ "\030\004 \001(\014\"\341\001\n\020WebSocketMessage\022/\n\004type\030\001 \001(" +
+ "\0162!.textsecure.WebSocketMessage.Type\0224\n\007" +
+ "request\030\002 \001(\0132#.textsecure.WebSocketRequ" +
+ "estMessage\0226\n\010response\030\003 \001(\0132$.textsecur" +
+ "e.WebSocketResponseMessage\".\n\004Type\022\013\n\007UN",
+ "KNOWN\020\000\022\013\n\007REQUEST\020\001\022\014\n\010RESPONSE\020\002BC\n0or" +
+ "g.whispersystems.textsecure.internal.web" +
+ "socketB\017WebSocketProtos"
+ };
+ com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+ new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
+ public com.google.protobuf.ExtensionRegistry assignDescriptors(
+ com.google.protobuf.Descriptors.FileDescriptor root) {
+ descriptor = root;
+ internal_static_textsecure_WebSocketRequestMessage_descriptor =
+ getDescriptor().getMessageTypes().get(0);
+ internal_static_textsecure_WebSocketRequestMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_WebSocketRequestMessage_descriptor,
+ new java.lang.String[] { "Verb", "Path", "Body", "Id", });
+ internal_static_textsecure_WebSocketResponseMessage_descriptor =
+ getDescriptor().getMessageTypes().get(1);
+ internal_static_textsecure_WebSocketResponseMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_WebSocketResponseMessage_descriptor,
+ new java.lang.String[] { "Id", "Status", "Message", "Body", });
+ internal_static_textsecure_WebSocketMessage_descriptor =
+ getDescriptor().getMessageTypes().get(2);
+ internal_static_textsecure_WebSocketMessage_fieldAccessorTable = new
+ com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+ internal_static_textsecure_WebSocketMessage_descriptor,
+ new java.lang.String[] { "Type", "Request", "Response", });
+ return null;
+ }
+ };
+ com.google.protobuf.Descriptors.FileDescriptor
+ .internalBuildGeneratedFileFrom(descriptorData,
+ new com.google.protobuf.Descriptors.FileDescriptor[] {
+ }, assigner);
+ }
+
+ // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java b/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java
index 67cf63713d..80aa544305 100644
--- a/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java
+++ b/src/org/thoughtcrime/securesms/PassphraseRequiredMixin.java
@@ -10,6 +10,7 @@ import android.view.WindowManager;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.service.KeyCachingService;
+import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@@ -27,11 +28,13 @@ public class PassphraseRequiredMixin {
initializeNewKeyReceiver(activity);
initializeFromMasterSecret(activity);
KeyCachingService.registerPassphraseActivityStarted(activity);
+ MessageRetrievalService.registerActivityStarted(activity);
}
public void onPause(T activity) {
removeNewKeyReceiver(activity);
KeyCachingService.registerPassphraseActivityStopped(activity);
+ MessageRetrievalService.registerActivityStopped(activity);
}
public void onDestroy(T activity) {
diff --git a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java
index 7d830a7230..9e27d09e68 100644
--- a/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java
+++ b/src/org/thoughtcrime/securesms/dependencies/TextSecureCommunicationModule.java
@@ -6,7 +6,6 @@ import org.thoughtcrime.securesms.Release;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore;
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob;
-import org.thoughtcrime.securesms.jobs.AvatarDownloadJob;
import org.thoughtcrime.securesms.jobs.CleanPreKeysJob;
import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob;
import org.thoughtcrime.securesms.jobs.DeliveryReceiptJob;
@@ -19,12 +18,13 @@ import org.thoughtcrime.securesms.push.TextSecurePushTrustStore;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
+import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libaxolotl.util.guava.Optional;
import org.whispersystems.textsecure.api.TextSecureAccountManager;
import org.whispersystems.textsecure.api.TextSecureMessageReceiver;
import org.whispersystems.textsecure.api.TextSecureMessageSender;
-import org.whispersystems.textsecure.api.push.PushAddress;
+import org.whispersystems.textsecure.api.util.CredentialsProvider;
import dagger.Module;
import dagger.Provides;
@@ -36,7 +36,8 @@ import dagger.Provides;
PushTextSendJob.class,
PushMediaSendJob.class,
AttachmentDownloadJob.class,
- RefreshPreKeysJob.class})
+ RefreshPreKeysJob.class,
+ MessageRetrievalService.class})
public class TextSecureCommunicationModule {
private final Context context;
@@ -77,13 +78,36 @@ public class TextSecureCommunicationModule {
@Provides TextSecureMessageReceiver provideTextSecureMessageReceiver() {
return new TextSecureMessageReceiver(Release.PUSH_URL,
- new TextSecurePushTrustStore(context),
- TextSecurePreferences.getLocalNumber(context),
- TextSecurePreferences.getPushServerPassword(context));
+ new TextSecurePushTrustStore(context),
+ new DynamicCredentialsProvider(context));
}
public static interface TextSecureMessageSenderFactory {
public TextSecureMessageSender create(MasterSecret masterSecret);
}
+ private static class DynamicCredentialsProvider implements CredentialsProvider {
+
+ private final Context context;
+
+ private DynamicCredentialsProvider(Context context) {
+ this.context = context.getApplicationContext();
+ }
+
+ @Override
+ public String getUser() {
+ return TextSecurePreferences.getLocalNumber(context);
+ }
+
+ @Override
+ public String getPassword() {
+ return TextSecurePreferences.getPushServerPassword(context);
+ }
+
+ @Override
+ public String getSignalingKey() {
+ return TextSecurePreferences.getSignalingKey(context);
+ }
+ }
+
}
diff --git a/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java b/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java
index 4975474521..843a2120ff 100644
--- a/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java
+++ b/src/org/thoughtcrime/securesms/gcm/GcmBroadcastReceiver.java
@@ -10,6 +10,7 @@ import com.google.android.gms.gcm.GoogleCloudMessaging;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.jobs.PushReceiveJob;
+import org.thoughtcrime.securesms.service.MessageRetrievalService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
public class GcmBroadcastReceiver extends BroadcastReceiver {
@@ -34,6 +35,7 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
if (!TextUtils.isEmpty(messageData)) handleReceivedMessage(context, messageData);
else if (!TextUtils.isEmpty(receiptData)) handleReceivedMessage(context, receiptData);
+ else if (intent.hasExtra("notification")) handleReceivedNotification(context);
}
}
@@ -42,4 +44,8 @@ public class GcmBroadcastReceiver extends BroadcastReceiver {
.getJobManager()
.add(new PushReceiveJob(context, data));
}
+
+ private void handleReceivedNotification(Context context) {
+ MessageRetrievalService.registerPushReceived(context);
+ }
}
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
index 56c740f251..52cd6d4e66 100644
--- a/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/AvatarDownloadJob.java
@@ -23,6 +23,7 @@ import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.textsecure.api.crypto.AttachmentCipherInputStream;
import org.whispersystems.textsecure.internal.push.PushServiceSocket;
import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException;
+import org.whispersystems.textsecure.internal.util.StaticCredentialsProvider;
import java.io.File;
import java.io.IOException;
@@ -99,8 +100,9 @@ public class AvatarDownloadJob extends MasterSecretJob {
private File downloadAttachment(String relay, long contentLocation) throws IOException {
PushServiceSocket socket = new PushServiceSocket(Release.PUSH_URL,
new TextSecurePushTrustStore(context),
- TextSecurePreferences.getLocalNumber(context),
- TextSecurePreferences.getPushServerPassword(context));
+ new StaticCredentialsProvider(TextSecurePreferences.getLocalNumber(context),
+ TextSecurePreferences.getPushServerPassword(context),
+ null));
File destination = File.createTempFile("avatar", "tmp");
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 5d95f88ccb..64ed7f366a 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -221,10 +221,12 @@ public class PushDecryptJob extends MasterSecretJob {
}
private void handleDuplicateMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
- Pair messageAndThreadId = insertPlaceholder(masterSecret, envelope);
- DatabaseFactory.getEncryptingSmsDatabase(context).markAsDecryptDuplicate(messageAndThreadId.first);
+ // Let's start ignoring these now.
- MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
+// Pair messageAndThreadId = insertPlaceholder(masterSecret, envelope);
+// DatabaseFactory.getEncryptingSmsDatabase(context).markAsDecryptDuplicate(messageAndThreadId.first);
+//
+// MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
}
private void handleUntrustedIdentityMessage(MasterSecret masterSecret, TextSecureEnvelope envelope) {
diff --git a/src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java b/src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java
index 348760132f..cbe3b2668a 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushReceiveJob.java
@@ -22,6 +22,11 @@ public class PushReceiveJob extends ContextJob {
private final String data;
+ public PushReceiveJob(Context context) {
+ super(context, JobParameters.newBuilder().create());
+ this.data = null;
+ }
+
public PushReceiveJob(Context context, String data) {
super(context, JobParameters.newBuilder()
.withPersistence()
@@ -39,16 +44,7 @@ public class PushReceiveJob extends ContextJob {
String sessionKey = TextSecurePreferences.getSignalingKey(context);
TextSecureEnvelope envelope = new TextSecureEnvelope(data, sessionKey);
- if (!isActiveNumber(context, envelope.getSource())) {
- TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
- ContactTokenDetails contactTokenDetails = new ContactTokenDetails();
- contactTokenDetails.setNumber(envelope.getSource());
-
- directory.setNumber(contactTokenDetails, true);
- }
-
- if (envelope.isReceipt()) handleReceipt(envelope);
- else handleMessage(envelope);
+ handle(envelope, true);
} catch (IOException | InvalidVersionException e) {
Log.w(TAG, e);
}
@@ -64,13 +60,28 @@ public class PushReceiveJob extends ContextJob {
return false;
}
- private void handleMessage(TextSecureEnvelope envelope) {
+ public void handle(TextSecureEnvelope envelope, boolean sendExplicitReceipt) {
+ if (!isActiveNumber(context, envelope.getSource())) {
+ TextSecureDirectory directory = TextSecureDirectory.getInstance(context);
+ ContactTokenDetails contactTokenDetails = new ContactTokenDetails();
+ contactTokenDetails.setNumber(envelope.getSource());
+
+ directory.setNumber(contactTokenDetails, true);
+ }
+
+ if (envelope.isReceipt()) handleReceipt(envelope);
+ else handleMessage(envelope, sendExplicitReceipt);
+ }
+
+ private void handleMessage(TextSecureEnvelope envelope, boolean sendExplicitReceipt) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
long messageId = DatabaseFactory.getPushDatabase(context).insert(envelope);
- jobManager.add(new DeliveryReceiptJob(context, envelope.getSource(),
- envelope.getTimestamp(),
- envelope.getRelay()));
+ if (sendExplicitReceipt) {
+ jobManager.add(new DeliveryReceiptJob(context, envelope.getSource(),
+ envelope.getTimestamp(),
+ envelope.getRelay()));
+ }
jobManager.add(new PushDecryptJob(context, messageId));
}
diff --git a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java
new file mode 100644
index 0000000000..5d866f9cd5
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java
@@ -0,0 +1,180 @@
+package org.thoughtcrime.securesms.service;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+import org.thoughtcrime.securesms.ApplicationContext;
+import org.thoughtcrime.securesms.dependencies.InjectableType;
+import org.thoughtcrime.securesms.jobs.PushReceiveJob;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+import org.whispersystems.jobqueue.requirements.NetworkRequirement;
+import org.whispersystems.jobqueue.requirements.NetworkRequirementProvider;
+import org.whispersystems.jobqueue.requirements.RequirementListener;
+import org.whispersystems.libaxolotl.InvalidVersionException;
+import org.whispersystems.textsecure.api.TextSecureMessagePipe;
+import org.whispersystems.textsecure.api.TextSecureMessageReceiver;
+import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.inject.Inject;
+
+public class MessageRetrievalService extends Service implements Runnable, InjectableType, RequirementListener {
+
+ private static final String TAG = MessageRetrievalService.class.getSimpleName();
+
+ public static final String ACTION_ACTIVITY_STARTED = "ACTIVITY_STARTED";
+ public static final String ACTION_ACTIVITY_FINISHED = "ACTIVITY_FINISHED";
+ public static final String ACTION_PUSH_RECEIVED = "PUSH_RECEIVED";
+ private static final long REQUEST_TIMEOUT_MINUTES = 1;
+
+ private NetworkRequirement networkRequirement;
+ private NetworkRequirementProvider networkRequirementProvider;
+
+ @Inject
+ public TextSecureMessageReceiver receiver;
+
+ private int activeActivities = 0;
+ private boolean pushPending = false;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ ApplicationContext.getInstance(this).injectDependencies(this);
+
+ networkRequirement = new NetworkRequirement(this);
+ networkRequirementProvider = new NetworkRequirementProvider(this);
+
+ networkRequirementProvider.setListener(this);
+ new Thread(this, "MessageRetrievalService").start();
+ }
+
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ if (intent == null) return START_STICKY;
+
+ if (ACTION_ACTIVITY_STARTED.equals(intent.getAction())) incrementActive();
+ else if (ACTION_ACTIVITY_FINISHED.equals(intent.getAction())) decrementActive();
+ else if (ACTION_PUSH_RECEIVED.equals(intent.getAction())) incrementPushReceived();
+
+ return START_STICKY;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ Log.w(TAG, "Waiting for websocket state change....");
+ waitForConnectionNecessary();
+
+ Log.w(TAG, "Making websocket connection....");
+ TextSecureMessagePipe pipe = receiver.createMessagePipe();
+
+ try {
+ while (isConnectionNecessary()) {
+ try {
+ Log.w(TAG, "Reading message...");
+ pipe.read(REQUEST_TIMEOUT_MINUTES, TimeUnit.MINUTES,
+ new TextSecureMessagePipe.MessagePipeCallback() {
+ @Override
+ public void onMessage(TextSecureEnvelope envelope) {
+ Log.w(TAG, "Retrieved envelope! " + envelope.getSource());
+
+ PushReceiveJob receiveJob = new PushReceiveJob(MessageRetrievalService.this);
+ receiveJob.handle(envelope, false);
+
+ decrementPushReceived();
+ }
+ });
+ } catch (TimeoutException | InvalidVersionException e) {
+ Log.w(TAG, e);
+ }
+ }
+ } catch (Throwable e) {
+ Log.w(TAG, e);
+ } finally {
+ Log.w(TAG, "Shutting down pipe...");
+ shutdown(pipe);
+ }
+
+ Log.w(TAG, "Looping...");
+ }
+ }
+
+ @Override
+ public void onRequirementStatusChanged() {
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private synchronized void incrementActive() {
+ activeActivities++;
+ Log.w(TAG, "Active Count: " + activeActivities);
+ notifyAll();
+ }
+
+ private synchronized void decrementActive() {
+ activeActivities--;
+ Log.w(TAG, "Active Count: " + activeActivities);
+ notifyAll();
+ }
+
+ private synchronized void incrementPushReceived() {
+ pushPending = true;
+ notifyAll();
+ }
+
+ private synchronized void decrementPushReceived() {
+ pushPending = false;
+ notifyAll();
+ }
+
+ private synchronized boolean isConnectionNecessary() {
+ Log.w(TAG, "Network requirement: " + networkRequirement.isPresent());
+ return TextSecurePreferences.isWebsocketRegistered(this) &&
+ (activeActivities > 0 || pushPending) &&
+ networkRequirement.isPresent();
+ }
+
+ private synchronized void waitForConnectionNecessary() {
+ try {
+ while (!isConnectionNecessary()) wait();
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ private void shutdown(TextSecureMessagePipe pipe) {
+ try {
+ pipe.shutdown();
+ } catch (Throwable t) {
+ Log.w(TAG, t);
+ }
+ }
+
+ public static void registerActivityStarted(Context activity) {
+ Intent intent = new Intent(activity, MessageRetrievalService.class);
+ intent.setAction(MessageRetrievalService.ACTION_ACTIVITY_STARTED);
+ activity.startService(intent);
+ }
+
+ public static void registerActivityStopped(Context activity) {
+ Intent intent = new Intent(activity, MessageRetrievalService.class);
+ intent.setAction(MessageRetrievalService.ACTION_ACTIVITY_FINISHED);
+ activity.startService(intent);
+ }
+
+ public static void registerPushReceived(Context context) {
+ Intent intent = new Intent(context, MessageRetrievalService.class);
+ intent.setAction(MessageRetrievalService.ACTION_PUSH_RECEIVED);
+ context.startService(intent);
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/service/RegistrationService.java b/src/org/thoughtcrime/securesms/service/RegistrationService.java
index 3f525b768a..b4e53c6ae5 100644
--- a/src/org/thoughtcrime/securesms/service/RegistrationService.java
+++ b/src/org/thoughtcrime/securesms/service/RegistrationService.java
@@ -245,9 +245,11 @@ public class RegistrationService extends Service {
setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number));
String gcmRegistrationId = GoogleCloudMessaging.getInstance(this).register(GcmRefreshJob.REGISTRATION_ID);
- TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId);
accountManager.setGcmId(Optional.of(gcmRegistrationId));
+ TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId);
+ TextSecurePreferences.setWebsocketRegistered(this, true);
+
DatabaseFactory.getIdentityDatabase(this).saveIdentity(masterSecret, self.getRecipientId(), identityKey.getPublicKey());
DirectoryHelper.refreshDirectory(this, accountManager, number);
diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
index dc743e61fa..6082af1d5a 100644
--- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
+++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
@@ -61,10 +61,19 @@ public class TextSecurePreferences {
private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
+ private static final String WEBSOCKET_REGISTERED_PREF = "pref_websocket_registered";
private static final String PUSH_REGISTRATION_REMINDER_PREF = "pref_push_registration_reminder";
public static final String REPEAT_ALERTS_PREF = "pref_repeat_alerts";
+ public static boolean isWebsocketRegistered(Context context) {
+ return getBooleanPreference(context, WEBSOCKET_REGISTERED_PREF, false);
+ }
+
+ public static void setWebsocketRegistered(Context context, boolean registered) {
+ setBooleanPreference(context, WEBSOCKET_REGISTERED_PREF, registered);
+ }
+
public static boolean isWifiSmsEnabled(Context context) {
return getBooleanPreference(context, WIFI_SMS_PREF, false);
}