Package gov.nist.javax.sip.stack

Examples of gov.nist.javax.sip.stack.SIPTransaction$LingerTimer


            }

            /*
             * A refer cannot be processed until previous transaction has been completed.
             */
            SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction();
            if (lastTransaction != null  && sipProvider.isDialogErrorsAutomaticallyHandled()) {
                SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest();
                if (lastTransaction instanceof SIPServerTransaction) {
                    if (lastTransaction.getState() == TransactionState.PROCEEDING
                            && lastRequest.getMethod().equals(Request.INVITE)) {
                        this.sendRequestPendingResponse(sipRequest, transaction);
                        return;
                    }
                } else if (lastTransaction != null && lastTransaction instanceof SIPClientTransaction) {
                    long cseqno = lastRequest.getCSeqHeader().getSeqNumber();
                    String method = lastRequest.getMethod();
                    if (method.equals(Request.INVITE) && lastTransaction.getState() != TransactionState.TERMINATED &&
                        lastTransaction.getState() != TransactionState.COMPLETED ) {
                        this.sendRequestPendingResponse(sipRequest, transaction);
                        return;
                    }
                }
            }

        } else if (sipRequest.getMethod().equals(Request.UPDATE)) {
            /*
             * Got an UPDATE method and the user dialog does not exist and the user wants to be a
             * User agent.
             *
             */
            if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
                this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction);
                return;
            }
        } else if (sipRequest.getMethod().equals(Request.ACK)) {

            if (transaction != null && transaction.isInviteTransaction()) {
                // This is an ack for a 3xx-6xx response. Just let the tx laer
                // take care of it.
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx ");
              

            } else {
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog);

                if (dialog == null) {
                    if (sipStack.isLoggingEnabled()) {
                        sipStack.getStackLogger().logDebug(
                                "Dialog does not exist " + sipRequest.getFirstLine()
                                        + " isServerTransaction = " + true);

                    }
                    SIPServerTransaction st = sipStack
                            .getRetransmissionAlertTransaction(dialogId);
                    if (st != null && st.isRetransmissionAlertEnabled()) {
                        st.disableRetransmissionAlerts();

                    }
                    /*
                     * JvB: must never drop ACKs that dont match a transaction! One cannot be sure
                     * if it isn't an ACK for a 2xx response
                     *
                     */
                    SIPServerTransaction ackTransaction = sipStack
                            .findTransactionPendingAck(sipRequest);
                    /*
                     * Found a transaction ( that we generated ) which is waiting for ACK. So ACK
                     * it and return.
                     */
                    if (ackTransaction != null) {
                        if (sipStack.isLoggingEnabled())
                            sipStack.getStackLogger().logDebug("Found Tx pending ACK");
                        try {
                            ackTransaction.setAckSeen();
                            sipStack.removeTransaction(ackTransaction);
                            sipStack.removeTransactionPendingAck(ackTransaction);
                        } catch (Exception ex) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logError(
                                        "Problem terminating transaction", ex);
                            }
                        }
                        return;
                    }

                } else {
                    if (!dialog.handleAck(transaction)) {
                        if (!dialog.isSequnceNumberValidation()) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logDebug(
                                        "Dialog exists with loose dialog validation "
                                                + sipRequest.getFirstLine()
                                                + " isServerTransaction = " + true + " dialog = "
                                                + dialog.getDialogId());

                            }
                            SIPServerTransaction st = sipStack
                                    .getRetransmissionAlertTransaction(dialogId);
                            if (st != null && st.isRetransmissionAlertEnabled()) {
                                st.disableRetransmissionAlerts();

                            }
                        } else {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logDebug(
                                        "Dropping ACK - cannot find a transaction or dialog");
                            }
                            SIPServerTransaction ackTransaction = sipStack
                                    .findTransactionPendingAck(sipRequest);
                            if (ackTransaction != null) {
                                if (sipStack.isLoggingEnabled())
                                    sipStack.getStackLogger().logDebug("Found Tx pending ACK");
                                try {
                                    ackTransaction.setAckSeen();
                                    sipStack.removeTransaction(ackTransaction);
                                    sipStack.removeTransactionPendingAck(ackTransaction);
                                } catch (Exception ex) {
                                    if (sipStack.isLoggingEnabled()) {
                                        sipStack.getStackLogger().logError(
                                                "Problem terminating transaction", ex);
                                    }
                                }
                            }
                            /*
                             * For test only we support a flag that will deliver retransmitted
                             * ACK for 200 OK responses to the listener.
                             */
                            if ( (! sipStack.isDeliverRetransmittedAckToListener() ) ||  ( ackTransaction != null &&
                                !sipStack.isNon2XXAckPassedToListener() ) ) {
                              return;
                            }
                        }
                    } else {
                      
                        dialog.addTransaction(transaction);
                        transaction.passToListener();
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                        if (sipRequest.getMethod().equals(Request.INVITE)
                                && sipProvider.isDialogErrorsAutomaticallyHandled()) {
                            sipStack.putInMergeTable(transaction, sipRequest);
                        }
                        /*
                         * Note that ACK is a pseudo transaction. It is never added to the stack
                         * and you do not get transaction terminated events on ACK.
                         */

                        if (sipStack.isDeliverTerminatedEventForAck()) {
                            try {
                                sipStack.addTransaction(transaction);
                                transaction.scheduleAckRemoval();
                            } catch (IOException ex) {

                            }
                        } else {
                            transaction.setMapped(true);
                        }

                    }
                }
            }
        } else if (sipRequest.getMethod().equals(Request.PRACK)) {

            /*
             * RFC 3262: A matching PRACK is defined as one within the same dialog as the
             * response, and whose method, CSeq-num, and response-num in the RAck header field
             * match, respectively, the method from the CSeq, the sequence number from the CSeq,
             * and the sequence number from the RSeq of the reliable provisional response.
             */

            if (sipStack.isLoggingEnabled())
                sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog);

            if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "Dialog does not exist " + sipRequest.getFirstLine()
                                    + " isServerTransaction = " + true);

                }
                if (sipStack.isLoggingEnabled()) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
                }
                SIPResponse notExist = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);

                try {
                    sipProvider.sendResponse(notExist);
                } catch (SipException e) {
                    sipStack.getStackLogger().logError("error sending response", e);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            } else if (dialog != null) {
                if (!dialog.handlePrack(sipRequest)) {
                    if (sipStack.isLoggingEnabled())
                        sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK ");
                    if (transaction != null) {
                        sipStack.removeTransaction(transaction);
                        transaction.releaseSem();
                    }
                    return;
                } else {
                    try {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                    } catch (Exception ex) {
                        InternalErrorHandler.handleException(ex);
                    }
                }
            } else {
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug(
                            "Processing PRACK without a DIALOG -- this must be a proxy element");
            }

        } else if (sipRequest.getMethod().equals(Request.BYE)) {
            // Check for correct sequence numbering of the BYE
            if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug(
                            "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " "
                                    + sipRequest.getCSeq().getSeqNumber());

                if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber()
                        && transaction.getState() == TransactionState.TRYING) {

                    this.sendServerInternalErrorResponse(sipRequest, transaction);

                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null)
                    sipStack.removeTransaction(transaction);
                return;

            } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
                // Drop bye's with 481 if dialog does not exist.
                // If dialog support is enabled then
                // there must be a dialog associated with the bye
                // No dialog could be found and requests on this
                // provider. Must act like a user agent -- so drop the request.
                // NOTE: if Automatic dialog support is not enabled,
                // then it is the application's responsibility to
                // take care of this error condition possibly.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                response.setReasonPhrase("Dialog Not Found");

                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug(
                            "dropping request -- automatic dialog "
                                    + "support enabled and dialog does not exist!");
                try {
                    transaction.sendResponse(response);
                } catch (SipException ex) {
                    sipStack.getStackLogger().logError("Error in sending response", ex);
                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                    transaction = null;
                }
                return;

            }

            // note that the transaction may be null (which
            // happens when no dialog for the bye was found.
            // and automatic dialog support is disabled (i.e. the app wants
            // to manage its own dialog layer.
            if (transaction != null && dialog != null) {
                try {
                    if (sipProvider == dialog.getSipProvider()) {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        transaction.setDialog(dialog, dialogId);
                    }

                } catch (IOException ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug(
                        "BYE Tx = " + transaction + " isMapped ="
                                + transaction.isTransactionMapped());
            }

        } else if (sipRequest.getMethod().equals(Request.CANCEL)) {

            SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction(
                    sipRequest, true);
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug(
                        "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = "
                                + transaction + " isMapped = "
                                + transaction.isTransactionMapped());

            }
            // Processing incoming CANCEL.
            // Check if we can process the CANCEL request.
            if (sipRequest.getMethod().equals(Request.CANCEL)) {
                // If the CANCEL comes in too late, there's not
                // much that the Listener can do so just do the
                // default action and avoid bothering the listener.
                if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) {
                    // If transaction already exists but it is
                    // too late to cancel the transaction then
                    // just respond OK to the CANCEL and bail.
                    if (sipStack.isLoggingEnabled())
                        sipStack.getStackLogger().logDebug("Too late to cancel Transaction");
                    // send OK and just ignore the CANCEL.
                    try {

                        transaction.sendResponse(sipRequest.createResponse(Response.OK));
                    } catch (Exception ex) {
                        if (ex.getCause() != null && ex.getCause() instanceof IOException) {
                            st.raiseIOExceptionEvent();
                        }
                    }
                    return;
                }
                if (sipStack.isLoggingEnabled())
                    sipStack.getStackLogger().logDebug("Cancel transaction = " + st);

            }
            if (transaction != null && st != null && st.getDialog() != null) {
                // Found an invite tx corresponding to the CANCEL.
                // Set up the client tx and pass up to listener.
                transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
                dialog = (SIPDialog) st.getDialog();
            } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled()
                    && transaction != null) {
                // Could not find a invite tx corresponding to the CANCEL.
                // Automatic dialog support is enabled so I must behave like
                // an endpoint on this provider.
                // Send the error response for the cancel.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "dropping request -- automatic dialog support "
                                    + "enabled and INVITE ST does not exist!");
                }
                try {
                    sipProvider.sendResponse(response);
                } catch (SipException ex) {
                    InternalErrorHandler.handleException(ex);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            }

            // INVITE was handled statefully so the CANCEL must also be
            // statefully handled.
            if (st != null) {
                try {
                    if (transaction != null) {
                        sipStack.addTransaction(transaction);
                        transaction.setPassToListener();
                        transaction.setInviteTransaction(st);
                        // Dont let the INVITE and CANCEL be concurrently
                        // processed.
                        st.acquireSem();

                    }

                } catch (Exception ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
        } else if (sipRequest.getMethod().equals(Request.INVITE)) {
            SIPTransaction lastTransaction = dialog == null ? null : dialog
                    .getInviteTransaction();

            /*
             * RFC 3261 Chapter 14. A UAS that receives a second INVITE before it sends the final
             * response to a first INVITE with a lower CSeq sequence number on the same dialog
             * MUST return a 500 (Server Internal Error) response to the second INVITE and MUST
             * include a Retry-After header field with a randomly chosen value of between 0 and 10
             * seconds.
             */

            if (dialog != null && transaction != null && lastTransaction != null
                    && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber()
                    && lastTransaction instanceof SIPServerTransaction
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && dialog.isSequnceNumberValidation()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction.getState() != TransactionState.COMPLETED
                    && lastTransaction.getState() != TransactionState.TERMINATED
                    && lastTransaction.getState() != TransactionState.CONFIRMED) {

                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 500 response for out of sequence message");
                }
                this.sendServerInternalErrorResponse(sipRequest, transaction);
                return;

            }

            /*
             * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that
             * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in
             * progress MUST return a 491 (Request Pending) response to the received INVITE.
             */
            lastTransaction = (dialog == null ? null : dialog.getLastTransaction());

            if (dialog != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction != null
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ClientTransaction
                    && lastTransaction.getLastResponse() != null
                    && lastTransaction.getLastResponse().getStatusCode() == 200
                    && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq()
                            .getSeqNumber())) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 491 response for client Dialog ACK not sent.");
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;
            }

            if (dialog != null && lastTransaction != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ServerTransaction
                    /* && !dialog.isAckSeen() */
                    && lastTransaction.getState().equals(TransactionState.PROCEEDING)
                    ) {
              // Note that the completed state will be reached when we have sent an error
              // response and the terminated state will be reached when we have sent an OK
              // response. We do not need to wait till the ACK to be seen.
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 491 response for server Dialog ACK not seen.");
                    sipStack.getStackLogger().logDebug("Last SipResponse sent " + dialog.getLastResponse());
                   
                    sipStack.getStackLogger().logDebug("last Transaction state = " + lastTransaction + " state "+ lastTransaction.getState());
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;

            }
