org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage Java Examples

The following examples show how to use org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage. 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
Source File: JsonCallMessage.java    From signal-cli with GNU General Public License v3.0 6 votes vote down vote up
JsonCallMessage(SignalServiceCallMessage callMessage) {
    if (callMessage.getOfferMessage().isPresent()) {
        this.offerMessage = callMessage.getOfferMessage().get();
    }
    if (callMessage.getAnswerMessage().isPresent()) {
        this.answerMessage = callMessage.getAnswerMessage().get();
    }
    if (callMessage.getBusyMessage().isPresent()) {
        this.busyMessage = callMessage.getBusyMessage().get();
    }
    if (callMessage.getHangupMessage().isPresent()) {
        this.hangupMessage = callMessage.getHangupMessage().get();
    }
    if (callMessage.getIceUpdateMessages().isPresent()) {
        this.iceUpdateMessages = callMessage.getIceUpdateMessages().get();
    }
}
 
Example #2
Source File: SignalServiceCipher.java    From libsignal-service-java with GNU General Public License v3.0 6 votes vote down vote up
private SignalServiceCallMessage createCallMessage(CallMessage content) {
  if (content.hasOffer()) {
    CallMessage.Offer offerContent = content.getOffer();
    return SignalServiceCallMessage.forOffer(new OfferMessage(offerContent.getId(), offerContent.getDescription()));
  } else if (content.hasAnswer()) {
    CallMessage.Answer answerContent = content.getAnswer();
    return SignalServiceCallMessage.forAnswer(new AnswerMessage(answerContent.getId(), answerContent.getDescription()));
  } else if (content.getIceUpdateCount() > 0) {
    List<IceUpdateMessage> iceUpdates = new LinkedList<>();

    for (CallMessage.IceUpdate iceUpdate : content.getIceUpdateList()) {
      iceUpdates.add(new IceUpdateMessage(iceUpdate.getId(), iceUpdate.getSdpMid(), iceUpdate.getSdpMLineIndex(), iceUpdate.getSdp()));
    }

    return SignalServiceCallMessage.forIceUpdates(iceUpdates);
  } else if (content.hasHangup()) {
    CallMessage.Hangup hangup = content.getHangup();
    return SignalServiceCallMessage.forHangup(new HangupMessage(hangup.getId()));
  } else if (content.hasBusy()) {
    CallMessage.Busy busy = content.getBusy();
    return SignalServiceCallMessage.forBusy(new BusyMessage(busy.getId()));
  }

  return SignalServiceCallMessage.empty();
}
 
Example #3
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
private void handleSendOffer(Intent intent) {
  RemotePeer        remotePeer   = getRemotePeer(intent);
  CallId            callId       = getCallId(intent);
  Integer           remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
  boolean           broadcast    = intent.getBooleanExtra(EXTRA_BROADCAST, false);
  String            offer        = intent.getStringExtra(EXTRA_OFFER_DESCRIPTION);
  OfferMessage.Type offerType    = OfferMessage.Type.fromCode(intent.getStringExtra(EXTRA_OFFER_TYPE));

  Log.i(TAG, "handleSendOffer: id: " + callId.format(remoteDevice));

  if (FeatureFlags.profileForCalling() && remotePeer.getRecipient().resolve().getProfileKey() == null) {
    offer     = "";
    offerType = OfferMessage.Type.NEED_PERMISSION;
  }

  OfferMessage             offerMessage        = new OfferMessage(callId.longValue(), offer, offerType);
  Integer                  destinationDeviceId = broadcast ? null : remoteDevice;
  SignalServiceCallMessage callMessage         = SignalServiceCallMessage.forOffer(offerMessage, true, destinationDeviceId);

  sendCallMessage(remotePeer, callMessage);
}
 
