&& lastTransaction.getState() != TransactionState.COMPLETED
    public void processRequest(SIPRequest sipRequest,            MessageChannel incomingMessageChannel) {        // Generate the wrapper JAIN-SIP object.        if (LogWriter.needsLogging)            sipStackImpl.logMessage("PROCESSING INCOMING REQUEST "                    + sipRequest.getFirstLine());        if (listeningPoint == null) {            if (LogWriter.needsLogging)                sipStackImpl                        .logMessage("Dropping message: No listening point registered!");            return;        }        SIPTransactionStack sipStack = (SIPTransactionStack) transactionChannel                .getSIPStack();        gov.nist.javax.sip.SipStackImpl sipStackImpl = (SipStackImpl) sipStack;        SipProviderImpl sipProvider = listeningPoint.getProvider();        if (sipProvider == null) {            if (LogWriter.needsLogging)                sipStackImpl.logMessage("No provider - dropping !!");            return;        }        SipListener sipListener = sipProvider.sipListener;        // Section 16.4 If the first value in the Route header        // field indicates this proxy,the proxy MUST remove that        // value from the request . Note: Bill Roome from AT&T        // noted that it may be necessary for the route header        // to be passed up to the application as the application        // may wish to extract some information from it. Thus        // a new configuration parameter was added.        if (sipRequest.getHeader(Route.NAME) != null                && sipStackImpl.stripRouteHeader) {            RouteList routes = sipRequest.getRouteHeaders();            Route route = (Route) routes.getFirst();            SipUri uri = (SipUri) route.getAddress().getURI();            int port;            if (uri.getHostPort().hasPort()) {                port = uri.getHostPort().getPort();            } else {                port = 5060;            }            String host = uri.getHost();            if (host.equals(listeningPoint.getHost())                    && port == listeningPoint.getPort()) {                if (routes.size() == 1)                    sipRequest.removeHeader(Route.NAME);                else                    routes.removeFirst();            }        }        SIPTransaction transaction = transactionChannel;        // Look for the registered SIPListener for the message channel.        // Removed unnecessary synchronization        // bug reported by John Martin.        if (sipRequest.getMethod().equalsIgnoreCase(Request.ACK)) {            // Could not find transaction. Generate an event            // with a null transaction identifier.            String dialogId = sipRequest.getDialogId(true);            SIPDialog dialog = sipStackImpl.getDialog(dialogId);            if (LogWriter.needsLogging)                sipStackImpl.logMessage("Processing ACK for dialog " + dialog);            if (dialog == null) {                if (LogWriter.needsLogging) {                    sipStackImpl.logMessage("Dialog does not exist "                            + sipRequest.getFirstLine()                            + " isServerTransaction = " + true);                }                // Bug reported by Antonis Karydas                transaction = sipStackImpl.findTransaction(sipRequest, true);            } else if (dialog.isAckSeen() &&                dialog.getRemoteSequenceNumber() == 		sipRequest.getCSeq().getSequenceNumber()) {                if (sipStackImpl.isRetransmissionFilterActive()) {                    if (LogWriter.needsLogging) {                        sipStackImpl                         .logMessage			("Retransmission Filter enabled - dropping Ack"                           + " retransmission");                    }                    return;                }                if (LogWriter.needsLogging)                    sipStackImpl                            .logMessage("ACK retransmission for 2XX response "                                    + "Sending ACK to the TU");                transaction.setDialog(dialog);            } else {                // This could be a re-invite processing.                // check to see if the ack matches with the last                // transaction.                SIPServerTransaction tr = dialog.getInviteTransaction();                SIPResponse sipResponse = (tr != null ? tr.getLastResponse()                        : null);                // Idiot check for sending ACK from the wrong side!                if (tr != null                        && sipResponse != null                        && sipResponse.getStatusCode() / 100 == 2                        && sipResponse.getCSeq().getMethod().equals(                                Request.INVITE)                        && sipResponse.getCSeq().getSequenceNumber() == sipRequest                                .getCSeq().getSequenceNumber()) {                    transaction.setDialog(dialog);                    // record that we already saw an ACK for                    // this dialog.                    dialog.ackReceived(sipRequest);                    sipStackImpl                            .logMessage("ACK for 2XX response --- sending to TU ");                } else {                    // This happens when the ACK is re-transmitted and arrives                    // too late                    // to be processed.                    if (LogWriter.needsLogging)                        sipStackImpl                                .logMessage(" INVITE transaction not found  -- Discarding ACK");                    return;                }            }        } else if (sipRequest.getMethod().equals(Request.BYE)) {            transaction = this.transactionChannel;            // If the stack has not mapped this transaction because            // of sequence number problem then just drop the BYE            if (transaction != null                    && ((SIPServerTransaction) transaction)                            .isTransactionMapped()) {                // Get the dialog identifier for the bye request.                String dialogId = sipRequest.getDialogId(true);                if (LogWriter.needsLogging)                    sipStackImpl.logMessage("dialogId = " + dialogId);                SIPDialog dialog = sipStackImpl.getDialog(dialogId);                if (dialog != null) {                    // check if request is in dialog sequence.                    if (dialog.isRequestConsumable(sipRequest)) {                        dialog.addTransaction(transaction);                    } else {                        // Remove the previously created transaction.                        //transaction.setState(TransactionState.TERMINATED);                        sipStack.removeTransaction(transaction);                        if (LogWriter.needsLogging)                            sipStackImpl.logMessage("Dropping bye  for "                                    + dialogId);                        return;                    }                }            } else if (transaction != null) {                // This is an out of sequence BYE                // transaction was allocated but                // not mapped to the stack so                // just discard it.                String dialogId = sipRequest.getDialogId(true);                SIPDialog dialog = sipStack.getDialog(dialogId);                if (dialog != null) {                    if (LogWriter.needsLogging)                        sipStackImpl.logMessage("Dropping out of sequence BYE");                    return;                } else if (sipStackImpl.dialogSupport) {                    // If dialog support is enabled then                    // there must be a dialog associated with the bye                    transaction = null;                }            }            // note that the transaction may be null (which            // happens when no dialog for the bye was fund.        } else if (sipRequest.getRequestLine().getMethod().equals(                Request.CANCEL)) {            // The ID refers to a previously sent            // INVITE therefore it refers to the            // server transaction table.            // Bug reported by Andreas Bystr�m            // Find the transaction to cancel.            // Send a 487 for the cancel to inform the            // other side that we've seen it but do not send the            // request up to the application layer.            // Get rid of the CANCEL transaction -- we pass the            // transaciton we are trying to cancel up to the TU.            // Antonis Karydas: Suggestion            // 'transaction' here refers to the transaction to            // be cancelled. Do not change            // it's state because of the CANCEL.            // Wait, instead for the 487 from TU.            // transaction.setState(SIPTransaction.TERMINATED_STATE);            SIPServerTransaction serverTransaction = (SIPServerTransaction) sipStack                    .findCancelTransaction(sipRequest, true);            // Generate an event            // with a null transaction identifier.            if (serverTransaction == null) {                // Could not find the invite transaction.                if (LogWriter.needsLogging) {                    sipStackImpl.logMessage("transaction " + " does not exist "                            + sipRequest.getFirstLine()                            + "isServerTransaction = " + true);                }                transaction = null;            } else {                transaction = serverTransaction;            }        } else if (sipRequest.getMethod().equals(Request.INVITE)) {            String dialogId = sipRequest.getDialogId(true);            SIPDialog dialog = sipStack.getDialog(dialogId);            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().getSequenceNumber() > dialog                            .getRemoteSequenceNumber()                    && lastTransaction instanceof SIPServerTransaction                    && lastTransaction.isInviteTransaction()                    && lastTransaction.getState() != TransactionState.COMPLETED                    && lastTransaction.getState() != TransactionState.TERMINATED                    && lastTransaction.getState() != TransactionState.CONFIRMED) {                if (LogWriter.needsLogging)                    sipStackImpl                            .logMessage("Sending 500 response for out of sequence message");                SIPResponse sipResponse = sipRequest                        .createResponse(Response.SERVER_INTERNAL_ERROR);                RetryAfter retryAfter = new RetryAfter();                try {                    retryAfter.setRetryAfter((int) (10 * Math.random()));                } catch (InvalidArgumentException ex) {                    ex.printStackTrace();                }                sipResponse.addHeader(retryAfter);                try {                    transaction.sendMessage(sipResponse);                } catch (IOException ex) {                    // Ignore.                }                return;            }            // 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                    && dialog.getLastTransaction() != null                    && lastTransaction.isInviteTransaction()                    && lastTransaction instanceof SIPClientTransaction                    && lastTransaction.getState() != TransactionState.TERMINATED) {                if (LogWriter.needsLogging)                    sipStackImpl                            .logMessage("Sending 491 response for out of sequence message");                SIPResponse sipResponse = sipRequest                        .createResponse(Response.REQUEST_PENDING);                try {                    transaction.sendMessage(sipResponse);                } catch (IOException ex) {                    // Ignore.                }                return;            }        }        if (LogWriter.needsLogging) {            sipStackImpl.logMessage("-----------------");            sipStackImpl.logMessage(sipRequest.encodeMessage());        }        // If the transaction is found then it is already managed so        // dont call the listener.        String dialogId = sipRequest.getDialogId(true);        SIPDialog dialog = sipStackImpl.getDialog(dialogId);        // Sequence numbers are supposed to be incremented        // sequentially within a dialog for RFC 3261        // Note BYE is handled above - so no check here.        if (dialog != null && transaction != null                && !sipRequest.getMethod().equals(Request.BYE)                && !sipRequest.getMethod().equals(Request.CANCEL)                && !sipRequest.getMethod().equals(Request.ACK)) {            if (dialog.getRemoteSequenceNumber() >= sipRequest.getCSeq()                    .getSequenceNumber()) {                if (LogWriter.needsLogging) {                    sipStackImpl.logMessage("Dropping out of sequence message "                            + dialog.getRemoteSequenceNumber() + " "                            + sipRequest.getCSeq());                }                // "UAS Behavior" section (12.2.2):                // If the remote sequence number was not empty, but the sequence                // number                // of the request is lower than the remote sequence number, the                // request                // is out of order and MUST be rejected with a 500 (Server                // Internal                // Error) response.                // This is rather strange because the error is on the side of                // the                // client and not the server but thats what the spec says....                if (dialog.getRemoteSequenceNumber() > sipRequest.getCSeq()                        .getSequenceNumber()) {                    if (LogWriter.needsLogging)                        sipStackImpl                                .logMessage("Sending 500 response for out of sequence message");                    SIPResponse sipResponse = sipRequest                            .createResponse(Response.SERVER_INTERNAL_ERROR);                    try {                        transaction.sendMessage(sipResponse);                    } catch (IOException ex) {                        // Ignore.                    }                }                return;            } else if (!dialog.isRequestConsumable(sipRequest)) {                // Bug noticed by Bruce Evangelder. Spec Section 12.2.1                // Check if sequence number of the request allows it to be                // consumed.                // Requests within a dialog MUST contain strictly monotonically                // increasing and contiguous CSeq sequence numbers                // (increasing-by-one)                // in each direction (excepting ACK and CANCEL of course, whose                // numbers                // equal the requests being acknowledged or cancelled).                // For efficient processing put in the pending queue                // and re-process later. It would be equally valid to drop here.               /*                * There's a bug with this optimization so I have removed it for now. Ranga                * Experiment here if you want to re-enable this optimization.                if (LogWriter.needsLogging)                    sipStackImpl                            .logMessage("sequence number is too large - putting pending!");                this.pendingRequest = sipRequest;                this.pendingMessageChannel = incomingMessageChannel;                dialog.putPending(this, sipRequest.getCSeq()                        .getSequenceNumber());               */                return;            }            // This will set the remote sequence number.            dialog.addTransaction(transaction);            dialog.addRoute(sipRequest);        }        RequestEvent sipEvent;        if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) {            SIPClientTransaction ct = sipStack                    .findSubscribeTransaction(sipRequest);            // From RFC 3265            // If the server transaction cannot be found or if it            // aleady has a dialog attached to it then just assign the            // notify to this dialog and pass it up.            if (ct != null) {                transaction.setDialog((SIPDialog) ct.getDialog());                if (ct.getDialog().getState() == null) {                    sipEvent = new RequestEvent(sipProvider, null,                            (Request) sipRequest);                } else {                    sipEvent = new RequestEvent((SipProvider) sipProvider,                            (ServerTransaction) transaction,                            (Request) sipRequest);                }            } else {                // Got a notify out of the blue - just pass it up                // for stateless handling by the application.                sipEvent = new RequestEvent(sipProvider, null,                        (Request) sipRequest);            }        } else {            // For a dialog creating event - set the transaction to null.            // The listener can create the dialog if needed.            if (transaction != null                    && ((SIPServerTransaction) transaction)                            .isTransactionMapped())                sipEvent = new RequestEvent(sipProvider,                        (ServerTransaction) transaction, (Request) sipRequest);            else                sipEvent = new RequestEvent(sipProvider, null,                        (Request) sipRequest);        }        sipProvider.handleEvent(sipEvent, transaction);    }