View Full Code Here


            }

            /*
             * A refer cannot be processed until previous transaction has been completed.
             */
            SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction();
            if (lastTransaction != null  && sipProvider.isDialogErrorsAutomaticallyHandled()) {
                SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest();
                if (lastTransaction instanceof SIPServerTransaction) {
                    if (lastTransaction.getState() == TransactionState.PROCEEDING
                            && lastRequest.getMethod().equals(Request.INVITE)) {
                        this.sendRequestPendingResponse(sipRequest, transaction);
                        return;
                    }
                } else if (lastTransaction != null && lastTransaction instanceof SIPClientTransaction) {
                    long cseqno = lastRequest.getCSeqHeader().getSeqNumber();
                    String method = lastRequest.getMethod();
                    if (method.equals(Request.INVITE) && lastTransaction.getState() != TransactionState.TERMINATED &&
                        lastTransaction.getState() != TransactionState.COMPLETED ) {
                        this.sendRequestPendingResponse(sipRequest, transaction);
                        return;
                    }
                }
            }

        } else if (sipRequest.getMethod().equals(Request.UPDATE)) {
            /*
             * Got an UPDATE method and the user dialog does not exist and the user wants to be a
             * User agent.
             *
             */
            if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
                this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction);
                return;
            }
        } else if (sipRequest.getMethod().equals(Request.ACK)) {

            if (transaction != null && transaction.isInviteTransaction()) {
                // This is an ack for a 3xx-6xx response. Just let the tx laer
                // take care of it.
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx ");
              

            } else {
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog);

                if (dialog == null) {
                    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                        sipStack.getStackLogger().logDebug(
                                "Dialog does not exist " + sipRequest.getFirstLine()
                                        + " isServerTransaction = " + true);

                    }
                    SIPServerTransaction st = sipStack
                            .getRetransmissionAlertTransaction(dialogId);
                    if (st != null && st.isRetransmissionAlertEnabled()) {
                        st.disableRetransmissionAlerts();

                    }
                    /*
                     * JvB: must never drop ACKs that dont match a transaction! One cannot be sure
                     * if it isn't an ACK for a 2xx response
                     *
                     */
                    SIPServerTransaction ackTransaction = sipStack
                            .findTransactionPendingAck(sipRequest);
                    /*
                     * Found a transaction ( that we generated ) which is waiting for ACK. So ACK
                     * it and return.
                     */
                    if (ackTransaction != null) {
                        if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                            sipStack.getStackLogger().logDebug("Found Tx pending ACK");
                        try {
                            ackTransaction.setAckSeen();
                            sipStack.removeTransaction(ackTransaction);
                            sipStack.removeTransactionPendingAck(ackTransaction);
                        } catch (Exception ex) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logError(
                                        "Problem terminating transaction", ex);
                            }
                        }
                        return;
                    }

                } else {
                    if (!dialog.handleAck(transaction)) {
                        if (!dialog.isSequnceNumberValidation()) {
                            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                                sipStack.getStackLogger().logDebug(
                                        "Dialog exists with loose dialog validation "
                                                + sipRequest.getFirstLine()
                                                + " isServerTransaction = " + true + " dialog = "
                                                + dialog.getDialogId());

                            }
                            SIPServerTransaction st = sipStack
                                    .getRetransmissionAlertTransaction(dialogId);
                            if (st != null && st.isRetransmissionAlertEnabled()) {
                                st.disableRetransmissionAlerts();

                            }
                        } else {
                            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                                sipStack.getStackLogger().logDebug(
                                        "Dropping ACK - cannot find a transaction or dialog");
                            }
                            SIPServerTransaction ackTransaction = sipStack
                                    .findTransactionPendingAck(sipRequest);
                            if (ackTransaction != null) {
                                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                                    sipStack.getStackLogger().logDebug("Found Tx pending ACK");
                                try {
                                    ackTransaction.setAckSeen();
                                    sipStack.removeTransaction(ackTransaction);
                                    sipStack.removeTransactionPendingAck(ackTransaction);
                                } catch (Exception ex) {
                                    if (sipStack.isLoggingEnabled()) {
                                        sipStack.getStackLogger().logError(
                                                "Problem terminating transaction", ex);
                                    }
                                }
                            }
                            /*
                             * For test only we support a flag that will deliver retransmitted
                             * ACK for 200 OK responses to the listener.
                             */
                            if ( (! sipStack.isDeliverRetransmittedAckToListener() ) ||  ( ackTransaction != null &&
                                !sipStack.isNon2XXAckPassedToListener() ) ) {
                              return;
                            }
                        }
                    } else {
                      
                        dialog.addTransaction(transaction);
                        transaction.passToListener();
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                        if (sipRequest.getMethod().equals(Request.INVITE)
                                && sipProvider.isDialogErrorsAutomaticallyHandled()) {
                            sipStack.putInMergeTable(transaction, sipRequest);
                        }
                        /*
                         * Note that ACK is a pseudo transaction. It is never added to the stack
                         * and you do not get transaction terminated events on ACK.
                         */

                        if (sipStack.isDeliverTerminatedEventForAck()) {
                            try {
                                sipStack.addTransaction(transaction);
                                transaction.scheduleAckRemoval();
                            } catch (IOException ex) {

                            }
                        } else {
                            transaction.setMapped(true);
                        }

                    }
                }
            }
        } else if (sipRequest.getMethod().equals(Request.PRACK)) {

            /*
             * RFC 3262: A matching PRACK is defined as one within the same dialog as the
             * response, and whose method, CSeq-num, and response-num in the RAck header field
             * match, respectively, the method from the CSeq, the sequence number from the CSeq,
             * and the sequence number from the RSeq of the reliable provisional response.
             */

            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog);

            if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "Dialog does not exist " + sipRequest.getFirstLine()
                                    + " isServerTransaction = " + true);

                }
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
                }
                SIPResponse notExist = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);

                try {
                    sipProvider.sendResponse(notExist);
                } catch (SipException e) {
                    sipStack.getStackLogger().logError("error sending response", e);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            } else if (dialog != null) {
                if (!dialog.handlePrack(sipRequest)) {
                    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                        sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK ");
                    if (transaction != null) {
                        sipStack.removeTransaction(transaction);
                        transaction.releaseSem();
                    }
                    return;
                } else {
                    try {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                    } catch (Exception ex) {
                        InternalErrorHandler.handleException(ex);
                    }
                }
            } else {
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Processing PRACK without a DIALOG -- this must be a proxy element");
            }

        } else if (sipRequest.getMethod().equals(Request.BYE)) {
            // Check for correct sequence numbering of the BYE
            if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " "
                                    + sipRequest.getCSeq().getSeqNumber());

                if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber()
                        && transaction.getState() == TransactionState.TRYING) {

                    this.sendServerInternalErrorResponse(sipRequest, transaction);

                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null)
                    sipStack.removeTransaction(transaction);
                return;

            } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
                // Drop bye's with 481 if dialog does not exist.
                // If dialog support is enabled then
                // there must be a dialog associated with the bye
                // No dialog could be found and requests on this
                // provider. Must act like a user agent -- so drop the request.
                // NOTE: if Automatic dialog support is not enabled,
                // then it is the application's responsibility to
                // take care of this error condition possibly.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                response.setReasonPhrase("Dialog Not Found");

                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "dropping request -- automatic dialog "
                                    + "support enabled and dialog does not exist!");
                try {
                    transaction.sendResponse(response);
                } catch (SipException ex) {
                    sipStack.getStackLogger().logError("Error in sending response", ex);
                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                    transaction = null;
                }
                return;

            }

            // note that the transaction may be null (which
            // happens when no dialog for the bye was found.
            // and automatic dialog support is disabled (i.e. the app wants
            // to manage its own dialog layer.
            if (transaction != null && dialog != null) {
                try {
                    if (sipProvider == dialog.getSipProvider()) {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        transaction.setDialog(dialog, dialogId);
                    }

                } catch (IOException ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                sipStack.getStackLogger().logDebug(
                        "BYE Tx = " + transaction + " isMapped ="
                                + transaction.isTransactionMapped());
            }

        } else if (sipRequest.getMethod().equals(Request.CANCEL)) {

            SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction(
                    sipRequest, true);
            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                sipStack.getStackLogger().logDebug(
                        "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = "
                                + transaction + " isMapped = "
                                + transaction.isTransactionMapped());

            }
            // Processing incoming CANCEL.
            // Check if we can process the CANCEL request.
            if (sipRequest.getMethod().equals(Request.CANCEL)) {
                // If the CANCEL comes in too late, there's not
                // much that the Listener can do so just do the
                // default action and avoid bothering the listener.
                if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) {
                    // If transaction already exists but it is
                    // too late to cancel the transaction then
                    // just respond OK to the CANCEL and bail.
                    if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                        sipStack.getStackLogger().logDebug("Too late to cancel Transaction");
                    // send OK and just ignore the CANCEL.
                    try {

                        transaction.sendResponse(sipRequest.createResponse(Response.OK));
                    } catch (Exception ex) {
                        if (ex.getCause() != null && ex.getCause() instanceof IOException) {
                            st.raiseIOExceptionEvent();
                        }
                    }
                    return;
                }
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug("Cancel transaction = " + st);

            }
            if (transaction != null && st != null && st.getDialog() != null) {
                // Found an invite tx corresponding to the CANCEL.
                // Set up the client tx and pass up to listener.
                transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
                dialog = (SIPDialog) st.getDialog();
            } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled()
                    && transaction != null) {
                // Could not find a invite tx corresponding to the CANCEL.
                // Automatic dialog support is enabled so I must behave like
                // an endpoint on this provider.
                // Send the error response for the cancel.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "dropping request -- automatic dialog support "
                                    + "enabled and INVITE ST does not exist!");
                }
                try {
                    sipProvider.sendResponse(response);
                } catch (SipException ex) {
                    InternalErrorHandler.handleException(ex);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            }

            // INVITE was handled statefully so the CANCEL must also be
            // statefully handled.
            if (st != null) {
                try {
                    if (transaction != null) {
                        sipStack.addTransaction(transaction);
                        transaction.setPassToListener();
                        transaction.setInviteTransaction(st);
                        // Dont let the INVITE and CANCEL be concurrently
                        // processed.
                        st.acquireSem();

                    }

                } catch (Exception ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
        } else if (sipRequest.getMethod().equals(Request.INVITE)) {
            SIPTransaction lastTransaction = dialog == null ? null : dialog
                    .getInviteTransaction();

            /*
             * RFC 3261 Chapter 14. A UAS that receives a second INVITE before it sends the final
             * response to a first INVITE with a lower CSeq sequence number on the same dialog
             * MUST return a 500 (Server Internal Error) response to the second INVITE and MUST
             * include a Retry-After header field with a randomly chosen value of between 0 and 10
             * seconds.
             */

            if (dialog != null && transaction != null && lastTransaction != null
                    && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber()
                    && lastTransaction instanceof SIPServerTransaction
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && dialog.isSequnceNumberValidation()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction.getState() != TransactionState.COMPLETED
                    && lastTransaction.getState() != TransactionState.TERMINATED
                    && lastTransaction.getState() != TransactionState.CONFIRMED) {

                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 500 response for out of sequence message");
                }
                this.sendServerInternalErrorResponse(sipRequest, transaction);
                return;

            }

            /*
             * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that
             * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in
             * progress MUST return a 491 (Request Pending) response to the received INVITE.
             */
            lastTransaction = (dialog == null ? null : dialog.getLastTransaction());

            if (dialog != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction != null
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ClientTransaction
                    && lastTransaction.getLastResponse() != null
                    && lastTransaction.getLastResponse().getStatusCode() == 200
                    && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq()
                            .getSeqNumber())) {
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 491 response for client Dialog ACK not sent.");
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;
            }

            if (dialog != null && lastTransaction != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ServerTransaction
                    /* && !dialog.isAckSeen() */
                    && lastTransaction.getState().equals(TransactionState.PROCEEDING)
                    ) {
              // Note that the completed state will be reached when we have sent an error
              // response and the terminated state will be reached when we have sent an OK
              // response. We do not need to wait till the ACK to be seen.
                if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 491 response for server Dialog ACK not seen.");
                    sipStack.getStackLogger().logDebug("Last SipResponse sent " + dialog.getLastResponse());
                   
                    sipStack.getStackLogger().logDebug("last Transaction state = " + lastTransaction + " state "+ lastTransaction.getState());
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;

            }