Example #4
Source File: WebRtcCallService.java    From bcm-android with GNU General Public License v3.0 6 votes vote down vote up
private void handleLocalHangup(Intent intent) {

        CallState currentState = this.callState.get();
        ALog.i(TAG, "handleLocalHangup: " + currentState);

        if (WebRtcCallService.accountContext == null || !WebRtcCallService.accountContext.equals(getAccountContextFromIntent(intent))) {
            ALog.w(TAG, "Account context is null or not equals to the intent's one");
            return;
        }

        if (this.dataChannel != null && this.recipient != null && this.callId != -1L) {

            this.dataChannel.send(new DataChannel.Buffer(ByteBuffer.wrap(Data.newBuilder().setHangup(Hangup.newBuilder().setId(this.callId)).build().toByteArray()), false));
            sendMessage(WebRtcCallService.accountContext, this.recipient, SignalServiceCallMessage.forHangup(new HangupMessage(this.callId)));

        }
        if (recipient != null) {
            sendMessage(WebRtcViewModel.State.CALL_DISCONNECTED, this.recipient, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled);

            if (currentState != CallState.STATE_IDLE && currentState != CallState.STATE_CONNECTED) {
                insertMissedCallFromHangup(WebRtcCallService.accountContext, this.recipient, false);
            }
        }
        terminate();
    }
 
Example #5
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
private void handleSendIceCandidates(Intent intent) {
  RemotePeer remotePeer   = getRemotePeer(intent);
  CallId     callId       = getCallId(intent);
  Integer    remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
  boolean    broadcast    = intent.getBooleanExtra(EXTRA_BROADCAST, false);
  ArrayList<IceCandidateParcel> iceCandidates = intent.getParcelableArrayListExtra(EXTRA_ICE_CANDIDATES);

  Log.i(TAG, "handleSendIceCandidates: id: " + callId.format(remoteDevice));

  LinkedList<IceUpdateMessage> iceUpdateMessages = new LinkedList();
  for (IceCandidateParcel parcel : iceCandidates) {
    iceUpdateMessages.add(parcel.getIceUpdateMessage(callId));
  }

  Integer                  destinationDeviceId = broadcast ? null : remoteDevice;
  SignalServiceCallMessage callMessage         = SignalServiceCallMessage.forIceUpdates(iceUpdateMessages, true, destinationDeviceId);

  sendCallMessage(remotePeer, callMessage);
}
 
Example #6
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
private void handleSendHangup(Intent intent) {
  RemotePeer         remotePeer   = getRemotePeer(intent);
  CallId             callId       = getCallId(intent);
  Integer            remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
  boolean            broadcast    = intent.getBooleanExtra(EXTRA_BROADCAST, false);
  HangupMessage.Type type         = HangupMessage.Type.fromCode(intent.getStringExtra(EXTRA_HANGUP_TYPE));
  boolean            isLegacy     = intent.getBooleanExtra(EXTRA_HANGUP_IS_LEGACY, true);
  int                deviceId     = intent.getIntExtra(EXTRA_HANGUP_DEVICE_ID, 0);

  Log.i(TAG, "handleSendHangup: id: " + callId.format(remoteDevice));

  HangupMessage            hangupMessage       = new HangupMessage(callId.longValue(), type, deviceId, isLegacy);
  Integer                  destinationDeviceId = broadcast ? null : remoteDevice;
  SignalServiceCallMessage callMessage         = SignalServiceCallMessage.forHangup(hangupMessage, true, destinationDeviceId);

  sendCallMessage(remotePeer, callMessage);
}
 
Example #7
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 6 votes vote down vote up
private ListenableFutureTask<Boolean> sendMessage(@NonNull final RemotePeer remotePeer,
                                                  @NonNull final SignalServiceCallMessage callMessage)
{
  Callable<Boolean> callable = new Callable<Boolean>() {
    @Override
    public Boolean call() throws Exception {
      Recipient recipient = remotePeer.getRecipient();
      messageSender.sendCallMessage(RecipientUtil.toSignalServiceAddress(WebRtcCallService.this, recipient),
                                    UnidentifiedAccessUtil.getAccessFor(WebRtcCallService.this, recipient),
                                    callMessage);
      return true;
    }
  };

  ListenableFutureTask<Boolean> listenableFutureTask = new ListenableFutureTask<>(callable, null, serviceExecutor);
  networkExecutor.execute(listenableFutureTask);

  return listenableFutureTask;
}
 
Example #8
Source File: SignalServiceMessageSender.java    From libsignal-service-java with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Send a call setup message to a single recipient.
 *
 * @param recipient The message's destination.
 * @param message The call message.
 * @throws IOException
 */
public void sendCallMessage(SignalServiceAddress recipient,
                            Optional<UnidentifiedAccessPair> unidentifiedAccess,
                            SignalServiceCallMessage message)
    throws IOException, UntrustedIdentityException
{
  byte[] content = createCallContent(message);
  sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), content, false);
}
 
