public void handleIncomingUpdate(Request msg) throws DialogStateException { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (!done.get()) { Logger.log("Remote party has sent update"); final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); assert dialog != null; checkUpdatePreconditions(dialog, msg); Logger.log(TAG, "mark dialog as update in progress"); dialog.markUpdateInProgress(InitiateParty.REMOTE); // TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> // transactionType = SIP_REINVITE_SERVER; TransactionType<UpdateSrvTransaction, UpdateServerTransaction> transactionType = SIP_UPDATE_SERVER; doHandleIncomingUpdate(msg, dialog, transactionType); } }
/** * Handles server noninvite message * * @param msg - noninvite message */ public void handleIncomingBye(final Request msg) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert msg != null && MessageType.SIP_BYE == MessageType.parse(msg.getMethod()); Logger.log("Remote party has sent noninvite"); if (!done.get()) { final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); assert dialog != null; assert STATED == dialog.getState(); dialog.getMessageHistory().addMessage(msg, true); final TransactionManager transactionManager = getTransactionManager(); transactionManager.addListener( new FirstMessageResolver(SIP_BYE_SERVER.getName(), dialog, msg, transactionManager)); final Transaction transaction = transactionManager.lookUpTransaction(dialog, null, SIP_BYE_SERVER); runAsynchronously(transaction, TRANSACTION_TIMEOUT); } }
public void onTransactionCreate(final TransactionBuildUpEvent<BaseSipMessage> event) { assert SIP_REINVITE_CLIENT == event.getTransaction().getTransactionType(); Dialog dialog = (Dialog) event.getEntity(); final Transaction<Boolean, BaseSipMessage> transaction = event.getTransaction(); // DIALOG.putCustomParameter(Dialog.ParamKey.REINVITE_IN_PROGRESS, Boolean.TRUE); dialog.markReInviteInProgress(InitiateParty.LOCAL); // listener will un-subscribe automatically on transaction complete transaction.addListener(new AuthChallengeListener<BaseSipMessage>(transaction, dialog)); // listener will un-subscribe automatically on transaction complete transaction.addListener( new MiddleManForClientMessageBuildingSupport<BaseSipMessage>(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 transaction.addListener( new ReinviteInProgressListener<BaseSipMessage>( transaction, dialog, InitiateParty.LOCAL)); }
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. */ }
/** * This method initiates SIP_BYE for established DIALOG * * @param dialog - DIALOG to terminate */ public void bye(final Dialog dialog) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (!done.get()) { assert STATED == dialog.getState() : "Wrong dialog state. Must be " + STATED + " now is " + dialog.getState(); doBye(dialog, TRANSACTION_TIMEOUT); } }
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); } }); }
public void update(Dialog dialog) throws DialogStateException { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert getStackContext().getDialogStorage().findDialogByCallId(dialog.getCallId()) != null : "DIALOG being updated is already terminated"; if (!done.get()) { checkUpdatePreconditions(dialog, null); dialog .getOutgoingSdpMessage() .setSessionVersion(dialog.getOutgoingSdpMessage().getSessionVersion() + 1); doUpdate(dialog); } }
private void checkReInvitePreconditions(final Dialog dialog, final Request msg) throws DialogStateException { if (EARLY == dialog.getState()) { throw new DialogStateException( dialog, REINVITE_FOR_EARLY_DIALOG, msg, "Can not update (reinvite) DIALOG. Dialog is not stated yet. Dialog state is " + dialog.getState()); } if (dialog.isReInviteInProgress()) { throw new DialogStateException( dialog, REINVITE_DURING_PREVIOUS_REINVITE, msg, "Can not update (reinvite) DIALOG. Previous reinvite still in progress."); } }
private void doHandleIncomingUpdate( Request msg, Dialog dialog, TransactionType<UpdateSrvTransaction, UpdateServerTransaction> transactionType) { dialog.getMessageHistory().addMessage(msg, true); SdpMessage sdp = SipMessageUtils.getSdpFromMessage(msg); if (sdp != null) { dialog.setIncomingSdpMessage(sdp); } final TransactionManager transactionManager = getTransactionManager(); transactionManager.addListener( new FirstMessageResolver(transactionType.getName(), dialog, msg, transactionManager)); final UpdateSrvTransaction transaction = transactionManager.lookUpTransaction(dialog, null, transactionType); runAsynchronously((Transaction<Boolean, BaseSipMessage>) transaction); }
public void reInvite(final Dialog dialog) throws DialogStateException { Logger.log(TAG, "reInvite#started"); assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert getStackContext().getDialogStorage().findDialogByCallId(dialog.getCallId()) != null : "DIALOG being re-invited is already terminated"; if (!done.get()) { checkReInvitePreconditions(dialog, null); dialog .getOutgoingSdpMessage() .setSessionVersion(dialog.getOutgoingSdpMessage().getSessionVersion() + 1); doReInvite(dialog, LONG_TRANSACTION_TIMEOUT); } Logger.log(TAG, "reInvite#finished"); }
private void doUpdate(Dialog dialog) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (dialog.getInitiateParty() == InitiateParty.LOCAL) { getTransactionManager().findTransaction(dialog, SIP_INVITE_CLIENT).update(); } else { getTransactionManager().findTransaction(dialog, SIP_INVITE_SERVER).update(); } }
public void handleIncomingCancel(Request msg) throws DialogStateException { assert !done.get(); assert msg != null && MessageType.SIP_CANCEL == MessageType.parse(msg.getMethod()); if (!done.get()) { Logger.log("Remote party has sent SIP_CANCEL"); final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); if (dialog != null) { dialog.getMessageHistory().addMessage(msg, true); final InviteSrvTransaction transaction = getTransactionManager().findTransaction(dialog, SIP_INVITE_SERVER); if (transaction != null) { final DialogStateEvent<BaseSipMessage> stateEvent = new DefaultDialogStateEvent<BaseSipMessage>( dialog, SessionState.SESSION_TERMINATED, msg); dialogStateListenerHolder.getNotifier().onSessionTerminated(stateEvent); dialogStateListenerHolder.getNotifier().onSessionEnded(stateEvent); // DIALOG.putCustomParameter(ParamKey.INITIAL_MESSAGE, ((Transaction) // transaction).getInitialMessage()); transaction.cancel(); } else { // assert false : "Transaction already terminated for msg: " + msg.shortDescription() + " // dialog: " + dialog; throw new DialogStateException( dialog, DialogStateException.Error.REQUEST_FOR_UNKNOWN_DIALOG, msg); } } else { // assert false : "Dialog is already terminated or never exist. Message :" + // msg.shortDescription(); throw new DialogStateException( dialog, DialogStateException.Error.REQUEST_FOR_UNKNOWN_DIALOG, msg); } } }
private void doHandleIncomingInvite( final Request msg, final Dialog dialog, final TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType) { dialog.getMessageHistory().addMessage(msg, true); // DIALOG.putCustomParameter(ParamKey.LAST_MESSAGE, msg); Logger.log("doHandleIncomingInvite", ""); SdpMessage sdp = SipMessageUtils.getSdpFromMessage(msg); if (sdp != null) { dialog.setIncomingSdpMessage(sdp); } final TransactionManager transactionManager = getTransactionManager(); transactionManager.addListener( new FirstMessageResolver(transactionType.getName(), dialog, msg, transactionManager)); final InviteSrvTransaction transaction = transactionManager.lookUpTransaction(dialog, null, transactionType); runAsynchronously((Transaction<Boolean, BaseSipMessage>) transaction); }
public void handleIncomingReInvite(final Request msg) throws DialogStateException { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); assert msg != null && MessageType.SIP_INVITE == MessageType.parse(msg.getMethod()); if (!done.get()) { Logger.log("Remote party has sent ReInvite"); final Dialog dialog = getStackContext().getDialogStorage().findDialogForMessage(msg); assert dialog != null; checkReInvitePreconditions(dialog, msg); dialog.markReInviteInProgress(InitiateParty.REMOTE); TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType = SIP_REINVITE_SERVER; doHandleIncomingInvite(msg, dialog, transactionType); } }
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(); } */ }
private void doPreAccept(final Dialog dialog) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType; if (dialog.isReInviteInProgress()) { transactionType = SIP_REINVITE_SERVER; } else { transactionType = SIP_INVITE_SERVER; } getTransactionManager().findTransaction(dialog, transactionType).preAccept(); }
/** * Rejects server invite * * @param dialog - associated DIALOG * @param statusCode - status code to send to remote party * @param alternativeUserAddress - alternative USER address for status code 302(Moved) */ private void doReject( final Dialog dialog, final int statusCode, final String alternativeUserAddress) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); TransactionType<InviteSrvTransaction, ? extends ServerCommonInviteTransaction> transactionType; if (dialog.isReInviteInProgress()) { transactionType = SIP_REINVITE_SERVER; } else { transactionType = SIP_INVITE_SERVER; } assert transactionType == SIP_INVITE_SERVER || statusCode == 488; getTransactionManager() .findTransaction(dialog, transactionType) .reject(statusCode, alternativeUserAddress); }
private void doRejectUpdate( final Dialog dialog, final int statusCode, final String alternativeUserAddress) { assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (dialog.getInitiateParty() == InitiateParty.LOCAL) { getTransactionManager() .findTransaction(dialog, SIP_INVITE_CLIENT) .rejectUpdate(statusCode, alternativeUserAddress); } else { // getTransactionManager().findTransaction(dialog, SIP_INVITE_SERVER).rejectUpdate(statusCode, // alternativeUserAddress); TransactionType<UpdateSrvTransaction, UpdateServerTransaction> transactionType = SIP_UPDATE_SERVER; getTransactionManager() .findTransaction(dialog, transactionType) .reject(statusCode, alternativeUserAddress); } }
/** This method tries to invite remote party */ public void invite(final Dialog dialog) throws DialogStateException { Logger.log(TAG, "invite#started"); assert TransactionUtils.isTransactionExecutionThread() : "Code run in wrong thread. Must be run in TransactionThread. Now in " + Thread.currentThread(); assert !done.get(); if (!done.get()) { if (STATED == dialog.getState()) { throw new DialogStateException( dialog, INVITE_FOR_STATED_DIALOG, null, "Can not invite remote party. Dialog is already stated."); } if (getStackContext().getConfig().useInviteRefresh()) { addDialogStateListener(dialog, listenerForInviteRefresh); } doInvite(dialog, LONG_TRANSACTION_TIMEOUT); } Logger.log(TAG, "invite#finished"); }