View Full Code Here

        if (!sipStack.isDialogCreated(transaction.getRequest().getMethod()))
            throw new SipException("Dialog cannot be created for this method "
                    + transaction.getRequest().getMethod());

        SIPDialog dialog = null;
        SIPTransaction sipTransaction = (SIPTransaction) transaction;

        if (transaction instanceof ServerTransaction) {
            SIPServerTransaction st = (SIPServerTransaction) transaction;
            Response response = st.getLastResponse();
            if (response != null) {
                if (response.getStatusCode() != 100)
                    throw new SipException(
                            "Cannot set dialog after response has been sent");
            }
            SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
            String dialogId = sipRequest.getDialogId(true);
            dialog = sipStack.getDialog(dialogId);
            if (dialog == null) {
                dialog = sipStack.createDialog((SIPTransaction) transaction);
                // create and register the dialog and add the inital route set.
                dialog.addTransaction(sipTransaction);
                dialog.addRoute(sipRequest);
                sipTransaction.setDialog(dialog, null);

            } else {
                sipTransaction.setDialog(dialog, sipRequest.getDialogId(true));
            }
            if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
                sipStack.putInMergeTable(st, sipRequest);
            }
        } else {
View Full Code Here

     * @param transactionErrorEvent
     *            Error event.
     */
    public void transactionErrorEvent(
            SIPTransactionErrorEvent transactionErrorEvent) {
        SIPTransaction transaction = (SIPTransaction) transactionErrorEvent
                .getSource();

        if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) {
            // There must be a way to inform the TU here!!
            if (sipStack.isLoggingEnabled(LogWriter.TRACE_DEBUG)) {
View Full Code Here

        if (!sipStack.isDialogCreated(transaction.getRequest().getMethod()))
            throw new SipException("Dialog cannot be created for this method "
                    + transaction.getRequest().getMethod());

        SIPDialog dialog = null;
        SIPTransaction sipTransaction = (SIPTransaction) transaction;

        if (transaction instanceof ServerTransaction) {
            SIPServerTransaction st = (SIPServerTransaction) transaction;
            Response response = st.getLastResponse();
            if (response != null) {
                if (response.getStatusCode() != 100)
                    throw new SipException(
                            "Cannot set dialog after response has been sent");
            }
            SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
            String dialogId = sipRequest.getDialogId(true);
            dialog = sipStack.getDialog(dialogId);
            if (dialog == null) {
                dialog = sipStack.createDialog((SIPTransaction) transaction);
                // create and register the dialog and add the inital route set.
                dialog.addTransaction(sipTransaction);
                dialog.addRoute(sipRequest);
                sipTransaction.setDialog(dialog, null);

            } else {
                sipTransaction.setDialog(dialog, sipRequest.getDialogId(true));
            }
            if (sipRequest.getMethod().equals(Request.INVITE) && this.isDialogErrorsAutomaticallyHandled()) {
                sipStack.putInMergeTable(st, sipRequest);
            }
        } else {
View Full Code Here

     * @param transactionErrorEvent
     *            Error event.
     */
    public void transactionErrorEvent(
            SIPTransactionErrorEvent transactionErrorEvent) {
        SIPTransaction transaction = (SIPTransaction) transactionErrorEvent
                .getSource();

        if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) {
            // There must be a way to inform the TU here!!
            if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
View Full Code Here

            /*
             * A refer cannot be processed until previous transaction has been
             * completed.
             */
            SIPTransaction lastTransaction = ((SIPDialog) dialog)
                    .getLastTransaction();
            if (lastTransaction != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()) {              
                final String lastTransactionMethod = lastTransaction.getMethod();
                if (lastTransaction instanceof SIPServerTransaction) {
                    if (lastTransaction.getInternalState() == TransactionState._PROCEEDING
                            && lastTransactionMethod.equals(Request.INVITE)) {
                        this
                                .sendRequestPendingResponse(sipRequest,
                                        transaction);
                        return;
                    }
                } else if (lastTransaction != null
                        && lastTransaction instanceof SIPClientTransaction) {
                    if (lastTransactionMethod.equals(Request.INVITE)
                            && lastTransaction.getInternalState() != TransactionState._TERMINATED
                            && lastTransaction.getInternalState() != TransactionState._COMPLETED) {
                        this
                                .sendRequestPendingResponse(sipRequest,
                                        transaction);
                        return;
                    }
                }
            }

        } else if (sipRequestMethod.equals(Request.UPDATE)) {
            /*
             * Got an UPDATE method and the user dialog does not exist and the
             * user wants to be a User agent.
             */
            if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
                this.sendCallOrTransactionDoesNotExistResponse(sipRequest,
                        transaction);
                return;
            }
        } else if (sipRequestMethod.equals(Request.ACK)) {

            if (transaction != null && transaction.isInviteTransaction()) {
                // This is an ack for a 3xx-6xx response. Just let the tx laer
                // take care of it.
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Processing ACK for INVITE Tx ");

            } else {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Processing ACK for dialog " + dialog);

                if (dialog == null) {
                    if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                        sipStack.getStackLogger().logDebug(
                                "Dialog does not exist "
                                        + sipRequest.getFirstLine()
                                        + " isServerTransaction = " + true);

                    }
                    SIPServerTransaction st = sipStack
                            .getRetransmissionAlertTransaction(dialogId);
                    if (st != null && st.isRetransmissionAlertEnabled()) {
                        st.disableRetransmissionAlerts();

                    }
                    /*
                     * JvB: must never drop ACKs that dont match a transaction!
                     * One cannot be sure if it isn't an ACK for a 2xx response
                     */
                    SIPServerTransaction ackTransaction = sipStack
                            .findTransactionPendingAck(sipRequest);
                    /*
                     * Found a transaction ( that we generated ) which is
                     * waiting for ACK. So ACK it and return.
                     */
                    if (ackTransaction != null) {
                        if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                            sipStack.getStackLogger().logDebug(
                                    "Found Tx pending ACK");
                        try {
                            ackTransaction.setAckSeen();
                            sipStack.removeTransaction(ackTransaction);
                            sipStack
                                    .removeTransactionPendingAck(ackTransaction);
                        } catch (Exception ex) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logError(
                                        "Problem terminating transaction", ex);
                            }
                        }
                        return;
                    }

                } else {
                    if (!dialog.handleAck(transaction)) {
                        if (!dialog.isSequnceNumberValidation()) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logDebug(
                                        "Dialog exists with loose dialog validation "
                                                + sipRequest.getFirstLine()
                                                + " isServerTransaction = "
                                                + true + " dialog = "
                                                + dialog.getDialogId());

                            }
                            SIPServerTransaction st = sipStack
                                    .getRetransmissionAlertTransaction(dialogId);                          
                            if (st != null && st.isRetransmissionAlertEnabled()) {
                              st.disableRetransmissionAlerts();

                            }
                            // Issue 319 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=319
                            // remove the pending ack to stop the transaction timer for transaction
                            // where the stack replied with a final error response.
                            SIPServerTransaction ackTransaction = sipStack
                                    .findTransactionPendingAck(sipRequest);
                            /*
                             * Found a transaction ( that we generated ) which is
                             * waiting for ACK. So ACK it and return.
                             */
                            if (ackTransaction != null) {
                                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                                    sipStack.getStackLogger().logDebug(
                                            "Found Tx pending ACK");
                                try {
                                    ackTransaction.setAckSeen();
                                    sipStack.removeTransaction(ackTransaction);
                                    sipStack
                                            .removeTransactionPendingAck(ackTransaction);
                                } catch (Exception ex) {
                                    if (sipStack.isLoggingEnabled()) {
                                        sipStack.getStackLogger().logError(
                                                "Problem terminating transaction", ex);
                                    }
                                }
                            }
                        } else {
                            if (sipStack
                                    .isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                                sipStack
                                        .getStackLogger()
                                        .logDebug(
                                                "Dropping ACK - cannot find a transaction or dialog");
                            }
                            SIPServerTransaction ackTransaction = sipStack
                                    .findTransactionPendingAck(sipRequest);
                            if (ackTransaction != null) {
                                if (sipStack.isLoggingEnabled())
                                    sipStack.getStackLogger().logDebug(
                                            "Found Tx pending ACK");
                                try {
                                    ackTransaction.setAckSeen();
                                    sipStack.removeTransaction(ackTransaction);
                                    sipStack
                                            .removeTransactionPendingAck(ackTransaction);
                                } catch (Exception ex) {
                                    if (sipStack.isLoggingEnabled()) {
                                        sipStack
                                                .getStackLogger()
                                                .logError(
                                                        "Problem terminating transaction",
                                                        ex);
                                    }
                                }
                            }
                            /*
                             * For test only we support a flag that will deliver
                             * retransmitted ACK for 200 OK responses to the
                             * listener.
                             */
                            if ((!sipStack
                                    .isDeliverRetransmittedAckToListener())
                                    || (ackTransaction != null && !sipStack
                                            .isNon2XXAckPassedToListener())) {
                                return;
                            }
                        }
                    } else {

                        dialog.addTransaction(transaction);
                        transaction.passToListener();
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                        if (sipRequest.getMethod().equals(Request.INVITE)
                                && sipProvider
                                        .isDialogErrorsAutomaticallyHandled()) {
                            sipStack.putInMergeTable(transaction, sipRequest);
                        }
                        /*
                         * Note that ACK is a pseudo transaction. It is never
                         * added to the stack and you do not get transaction
                         * terminated events on ACK.
                         */

                        if (sipStack.isDeliverTerminatedEventForAck()) {
                            try {
                                sipStack.addTransaction(transaction);
                                transaction.scheduleAckRemoval();
                            } catch (IOException ex) {

                            }
                        } else {
                            transaction.setMapped(true);
                        }

                    }
                }
            }
        } else if (sipRequestMethod.equals(Request.PRACK)) {

            /*
             * RFC 3262: A matching PRACK is defined as one within the same
             * dialog as the response, and whose method, CSeq-num, and
             * response-num in the RAck header field match, respectively, the
             * method from the CSeq, the sequence number from the CSeq, and the
             * sequence number from the RSeq of the reliable provisional
             * response.
             */

            if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                sipStack.getStackLogger().logDebug(
                        "Processing PRACK for dialog " + dialog);

            if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "Dialog does not exist "
                                    + sipRequest.getFirstLine()
                                    + " isServerTransaction = " + true);

                }
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
                }
                SIPResponse notExist = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);

                try {
                    sipProvider.sendResponse(notExist);
                } catch (SipException e) {
                    sipStack.getStackLogger().logError(
                            "error sending response", e);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            } else if (dialog != null) {
                if (!dialog.handlePrack(sipRequest)) {
                    if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                        sipStack.getStackLogger().logDebug(
                                "Dropping out of sequence PRACK ");
                    if (transaction != null) {
                        sipStack.removeTransaction(transaction);
                        transaction.releaseSem();
                    }
                    return;
                } else {
                    try {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                    } catch (Exception ex) {
                        InternalErrorHandler.handleException(ex);
                    }
                }
            } else {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Processing PRACK without a DIALOG -- this must be a proxy element");
            }

        } else if (sipRequestMethod.equals(Request.BYE)) {
            // Check for correct sequence numbering of the BYE
            if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Dropping out of sequence BYE "
                                    + dialog.getRemoteSeqNumber() + " "
                                    + sipRequest.getCSeq().getSeqNumber());

                if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq()
                        .getSeqNumber()
                        && transaction.getInternalState() == TransactionState._TRYING) {

                    this.sendServerInternalErrorResponse(sipRequest,
                            transaction);

                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null)
                    sipStack.removeTransaction(transaction);
                return;

            } else if (dialog == null
                    && sipProvider.isAutomaticDialogSupportEnabled()) {
                // Drop bye's with 481 if dialog does not exist.
                // If dialog support is enabled then
                // there must be a dialog associated with the bye
                // No dialog could be found and requests on this
                // provider. Must act like a user agent -- so drop the request.
                // NOTE: if Automatic dialog support is not enabled,
                // then it is the application's responsibility to
                // take care of this error condition possibly.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                response.setReasonPhrase("Dialog Not Found");

                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "dropping request -- automatic dialog "
                                            + "support enabled and dialog does not exist!");
                try {
                    transaction.sendResponse(response);
                } catch (SipException ex) {
                    sipStack.getStackLogger().logError(
                            "Error in sending response", ex);
                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                    transaction = null;
                }
                return;

            }

            // note that the transaction may be null (which
            // happens when no dialog for the bye was found.
            // and automatic dialog support is disabled (i.e. the app wants
            // to manage its own dialog layer.
            if (transaction != null && dialog != null) {
                try {
                    if (sipProvider == dialog.getSipProvider()) {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        transaction.setDialog(dialog, dialogId);
                    }

                } catch (IOException ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug(
                        "BYE Tx = " + transaction + " isMapped ="
                                + transaction.isTransactionMapped());
            }

        } else if (sipRequestMethod.equals(Request.CANCEL)) {

            SIPServerTransaction st = (SIPServerTransaction) sipStack
                    .findCancelTransaction(sipRequest, true);
            if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                sipStack.getStackLogger().logDebug(
                        "Got a CANCEL, InviteServerTx = " + st
                                + " cancel Server Tx ID = " + transaction
                                + " isMapped = "
                                + transaction.isTransactionMapped());

            }
            // Processing incoming CANCEL.
            // Check if we can process the CANCEL request.
            if (sipRequest.getMethod().equals(Request.CANCEL)) {
                // If the CANCEL comes in too late, there's not
                // much that the Listener can do so just do the
                // default action and avoid bothering the listener.
                if (st != null
                        && st.getInternalState() == TransactionState._TERMINATED) {
                    // If transaction already exists but it is
                    // too late to cancel the transaction then
                    // just respond OK to the CANCEL and bail.
                    if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                        sipStack.getStackLogger().logDebug(
                                "Too late to cancel Transaction");
                    // send OK and just ignore the CANCEL.
                    try {

                        transaction.sendResponse(sipRequest
                                .createResponse(Response.OK));
                    } catch (Exception ex) {
                        if (ex.getCause() != null
                                && ex.getCause() instanceof IOException) {
                            st.raiseIOExceptionEvent();
                        }
                    }
                    return;
                }
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Cancel transaction = " + st);

            }
            if (transaction != null && st != null && st.getDialog() != null) {
                // Found an invite tx corresponding to the CANCEL.
                // Set up the client tx and pass up to listener.
                transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
                dialog = (SIPDialog) st.getDialog();
            } else if (st == null
                    && sipProvider.isAutomaticDialogSupportEnabled()
                    && transaction != null) {
                // Could not find a invite tx corresponding to the CANCEL.
                // Automatic dialog support is enabled so I must behave like
                // an endpoint on this provider.
                // Send the error response for the cancel.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "dropping request -- automatic dialog support "
                                    + "enabled and INVITE ST does not exist!");
                }
                try {
                    sipProvider.sendResponse(response);
                } catch (SipException ex) {
                    InternalErrorHandler.handleException(ex);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            }

            // INVITE was handled statefully so the CANCEL must also be
            // statefully handled.
            if (st != null) {
                try {
                    if (transaction != null) {
                        sipStack.addTransaction(transaction);
                        transaction.setPassToListener();
                        transaction.setInviteTransaction(st);
                        // Dont let the INVITE and CANCEL be concurrently
                        // processed.
                        st.acquireSem();

                    }

                } catch (Exception ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
        } else if (sipRequestMethod.equals(Request.INVITE)) {
            SIPTransaction lastTransaction = dialog == null ? null : dialog
                    .getInviteTransaction();

            /*
             * RFC 3261 Chapter 14. A UAS that receives a second INVITE before
             * it sends the final response to a first INVITE with a lower CSeq
             * sequence number on the same dialog MUST return a 500 (Server
             * Internal Error) response to the second INVITE and MUST include a
             * Retry-After header field with a randomly chosen value of between
             * 0 and 10 seconds.
             */

            if (dialog != null
                    && transaction != null
                    && lastTransaction != null
                    && sipRequest.getCSeq().getSeqNumber() > dialog
                            .getRemoteSeqNumber()
                    && lastTransaction instanceof SIPServerTransaction
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && dialog.isSequnceNumberValidation()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction.getInternalState() != TransactionState._COMPLETED
                    && lastTransaction.getInternalState() != TransactionState._TERMINATED
                    && lastTransaction.getInternalState() != TransactionState._CONFIRMED) {

                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 500 response for out of sequence message");
                }
                this.sendServerInternalErrorResponse(sipRequest, transaction);
                return;

            }

            /*
             * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter
             * 14. A UAS that receives an INVITE on a dialog while an INVITE it
             * had sent on that dialog is in progress MUST return a 491 (Request
             * Pending) response to the received INVITE.
             */
            lastTransaction = (dialog == null ? null : dialog
                    .getLastTransaction());

            if (dialog != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction != null
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ClientTransaction
                    && lastTransaction.getLastResponse() != null
                    && lastTransaction.getLastResponse().getStatusCode() == 200
                    && !dialog.isAckSent(lastTransaction.getLastResponse()
                            .getCSeq().getSeqNumber())) {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 491 response for client Dialog ACK not sent.");
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;
            }

            if (dialog != null
                    && lastTransaction != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ServerTransaction
                    && lastTransaction.getInternalState() == TransactionState._PROCEEDING) {
                // Note that the completed state will be reached when we have
                // sent an error
                // response and the terminated state will be reached when we
                // have sent an OK
                // response. We do not need to wait till the ACK to be seen.
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 491 response. Last transaction is in PROCEEDING state.");
                    sipStack.getStackLogger().logDebug(
                            "last Transaction state = " + lastTransaction
                                    + " state " + lastTransaction.getState());
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;

            }
View Full Code Here

            /*
             * A refer cannot be processed until previous transaction has been
             * completed.
             */
            SIPTransaction lastTransaction = ((SIPDialog) dialog)
                    .getLastTransaction();
            if (lastTransaction != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()) {              
                final String lastTransactionMethod = lastTransaction.getMethod();
                if (lastTransaction instanceof SIPServerTransaction) {
                    // Handle Pseudo State Trying on Server Transaction
                    if ((lastTransaction.getInternalState() == TransactionState._PROCEEDING
                                    || lastTransaction.getInternalState() == TransactionState._TRYING)
                            && lastTransactionMethod.equals(Request.INVITE)) {
                        this
                                .sendRequestPendingResponse(sipRequest,
                                        transaction);
                        return;
                    }
                } else if (lastTransaction != null
                        && lastTransaction instanceof SIPClientTransaction) {
                    if (lastTransactionMethod.equals(Request.INVITE)
                            && lastTransaction.getInternalState() != TransactionState._TERMINATED
                            && lastTransaction.getInternalState() != TransactionState._COMPLETED) {
                        this
                                .sendRequestPendingResponse(sipRequest,
                                        transaction);
                        return;
                    }
                }
            }

        } else if (sipRequestMethod.equals(Request.UPDATE)) {
            /*
             * Got an UPDATE method and the user dialog does not exist and the
             * user wants to be a User agent.
             */
            if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
                this.sendCallOrTransactionDoesNotExistResponse(sipRequest,
                        transaction);
                return;
            }
        } else if (sipRequestMethod.equals(Request.ACK)) {

            if (transaction != null && transaction.isInviteTransaction()) {
                // This is an ack for a 3xx-6xx response. Just let the tx laer
                // take care of it.
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Processing ACK for INVITE Tx ");

            } else {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Processing ACK for dialog " + dialog);

                if (dialog == null) {
                    if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                        sipStack.getStackLogger().logDebug(
                                "Dialog does not exist "
                                        + sipRequest.getFirstLine()
                                        + " isServerTransaction = " + true);

                    }
                    SIPServerTransaction st = sipStack
                            .getRetransmissionAlertTransaction(dialogId);
                    if (st != null && st.isRetransmissionAlertEnabled()) {
                        st.disableRetransmissionAlerts();

                    }
                    /*
                     * JvB: must never drop ACKs that dont match a transaction!
                     * One cannot be sure if it isn't an ACK for a 2xx response
                     */
                    SIPServerTransaction ackTransaction = sipStack
                            .findTransactionPendingAck(sipRequest);
                    /*
                     * Found a transaction ( that we generated ) which is
                     * waiting for ACK. So ACK it and return.
                     */
                    if (ackTransaction != null) {
                        if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                            sipStack.getStackLogger().logDebug(
                                    "Found Tx pending ACK");
                        try {
                            ackTransaction.setAckSeen();
                            sipStack.removeTransaction(ackTransaction);
                            sipStack
                                    .removeTransactionPendingAck(ackTransaction);
                        } catch (Exception ex) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logError(
                                        "Problem terminating transaction", ex);
                            }
                        }
                        return;
                    }

                } else {
                    if (!dialog.handleAck(transaction)) {
                        if (!dialog.isSequnceNumberValidation()) {
                            if (sipStack.isLoggingEnabled()) {
                                sipStack.getStackLogger().logDebug(
                                        "Dialog exists with loose dialog validation "
                                                + sipRequest.getFirstLine()
                                                + " isServerTransaction = "
                                                + true + " dialog = "
                                                + dialog.getDialogId());

                            }
                            SIPServerTransaction st = sipStack
                                    .getRetransmissionAlertTransaction(dialogId);                          
                            if (st != null && st.isRetransmissionAlertEnabled()) {
                              st.disableRetransmissionAlerts();

                            }
                            // Issue 319 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=319
                            // remove the pending ack to stop the transaction timer for transaction
                            // where the stack replied with a final error response.
                            SIPServerTransaction ackTransaction = sipStack
                                    .findTransactionPendingAck(sipRequest);
                            /*
                             * Found a transaction ( that we generated ) which is
                             * waiting for ACK. So ACK it and return.
                             */
                            if (ackTransaction != null) {
                                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                                    sipStack.getStackLogger().logDebug(
                                            "Found Tx pending ACK");
                                try {
                                    ackTransaction.setAckSeen();
                                    sipStack.removeTransaction(ackTransaction);
                                    sipStack
                                            .removeTransactionPendingAck(ackTransaction);
                                } catch (Exception ex) {
                                    if (sipStack.isLoggingEnabled()) {
                                        sipStack.getStackLogger().logError(
                                                "Problem terminating transaction", ex);
                                    }
                                }
                            }
                        } else {
                            if (sipStack
                                    .isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                                sipStack
                                        .getStackLogger()
                                        .logDebug(
                                                "Dropping ACK - cannot find a transaction or dialog");
                            }
                            SIPServerTransaction ackTransaction = sipStack
                                    .findTransactionPendingAck(sipRequest);
                            if (ackTransaction != null) {
                                if (sipStack.isLoggingEnabled())
                                    sipStack.getStackLogger().logDebug(
                                            "Found Tx pending ACK");
                                try {
                                    ackTransaction.setAckSeen();
                                    sipStack.removeTransaction(ackTransaction);
                                    sipStack
                                            .removeTransactionPendingAck(ackTransaction);
                                } catch (Exception ex) {
                                    if (sipStack.isLoggingEnabled()) {
                                        sipStack
                                                .getStackLogger()
                                                .logError(
                                                        "Problem terminating transaction",
                                                        ex);
                                    }
                                }
                            }
                            /*
                             * For test only we support a flag that will deliver
                             * retransmitted ACK for 200 OK responses to the
                             * listener.
                             */
                            if ((!sipStack
                                    .isDeliverRetransmittedAckToListener())
                                    || (ackTransaction != null && !sipStack
                                            .isNon2XXAckPassedToListener())) {
                                return;
                            }
                        }
                    } else {

                        dialog.addTransaction(transaction);
                        transaction.passToListener();
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                        if (sipRequest.getMethod().equals(Request.INVITE)
                                && sipProvider
                                        .isDialogErrorsAutomaticallyHandled()) {
                            sipStack.putInMergeTable(transaction, sipRequest);
                        }
                        /*
                         * Note that ACK is a pseudo transaction. It is never
                         * added to the stack and you do not get transaction
                         * terminated events on ACK.
                         */

                        if (sipStack.isDeliverTerminatedEventForAck()) {
                            try {
                                sipStack.addTransaction(transaction);
                                transaction.scheduleAckRemoval();
                            } catch (IOException ex) {

                            }
                        } else {
                            transaction.setMapped(true);
                        }

                    }
                }
            }
        } else if (sipRequestMethod.equals(Request.PRACK)) {

            /*
             * RFC 3262: A matching PRACK is defined as one within the same
             * dialog as the response, and whose method, CSeq-num, and
             * response-num in the RAck header field match, respectively, the
             * method from the CSeq, the sequence number from the CSeq, and the
             * sequence number from the RSeq of the reliable provisional
             * response.
             */

            if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                sipStack.getStackLogger().logDebug(
                        "Processing PRACK for dialog " + dialog);

            if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
                if (sipStack.isLoggingEnabled()) {
                    sipStack.getStackLogger().logDebug(
                            "Dialog does not exist "
                                    + sipRequest.getFirstLine()
                                    + " isServerTransaction = " + true);

                }
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
                }
                SIPResponse notExist = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);

                try {
                    sipProvider.sendResponse(notExist);
                } catch (SipException e) {
                    sipStack.getStackLogger().logError(
                            "error sending response", e);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            } else if (dialog != null) {
                if (!dialog.handlePrack(sipRequest)) {
                    if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                        sipStack.getStackLogger().logDebug(
                                "Dropping out of sequence PRACK ");
                    if (transaction != null) {
                        sipStack.removeTransaction(transaction);
                        transaction.releaseSem();
                    }
                    return;
                } else {
                    try {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        dialog.addRoute(sipRequest);
                        transaction.setDialog(dialog, dialogId);
                    } catch (Exception ex) {
                        InternalErrorHandler.handleException(ex);
                    }
                }
            } else {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Processing PRACK without a DIALOG -- this must be a proxy element");
            }

        } else if (sipRequestMethod.equals(Request.BYE)) {
            // Check for correct sequence numbering of the BYE
            if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Dropping out of sequence BYE "
                                    + dialog.getRemoteSeqNumber() + " "
                                    + sipRequest.getCSeq().getSeqNumber());

                if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq()
                        .getSeqNumber()
                        && transaction.getInternalState() == TransactionState._TRYING) {

                    this.sendServerInternalErrorResponse(sipRequest,
                            transaction);

                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null)
                    sipStack.removeTransaction(transaction);
                return;

            } else if (dialog == null
                    && sipProvider.isAutomaticDialogSupportEnabled()) {
                // Drop bye's with 481 if dialog does not exist.
                // If dialog support is enabled then
                // there must be a dialog associated with the bye
                // No dialog could be found and requests on this
                // provider. Must act like a user agent -- so drop the request.
                // NOTE: if Automatic dialog support is not enabled,
                // then it is the application's responsibility to
                // take care of this error condition possibly.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                response.setReasonPhrase("Dialog Not Found");

                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "dropping request -- automatic dialog "
                                            + "support enabled and dialog does not exist!");
                try {
                    transaction.sendResponse(response);
                } catch (SipException ex) {
                    sipStack.getStackLogger().logError(
                            "Error in sending response", ex);
                }
                // If the stack knows about the tx, then remove it.
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                    transaction = null;
                }
                return;

            }

            // note that the transaction may be null (which
            // happens when no dialog for the bye was found.
            // and automatic dialog support is disabled (i.e. the app wants
            // to manage its own dialog layer.
            if (transaction != null && dialog != null) {
                try {
                    if (sipProvider == dialog.getSipProvider()) {
                        sipStack.addTransaction(transaction);
                        dialog.addTransaction(transaction);
                        transaction.setDialog(dialog, dialogId);
                    }

                } catch (IOException ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
            if (sipStack.isLoggingEnabled()) {
                sipStack.getStackLogger().logDebug(
                        "BYE Tx = " + transaction + " isMapped ="
                                + transaction.isTransactionMapped());
            }

        } else if (sipRequestMethod.equals(Request.CANCEL)) {

            SIPServerTransaction st = (SIPServerTransaction) sipStack
                    .findCancelTransaction(sipRequest, true);
            if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                sipStack.getStackLogger().logDebug(
                        "Got a CANCEL, InviteServerTx = " + st
                                + " cancel Server Tx ID = " + transaction
                                + " isMapped = "
                                + transaction.isTransactionMapped());

            }
            // Processing incoming CANCEL.
            // Check if we can process the CANCEL request.
            if (sipRequest.getMethod().equals(Request.CANCEL)) {
                // If the CANCEL comes in too late, there's not
                // much that the Listener can do so just do the
                // default action and avoid bothering the listener.
                if (st != null
                        && st.getInternalState() == TransactionState._TERMINATED) {
                    // If transaction already exists but it is
                    // too late to cancel the transaction then
                    // just respond OK to the CANCEL and bail.
                    if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                        sipStack.getStackLogger().logDebug(
                                "Too late to cancel Transaction");
                    // send OK and just ignore the CANCEL.
                    try {

                        transaction.sendResponse(sipRequest
                                .createResponse(Response.OK));
                    } catch (Exception ex) {
                        if (ex.getCause() != null
                                && ex.getCause() instanceof IOException) {
                            st.raiseIOExceptionEvent();
                        }
                    }
                    return;
                }
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG))
                    sipStack.getStackLogger().logDebug(
                            "Cancel transaction = " + st);

            }
            if (transaction != null && st != null && st.getDialog() != null) {
                // Found an invite tx corresponding to the CANCEL.
                // Set up the client tx and pass up to listener.
                transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
                dialog = (SIPDialog) st.getDialog();
            } else if (st == null
                    && sipProvider.isAutomaticDialogSupportEnabled()
                    && transaction != null) {
                // Could not find a invite tx corresponding to the CANCEL.
                // Automatic dialog support is enabled so I must behave like
                // an endpoint on this provider.
                // Send the error response for the cancel.

                SIPResponse response = sipRequest
                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "dropping request -- automatic dialog support "
                                    + "enabled and INVITE ST does not exist!");
                }
                try {
                    sipProvider.sendResponse(response);
                } catch (SipException ex) {
                    InternalErrorHandler.handleException(ex);
                }
                if (transaction != null) {
                    sipStack.removeTransaction(transaction);
                    transaction.releaseSem();
                }
                return;

            }

            // INVITE was handled statefully so the CANCEL must also be
            // statefully handled.
            if (st != null) {
                try {
                    if (transaction != null) {
                        sipStack.addTransaction(transaction);
                        transaction.setPassToListener();
                        transaction.setInviteTransaction(st);
                        // Dont let the INVITE and CANCEL be concurrently
                        // processed.
                        st.acquireSem();

                    }

                } catch (Exception ex) {
                    InternalErrorHandler.handleException(ex);
                }
            }
        } else if (sipRequestMethod.equals(Request.INVITE)) {
            SIPTransaction lastTransaction = dialog == null ? null : dialog
                    .getInviteTransaction();

            /*
             * RFC 3261 Chapter 14. A UAS that receives a second INVITE before
             * it sends the final response to a first INVITE with a lower CSeq
             * sequence number on the same dialog MUST return a 500 (Server
             * Internal Error) response to the second INVITE and MUST include a
             * Retry-After header field with a randomly chosen value of between
             * 0 and 10 seconds.
             */

            if (dialog != null
                    && transaction != null
                    && lastTransaction != null
                    && sipRequest.getCSeq().getSeqNumber() > dialog
                            .getRemoteSeqNumber()
                    && lastTransaction instanceof SIPServerTransaction
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && dialog.isSequnceNumberValidation()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction.getInternalState() != TransactionState._COMPLETED
                    && lastTransaction.getInternalState() != TransactionState._TERMINATED
                    && lastTransaction.getInternalState() != TransactionState._CONFIRMED) {

                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack.getStackLogger().logDebug(
                            "Sending 500 response for out of sequence message");
                }
                this.sendServerInternalErrorResponse(sipRequest, transaction);
                return;

            }

            /*
             * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter
             * 14. A UAS that receives an INVITE on a dialog while an INVITE it
             * had sent on that dialog is in progress MUST return a 491 (Request
             * Pending) response to the received INVITE.
             */
            lastTransaction = (dialog == null ? null : dialog
                    .getLastTransaction());

            if (dialog != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction != null
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ClientTransaction
                    && lastTransaction.getLastResponse() != null
                    && lastTransaction.getLastResponse().getStatusCode() == 200
                    && !dialog.isAckSent(lastTransaction.getLastResponse()
                            .getCSeq().getSeqNumber())) {
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 491 response for client Dialog ACK not sent.");
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;
            }

            if (dialog != null
                    && lastTransaction != null
                    && sipProvider.isDialogErrorsAutomaticallyHandled()
                    && lastTransaction.isInviteTransaction()
                    && lastTransaction instanceof ServerTransaction
                    // Handle Pseudo State Trying on Server Transaction
                    && (lastTransaction.getInternalState() == TransactionState._PROCEEDING
                                    || lastTransaction.getInternalState() == TransactionState._TRYING)) {
                // Note that the completed state will be reached when we have
                // sent an error
                // response and the terminated state will be reached when we
                // have sent an OK
                // response. We do not need to wait till the ACK to be seen.
                if (sipStack.isLoggingEnabled(LogLevels.TRACE_DEBUG)) {
                    sipStack
                            .getStackLogger()
                            .logDebug(
                                    "Sending 491 response. Last transaction is in PROCEEDING state.");
                    sipStack.getStackLogger().logDebug(
                            "last Transaction state = " + lastTransaction
                                    + " state " + lastTransaction.getState());
                }
                this.sendRequestPendingResponse(sipRequest, transaction);
                return;

            }