Example #9
Source File: WebRtcCallService.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
private ListenableFutureTask<Boolean> sendMessage(@NonNull AccountContext accountContext,
                                                  @NonNull final Recipient recipient,
                                                  @NonNull final SignalServiceCallMessage callMessage) {

    ALog.i(TAG, "Send message");
    if (recipient.getAddress().toString().equals(accountContext.getUid())) {
        // Don't send call message to major
        ALog.w(TAG, "Recipient is not the same");
        return null;
    }

    ListenableFutureTask<Boolean> listenableFutureTask = new ListenableFutureTask<>(() -> {
        ThreadRepo threadRepo = Repository.getInstance(accountContext).getThreadRepo();
        long threadId = threadRepo.getThreadIdIfExist(recipient);
        BcmChatCore.INSTANCE.sendCallMessage(accountContext, threadId, new SignalServiceAddress(recipient.getAddress().serialize()), callMessage);
        return true;
    }, null, serviceExecutor);

    Optional<BusyMessage> busyMessageOptional = callMessage.getBusyMessage();
    if (busyMessageOptional.isPresent()) {
        insertMissedCall(accountContext, recipient, NOTIFICATION_SIMPLY);
    }

    Optional<HangupMessage> hangupMessageOptional = callMessage.getHangupMessage();
    if (hangupMessageOptional.isPresent()) {
        EventBus.getDefault().postSticky(new WebRtcViewModel(WebRtcViewModel.State.CALL_DISCONNECTED, videoCall, recipient, localCameraState, localRenderer, remoteRenderer, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled));
    }

    networkExecutor.execute(listenableFutureTask);

    return listenableFutureTask;
}
 
Example #10
Source File: WebRtcCallService.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
private void handleDenyCall(Intent intent) {
    try {
        CallState currentState = this.callState.get();
        if (currentState != CallState.STATE_LOCAL_RINGING) {
            ALog.w(TAG, "handleDenyCall fail, current state is not local ringing");
            return;
        }

        if (recipient == null || callId == -1L || dataChannel == null || WebRtcCallService.accountContext == null) {
            ALog.i(TAG, "handleDenyCall fail, recipient or callId or dataChannel is null");
            return;
        }

        if (!WebRtcCallService.accountContext.equals(getAccountContextFromIntent(intent))) {
            ALog.w(TAG, "Not current major user.");
            return;
        }

        this.dataChannel.send(new DataChannel.Buffer(ByteBuffer.wrap(Data.newBuilder().setHangup(Hangup.newBuilder().setId(this.callId)).build().toByteArray()), false));
        sendMessage(WebRtcCallService.accountContext, recipient, SignalServiceCallMessage.forHangup(new HangupMessage(this.callId)));

        if (currentState != CallState.STATE_IDLE && currentState != CallState.STATE_CONNECTED) {
            insertMissedCallFromHangup(WebRtcCallService.accountContext, this.recipient, true);
        }
    } finally {
        this.terminate();
    }
}
 
Example #11
Source File: WebRtcCallService.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * @param intent
 */
private void handleBusyCall(Intent intent) throws Exception {
    ALog.w(TAG, "handleBusyCall");
    this.mIncoming.set(true);
    Recipient recipient = getRemoteRecipient(intent);
    long callId = getCallId(intent);
    AccountContext accountContext = getAccountContextFromIntent(intent);
    sendMessage(accountContext, recipient, SignalServiceCallMessage.forBusy(new BusyMessage(callId)));
}
 
