Java Code Examples for org.whispersystems.libsignal.util.Pair

The following examples show how to use org.whispersystems.libsignal.util.Pair. These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
public static RemoteAttestation getAndVerifyRemoteAttestation(PushServiceSocket socket,
                                                              PushServiceSocket.ClientSet clientSet,
                                                              KeyStore iasKeyStore,
                                                              String enclaveName,
                                                              String mrenclave,
                                                              String authorization)
  throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException
{
  Curve25519                                    curve                   = Curve25519.getInstance(Curve25519.BEST);
  Curve25519KeyPair                             keyPair                 = curve.generateKeyPair();
  RemoteAttestationRequest                      attestationRequest      = new RemoteAttestationRequest(keyPair.getPublicKey());
  Pair<RemoteAttestationResponse, List<String>> attestationResponsePair = getRemoteAttestation(socket, clientSet, authorization, attestationRequest, enclaveName);
  RemoteAttestationResponse                     attestationResponse     = attestationResponsePair.first();
  List<String>                                  attestationCookies      = attestationResponsePair.second();

  RemoteAttestationKeys keys      = new RemoteAttestationKeys(keyPair, attestationResponse.getServerEphemeralPublic(), attestationResponse.getServerStaticPublic());
  Quote                 quote     = new Quote(attestationResponse.getQuote());
  byte[]                requestId = RemoteAttestationCipher.getRequestId(keys, attestationResponse);

  RemoteAttestationCipher.verifyServerQuote(quote, attestationResponse.getServerStaticPublic(), mrenclave);

  RemoteAttestationCipher.verifyIasSignature(iasKeyStore, attestationResponse.getCertificates(), attestationResponse.getSignatureBody(), attestationResponse.getSignature(), quote);

  return new RemoteAttestation(requestId, keys, attestationCookies);
}
 
Example 2
private static Pair<RemoteAttestationResponse, List<String>> getRemoteAttestation(PushServiceSocket socket,
                                                                                  PushServiceSocket.ClientSet clientSet,
                                                                                  String authorization,
                                                                                  RemoteAttestationRequest request,
                                                                                  String enclaveName)
  throws IOException
{
  Response response       = socket.makeRequest(clientSet, authorization, new LinkedList<String>(), "/v1/attestation/" + enclaveName, "PUT", JsonUtil.toJson(request));
  ResponseBody body       = response.body();
  List<String> rawCookies = response.headers("Set-Cookie");
  List<String> cookies    = new LinkedList<>();

  for (String cookie : rawCookies) {
    cookies.add(cookie.split(";")[0]);
  }

  if (body != null) {
    return new Pair<>(JsonUtil.fromJson(body.string(), RemoteAttestationResponse.class), cookies);
  } else {
    throw new NonSuccessfulResponseCodeException("Empty response!");
  }
}
 
Example 3
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
    throws CertificateException
{
  trustManager.checkServerTrusted(chain, authType);

  for (X509Certificate certificate : chain) {
    for (Pair<String, BigInteger> blacklistedSerial : BLACKLIST) {
      if (certificate.getIssuerDN().getName().equals(blacklistedSerial.first()) &&
          certificate.getSerialNumber().equals(blacklistedSerial.second()))
      {
        throw new CertificateException("Blacklisted Serial: " + certificate.getSerialNumber());
      }
    }
  }

}
 
Example 4
Source Project: mollyim-android   Source File: StickerUrl.java    License: GNU General Public License v3.0 6 votes vote down vote up
public static @NonNull Optional<Pair<String, String>> parseShareLink(@Nullable String url) {
  if (url == null) return Optional.absent();

  Matcher matcher = STICKER_URL_PATTERN.matcher(url);

  if (matcher.matches() && matcher.groupCount() == 2) {
    String packId  = matcher.group(1);
    String packKey = matcher.group(2);

    if (isValidHex(packId) && isValidHex(packKey)) {
      return Optional.of(new Pair<>(packId, packKey));
    }
  }

  return Optional.absent();
}
 
Example 5
@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
  setContentView(R.layout.sticker_preview_activity);

  Optional<Pair<String, String>> stickerParams = StickerUrl.parseExternalUri(getIntent().getData());

  if (!stickerParams.isPresent()) {
    Log.w(TAG, "Invalid URI!");
    presentError();
    return;
  }

  String packId  = stickerParams.get().first();
  String packKey = stickerParams.get().second();

  initToolbar();
  initView();
  initViewModel(packId, packKey);
}
 