View Full Code Here

    if (!sipStack.isDialogCreated(transaction.getRequest().getMethod()))
      throw new SipException("Dialog cannot be created for this method "
          + transaction.getRequest().getMethod());

    SIPDialog dialog = null;
    SIPTransaction sipTransaction = (SIPTransaction) transaction;

    if (transaction instanceof ServerTransaction) {
      SIPServerTransaction st = (SIPServerTransaction) transaction;
      Response response = st.getLastResponse();
      if (response != null) {
        if (response.getStatusCode() != 100)
          throw new SipException(
              "Cannot set dialog after response has been sent");
      }
      SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
      String dialogId = sipRequest.getDialogId(true);
      dialog = sipStack.getDialog(dialogId);
      if (dialog == null) {
        dialog = sipStack.createDialog((SIPTransaction) transaction);
        // create and register the dialog and add the inital route set.
        dialog.addTransaction(sipTransaction);
        dialog.addRoute(sipRequest);
        sipTransaction.setDialog(dialog, null);

      } else {
        sipTransaction.setDialog(dialog, sipRequest.getDialogId(true));
      }
      if (sipStack.isDialogCreated(sipRequest.getMethod())) {
        sipStack.putInMergeTable(st, sipRequest);
      }
    } else {
View Full Code Here

   * @param transactionErrorEvent
   *            Error event.
   */
  public void transactionErrorEvent(
      SIPTransactionErrorEvent transactionErrorEvent) {
    SIPTransaction transaction = (SIPTransaction) transactionErrorEvent
        .getSource();

    if (transactionErrorEvent.getErrorID() == SIPTransactionErrorEvent.TRANSPORT_ERROR) {
      // There must be a way to inform the TU here!!
      if (sipStack.isLoggingEnabled()) {
View Full Code Here

TOP

Related Classes of gov.nist.javax.sip.stack.SIPTransaction$LingerTimer

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.