Example #12
Source File: SignalServiceMessageSender.java    From libsignal-service-java with GNU General Public License v3.0 5 votes vote down vote up
private byte[] createCallContent(SignalServiceCallMessage callMessage) {
  Content.Builder     container = Content.newBuilder();
  CallMessage.Builder builder   = CallMessage.newBuilder();

  if (callMessage.getOfferMessage().isPresent()) {
    OfferMessage offer = callMessage.getOfferMessage().get();
    builder.setOffer(CallMessage.Offer.newBuilder()
                                      .setId(offer.getId())
                                      .setDescription(offer.getDescription()));
  } else if (callMessage.getAnswerMessage().isPresent()) {
    AnswerMessage answer = callMessage.getAnswerMessage().get();
    builder.setAnswer(CallMessage.Answer.newBuilder()
                                        .setId(answer.getId())
                                        .setDescription(answer.getDescription()));
  } else if (callMessage.getIceUpdateMessages().isPresent()) {
    List<IceUpdateMessage> updates = callMessage.getIceUpdateMessages().get();

    for (IceUpdateMessage update : updates) {
      builder.addIceUpdate(CallMessage.IceUpdate.newBuilder()
                                                .setId(update.getId())
                                                .setSdp(update.getSdp())
                                                .setSdpMid(update.getSdpMid())
                                                .setSdpMLineIndex(update.getSdpMLineIndex()));
    }
  } else if (callMessage.getHangupMessage().isPresent()) {
    builder.setHangup(CallMessage.Hangup.newBuilder().setId(callMessage.getHangupMessage().get().getId()));
  } else if (callMessage.getBusyMessage().isPresent()) {
    builder.setBusy(CallMessage.Busy.newBuilder().setId(callMessage.getBusyMessage().get().getId()));
  }

  container.setCallMessage(builder);
  return container.build().toByteArray();
}
 
Example #13
Source File: SignalServiceCipher.java    From bcm-android with GNU General Public License v3.0 5 votes vote down vote up
private SignalServiceCallMessage createCallMessage(CallMessage content) {
  if (content.hasOffer()) {
    CallMessage.Offer offerContent = content.getOffer();
    CallMessage.Offer.CallType callType = CallMessage.Offer.CallType.AUDIO;
    if (offerContent.hasType()) {
      callType = offerContent.getType();
    }
    return SignalServiceCallMessage.forOffer(new OfferMessage(offerContent.getId(), offerContent.getDescription(), callType));
  } else if (content.hasAnswer()) {
    CallMessage.Answer answerContent = content.getAnswer();
    return SignalServiceCallMessage.forAnswer(new AnswerMessage(answerContent.getId(), answerContent.getDescription()));
  } else if (content.getIceUpdateCount() > 0) {
    List<IceUpdateMessage> iceUpdates = new LinkedList<>();

    for (CallMessage.IceUpdate iceUpdate : content.getIceUpdateList()) {
      iceUpdates.add(new IceUpdateMessage(iceUpdate.getId(), iceUpdate.getSdpMid(), iceUpdate.getSdpMLineIndex(), iceUpdate.getSdp()));
    }

    return SignalServiceCallMessage.forIceUpdates(iceUpdates);
  } else if (content.hasHangup()) {
    CallMessage.Hangup hangup = content.getHangup();
    return SignalServiceCallMessage.forHangup(new HangupMessage(hangup.getId()));
  } else if (content.hasBusy()) {
    CallMessage.Busy busy = content.getBusy();
    return SignalServiceCallMessage.forBusy(new BusyMessage(busy.getId()));
  }

  return SignalServiceCallMessage.empty();
}
 
Example #14
Source File: SignalServiceMessageSender.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Send a call setup message to a single recipient.
 *
 * @param recipient The message's destination.
 * @param message The call message.
 * @throws IOException
 */
public void sendCallMessage(SignalServiceAddress recipient,
                            Optional<UnidentifiedAccessPair> unidentifiedAccess,
                            SignalServiceCallMessage message)
    throws IOException, UntrustedIdentityException
{
  byte[] content = createCallContent(message);
  sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), content, false);
}
 
Example #15
Source File: SignalServiceContent.java    From libsignal-service-java with GNU General Public License v3.0 5 votes vote down vote up
public SignalServiceContent(SignalServiceCallMessage callMessage, SignalServiceAddress sender, int senderDevice, long timestamp, boolean needsReceipt) {
  this.sender       = sender;
  this.senderDevice = senderDevice;
  this.timestamp    = timestamp;
  this.needsReceipt = needsReceipt;

  this.message            = Optional.absent();
  this.synchronizeMessage = Optional.absent();
  this.callMessage        = Optional.of(callMessage);
  this.readMessage        = Optional.absent();
  this.typingMessage      = Optional.absent();
}
 
