Home | History | Annotate | Download | only in sip
      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  ******************************************************************************/
     29 package gov.nist.javax.sip;
     30 
     31 import gov.nist.core.InternalErrorHandler;
     32 import gov.nist.javax.sip.address.SipUri;
     33 import gov.nist.javax.sip.header.Contact;
     34 import gov.nist.javax.sip.header.Event;
     35 import gov.nist.javax.sip.header.ReferTo;
     36 import gov.nist.javax.sip.header.RetryAfter;
     37 import gov.nist.javax.sip.header.Route;
     38 import gov.nist.javax.sip.header.RouteList;
     39 import gov.nist.javax.sip.header.Server;
     40 import gov.nist.javax.sip.message.MessageFactoryImpl;
     41 import gov.nist.javax.sip.message.SIPRequest;
     42 import gov.nist.javax.sip.message.SIPResponse;
     43 import gov.nist.javax.sip.stack.MessageChannel;
     44 import gov.nist.javax.sip.stack.SIPClientTransaction;
     45 import gov.nist.javax.sip.stack.SIPDialog;
     46 import gov.nist.javax.sip.stack.SIPServerTransaction;
     47 import gov.nist.javax.sip.stack.SIPTransaction;
     48 import gov.nist.javax.sip.stack.ServerRequestInterface;
     49 import gov.nist.javax.sip.stack.ServerResponseInterface;
     50 
     51 import java.io.IOException;
     52 import java.util.TimerTask;
     53 
     54 import javax.sip.ClientTransaction;
     55 import javax.sip.DialogState;
     56 import javax.sip.InvalidArgumentException;
     57 import javax.sip.ObjectInUseException;
     58 import javax.sip.RequestEvent;
     59 import javax.sip.ResponseEvent;
     60 import javax.sip.ServerTransaction;
     61 import javax.sip.SipException;
     62 import javax.sip.SipProvider;
     63 import javax.sip.TransactionState;
     64 import javax.sip.header.CSeqHeader;
     65 import javax.sip.header.EventHeader;
     66 import javax.sip.header.ReferToHeader;
     67 import javax.sip.header.ServerHeader;
     68 import javax.sip.message.Request;
     69 import 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  */
     89 class 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