1/*
2 * Conditions Of Use
3 *
4 * This software was developed by employees of the National Institute of
5 * Standards and Technology (NIST), an agency of the Federal Government.
6 * Pursuant to title 15 Untied States Code Section 105, works of NIST
7 * employees are not subject to copyright protection in the United States
8 * and are considered to be in the public domain.  As a result, a formal
9 * license is not needed to use the software.
10 *
11 * This software is provided by NIST as a service and is expressly
12 * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13 * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15 * AND DATA ACCURACY.  NIST does not warrant or make any representations
16 * regarding the use of the software or the results thereof, including but
17 * not limited to the correctness, accuracy, reliability or usefulness of
18 * the software.
19 *
20 * Permission to use this software is contingent upon your acceptance
21 * of the terms of this agreement
22 *
23 * .
24 *
25 */
26/******************************************************************************
27 * Product of NIST/ITL Advanced Networking Technologies Division (ANTD).      *
28 ******************************************************************************/
29package gov.nist.javax.sip;
30
31import gov.nist.core.InternalErrorHandler;
32import gov.nist.javax.sip.address.SipUri;
33import gov.nist.javax.sip.header.Contact;
34import gov.nist.javax.sip.header.Event;
35import gov.nist.javax.sip.header.ReferTo;
36import gov.nist.javax.sip.header.RetryAfter;
37import gov.nist.javax.sip.header.Route;
38import gov.nist.javax.sip.header.RouteList;
39import gov.nist.javax.sip.header.Server;
40import gov.nist.javax.sip.message.MessageFactoryImpl;
41import gov.nist.javax.sip.message.SIPRequest;
42import gov.nist.javax.sip.message.SIPResponse;
43import gov.nist.javax.sip.stack.MessageChannel;
44import gov.nist.javax.sip.stack.SIPClientTransaction;
45import gov.nist.javax.sip.stack.SIPDialog;
46import gov.nist.javax.sip.stack.SIPServerTransaction;
47import gov.nist.javax.sip.stack.SIPTransaction;
48import gov.nist.javax.sip.stack.ServerRequestInterface;
49import gov.nist.javax.sip.stack.ServerResponseInterface;
50
51import java.io.IOException;
52import java.util.TimerTask;
53
54import javax.sip.ClientTransaction;
55import javax.sip.DialogState;
56import javax.sip.InvalidArgumentException;
57import javax.sip.ObjectInUseException;
58import javax.sip.RequestEvent;
59import javax.sip.ResponseEvent;
60import javax.sip.ServerTransaction;
61import javax.sip.SipException;
62import javax.sip.SipProvider;
63import javax.sip.TransactionState;
64import javax.sip.header.CSeqHeader;
65import javax.sip.header.EventHeader;
66import javax.sip.header.ReferToHeader;
67import javax.sip.header.ServerHeader;
68import javax.sip.message.Request;
69import javax.sip.message.Response;
70
71/*
72 * Bug fix Contributions by Lamine Brahimi, Andreas Bystrom, Bill Roome, John Martin, Daniel
73 * Machin Vasquez-Illa, Antonis Karydas, Joe Provino, Bruce Evangelder, Jeroen van Bemmel, Robert
74 * S. Rosen.
75 */
76/**
77 * An adapter class from the JAIN implementation objects to the NIST-SIP stack. The primary
78 * purpose of this class is to do early rejection of bad messages and deliver meaningful messages
79 * to the application. This class is essentially a Dialog filter. It is a helper for the UAC Core.
80 * It checks for and rejects requests and responses which may be filtered out because of sequence
81 * number, Dialog not found, etc. Note that this is not part of the JAIN-SIP spec (it does not
82 * implement a JAIN-SIP interface). This is part of the glue that ties together the NIST-SIP stack
83 * and event model with the JAIN-SIP stack. This is strictly an implementation class.
84 *
85 * @version 1.2 $Revision: 1.64 $ $Date: 2010/01/14 18:58:30 $
86 *
87 * @author M. Ranganathan
88 */
89class DialogFilter implements ServerRequestInterface, ServerResponseInterface {
90
91    protected SIPTransaction transactionChannel;
92
93    protected ListeningPointImpl listeningPoint;
94
95    private SipStackImpl sipStack;
96
97    public DialogFilter(SipStackImpl sipStack) {
98        this.sipStack = sipStack;
99
100    }
101
102    /**
103     * Send back a Request Pending response.
104     *
105     * @param sipRequest
106     * @param transaction
107     */
108    private void sendRequestPendingResponse(SIPRequest sipRequest,
109            SIPServerTransaction transaction) {
110        SIPResponse sipResponse = sipRequest.createResponse(Response.REQUEST_PENDING);
111        ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
112        if (serverHeader != null) {
113            sipResponse.setHeader(serverHeader);
114        }
115        try {
116            RetryAfter retryAfter = new RetryAfter();
117            retryAfter.setRetryAfter(1);
118            sipResponse.setHeader(retryAfter);
119            if (sipRequest.getMethod().equals(Request.INVITE)) {
120                sipStack.addTransactionPendingAck(transaction);
121            }
122            transaction.sendResponse(sipResponse);
123            transaction.releaseSem();
124        } catch (Exception ex) {
125            sipStack.getStackLogger().logError("Problem sending error response", ex);
126            transaction.releaseSem();
127            sipStack.removeTransaction(transaction);
128        }
129    }
130
131    /**
132     * Send a BAD REQUEST response.
133     *
134     * @param sipRequest
135     * @param transaction
136     * @param reasonPhrase
137     */
138
139    private void sendBadRequestResponse(SIPRequest sipRequest, SIPServerTransaction transaction,
140            String reasonPhrase) {
141        SIPResponse sipResponse = sipRequest.createResponse(Response.BAD_REQUEST);
142        if (reasonPhrase != null)
143            sipResponse.setReasonPhrase(reasonPhrase);
144        ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
145        if (serverHeader != null) {
146            sipResponse.setHeader(serverHeader);
147        }
148        try {
149            if (sipRequest.getMethod().equals(Request.INVITE)) {
150                sipStack.addTransactionPendingAck(transaction);
151            }
152            transaction.sendResponse(sipResponse);
153            transaction.releaseSem();
154        } catch (Exception ex) {
155            sipStack.getStackLogger().logError("Problem sending error response", ex);
156            transaction.releaseSem();
157            sipStack.removeTransaction(transaction);
158
159        }
160    }
161
162    /**
163     * Send a CALL OR TRANSACTION DOES NOT EXIST response.
164     *
165     * @param sipRequest
166     * @param transaction
167     */
168
169    private void sendCallOrTransactionDoesNotExistResponse(SIPRequest sipRequest,
170            SIPServerTransaction transaction) {
171
172        SIPResponse sipResponse = sipRequest
173                .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
174
175        ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
176        if (serverHeader != null) {
177            sipResponse.setHeader(serverHeader);
178        }
179        try {
180            if (sipRequest.getMethod().equals(Request.INVITE)) {
181                sipStack.addTransactionPendingAck(transaction);
182            }
183            transaction.sendResponse(sipResponse);
184            transaction.releaseSem();
185        } catch (Exception ex) {
186            sipStack.getStackLogger().logError("Problem sending error response", ex);
187            transaction.releaseSem();
188            sipStack.removeTransaction(transaction);
189
190        }
191
192    }
193
194    /**
195     * Send back a LOOP Detected Response.
196     *
197     * @param sipRequest
198     * @param transaction
199     *
200     */
201    private void sendLoopDetectedResponse(SIPRequest sipRequest, SIPServerTransaction transaction) {
202        SIPResponse sipResponse = sipRequest.createResponse(Response.LOOP_DETECTED);
203
204        ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
205        if (serverHeader != null) {
206            sipResponse.setHeader(serverHeader);
207        }
208        try {
209            sipStack.addTransactionPendingAck(transaction);
210            transaction.sendResponse(sipResponse);
211            transaction.releaseSem();
212        } catch (Exception ex) {
213            sipStack.getStackLogger().logError("Problem sending error response", ex);
214            transaction.releaseSem();
215            sipStack.removeTransaction(transaction);
216
217        }
218
219    }
220
221    /**
222     * Send back an error Response.
223     *
224     * @param sipRequest
225     * @param transaction
226     */
227
228    private void sendServerInternalErrorResponse(SIPRequest sipRequest,
229            SIPServerTransaction transaction) {
230        if (sipStack.isLoggingEnabled())
231            sipStack.getStackLogger()
232                    .logDebug("Sending 500 response for out of sequence message");
233        SIPResponse sipResponse = sipRequest.createResponse(Response.SERVER_INTERNAL_ERROR);
234        sipResponse.setReasonPhrase("Request out of order");
235        if (MessageFactoryImpl.getDefaultServerHeader() != null) {
236            ServerHeader serverHeader = MessageFactoryImpl.getDefaultServerHeader();
237            sipResponse.setHeader(serverHeader);
238        }
239
240        try {
241            RetryAfter retryAfter = new RetryAfter();
242            retryAfter.setRetryAfter(10);
243            sipResponse.setHeader(retryAfter);
244            sipStack.addTransactionPendingAck(transaction);
245            transaction.sendResponse(sipResponse);
246            transaction.releaseSem();
247        } catch (Exception ex) {
248            sipStack.getStackLogger().logError("Problem sending response", ex);
249            transaction.releaseSem();
250            sipStack.removeTransaction(transaction);
251        }
252    }
253
254    /**
255     * Process a request. Check for various conditions in the dialog that can result in the
256     * message being dropped. Possibly return errors for these conditions.
257     *
258     * @exception SIPServerException is thrown when there is an error processing the request.
259     */
260    public void processRequest(SIPRequest sipRequest, MessageChannel incomingMessageChannel) {
261        // Generate the wrapper JAIN-SIP object.
262        if (sipStack.isLoggingEnabled())
263            sipStack.getStackLogger().logDebug(
264                    "PROCESSING INCOMING REQUEST " + sipRequest + " transactionChannel = "
265                            + transactionChannel + " listening point = "
266                            + listeningPoint.getIPAddress() + ":" + listeningPoint.getPort());
267        if (listeningPoint == null) {
268            if (sipStack.isLoggingEnabled())
269                sipStack.getStackLogger().logDebug(
270                        "Dropping message: No listening point registered!");
271            return;
272        }
273
274        SipStackImpl sipStack = (SipStackImpl) transactionChannel.getSIPStack();
275
276        SipProviderImpl sipProvider = listeningPoint.getProvider();
277        if (sipProvider == null) {
278            if (sipStack.isLoggingEnabled())
279                sipStack.getStackLogger().logDebug("No provider - dropping !!");
280            return;
281        }
282
283        if (sipStack == null)
284            InternalErrorHandler.handleException("Egads! no sip stack!");
285
286        // Look for the registered SIPListener for the message channel.
287
288        SIPServerTransaction transaction = (SIPServerTransaction) this.transactionChannel;
289        if (transaction != null) {
290            if (sipStack.isLoggingEnabled())
291                sipStack.getStackLogger().logDebug(
292                        "transaction state = " + transaction.getState());
293        }
294        String dialogId = sipRequest.getDialogId(true);
295        SIPDialog dialog = sipStack.getDialog(dialogId);
296        /*
297         * Check if we got this request on the contact address of the dialog If not the dialog
298         * does not belong to this request. We check this condition if a contact address has been
299         * assigned to the dialog. Forgive the sins of B2BUA's that like to record route ACK's
300         */
301        if (dialog != null && sipProvider != dialog.getSipProvider()) {
302            Contact contact = dialog.getMyContactHeader();
303            if (contact != null) {
304                SipUri contactUri = (SipUri) (contact.getAddress().getURI());
305                String ipAddress = contactUri.getHost();
306                int contactPort = contactUri.getPort();
307                String contactTransport = contactUri.getTransportParam();
308                if (contactTransport == null)
309                    contactTransport = "udp";
310                if (contactPort == -1) {
311                    if (contactTransport.equals("udp") || contactTransport.equals("tcp"))
312                        contactPort = 5060;
313                    else
314                        contactPort = 5061;
315                }
316                // Check if the dialog contact is the same as the provider on
317                // which we got the request. Otherwise, dont assign this
318                // dialog to the request.
319                if (ipAddress != null
320                        && (!ipAddress.equals(listeningPoint.getIPAddress()) || contactPort != listeningPoint
321                                .getPort())) {
322                    if (sipStack.isLoggingEnabled()) {
323                        sipStack.getStackLogger().logDebug(
324                                "nulling dialog -- listening point mismatch!  " + contactPort
325                                        + "  lp port = " + listeningPoint.getPort());
326
327                    }
328                    dialog = null;
329                }
330
331            }
332        }
333
334        /*
335         * RFC 3261 8.2.2.2 Merged requests: If the request has no tag in the To header field, the
336         * UAS core MUST check the request against ongoing transactions. If the From tag, Call-ID,
337         * and CSeq exactly match those associated with an ongoing transaction, but the request
338         * does not match that transaction (based on the matching rules in Section 17.2.3), the
339         * UAS core SHOULD generate a 482 (Loop Detected) response and pass it to the server
340         * transaction. This support is only enabled when the stack has been instructed to
341         * function with Automatic Dialog Support.
342         */
343        if (sipProvider.isAutomaticDialogSupportEnabled()
344                && sipProvider.isDialogErrorsAutomaticallyHandled()
345                && sipRequest.getToTag() == null) {
346            SIPServerTransaction sipServerTransaction = sipStack
347                    .findMergedTransaction(sipRequest);
348            if (sipServerTransaction != null) {
349                this.sendLoopDetectedResponse(sipRequest, transaction);
350                return;
351            }
352        }
353
354        if (sipStack.isLoggingEnabled()) {
355            sipStack.getStackLogger().logDebug("dialogId = " + dialogId);
356            sipStack.getStackLogger().logDebug("dialog = " + dialog);
357        }
358
359        /*
360         * RFC 3261 Section 16.4 If the first value in the Route header field indicates this
361         * proxy,the proxy MUST remove that value from the request .
362         */
363
364        // If the message is being processed
365        // by a Proxy, then the proxy will take care of stripping the
366        // Route header. If the request is being processed by an
367        // endpoint, then the stack strips off the route header.
368        if (sipRequest.getHeader(Route.NAME) != null && transaction.getDialog() != null) {
369            RouteList routes = sipRequest.getRouteHeaders();
370            Route route = (Route) routes.getFirst();
371            SipUri uri = (SipUri) route.getAddress().getURI();
372            int port;
373            if (uri.getHostPort().hasPort()) {
374                port = uri.getHostPort().getPort();
375            } else {
376                if (listeningPoint.getTransport().equalsIgnoreCase("TLS"))
377                    port = 5061;
378                else
379                    port = 5060;
380            }
381            String host = uri.getHost();
382            if ((host.equals(listeningPoint.getIPAddress()) || host
383                    .equalsIgnoreCase(listeningPoint.getSentBy()))
384                    && port == listeningPoint.getPort()) {
385                if (routes.size() == 1)
386                    sipRequest.removeHeader(Route.NAME);
387                else
388                    routes.removeFirst();
389            }
390        }
391
392        if (sipRequest.getMethod().equals(Request.REFER) && dialog != null
393                && sipProvider.isDialogErrorsAutomaticallyHandled()) {
394            /*
395             * An agent responding to a REFER method MUST return a 400 (Bad Request) if the
396             * request contained zero or more than one Refer-To header field values.
397             */
398            ReferToHeader sipHeader = (ReferToHeader) sipRequest.getHeader(ReferTo.NAME);
399            if (sipHeader == null) {
400                this
401                        .sendBadRequestResponse(sipRequest, transaction,
402                                "Refer-To header is missing");
403                return;
404
405            }
406
407            /*
408             * A refer cannot be processed until we have either sent or received an ACK.
409             */
410            SIPTransaction lastTransaction = ((SIPDialog) dialog).getLastTransaction();
411            if (lastTransaction != null  && sipProvider.isDialogErrorsAutomaticallyHandled()) {
412                SIPRequest lastRequest = (SIPRequest) lastTransaction.getRequest();
413                if (lastTransaction instanceof SIPServerTransaction) {
414                    if (!((SIPDialog) dialog).isAckSeen()
415                            && lastRequest.getMethod().equals(Request.INVITE)) {
416                        this.sendRequestPendingResponse(sipRequest, transaction);
417                        return;
418                    }
419                } else if (lastTransaction instanceof SIPClientTransaction) {
420                    long cseqno = lastRequest.getCSeqHeader().getSeqNumber();
421                    String method = lastRequest.getMethod();
422                    if (method.equals(Request.INVITE) && !dialog.isAckSent(cseqno)) {
423                        this.sendRequestPendingResponse(sipRequest, transaction);
424                        return;
425                    }
426                }
427            }
428
429        } else if (sipRequest.getMethod().equals(Request.UPDATE)) {
430            /*
431             * Got an UPDATE method and the user dialog does not exist and the user wants to be a
432             * User agent.
433             *
434             */
435            if (sipProvider.isAutomaticDialogSupportEnabled() && dialog == null) {
436                this.sendCallOrTransactionDoesNotExistResponse(sipRequest, transaction);
437                return;
438            }
439        } else if (sipRequest.getMethod().equals(Request.ACK)) {
440
441            if (transaction != null && transaction.isInviteTransaction()) {
442                // This is an ack for a 3xx-6xx response. Just let the tx laer
443                // take care of it.
444                if (sipStack.isLoggingEnabled())
445                    sipStack.getStackLogger().logDebug("Processing ACK for INVITE Tx ");
446
447            } else {
448                if (sipStack.isLoggingEnabled())
449                    sipStack.getStackLogger().logDebug("Processing ACK for dialog " + dialog);
450
451                if (dialog == null) {
452                    if (sipStack.isLoggingEnabled()) {
453                        sipStack.getStackLogger().logDebug(
454                                "Dialog does not exist " + sipRequest.getFirstLine()
455                                        + " isServerTransaction = " + true);
456
457                    }
458                    SIPServerTransaction st = sipStack
459                            .getRetransmissionAlertTransaction(dialogId);
460                    if (st != null && st.isRetransmissionAlertEnabled()) {
461                        st.disableRetransmissionAlerts();
462
463                    }
464                    /*
465                     * JvB: must never drop ACKs that dont match a transaction! One cannot be sure
466                     * if it isn't an ACK for a 2xx response
467                     *
468                     */
469                    SIPServerTransaction ackTransaction = sipStack
470                            .findTransactionPendingAck(sipRequest);
471                    /*
472                     * Found a transaction ( that we generated ) which is waiting for ACK. So ACK
473                     * it and return.
474                     */
475                    if (ackTransaction != null) {
476                        if (sipStack.isLoggingEnabled())
477                            sipStack.getStackLogger().logDebug("Found Tx pending ACK");
478                        try {
479                            ackTransaction.setAckSeen();
480                            sipStack.removeTransaction(ackTransaction);
481                            sipStack.removeTransactionPendingAck(ackTransaction);
482                        } catch (Exception ex) {
483                            if (sipStack.isLoggingEnabled()) {
484                                sipStack.getStackLogger().logError(
485                                        "Problem terminating transaction", ex);
486                            }
487                        }
488                        return;
489                    }
490
491                } else {
492                    if (!dialog.handleAck(transaction)) {
493                        if (!dialog.isSequnceNumberValidation()) {
494                            if (sipStack.isLoggingEnabled()) {
495                                sipStack.getStackLogger().logDebug(
496                                        "Dialog exists with loose dialog validation "
497                                                + sipRequest.getFirstLine()
498                                                + " isServerTransaction = " + true + " dialog = "
499                                                + dialog.getDialogId());
500
501                            }
502                            SIPServerTransaction st = sipStack
503                                    .getRetransmissionAlertTransaction(dialogId);
504                            if (st != null && st.isRetransmissionAlertEnabled()) {
505                                st.disableRetransmissionAlerts();
506
507                            }
508                        } else {
509                            if (sipStack.isLoggingEnabled()) {
510                                sipStack.getStackLogger().logDebug(
511                                        "Dropping ACK - cannot find a transaction or dialog");
512                            }
513                            SIPServerTransaction ackTransaction = sipStack
514                                    .findTransactionPendingAck(sipRequest);
515                            if (ackTransaction != null) {
516                                if (sipStack.isLoggingEnabled())
517                                    sipStack.getStackLogger().logDebug("Found Tx pending ACK");
518                                try {
519                                    ackTransaction.setAckSeen();
520                                    sipStack.removeTransaction(ackTransaction);
521                                    sipStack.removeTransactionPendingAck(ackTransaction);
522                                } catch (Exception ex) {
523                                    if (sipStack.isLoggingEnabled()) {
524                                        sipStack.getStackLogger().logError(
525                                                "Problem terminating transaction", ex);
526                                    }
527                                }
528                            }
529                            return;
530                        }
531                    } else {
532                        transaction.passToListener();
533                        dialog.addTransaction(transaction);
534                        dialog.addRoute(sipRequest);
535                        transaction.setDialog(dialog, dialogId);
536                        if (sipRequest.getMethod().equals(Request.INVITE)
537                                && sipProvider.isDialogErrorsAutomaticallyHandled()) {
538                            sipStack.putInMergeTable(transaction, sipRequest);
539                        }
540                        /*
541                         * Note that ACK is a pseudo transaction. It is never added to the stack
542                         * and you do not get transaction terminated events on ACK.
543                         */
544
545                        if (sipStack.deliverTerminatedEventForAck) {
546                            try {
547                                sipStack.addTransaction(transaction);
548                                transaction.scheduleAckRemoval();
549                            } catch (IOException ex) {
550
551                            }
552                        } else {
553                            transaction.setMapped(true);
554                        }
555
556                    }
557                }
558            }
559        } else if (sipRequest.getMethod().equals(Request.PRACK)) {
560
561            /*
562             * RFC 3262: A matching PRACK is defined as one within the same dialog as the
563             * response, and whose method, CSeq-num, and response-num in the RAck header field
564             * match, respectively, the method from the CSeq, the sequence number from the CSeq,
565             * and the sequence number from the RSeq of the reliable provisional response.
566             */
567
568            if (sipStack.isLoggingEnabled())
569                sipStack.getStackLogger().logDebug("Processing PRACK for dialog " + dialog);
570
571            if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
572                if (sipStack.isLoggingEnabled()) {
573                    sipStack.getStackLogger().logDebug(
574                            "Dialog does not exist " + sipRequest.getFirstLine()
575                                    + " isServerTransaction = " + true);
576
577                }
578                if (sipStack.isLoggingEnabled()) {
579                    sipStack
580                            .getStackLogger()
581                            .logDebug(
582                                    "Sending 481 for PRACK - automatic dialog support is enabled -- cant find dialog!");
583                }
584                SIPResponse notExist = sipRequest
585                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
586
587                try {
588                    sipProvider.sendResponse(notExist);
589                } catch (SipException e) {
590                    sipStack.getStackLogger().logError("error sending response", e);
591                }
592                if (transaction != null) {
593                    sipStack.removeTransaction(transaction);
594                    transaction.releaseSem();
595                }
596                return;
597
598            } else if (dialog != null) {
599                if (!dialog.handlePrack(sipRequest)) {
600                    if (sipStack.isLoggingEnabled())
601                        sipStack.getStackLogger().logDebug("Dropping out of sequence PRACK ");
602                    if (transaction != null) {
603                        sipStack.removeTransaction(transaction);
604                        transaction.releaseSem();
605                    }
606                    return;
607                } else {
608                    try {
609                        sipStack.addTransaction(transaction);
610                        dialog.addTransaction(transaction);
611                        dialog.addRoute(sipRequest);
612                        transaction.setDialog(dialog, dialogId);
613                    } catch (Exception ex) {
614                        InternalErrorHandler.handleException(ex);
615                    }
616                }
617            } else {
618                if (sipStack.isLoggingEnabled())
619                    sipStack.getStackLogger().logDebug(
620                            "Processing PRACK without a DIALOG -- this must be a proxy element");
621            }
622
623        } else if (sipRequest.getMethod().equals(Request.BYE)) {
624            // Check for correct sequence numbering of the BYE
625            if (dialog != null && !dialog.isRequestConsumable(sipRequest)) {
626                if (sipStack.isLoggingEnabled())
627                    sipStack.getStackLogger().logDebug(
628                            "Dropping out of sequence BYE " + dialog.getRemoteSeqNumber() + " "
629                                    + sipRequest.getCSeq().getSeqNumber());
630
631                if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber()
632                        && transaction.getState() == TransactionState.TRYING) {
633
634                    this.sendServerInternalErrorResponse(sipRequest, transaction);
635
636                }
637                // If the stack knows about the tx, then remove it.
638                if (transaction != null)
639                    sipStack.removeTransaction(transaction);
640                return;
641
642            } else if (dialog == null && sipProvider.isAutomaticDialogSupportEnabled()) {
643                // Drop bye's with 481 if dialog does not exist.
644                // If dialog support is enabled then
645                // there must be a dialog associated with the bye
646                // No dialog could be found and requests on this
647                // provider. Must act like a user agent -- so drop the request.
648                // NOTE: if Automatic dialog support is not enabled,
649                // then it is the application's responsibility to
650                // take care of this error condition possibly.
651
652                SIPResponse response = sipRequest
653                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
654                response.setReasonPhrase("Dialog Not Found");
655
656                if (sipStack.isLoggingEnabled())
657                    sipStack.getStackLogger().logDebug(
658                            "dropping request -- automatic dialog "
659                                    + "support enabled and dialog does not exist!");
660                try {
661                    transaction.sendResponse(response);
662                } catch (SipException ex) {
663                    sipStack.getStackLogger().logError("Error in sending response", ex);
664                }
665                // If the stack knows about the tx, then remove it.
666                if (transaction != null) {
667                    sipStack.removeTransaction(transaction);
668                    transaction.releaseSem();
669                    transaction = null;
670                }
671                return;
672
673            }
674
675            // note that the transaction may be null (which
676            // happens when no dialog for the bye was found.
677            // and automatic dialog support is disabled (i.e. the app wants
678            // to manage its own dialog layer.
679            if (transaction != null && dialog != null) {
680                try {
681                    if (sipProvider == dialog.getSipProvider()) {
682                        sipStack.addTransaction(transaction);
683                        dialog.addTransaction(transaction);
684                        transaction.setDialog(dialog, dialogId);
685                    }
686
687                } catch (IOException ex) {
688                    InternalErrorHandler.handleException(ex);
689                }
690            }
691            if (sipStack.isLoggingEnabled()) {
692                sipStack.getStackLogger().logDebug(
693                        "BYE Tx = " + transaction + " isMapped ="
694                                + transaction.isTransactionMapped());
695            }
696
697        } else if (sipRequest.getMethod().equals(Request.CANCEL)) {
698
699            SIPServerTransaction st = (SIPServerTransaction) sipStack.findCancelTransaction(
700                    sipRequest, true);
701            if (sipStack.isLoggingEnabled()) {
702                sipStack.getStackLogger().logDebug(
703                        "Got a CANCEL, InviteServerTx = " + st + " cancel Server Tx ID = "
704                                + transaction + " isMapped = "
705                                + transaction.isTransactionMapped());
706
707            }
708            // Processing incoming CANCEL.
709            // Check if we can process the CANCEL request.
710            if (sipRequest.getMethod().equals(Request.CANCEL)) {
711                // If the CANCEL comes in too late, there's not
712                // much that the Listener can do so just do the
713                // default action and avoid bothering the listener.
714                if (st != null && st.getState() == SIPTransaction.TERMINATED_STATE) {
715                    // If transaction already exists but it is
716                    // too late to cancel the transaction then
717                    // just respond OK to the CANCEL and bail.
718                    if (sipStack.isLoggingEnabled())
719                        sipStack.getStackLogger().logDebug("Too late to cancel Transaction");
720                    // send OK and just ignore the CANCEL.
721                    try {
722
723                        transaction.sendResponse(sipRequest.createResponse(Response.OK));
724                    } catch (Exception ex) {
725                        if (ex.getCause() != null && ex.getCause() instanceof IOException) {
726                            st.raiseIOExceptionEvent();
727                        }
728                    }
729                    return;
730                }
731                if (sipStack.isLoggingEnabled())
732                    sipStack.getStackLogger().logDebug("Cancel transaction = " + st);
733
734            }
735            if (transaction != null && st != null && st.getDialog() != null) {
736                // Found an invite tx corresponding to the CANCEL.
737                // Set up the client tx and pass up to listener.
738                transaction.setDialog((SIPDialog) st.getDialog(), dialogId);
739                dialog = (SIPDialog) st.getDialog();
740            } else if (st == null && sipProvider.isAutomaticDialogSupportEnabled()
741                    && transaction != null) {
742                // Could not find a invite tx corresponding to the CANCEL.
743                // Automatic dialog support is enabled so I must behave like
744                // an endpoint on this provider.
745                // Send the error response for the cancel.
746
747                SIPResponse response = sipRequest
748                        .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
749                if (sipStack.isLoggingEnabled()) {
750                    sipStack.getStackLogger().logDebug(
751                            "dropping request -- automatic dialog support "
752                                    + "enabled and INVITE ST does not exist!");
753                }
754                try {
755                    sipProvider.sendResponse(response);
756                } catch (SipException ex) {
757                    InternalErrorHandler.handleException(ex);
758                }
759                if (transaction != null) {
760                    sipStack.removeTransaction(transaction);
761                    transaction.releaseSem();
762                }
763                return;
764
765            }
766
767            // INVITE was handled statefully so the CANCEL must also be
768            // statefully handled.
769            if (st != null) {
770                try {
771                    if (transaction != null) {
772                        sipStack.addTransaction(transaction);
773                        transaction.setPassToListener();
774                        transaction.setInviteTransaction(st);
775                        // Dont let the INVITE and CANCEL be concurrently
776                        // processed.
777                        st.acquireSem();
778
779                    }
780
781                } catch (Exception ex) {
782                    InternalErrorHandler.handleException(ex);
783                }
784            }
785        } else if (sipRequest.getMethod().equals(Request.INVITE)) {
786            SIPTransaction lastTransaction = dialog == null ? null : dialog
787                    .getInviteTransaction();
788
789            /*
790             * RFC 3261 Chapter 14. A UAS that receives a second INVITE before it sends the final
791             * response to a first INVITE with a lower CSeq sequence number on the same dialog
792             * MUST return a 500 (Server Internal Error) response to the second INVITE and MUST
793             * include a Retry-After header field with a randomly chosen value of between 0 and 10
794             * seconds.
795             */
796
797            if (dialog != null && transaction != null && lastTransaction != null
798                    && sipRequest.getCSeq().getSeqNumber() > dialog.getRemoteSeqNumber()
799                    && lastTransaction instanceof SIPServerTransaction
800                    && sipProvider.isDialogErrorsAutomaticallyHandled()
801                    && dialog.isSequnceNumberValidation()
802                    && lastTransaction.isInviteTransaction()
803                    && lastTransaction.getState() != TransactionState.COMPLETED
804                    && lastTransaction.getState() != TransactionState.TERMINATED
805                    && lastTransaction.getState() != TransactionState.CONFIRMED) {
806
807                if (sipStack.isLoggingEnabled()) {
808                    sipStack.getStackLogger().logDebug(
809                            "Sending 500 response for out of sequence message");
810                }
811                this.sendServerInternalErrorResponse(sipRequest, transaction);
812                return;
813
814            }
815
816            /*
817             * Saw an interleaved invite before ACK was sent. RFC 3261 Chapter 14. A UAS that
818             * receives an INVITE on a dialog while an INVITE it had sent on that dialog is in
819             * progress MUST return a 491 (Request Pending) response to the received INVITE.
820             */
821            lastTransaction = (dialog == null ? null : dialog.getLastTransaction());
822
823            if (dialog != null
824                    && sipProvider.isDialogErrorsAutomaticallyHandled()
825                    && lastTransaction != null
826                    && lastTransaction.isInviteTransaction()
827                    && lastTransaction instanceof ClientTransaction
828                    && lastTransaction.getLastResponse() != null
829                    && lastTransaction.getLastResponse().getStatusCode() == 200
830                    && !dialog.isAckSent(lastTransaction.getLastResponse().getCSeq()
831                            .getSeqNumber())) {
832                if (sipStack.isLoggingEnabled()) {
833                    sipStack.getStackLogger().logDebug(
834                            "Sending 491 response for client Dialog ACK not sent.");
835                }
836                this.sendRequestPendingResponse(sipRequest, transaction);
837                return;
838            }
839
840            if (dialog != null && lastTransaction != null
841                    && sipProvider.isDialogErrorsAutomaticallyHandled()
842                    && lastTransaction.isInviteTransaction()
843                    && lastTransaction instanceof ServerTransaction && !dialog.isAckSeen()) {
844                if (sipStack.isLoggingEnabled()) {
845                    sipStack.getStackLogger().logDebug(
846                            "Sending 491 response for server Dialog ACK not seen.");
847                }
848                this.sendRequestPendingResponse(sipRequest, transaction);
849                return;
850
851            }
852        }
853
854        // Sequence numbers are supposed to be incremented
855        // sequentially within a dialog for RFC 3261
856        // Note BYE, CANCEL and ACK is handled above - so no check here.
857
858        if (sipStack.isLoggingEnabled()) {
859            sipStack.getStackLogger().logDebug(
860                    "CHECK FOR OUT OF SEQ MESSAGE " + dialog + " transaction " + transaction);
861        }
862
863        if (dialog != null && transaction != null && !sipRequest.getMethod().equals(Request.BYE)
864                && !sipRequest.getMethod().equals(Request.CANCEL)
865                && !sipRequest.getMethod().equals(Request.ACK)
866                && !sipRequest.getMethod().equals(Request.PRACK)) {
867
868            if (!dialog.isRequestConsumable(sipRequest)) {
869
870                /*
871                 * RFC 3261: "UAS Behavior" section (12.2.2): If the remote sequence number was
872                 * not empty, but the sequence number of the request is lower than the remote
873                 * sequence number, the request is out of order and MUST be rejected with a 500
874                 * (Server Internal Error) response.
875                 */
876
877                // Drop the request
878                if (sipStack.isLoggingEnabled()) {
879                    sipStack.getStackLogger().logDebug(
880                            "Dropping out of sequence message " + dialog.getRemoteSeqNumber()
881                                    + " " + sipRequest.getCSeq());
882                }
883
884                // send error when stricly higher, ignore when ==
885                // (likely still processing, error would interrupt that)
886
887                if (dialog.getRemoteSeqNumber() >= sipRequest.getCSeq().getSeqNumber()
888                        && sipProvider.isDialogErrorsAutomaticallyHandled()
889                        && (transaction.getState() == TransactionState.TRYING || transaction
890                                .getState() == TransactionState.PROCEEDING)) {
891                    this.sendServerInternalErrorResponse(sipRequest, transaction);
892
893                }
894                return;
895            }
896
897            try {
898                if (sipProvider == dialog.getSipProvider()) {
899                    sipStack.addTransaction(transaction);
900                    // This will set the remote sequence number.
901                    dialog.addTransaction(transaction);
902                    dialog.addRoute(sipRequest);
903                    transaction.setDialog(dialog, dialogId);
904
905                }
906            } catch (IOException ex) {
907                transaction.raiseIOExceptionEvent();
908                sipStack.removeTransaction(transaction);
909                return;
910            }
911
912        }
913
914        RequestEvent sipEvent;
915
916        if (sipStack.isLoggingEnabled()) {
917            sipStack.getStackLogger().logDebug(
918                    sipRequest.getMethod() + " transaction.isMapped = "
919                            + transaction.isTransactionMapped());
920        }
921
922        /*
923         * RFC 3265: Each event package MUST specify whether forked SUBSCRIBE requests are allowed
924         * to install multiple subscriptions. If such behavior is not allowed, the first potential
925         * dialog- establishing message will create a dialog. All subsequent NOTIFY messages which
926         * correspond to the SUBSCRIBE message (i.e., match "To", "From", "From" header "tag"
927         * parameter, "Call-ID", "CSeq", "Event", and "Event" header "id" parameter) but which do
928         * not match the dialog would be rejected with a 481 response. Note that the 200-class
929         * response to the SUBSCRIBE can arrive after a matching NOTIFY has been received; such
930         * responses might not correlate to the same dialog established by the NOTIFY. Except as
931         * required to complete the SUBSCRIBE transaction, such non-matching 200-class responses
932         * are ignored.
933         */
934
935        if (dialog == null && sipRequest.getMethod().equals(Request.NOTIFY)) {
936
937            SIPClientTransaction pendingSubscribeClientTx = sipStack.findSubscribeTransaction(
938                    sipRequest, listeningPoint);
939
940            if (sipStack.isLoggingEnabled()) {
941                sipStack.getStackLogger().logDebug(
942                        "PROCESSING NOTIFY  DIALOG == null " + pendingSubscribeClientTx);
943            }
944
945            /*
946             * RFC 3265: Upon receiving a NOTIFY request, the subscriber should check that it
947             * matches at least one of its outstanding subscriptions; if not, it MUST return a
948             * "481 Subscription does not exist" response unless another 400- or -class response
949             * is more appropriate.
950             */
951            if (sipProvider.isAutomaticDialogSupportEnabled() && pendingSubscribeClientTx == null
952                    && !sipStack.deliverUnsolicitedNotify) {
953                /*
954                 * This is the case of the UAC receiving a Stray NOTIFY for which it has not
955                 * previously sent out a SUBSCRIBE and for which it does not have an established
956                 * dialog.
957                 */
958                try {
959                    if (sipStack.isLoggingEnabled()) {
960                        sipStack.getStackLogger().logDebug(
961                                "Could not find Subscription for Notify Tx.");
962                    }
963                    Response errorResponse = sipRequest
964                            .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST);
965                    errorResponse.setReasonPhrase("Subscription does not exist");
966                    sipProvider.sendResponse(errorResponse);
967                    return;
968
969                } catch (Exception ex) {
970                    sipStack.getStackLogger().logError(
971                            "Exception while sending error response statelessly", ex);
972                    return;
973                }
974
975            }
976
977            // If the server transaction cannot be found or if it
978            // aleady has a dialog attached to it then just assign the
979            // notify to this dialog and pass it up.
980            if (pendingSubscribeClientTx != null) {
981                // The response to the pending subscribe tx can try to create
982                // a dialog at the same time that the notify is trying to
983                // create a dialog. Thus we cannot process both at the
984                // same time.
985
986                transaction.setPendingSubscribe(pendingSubscribeClientTx);
987                // The transaction gets assigned to the dialog from the
988                // outgoing subscribe. First see if anybody claimed the
989                // default Dialog for the outgoing Subscribe request.
990                SIPDialog subscriptionDialog = (SIPDialog) pendingSubscribeClientTx
991                        .getDefaultDialog();
992
993                // TODO -- refactor this. Can probably be written far cleaner.
994                if (subscriptionDialog == null || subscriptionDialog.getDialogId() == null
995                        || !subscriptionDialog.getDialogId().equals(dialogId)) {
996                    // Notify came in before you could assign a response to
997                    // the subscribe.
998                    // grab the default dialog and assign it to the tags in
999                    // the notify.
1000                    if (subscriptionDialog != null && subscriptionDialog.getDialogId() == null) {
1001                        subscriptionDialog.setDialogId(dialogId);
1002
1003                    } else {
1004                        subscriptionDialog = pendingSubscribeClientTx.getDialog(dialogId);
1005                    }
1006                    if (sipStack.isLoggingEnabled()) {
1007                        sipStack.getStackLogger().logDebug(
1008                                "PROCESSING NOTIFY Subscribe DIALOG " + subscriptionDialog);
1009                    }
1010
1011                    // The user could have createed a dialog before sending out
1012                    // the SUBSCRIBE on the subscribe tx.
1013                    if (subscriptionDialog == null
1014                            && (sipProvider.isAutomaticDialogSupportEnabled() || pendingSubscribeClientTx
1015                                    .getDefaultDialog() != null)) {
1016                        Event event = (Event) sipRequest.getHeader(EventHeader.NAME);
1017                        if (sipStack.isEventForked(event.getEventType())) {
1018
1019                            subscriptionDialog = SIPDialog.createFromNOTIFY(
1020                                    pendingSubscribeClientTx, transaction);
1021
1022                        }
1023
1024                    }
1025                    if (subscriptionDialog != null) {
1026                        transaction.setDialog(subscriptionDialog, dialogId);
1027                        subscriptionDialog.setState(DialogState.CONFIRMED.getValue());
1028                        sipStack.putDialog(subscriptionDialog);
1029                        pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId);
1030                        if (!transaction.isTransactionMapped()) {
1031                            this.sipStack.mapTransaction(transaction);
1032                            // Let the listener see it if it just got
1033                            // created.
1034                            // otherwise, we have already processed the tx
1035                            // so
1036                            // we dont want the listener to see it.
1037                            transaction.setPassToListener();
1038                            try {
1039                                this.sipStack.addTransaction(transaction);
1040                            } catch (Exception ex) {
1041                            }
1042                        }
1043                    }
1044                } else {
1045                    // The subscription default dialog is our dialog.
1046                    // Found a subscrbe dialog for the NOTIFY
1047                    // So map the tx.
1048                    transaction.setDialog(subscriptionDialog, dialogId);
1049                    dialog = subscriptionDialog;
1050                    if (!transaction.isTransactionMapped()) {
1051                        this.sipStack.mapTransaction(transaction);
1052                        // Let the listener see it if it just got created.
1053                        // otherwise, we have already processed the tx so
1054                        // we dont want the listener to see it.
1055                        transaction.setPassToListener();
1056                        try {
1057                            this.sipStack.addTransaction(transaction);
1058                        } catch (Exception ex) {
1059                        }
1060                    }
1061                    sipStack.putDialog(subscriptionDialog);
1062                    if (pendingSubscribeClientTx != null) {
1063                        subscriptionDialog.addTransaction(pendingSubscribeClientTx);
1064                        pendingSubscribeClientTx.setDialog(subscriptionDialog, dialogId);
1065
1066                    }
1067                }
1068                if (transaction != null
1069                        && ((SIPServerTransaction) transaction).isTransactionMapped()) {
1070                    // Shadow transaction has been created and the stack
1071                    // knows
1072                    // about it.
1073                    sipEvent = new RequestEvent((SipProvider) sipProvider,
1074                            (ServerTransaction) transaction, subscriptionDialog,
1075                            (Request) sipRequest);
1076                } else {
1077                    // Shadow transaction has been created but the stack
1078                    // does
1079                    // not know
1080                    // about it.
1081                    sipEvent = new RequestEvent((SipProvider) sipProvider, null,
1082                            subscriptionDialog, (Request) sipRequest);
1083                }
1084
1085            } else {
1086                if (sipStack.isLoggingEnabled()) {
1087                    sipStack.getStackLogger().logDebug("could not find subscribe tx");
1088                }
1089
1090                // Got a notify out of the blue - just pass it up
1091                // for stateless handling by the application.
1092                sipEvent = new RequestEvent(sipProvider, null, null, (Request) sipRequest);
1093            }
1094
1095        } else {
1096
1097            // For a dialog creating event - set the transaction to null.
1098            // The listener can create the dialog if needed.
1099            if (transaction != null
1100                    && (((SIPServerTransaction) transaction).isTransactionMapped())) {
1101                sipEvent = new RequestEvent(sipProvider, (ServerTransaction) transaction, dialog,
1102                        (Request) sipRequest);
1103            } else {
1104                sipEvent = new RequestEvent(sipProvider, null, dialog, (Request) sipRequest);
1105            }
1106        }
1107        sipProvider.handleEvent(sipEvent, transaction);
1108
1109    }
1110
1111    /**
1112     * Process the response.
1113     *
1114     * @exception SIPServerException is thrown when there is an error processing the response
1115     * @param incomingMessageChannel -- message channel on which the response is received.
1116     */
1117    public void processResponse(SIPResponse response, MessageChannel incomingMessageChannel,
1118            SIPDialog dialog) {
1119        if (sipStack.isLoggingEnabled()) {
1120            sipStack.getStackLogger().logDebug(
1121                    "PROCESSING INCOMING RESPONSE" + response.encodeMessage());
1122        }
1123        if (listeningPoint == null) {
1124            if (sipStack.isLoggingEnabled())
1125                sipStack.getStackLogger().logError(
1126                        "Dropping message: No listening point" + " registered!");
1127            return;
1128        }
1129
1130        if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(response)) {
1131            if (sipStack.isLoggingEnabled()) {
1132                sipStack
1133                        .getStackLogger()
1134                        .logError(
1135                                "Dropping response - topmost VIA header does not originate from this stack");
1136            }
1137            return;
1138        }
1139
1140        SipProviderImpl sipProvider = listeningPoint.getProvider();
1141        if (sipProvider == null) {
1142            if (sipStack.isLoggingEnabled()) {
1143                sipStack.getStackLogger().logError("Dropping message:  no provider");
1144            }
1145            return;
1146        }
1147        if (sipProvider.getSipListener() == null) {
1148            if (sipStack.isLoggingEnabled()) {
1149                sipStack.getStackLogger().logError("No listener -- dropping response!");
1150            }
1151            return;
1152        }
1153
1154        SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel;
1155        SipStackImpl sipStackImpl = sipProvider.sipStack;
1156
1157        if (sipStack.isLoggingEnabled()) {
1158            sipStackImpl.getStackLogger().logDebug("Transaction = " + transaction);
1159        }
1160
1161        if (transaction == null) {
1162            // Transaction is null but the dialog is not null. This means that
1163            // the transaction has been removed by the stack.
1164            // If the dialog exists, then it may need to retransmit ACK so
1165            // we cannot drop the response.
1166            if (dialog != null) {
1167                if (response.getStatusCode() / 100 != 2) {
1168                    if (sipStack.isLoggingEnabled()) {
1169                        sipStack
1170                                .getStackLogger()
1171                                .logDebug(
1172                                        "Response is not a final response and dialog is found for response -- dropping response!");
1173                    }
1174                    return;
1175                } else if (dialog.getState() == DialogState.TERMINATED) {
1176                    if (sipStack.isLoggingEnabled()) {
1177                        sipStack.getStackLogger().logDebug(
1178                                "Dialog is terminated -- dropping response!");
1179                    }
1180                    return;
1181                } else {
1182                    boolean ackAlreadySent = false;
1183                    if (dialog.isAckSeen() && dialog.getLastAckSent() != null) {
1184                        if (dialog.getLastAckSent().getCSeq().getSeqNumber() == response
1185                                .getCSeq().getSeqNumber()) {
1186                            // the last ack sent corresponded to this 200
1187                            ackAlreadySent = true;
1188                        }
1189                    }
1190                    // 200 retransmission for the final response.
1191                    if (ackAlreadySent
1192                            && response.getCSeq().getMethod().equals(dialog.getMethod())) {
1193                        try {
1194                            // Found the dialog - resend the ACK and
1195                            // dont pass up the null transaction
1196                            if (sipStack.isLoggingEnabled()) {
1197                                sipStack.getStackLogger().logDebug(
1198                                        "Retransmission of OK detected: Resending last ACK");
1199                            }
1200                            dialog.resendAck();
1201                            return;
1202                        } catch (SipException ex) {
1203                            // What to do here ?? kill the dialog?
1204                            sipStack.getStackLogger().logError("could not resend ack", ex);
1205                        }
1206                    }
1207                }
1208            }
1209
1210            if (sipStack.isLoggingEnabled()) {
1211                sipStack.getStackLogger().logDebug(
1212                        "could not find tx, handling statelessly Dialog =  " + dialog);
1213            }
1214            // Pass the response up to the application layer to handle
1215            // statelessly.
1216
1217            ResponseEventExt sipEvent = new ResponseEventExt(sipProvider, transaction, dialog,
1218                    (Response) response);
1219
1220            if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) {
1221                SIPClientTransaction forked = this.sipStack.getForkedTransaction(response
1222                        .getTransactionId());
1223                sipEvent.setOriginalTransaction(forked);
1224            }
1225
1226            sipProvider.handleEvent(sipEvent, transaction);
1227            return;
1228        }
1229
1230        ResponseEventExt responseEvent = null;
1231
1232        // Here if there is an assigned dialog
1233        responseEvent = new ResponseEventExt(sipProvider, (ClientTransactionExt) transaction,
1234                dialog, (Response) response);
1235        if (response.getCSeqHeader().getMethod().equals(Request.INVITE)) {
1236            SIPClientTransaction forked = this.sipStack.getForkedTransaction(response
1237                    .getTransactionId());
1238            responseEvent.setOriginalTransaction(forked);
1239        }
1240
1241        // Set the Dialog for the response.
1242        if (dialog != null && response.getStatusCode() != 100) {
1243            // set the last response for the dialog.
1244            dialog.setLastResponse(transaction, response);
1245            transaction.setDialog(dialog, dialog.getDialogId());
1246        }
1247
1248        sipProvider.handleEvent(responseEvent, transaction);
1249
1250    }
1251
1252    /**
1253     * Just a placeholder. This is called from the stack for message logging. Auxiliary processing
1254     * information can be passed back to be written into the log file.
1255     *
1256     * @return auxiliary information that we may have generated during the message processing
1257     *         which is retrieved by the message logger.
1258     */
1259    public String getProcessingInfo() {
1260        return null;
1261    }
1262
1263    /*
1264     * (non-Javadoc)
1265     *
1266     * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse,
1267     *      gov.nist.javax.sip.stack.MessageChannel)
1268     */
1269    public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) {
1270        String dialogID = sipResponse.getDialogId(false);
1271        SIPDialog sipDialog = this.sipStack.getDialog(dialogID);
1272
1273        String method = sipResponse.getCSeq().getMethod();
1274        if (sipStack.isLoggingEnabled()) {
1275            sipStack.getStackLogger().logDebug(
1276                    "PROCESSING INCOMING RESPONSE: " + sipResponse.encodeMessage());
1277        }
1278
1279        if (sipStack.checkBranchId() && !Utils.getInstance().responseBelongsToUs(sipResponse)) {
1280            if (sipStack.isLoggingEnabled()) {
1281                sipStack.getStackLogger().logError("Detected stray response -- dropping");
1282            }
1283            return;
1284        }
1285
1286        if (listeningPoint == null) {
1287            if (sipStack.isLoggingEnabled())
1288                sipStack.getStackLogger().logDebug(
1289                        "Dropping message: No listening point" + " registered!");
1290            return;
1291        }
1292
1293        SipProviderImpl sipProvider = listeningPoint.getProvider();
1294        if (sipProvider == null) {
1295            if (sipStack.isLoggingEnabled()) {
1296                sipStack.getStackLogger().logDebug("Dropping message:  no provider");
1297            }
1298            return;
1299        }
1300
1301        if (sipProvider.getSipListener() == null) {
1302            if (sipStack.isLoggingEnabled()) {
1303                sipStack.getStackLogger().logDebug(
1304                        "Dropping message:  no sipListener registered!");
1305            }
1306            return;
1307        }
1308
1309        SIPClientTransaction transaction = (SIPClientTransaction) this.transactionChannel;
1310        // This may be a dialog creating method for which the ACK has not yet
1311        // been sent
1312        // but the dialog has already been assigned ( happens this way for
1313        // 3PCC).
1314        if (sipDialog == null && transaction != null) {
1315            sipDialog = transaction.getDialog(dialogID);
1316            if (sipDialog != null && sipDialog.getState() == DialogState.TERMINATED)
1317                sipDialog = null;
1318        }
1319
1320        if (sipStack.isLoggingEnabled())
1321            sipStack.getStackLogger().logDebug(
1322                    "Transaction = " + transaction + " sipDialog = " + sipDialog);
1323
1324        if (this.transactionChannel != null) {
1325            String originalFrom = ((SIPRequest) this.transactionChannel.getRequest())
1326                    .getFromTag();
1327            if (originalFrom == null ^ sipResponse.getFrom().getTag() == null) {
1328                if (sipStack.isLoggingEnabled())
1329                    sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
1330                return;
1331            }
1332            if (originalFrom != null
1333                    && !originalFrom.equalsIgnoreCase(sipResponse.getFrom().getTag())) {
1334                if (sipStack.isLoggingEnabled())
1335                    sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
1336                return;
1337            }
1338
1339        }
1340        if (sipStack.isDialogCreated(method) && sipResponse.getStatusCode() != 100
1341                && sipResponse.getFrom().getTag() != null && sipResponse.getTo().getTag() != null
1342                && sipDialog == null) {
1343            if (sipProvider.isAutomaticDialogSupportEnabled()) {
1344                if (this.transactionChannel != null) {
1345                    if (sipDialog == null) {
1346                        // There could be an existing dialog for this response.
1347                        sipDialog = sipStack.createDialog(
1348                                (SIPClientTransaction) this.transactionChannel, sipResponse);
1349
1350                        this.transactionChannel.setDialog(sipDialog, sipResponse
1351                                .getDialogId(false));
1352                    }
1353                } else {
1354                    sipDialog = this.sipStack.createDialog(sipProvider, sipResponse);
1355                }
1356            }
1357
1358        } else {
1359            // Have a dialog but could not find transaction.
1360            if (sipDialog != null && transaction == null
1361                    && sipDialog.getState() != DialogState.TERMINATED) {
1362                if (sipResponse.getStatusCode() / 100 != 2) {
1363                    if (sipStack.isLoggingEnabled())
1364                        sipStack.getStackLogger().logDebug(
1365                                "status code != 200 ; statusCode = "
1366                                        + sipResponse.getStatusCode());
1367                } else if (sipDialog.getState() == DialogState.TERMINATED) {
1368                    if (sipStack.isLoggingEnabled()) {
1369                        sipStack.getStackLogger().logDebug(
1370                                "Dialog is terminated -- dropping response!");
1371                    }
1372                    // Dialog exists but was terminated - just create and send an ACK for the OK.
1373                    // It could be late arriving.
1374                    if (sipResponse.getStatusCode() / 100 == 2
1375                            && sipResponse.getCSeq().getMethod().equals(Request.INVITE)) {
1376                        try {
1377                            Request ackRequest = sipDialog.createAck(sipResponse.getCSeq()
1378                                    .getSeqNumber());
1379                            sipDialog.sendAck(ackRequest);
1380                        } catch (Exception ex) {
1381                            sipStack.getStackLogger().logError("Error creating ack", ex);
1382                        }
1383                    }
1384                    return;
1385                } else {
1386                    boolean ackAlreadySent = false;
1387                    if (sipDialog.isAckSeen() && sipDialog.getLastAckSent() != null) {
1388                        if (sipDialog.getLastAckSent().getCSeq().getSeqNumber() == sipResponse
1389                                .getCSeq().getSeqNumber()
1390                                && sipResponse.getDialogId(false).equals(
1391                                        sipDialog.getLastAckSent().getDialogId(false))) {
1392                            // the last ack sent corresponded to this 200
1393                            ackAlreadySent = true;
1394                        }
1395                    }
1396                    // 200 retransmission for the final response.
1397                    if (ackAlreadySent
1398                            && sipResponse.getCSeq().getMethod().equals(sipDialog.getMethod())) {
1399                        try {
1400                            // Found the dialog - resend the ACK and
1401                            // dont pass up the null transaction
1402                            if (sipStack.isLoggingEnabled())
1403                                sipStack.getStackLogger().logDebug("resending ACK");
1404
1405                            sipDialog.resendAck();
1406                            return;
1407                        } catch (SipException ex) {
1408                            // What to do here ?? kill the dialog?
1409                        }
1410                    }
1411                }
1412            }
1413            // Pass the response up to the application layer to handle
1414            // statelessly.
1415
1416        }
1417        if (sipStack.isLoggingEnabled())
1418            sipStack.getStackLogger().logDebug("sending response to TU for processing ");
1419
1420        if (sipDialog != null && sipResponse.getStatusCode() != 100
1421                && sipResponse.getTo().getTag() != null) {
1422            sipDialog.setLastResponse(transaction, sipResponse);
1423        }
1424
1425        ResponseEventExt responseEvent = new ResponseEventExt(sipProvider,
1426                (ClientTransactionExt) transaction, sipDialog, (Response) sipResponse);
1427
1428        if (sipResponse.getCSeq().getMethod().equals(Request.INVITE)) {
1429            ClientTransactionExt originalTx = this.sipStack.getForkedTransaction(sipResponse
1430                    .getTransactionId());
1431            responseEvent.setOriginalTransaction(originalTx);
1432        }
1433
1434        sipProvider.handleEvent(responseEvent, transaction);
1435
1436    }
1437}
1438