Example #16
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
private void handleSendBusy(Intent intent) {
  RemotePeer remotePeer   = getRemotePeer(intent);
  CallId     callId       = getCallId(intent);
  Integer    remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
  boolean    broadcast    = intent.getBooleanExtra(EXTRA_BROADCAST, false);

  Log.i(TAG, "handleSendBusy: id: " + callId.format(remoteDevice));

  BusyMessage              busyMessage         = new BusyMessage(callId.longValue());
  Integer                  destinationDeviceId = broadcast ? null : remoteDevice;
  SignalServiceCallMessage callMessage         = SignalServiceCallMessage.forBusy(busyMessage, true, destinationDeviceId);

  sendCallMessage(remotePeer, callMessage);
}
 
Example #17
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
private void handleSendAnswer(Intent intent) {
  RemotePeer remotePeer   = getRemotePeer(intent);
  CallId     callId       = getCallId(intent);
  Integer    remoteDevice = intent.getIntExtra(EXTRA_REMOTE_DEVICE, -1);
  boolean    broadcast    = intent.getBooleanExtra(EXTRA_BROADCAST, false);
  String     answer       = intent.getStringExtra(EXTRA_ANSWER_DESCRIPTION);

  Log.i(TAG, "handleSendAnswer: id: " + callId.format(remoteDevice));

  AnswerMessage            answerMessage       = new AnswerMessage(callId.longValue(), answer);
  Integer                  destinationDeviceId = broadcast ? null : remoteDevice;
  SignalServiceCallMessage callMessage         = SignalServiceCallMessage.forAnswer(answerMessage, true, destinationDeviceId);

  sendCallMessage(remotePeer, callMessage);
}
 
Example #18
Source File: SignalServiceContent.java    From mollyim-android with GNU General Public License v3.0 5 votes vote down vote up
private SignalServiceContent(SignalServiceCallMessage callMessage, SignalServiceAddress sender, int senderDevice, long timestamp, long serverTimestamp, boolean needsReceipt, SignalServiceContentProto serializedState) {
  this.sender          = sender;
  this.senderDevice    = senderDevice;
  this.timestamp       = timestamp;
  this.serverTimestamp = serverTimestamp;
  this.needsReceipt    = needsReceipt;
  this.serializedState = serializedState;

  this.message            = Optional.absent();
  this.synchronizeMessage = Optional.absent();
  this.callMessage        = Optional.of(callMessage);
  this.readMessage        = Optional.absent();
  this.typingMessage      = Optional.absent();
}
 
Example #19
Source File: SignalServiceContent.java    From libsignal-service-java with GNU General Public License v3.0 4 votes vote down vote up
public Optional<SignalServiceCallMessage> getCallMessage() {
  return callMessage;
}
 
Example #20
Source File: SignalServiceContent.java    From bcm-android with GNU General Public License v3.0 4 votes vote down vote up
public Optional<SignalServiceCallMessage> getCallMessage() {
  return callMessage;
}
 
Example #21
Source File: WebRtcCallService.java    From bcm-android with GNU General Public License v3.0 4 votes vote down vote up
private void handleLocalIceCandidate(Intent intent) {
    CallState currentState = this.callState.get();
    if (currentState == CallState.STATE_IDLE || !Util.isEquals(this.callId, getCallId(intent))) {
        ALog.w(TAG, "State is now idle, ignoring ice candidate...");
        return;
    }

    if (recipient == null || callId == -1L) {
        ALog.i(TAG, "handleLocalIceCandidate fail, recipient is null or callId is null");
        terminate();
        return;
    }

    IceUpdateMessage iceUpdateMessage = new IceUpdateMessage(this.callId, intent.getStringExtra(EXTRA_ICE_SDP_MID),
            intent.getIntExtra(EXTRA_ICE_SDP_LINE_INDEX, 0),
            intent.getStringExtra(EXTRA_ICE_SDP));

    ALog.d(TAG, "handleLocalIceCandidate  " + new Gson().toJson(iceUpdateMessage));

    if (pendingOutgoingIceUpdates != null) {
        ALog.i(TAG, "Adding to pending ice candidates...");
        this.pendingOutgoingIceUpdates.add(iceUpdateMessage);
        return;
    }

    ListenableFutureTask<Boolean> listenableFutureTask = sendMessage(WebRtcCallService.accountContext, recipient, SignalServiceCallMessage.forIceUpdate(iceUpdateMessage));
    if (listenableFutureTask != null) {
        listenableFutureTask.addListener(new FailureListener<Boolean>(currentState, callId) {
            @Override
            public void onFailureContinue(Throwable error) {
                ALog.e(TAG, "sendMessage", error);
                sendMessage(WebRtcViewModel.State.NETWORK_FAILURE, recipient, localCameraState, remoteVideoEnabled, bluetoothAvailable, microphoneEnabled);

                IMetricsModule metricsModule = AmeModuleCenter.INSTANCE.metric(WebRtcCallService.accountContext);
                if (metricsModule != null) {
                    metricsModule.addCustomCounterReportData(currentMetric, MetricsConstKt.CALL_FAILED, true);
                    metricsModule.addCustomCounterReportData(currentMetric, MetricsConstKt.CALL_SUCCESS, false);
                }

                terminate();
            }
        });
    }
}
 