Example 6
private @NonNull ConversationData getConversationDataInternal(long threadId, int jumpToPosition) {
  Pair<Long, Boolean> lastSeenAndHasSent = DatabaseFactory.getThreadDatabase(context).getLastSeenAndHasSent(threadId);

  long    lastSeen         = lastSeenAndHasSent.first();
  boolean hasSent          = lastSeenAndHasSent.second();
  int     lastSeenPosition = 0;

  boolean isMessageRequestAccepted     = RecipientUtil.isMessageRequestAccepted(context, threadId);
  boolean hasPreMessageRequestMessages = RecipientUtil.isPreMessageRequestThread(context, threadId);

  if (lastSeen > 0) {
    lastSeenPosition = DatabaseFactory.getMmsSmsDatabase(context).getMessagePositionForLastSeen(threadId, lastSeen);
  }

  if (lastSeenPosition <= 0) {
    lastSeen = 0;
  }

  return new ConversationData(threadId, lastSeen, lastSeenPosition, hasSent, isMessageRequestAccepted, hasPreMessageRequestMessages, jumpToPosition);
}
 
Example 7
@Override
public void onRecorderCanceled() {
  updateToggleButtonState();
  Vibrator vibrator = ServiceUtil.getVibrator(this);
  vibrator.vibrate(50);

  getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

  ListenableFuture<Pair<Uri, Long>> future = audioRecorder.stopRecording();
  future.addListener(new ListenableFuture.Listener<Pair<Uri, Long>>() {
    @Override
    public void onSuccess(final Pair<Uri, Long> result) {
      new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
          BlobProvider.getInstance().delete(ConversationActivity.this, result.first());
          return null;
        }
      }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    @Override
    public void onFailure(ExecutionException e) {}
  });
}
 
Example 8
public static @NonNull PhoneNumberFormatter get(Context context) {
  String localNumber = TextSecurePreferences.getLocalNumber(context);

  if (!TextUtils.isEmpty(localNumber)) {
    Pair<String, PhoneNumberFormatter> cached = cachedFormatter.get();

    if (cached != null && cached.first().equals(localNumber)) return cached.second();

    PhoneNumberFormatter formatter = new PhoneNumberFormatter(localNumber);
    cachedFormatter.set(new Pair<>(localNumber, formatter));

    return formatter;
  } else {
    return new PhoneNumberFormatter(Util.getSimCountryIso(context).or("US"), true);
  }
}
 
Example 9
public void setUnidentified(Collection<Pair<RecipientId, Boolean>> results, long mmsId) {
  SQLiteDatabase db  = databaseHelper.getWritableDatabase();

  db.beginTransaction();
  try {
    String query = MMS_ID + " = ? AND " + RECIPIENT_ID + " = ?";

    for (Pair<RecipientId, Boolean> result : results) {
      ContentValues values = new ContentValues(1);
      values.put(UNIDENTIFIED, result.second() ? 1 : 0);

      db.update(TABLE_NAME, values, query, new String[]{ String.valueOf(mmsId), result.first().serialize()});
    }

    db.setTransactionSuccessful();
  } finally {
    db.endTransaction();
  }
}
 
Example 10
/**
 * @return The user that added you to the group, otherwise null.
 */
public @Nullable RecipientId getGroupAddedBy(long threadId) {
  long lastQuitChecked = System.currentTimeMillis();
  Pair<RecipientId, Long> pair;

  do {
    pair = getGroupAddedBy(threadId, lastQuitChecked);
    if (pair.first() != null) {
      return pair.first();
    } else {
      lastQuitChecked = pair.second();
    }

  } while (pair.second() != -1);

  return null;
}
 
