private void checkUpdatePreconditions(final Dialog dialog, final Request msg)
      throws DialogStateException {
    if (STATED == dialog.getState()) {
      throw new DialogStateException(
          dialog,
          UPDATE_FOR_STATED_DIALOG,
          msg,
          "Can not update DIALOG. Dialog is stated already. ");
    }
    if (dialog.isUpdateInProgress()) {
      throw new DialogStateException(
          dialog,
          UPDATE_DURING_PREVIOUS_UPDATE,
          msg,
          "Can not update DIALOG. Previous update still in progress.");
    }

    /**
     * A UAS that receives an UPDATE before it has generated a final response to a previous UPDATE
     * on the same dialog MUST return a 500 response to the new UPDATE, and MUST include a
     * Retry-After HEADER field with a randomly chosen value between 0 and 10 seconds.
     *
     * <p>If an UPDATE is received that contains an offer, and the UAS has generated an offer (in an
     * UPDATE, PRACK or INVITE) to which it has not yet received an answer, the UAS MUST reject the
     * UPDATE with a 491 response. Similarly, if an UPDATE is received that contains an offer, and
     * the UAS has received an offer (in an UPDATE, PRACK, or INVITE) to which it has not yet
     * generated an answer, the UAS MUST reject the UPDATE with a 500 response, and MUST include a
     * Retry-After HEADER field with a randomly chosen value between 0 and 10 seconds.
     *
     * <p>If a UA receives an UPDATE for an existing dialog, it MUST check any version identifiers
     * in the SESSION description or, if there are no version identifiers, the content of the
     * SESSION description to see if it has changed. If the SESSION description has changed, the UAS
     * MUST adjust the SESSION parameters accordingly and generate an answer in the 2xx response.
     * However, unlike a re-INVITE, the UPDATE MUST be responded to promptly, and therefore the USER
     * cannot generally be prompted to approve the SESSION changes. If the UAS cannot change the
     * SESSION parameters without prompting the USER, it SHOULD reject the request with a 504
     * response. If the new SESSION description is not acceptable, the UAS can reject it by
     * returning a 488 (Not Acceptable Here) response for the UPDATE. This response SHOULD include a
     * Warning HEADER field.
     *
     * <p>If a UAC receives a 491 response to a UPDATE, it SHOULD start a timer with a value T
     * chosen as follows:
     *
     * <p>1. If the UAC is the owner of the Call-ID of the dialog ID (meaning it generated the
     * value), T has a randomly chosen value between 2.1 and 4 seconds in units of 10 ms.
     *
     * <p>2. If the UAC is not the owner of the Call-ID of the dialog ID, T has a randomly chosen
     * value between 0 and 2 seconds in units of 10 ms.
     *
     * <p>When the timer fires, the UAC SHOULD attempt the UPDATE once more, if it still desires for
     * that SESSION modification to take place. For example, if the call was already hung up with a
     * BYE, the UPDATE would not take place.
     */
  }
        public void onTransactionCreate(final TransactionBuildUpEvent<BaseSipMessage> event) {
          assert SIP_REINVITE_SERVER == event.getTransaction().getTransactionType();

          Dialog dialog = (Dialog) event.getEntity();
          final Transaction<Boolean, BaseSipMessage> transaction = event.getTransaction();

          // DIALOG.putCustomParameter(Dialog.ParamKey.REINVITE_IN_PROGRESS, Boolean.TRUE);
          // TODo reinvire is used for update too
          // dialog.markReInviteInProgress(InitiateParty.REMOTE);

          // listener will un-subscribe automatically on transaction complete
          transaction.addListener(
              new IncomingReInviteListener<BaseSipMessage>(
                  dialog,
                  createSafeInviteAcceptable(dialog),
                  transaction,
                  incomingCallListenerHolder));

          // listener will un-subscribe automatically on transaction complete
          transaction.addListener(
              new MiddleManForServerMessageBuildingSupport(transaction, dialog));
          // listener will un-subscribe automatically on transaction complete
          transaction.addListener(
              new ReInviteStateMiddleMan<BaseSipMessage>(
                  transaction, dialog, dialogStateListenerHolder) {

                protected void onDialogCleanUp(final Dialog dialog) {
                  getStackContext().getDialogStorage().cleanUpDialog(dialog);
                }
              });
          // listener will un-subscribe automatically on transaction complete
          // TODO change
          if (dialog.isUpdateInProgress()) {
            transaction.addListener(
                new UpdateInProgressListener<BaseSipMessage>(
                    transaction, dialog, InitiateParty.REMOTE));
          } else {
            transaction.addListener(
                new ReinviteInProgressListener<BaseSipMessage>(
                    transaction, dialog, InitiateParty.REMOTE));
          }
          // listener will un-subscribe automatically on transaction complete
          transaction.addListener(
              new DialogCleanUpListener<BaseSipMessage>(transaction, dialog, false) {

                protected void onDialogCleanUp(final Dialog dialog) {
                  getStackContext().getDialogStorage().cleanUpDialog(dialog);
                }
              });
        }
  private void doAcceptUpdate(final Dialog dialog) {
    assert TransactionUtils.isTransactionExecutionThread()
        : "Code run in wrong thread. Must be run in TransactionThread. Now in "
            + Thread.currentThread();
    assert !done.get();

    if (dialog.isReInviteInProgress() || dialog.isUpdateInProgress()) {
      // transactionType = SIP_REINVITE_SERVER;
      TransactionType<UpdateSrvTransaction, UpdateServerTransaction> transactionType =
          SIP_UPDATE_SERVER;
      getTransactionManager().findTransaction(dialog, transactionType).accept();
    } else {
      TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction>
          transactionType = SIP_INVITE_SERVER;
      getTransactionManager().findTransaction(dialog, transactionType).acceptUpdate();
    }

    /*        if (dialog.getInitiateParty() == InitiateParty.LOCAL) {
                getTransactionManager().findTransaction(dialog, SIP_INVITE_CLIENT).acceptUpdate();
            }
            else {
                getTransactionManager().findTransaction(dialog, SIP_INVITE_SERVER).acceptUpdate();
            }
    */ }