Example #22
Source File: SignalServiceContent.java    From bcm-android with GNU General Public License v3.0 4 votes vote down vote up
public SignalServiceContent(SignalServiceCallMessage callMessage) {
  this.message            = Optional.absent();
  this.synchronizeMessage = Optional.absent();
  this.callMessage        = Optional.of(callMessage);
  this.readMessage        = Optional.absent();
}
 
Example #23
Source File: WebRtcCallService.java    From mollyim-android with GNU General Public License v3.0 4 votes vote down vote up
private void sendCallMessage(RemotePeer remotePeer, SignalServiceCallMessage callMessage) {
  ListenableFutureTask<Boolean> listenableFutureTask = sendMessage(remotePeer, callMessage);
  listenableFutureTask.addListener(new SendCallMessageListener<>(remotePeer));
}
 
Example #24
Source File: SignalServiceContent.java    From mollyim-android with GNU General Public License v3.0 4 votes vote down vote up
public Optional<SignalServiceCallMessage> getCallMessage() {
  return callMessage;
}
 
Example #25
Source File: SignalServiceMessageSender.java    From mollyim-android with GNU General Public License v3.0 4 votes vote down vote up
private byte[] createCallContent(SignalServiceCallMessage callMessage) {
  Content.Builder     container = Content.newBuilder();
  CallMessage.Builder builder   = CallMessage.newBuilder();

  if (callMessage.getOfferMessage().isPresent()) {
    OfferMessage offer = callMessage.getOfferMessage().get();
    builder.setOffer(CallMessage.Offer.newBuilder()
                                      .setId(offer.getId())
                                      .setDescription(offer.getDescription())
                                      .setType(offer.getType().getProtoType()));
  } else if (callMessage.getAnswerMessage().isPresent()) {
    AnswerMessage answer = callMessage.getAnswerMessage().get();
    builder.setAnswer(CallMessage.Answer.newBuilder()
                                        .setId(answer.getId())
                                        .setDescription(answer.getDescription()));
  } else if (callMessage.getIceUpdateMessages().isPresent()) {
    List<IceUpdateMessage> updates = callMessage.getIceUpdateMessages().get();

    for (IceUpdateMessage update : updates) {
      builder.addIceUpdate(CallMessage.IceUpdate.newBuilder()
                                                .setId(update.getId())
                                                .setSdp(update.getSdp())
                                                .setSdpMid(update.getSdpMid())
                                                .setSdpMLineIndex(update.getSdpMLineIndex()));
    }
  } else if (callMessage.getHangupMessage().isPresent()) {
    CallMessage.Hangup.Type    protoType        = callMessage.getHangupMessage().get().getType().getProtoType();
    CallMessage.Hangup.Builder builderForHangup = CallMessage.Hangup.newBuilder()
                                                                    .setType(protoType)
                                                                    .setId(callMessage.getHangupMessage().get().getId());

    if (protoType != CallMessage.Hangup.Type.HANGUP_NORMAL) {
      builderForHangup.setDeviceId(callMessage.getHangupMessage().get().getDeviceId());
    }

    if (callMessage.getHangupMessage().get().isLegacy()) {
      builder.setLegacyHangup(builderForHangup);
    } else {
      builder.setHangup(builderForHangup);
    }
  } else if (callMessage.getBusyMessage().isPresent()) {
    builder.setBusy(CallMessage.Busy.newBuilder().setId(callMessage.getBusyMessage().get().getId()));
  }

  builder.setMultiRing(callMessage.isMultiRing());

  if (callMessage.getDestinationDeviceId().isPresent()) {
    builder.setDestinationDeviceId(callMessage.getDestinationDeviceId().get());
  }

  container.setCallMessage(builder);
  return container.build().toByteArray();
}