Example 11
@Override
public @NonNull CharSequence getContent(@NonNull Context context) {
  StringBuilder               out    = new StringBuilder();
  List<Pair<String, Boolean>> status = new ArrayList<>();

  try {
    PackageInfo info = context.getPackageManager().getPackageInfo("org.thoughtcrime.securesms", PackageManager.GET_PERMISSIONS);

    for (int i = 0; i < info.requestedPermissions.length; i++) {
      status.add(new Pair<>(info.requestedPermissions[i],
                            (info.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0));
    }
  } catch (PackageManager.NameNotFoundException e) {
    return "Unable to retrieve.";
  }

  Collections.sort(status, (o1, o2) -> o1.first().compareTo(o2.first()));

  for (Pair<String, Boolean> pair : status) {
    out.append(pair.first()).append(": ");
    out.append(pair.second() ? "YES" : "NO");
    out.append("\n");
  }

  return out;
}
 
Example 12
@Override
protected void onPostExecute(final Pair<Integer, String> result) {
  super.onPostExecute(result);
  final Context context = contextReference.get();
  if (context == null) return;

  switch (result.first()) {
    case FAILURE:
      Toast.makeText(context,
                     context.getResources().getQuantityText(R.plurals.ConversationFragment_error_while_saving_attachments_to_sd_card,
                                                            attachmentCount),
                     Toast.LENGTH_LONG).show();
      break;
    case SUCCESS:
      String message = !TextUtils.isEmpty(result.second())  ? context.getResources().getString(R.string.SaveAttachmentTask_saved_to, result.second())
                                                            : context.getResources().getString(R.string.SaveAttachmentTask_saved);
      Toast.makeText(context, message, Toast.LENGTH_LONG).show();
      break;
    case WRITE_ACCESS_FAILURE:
      Toast.makeText(context, R.string.ConversationFragment_unable_to_write_to_sd_card_exclamation,
          Toast.LENGTH_LONG).show();
      break;
  }
}
 
Example 13
Source Project: mollyim-android   Source File: SearchUtil.java    License: GNU General Public License v3.0 6 votes vote down vote up
public static Spannable getHighlightedSpan(@NonNull Locale locale,
                                           @NonNull StyleFactory styleFactory,
                                           @Nullable Spannable text,
                                           @Nullable String highlight)
{
  if (TextUtils.isEmpty(text)) {
    return new SpannableString("");
  }


  if (TextUtils.isEmpty(highlight)) {
    return text;
  }

  List<Pair<Integer, Integer>> ranges  = getHighlightRanges(locale, text.toString(), highlight);
  SpannableString              spanned = new SpannableString(text);

  for (Pair<Integer, Integer> range : ranges) {
    spanned.setSpan(styleFactory.create(), range.first(), range.second(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
  }

  return spanned;
}
 
Example 14
Source Project: mollyim-android   Source File: EmojiUtil.java    License: GNU General Public License v3.0 6 votes vote down vote up
/**
 * This will return all ways we know of expressing a singular emoji. This is to aid in search,
 * where some platforms may send an emoji we've locally marked as 'obsolete'.
 */
public static @NonNull Set<String> getAllRepresentations(@NonNull String emoji) {
  Set<String> out = new HashSet<>();

  out.add(emoji);

  for (Pair<String, String> pair : EmojiPages.OBSOLETE) {
    if (pair.first().equals(emoji)) {
      out.add(pair.second());
    } else if (pair.second().equals(emoji)) {
      out.add(pair.first());
    }
  }

  return out;
}
 
Example 15
private EmojiProvider(Context context) {
  this.decodeScale = Math.min(1f, context.getResources().getDimension(R.dimen.emoji_drawer_size) / EMOJI_RAW_HEIGHT);
  this.verticalPad = EMOJI_VERT_PAD * this.decodeScale;

  for (EmojiPageModel page : EmojiPages.DATA_PAGES) {
    if (page.hasSpriteMap()) {
      EmojiPageBitmap pageBitmap = new EmojiPageBitmap(context, page, decodeScale);

      List<String> emojis = page.getEmoji();
      for (int i = 0; i < emojis.size(); i++) {
        emojiTree.add(emojis.get(i), new EmojiDrawInfo(pageBitmap, i));
      }
    }
  }

  for (Pair<String,String> obsolete : EmojiPages.OBSOLETE) {
    emojiTree.add(obsolete.first(), emojiTree.getEmoji(obsolete.second(), 0, obsolete.second().length()));
  }
}
 
Example 16
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
    throws CertificateException
{
  trustManager.checkServerTrusted(chain, authType);

  for (X509Certificate certificate : chain) {
    for (Pair<String, BigInteger> blacklistedSerial : BLACKLIST) {
      if (certificate.getIssuerDN().getName().equals(blacklistedSerial.first()) &&
          certificate.getSerialNumber().equals(blacklistedSerial.second()))
      {
        throw new CertificateException("Blacklisted Serial: " + certificate.getSerialNumber());
      }
    }
  }

}
 
Example 17
Source Project: bcm-android   Source File: ThreadDatabase.java    License: GNU General Public License v3.0 6 votes vote down vote up
public Pair<Long, Boolean> getLastSeenAndHasSent(long threadId) {
    SQLiteDatabase db = databaseHelper.getReadableDatabase();
    Cursor cursor = db.query(TABLE_NAME, new String[]{LAST_SEEN, HAS_SENT}, ID_WHERE, new String[]{String.valueOf(threadId)}, null, null, null);

    try {
        if (cursor != null && cursor.moveToFirst()) {
            return new Pair<>(cursor.getLong(0), cursor.getLong(1) == 1);
        }

        return new Pair<>(-1L, false);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}
 
Example 18
Source Project: bcm-android   Source File: EmojiProvider.java    License: GNU General Public License v3.0 6 votes vote down vote up
private EmojiProvider(Context context) {
    this.decodeScale = Math.min(1f, context.getResources().getDimension(R.dimen.emoji_drawer_size) / EMOJI_RAW_HEIGHT);
    this.verticalPad = EMOJI_VERT_PAD * this.decodeScale;

    for (EmojiPageModel page : EmojiPages.PAGES) {
        if (page.hasSpriteMap()) {
            EmojiPageBitmap pageBitmap = new EmojiPageBitmap(context, page, decodeScale);

            for (int i = 0; i < page.getEmoji().length; i++) {
                emojiTree.add(page.getEmoji()[i], new EmojiDrawInfo(pageBitmap, i));
            }
        }
    }

    for (Pair<String,String> obsolete : EmojiPages.OBSOLETE) {
        emojiTree.add(obsolete.first(), emojiTree.getEmoji(obsolete.second(), 0, obsolete.second().length()));
    }
}
 
Example 19
public AttachmentUploadAttributes getAttachmentUploadAttributes() throws IOException {
  try {
    WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder()
                                                                    .setId(new SecureRandom().nextLong())
                                                                    .setVerb("GET")
                                                                    .setPath("/v2/attachments/form/upload")
                                                                    .build();

    Pair<Integer, String> response = websocket.sendRequest(requestMessage).get(10, TimeUnit.SECONDS);

    if (response.first() < 200 || response.first() >= 300) {
      throw new IOException("Non-successful response: " + response.first());
    }

    return JsonUtil.fromJson(response.second(), AttachmentUploadAttributes.class);
  } catch (InterruptedException | ExecutionException | TimeoutException e) {
    throw new IOException(e);
  }
}
 
Example 20
public Pair<RemoteAttestationResponse, List<String>> getContactDiscoveryRemoteAttestation(String authorization, RemoteAttestationRequest request, String mrenclave)
    throws IOException
{
  Response     response   = makeContactDiscoveryRequest(authorization, new LinkedList<String>(), "/v1/attestation/" + mrenclave, "PUT", JsonUtil.toJson(request));
  ResponseBody body       = response.body();
  List<String> rawCookies = response.headers("Set-Cookie");
  List<String> cookies    = new LinkedList<>();

  for (String cookie : rawCookies) {
    cookies.add(cookie.split(";")[0]);
  }

  if (body != null) {
    return new Pair<>(JsonUtil.fromJson(body.string(), RemoteAttestationResponse.class), cookies);
  } else {
    throw new NonSuccessfulResponseCodeException("Empty response!");
  }
}
 
Example 21
public synchronized Future<Pair<Integer, String>> sendRequest(WebSocketRequestMessage request) throws IOException {
  if (client == null || !connected) throw new IOException("No connection!");

  WebSocketMessage message = WebSocketMessage.newBuilder()
                                             .setType(WebSocketMessage.Type.REQUEST)
                                             .setRequest(request)
                                             .build();

  SettableFuture<Pair<Integer, String>> future = new SettableFuture<>();
  outgoingRequests.put(request.getId(), future);

  if (!client.send(ByteString.of(message.toByteArray()))) {
    throw new IOException("Write failed!");
  }

  return future;
}
 
Example 22
@Override
public synchronized void onMessage(WebSocket webSocket, ByteString payload) {
  Log.w(TAG, "WSC onMessage()");
  try {
    WebSocketMessage message = WebSocketMessage.parseFrom(payload.toByteArray());

    Log.w(TAG, "Message Type: " + message.getType().getNumber());

    if (message.getType().getNumber() == WebSocketMessage.Type.REQUEST_VALUE)  {
      incomingRequests.add(message.getRequest());
    } else if (message.getType().getNumber() == WebSocketMessage.Type.RESPONSE_VALUE) {
      SettableFuture<Pair<Integer, String>> listener = outgoingRequests.get(message.getResponse().getId());
      if (listener != null) listener.set(new Pair<>(message.getResponse().getStatus(),
                                                    new String(message.getResponse().getBody().toByteArray())));
    }

    notifyAll();
  } catch (InvalidProtocolBufferException e) {
    Log.w(TAG, e);
  }
}
 
Example 23
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
    throws CertificateException
{
  trustManager.checkServerTrusted(chain, authType);

  for (X509Certificate certificate : chain) {
    for (Pair<String, BigInteger> blacklistedSerial : BLACKLIST) {
      if (certificate.getIssuerDN().getName().equals(blacklistedSerial.first()) &&
          certificate.getSerialNumber().equals(blacklistedSerial.second()))
      {
        throw new CertificateException("Blacklisted Serial: " + certificate.getSerialNumber());
      }
    }
  }

}
 
Example 24
Source Project: signal-cli   Source File: SignalAccount.java    License: GNU General Public License v3.0 6 votes vote down vote up
public static SignalAccount create(String dataPath, String username, IdentityKeyPair identityKey, int registrationId, ProfileKey profileKey) throws IOException {
    IOUtils.createPrivateDirectories(dataPath);
    String fileName = getFileName(dataPath, username);
    if (!new File(fileName).exists()) {
        IOUtils.createPrivateFile(fileName);
    }

    final Pair<FileChannel, FileLock> pair = openFileChannel(fileName);
    SignalAccount account = new SignalAccount(pair.first(), pair.second());

    account.username = username;
    account.profileKey = profileKey;
    account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
    account.groupStore = new JsonGroupStore();
    account.contactStore = new JsonContactsStore();
    account.recipientStore = new RecipientStore();
    account.registered = false;

    return account;
}
 
Example 25
Source Project: signal-cli   Source File: SignalAccount.java    License: GNU General Public License v3.0 6 votes vote down vote up
public static SignalAccount createLinkedAccount(String dataPath, String username, UUID uuid, String password, int deviceId, IdentityKeyPair identityKey, int registrationId, String signalingKey, ProfileKey profileKey) throws IOException {
    IOUtils.createPrivateDirectories(dataPath);
    String fileName = getFileName(dataPath, username);
    if (!new File(fileName).exists()) {
        IOUtils.createPrivateFile(fileName);
    }

    final Pair<FileChannel, FileLock> pair = openFileChannel(fileName);
    SignalAccount account = new SignalAccount(pair.first(), pair.second());

    account.username = username;
    account.uuid = uuid;
    account.password = password;
    account.profileKey = profileKey;
    account.deviceId = deviceId;
    account.signalingKey = signalingKey;
    account.signalProtocolStore = new JsonSignalProtocolStore(identityKey, registrationId);
    account.groupStore = new JsonGroupStore();
    account.contactStore = new JsonContactsStore();
    account.recipientStore = new RecipientStore();
    account.registered = true;
    account.isMultiDevice = true;

    return account;
}
 
Example 26
private Pair<Chain,Integer> getReceiverChain(ECPublicKey senderEphemeral) {
  List<Chain> receiverChains = sessionStructure.getReceiverChainsList();
  int         index          = 0;

  for (Chain receiverChain : receiverChains) {
    try {
      ECPublicKey chainSenderRatchetKey = Curve.decodePoint(receiverChain.getSenderRatchetKey().toByteArray(), 0);

      if (chainSenderRatchetKey.equals(senderEphemeral)) {
        return new Pair<>(receiverChain,index);
      }
    } catch (InvalidKeyException e) {
      Log.w("SessionRecordV2", e);
    }

    index++;
  }

  return null;
}
 
Example 27
public boolean hasMessageKeys(ECPublicKey senderEphemeral, int counter) {
  Pair<Chain,Integer> chainAndIndex = getReceiverChain(senderEphemeral);
  Chain               chain         = chainAndIndex.first();

  if (chain == null) {
    return false;
  }

  List<Chain.MessageKey> messageKeyList = chain.getMessageKeysList();

  for (Chain.MessageKey messageKey : messageKeyList) {
    if (messageKey.getIndex() == counter) {
      return true;
    }
  }

  return false;
}
 
Example 28
public void setMessageKeys(ECPublicKey senderEphemeral, MessageKeys messageKeys) {
  Pair<Chain,Integer> chainAndIndex       = getReceiverChain(senderEphemeral);
  Chain               chain               = chainAndIndex.first();
  Chain.MessageKey    messageKeyStructure = Chain.MessageKey.newBuilder()
                                                            .setCipherKey(ByteString.copyFrom(messageKeys.getCipherKey().getEncoded()))
                                                            .setMacKey(ByteString.copyFrom(messageKeys.getMacKey().getEncoded()))
                                                            .setIndex(messageKeys.getCounter())
                                                            .setIv(ByteString.copyFrom(messageKeys.getIv().getIV()))
                                                            .build();

  Chain.Builder updatedChain = chain.toBuilder().addMessageKeys(messageKeyStructure);

  if (updatedChain.getMessageKeysCount() > MAX_MESSAGE_KEYS) {
    updatedChain.removeMessageKeys(0);
  }

  this.sessionStructure = this.sessionStructure.toBuilder()
                                               .setReceiverChains(chainAndIndex.second(),
                                                                  updatedChain.build())
                                               .build();
}
 
Example 29
private ChainKey getOrCreateChainKey(SessionState sessionState, ECPublicKey theirEphemeral)
    throws InvalidMessageException
{
  try {
    if (sessionState.hasReceiverChain(theirEphemeral)) {
      return sessionState.getReceiverChainKey(theirEphemeral);
    } else {
      RootKey                 rootKey         = sessionState.getRootKey();
      ECKeyPair               ourEphemeral    = sessionState.getSenderRatchetKeyPair();
      Pair<RootKey, ChainKey> receiverChain   = rootKey.createChain(theirEphemeral, ourEphemeral);
      ECKeyPair               ourNewEphemeral = Curve.generateKeyPair();
      Pair<RootKey, ChainKey> senderChain     = receiverChain.first().createChain(theirEphemeral, ourNewEphemeral);

      sessionState.setRootKey(senderChain.first());
      sessionState.addReceiverChain(theirEphemeral, receiverChain.second());
      sessionState.setPreviousCounter(Math.max(sessionState.getSenderChainKey().getIndex()-1, 0));
      sessionState.setSenderChain(ourNewEphemeral, senderChain.second());

      return receiverChain.second();
    }
  } catch (InvalidKeyException e) {
    throw new InvalidMessageException(e);
  }
}
 
Example 30
private SignalServiceAttachmentPointer uploadAttachmentV2(SignalServiceAttachmentStream attachment, byte[] attachmentKey, PushAttachmentData attachmentData) throws NonSuccessfulResponseCodeException, PushNetworkException {
  AttachmentV2UploadAttributes       v2UploadAttributes = null;
  Optional<SignalServiceMessagePipe> localPipe          = pipe.get();

  if (localPipe.isPresent()) {
    Log.d(TAG, "Using pipe to retrieve attachment upload attributes...");
    try {
      v2UploadAttributes = localPipe.get().getAttachmentV2UploadAttributes();
    } catch (IOException e) {
      Log.w(TAG, "Failed to retrieve attachment upload attributes using pipe. Falling back...");
    }
  }

  if (v2UploadAttributes == null) {
    Log.d(TAG, "Not using pipe to retrieve attachment upload attributes...");
    v2UploadAttributes = socket.getAttachmentV2UploadAttributes();
  }

  Pair<Long, byte[]> attachmentIdAndDigest = socket.uploadAttachment(attachmentData, v2UploadAttributes);

  return new SignalServiceAttachmentPointer(0,
                                            new SignalServiceAttachmentRemoteId(attachmentIdAndDigest.first()),
                                            attachment.getContentType(),
                                            attachmentKey,
                                            Optional.of(Util.toIntExact(attachment.getLength())),
                                            attachment.getPreview(),
                                            attachment.getWidth(), attachment.getHeight(),
                                            Optional.of(attachmentIdAndDigest.second()),
                                            attachment.getFileName(),
                                            attachment.getVoiceNote(),
                                            attachment.getCaption(),
                                            attachment.getBlurHash(),
                                            attachment.getUploadTimestamp());
}