Home | History | Annotate | Download | only in stack
      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 Advanced Networking Technologies Division      */
     28 /**************************************************************************/
     29 package gov.nist.javax.sip.stack;
     30 
     31 import gov.nist.core.InternalErrorHandler;
     32 import gov.nist.core.NameValueList;
     33 import gov.nist.javax.sip.DialogExt;
     34 import gov.nist.javax.sip.ListeningPointImpl;
     35 import gov.nist.javax.sip.SipListenerExt;
     36 import gov.nist.javax.sip.SipProviderImpl;
     37 import gov.nist.javax.sip.Utils;
     38 import gov.nist.javax.sip.address.AddressImpl;
     39 import gov.nist.javax.sip.address.SipUri;
     40 import gov.nist.javax.sip.header.Authorization;
     41 import gov.nist.javax.sip.header.CSeq;
     42 import gov.nist.javax.sip.header.Contact;
     43 import gov.nist.javax.sip.header.ContactList;
     44 import gov.nist.javax.sip.header.From;
     45 import gov.nist.javax.sip.header.MaxForwards;
     46 import gov.nist.javax.sip.header.RAck;
     47 import gov.nist.javax.sip.header.RSeq;
     48 import gov.nist.javax.sip.header.Reason;
     49 import gov.nist.javax.sip.header.RecordRoute;
     50 import gov.nist.javax.sip.header.RecordRouteList;
     51 import gov.nist.javax.sip.header.Require;
     52 import gov.nist.javax.sip.header.Route;
     53 import gov.nist.javax.sip.header.RouteList;
     54 import gov.nist.javax.sip.header.SIPHeader;
     55 import gov.nist.javax.sip.header.TimeStamp;
     56 import gov.nist.javax.sip.header.To;
     57 import gov.nist.javax.sip.header.Via;
     58 import gov.nist.javax.sip.message.MessageFactoryImpl;
     59 import gov.nist.javax.sip.message.SIPMessage;
     60 import gov.nist.javax.sip.message.SIPRequest;
     61 import gov.nist.javax.sip.message.SIPResponse;
     62 
     63 import java.io.IOException;
     64 import java.io.PrintWriter;
     65 import java.io.Serializable;
     66 import java.io.StringWriter;
     67 import java.net.InetAddress;
     68 import java.text.ParseException;
     69 import java.util.ArrayList;
     70 import java.util.Iterator;
     71 import java.util.LinkedList;
     72 import java.util.List;
     73 import java.util.ListIterator;
     74 import java.util.Set;
     75 import java.util.concurrent.CopyOnWriteArraySet;
     76 import java.util.concurrent.Semaphore;
     77 import java.util.concurrent.TimeUnit;
     78 
     79 import javax.sip.ClientTransaction;
     80 import javax.sip.DialogDoesNotExistException;
     81 import javax.sip.DialogState;
     82 import javax.sip.IOExceptionEvent;
     83 import javax.sip.InvalidArgumentException;
     84 import javax.sip.ListeningPoint;
     85 import javax.sip.ObjectInUseException;
     86 import javax.sip.SipException;
     87 import javax.sip.Transaction;
     88 import javax.sip.TransactionDoesNotExistException;
     89 import javax.sip.TransactionState;
     90 import javax.sip.address.Address;
     91 import javax.sip.address.Hop;
     92 import javax.sip.address.SipURI;
     93 import javax.sip.header.CallIdHeader;
     94 import javax.sip.header.ContactHeader;
     95 import javax.sip.header.EventHeader;
     96 import javax.sip.header.OptionTag;
     97 import javax.sip.header.RAckHeader;
     98 import javax.sip.header.RSeqHeader;
     99 import javax.sip.header.ReasonHeader;
    100 import javax.sip.header.RequireHeader;
    101 import javax.sip.header.RouteHeader;
    102 import javax.sip.header.SupportedHeader;
    103 import javax.sip.header.TimeStampHeader;
    104 import javax.sip.message.Request;
    105 import javax.sip.message.Response;
    106 
    107 /*
    108  * Acknowledgements:
    109  *
    110  * Bugs in this class were reported by Antonis Karydas, Brad Templeton, Jeff Adams, Alex Rootham ,
    111  * Martin Le Clerk, Christophe Anzille, Andreas Bystrom, Lebing Xie, Jeroen van Bemmel. Hagai Sela
    112  * reported a bug in updating the route set (on RE-INVITE). Jens Tinfors submitted a bug fix and
    113  * the .equals method. Jan Schaumloeffel contributed a buf fix ( memory leak was happening when
    114  * 180 contained a To tag.
    115  *
    116  */
    117 
    118 /**
    119  * Tracks dialogs. A dialog is a peer to peer association of communicating SIP entities. For
    120  * INVITE transactions, a Dialog is created when a success message is received (i.e. a response
    121  * that has a To tag). The SIP Protocol stores enough state in the message structure to extract a
    122  * dialog identifier that can be used to retrieve this structure from the SipStack.
    123  *
    124  * @version 1.2 $Revision: 1.159 $ $Date: 2010/01/08 15:14:12 $
    125  *
    126  * @author M. Ranganathan
    127  *
    128  *
    129  */
    130 
    131 public class SIPDialog implements javax.sip.Dialog, DialogExt {
    132 
    133     private static final long serialVersionUID = -1429794423085204069L;
    134 
    135     private transient boolean dialogTerminatedEventDelivered; // prevent duplicate
    136 
    137     private transient String stackTrace; // for semaphore debugging.
    138 
    139     private String method;
    140 
    141     // delivery of the event
    142     private transient boolean isAssigned;
    143 
    144     private boolean reInviteFlag;
    145 
    146     private transient Object applicationData; // Opaque pointer to application data.
    147 
    148     private transient SIPRequest originalRequest;
    149 
    150     // Last response (JvB: either sent or received).
    151     private SIPResponse lastResponse;
    152 
    153     // Should be transient, in case the dialog is serialized it will be null
    154     // so when a subsequent request will be sent it will be set and a new message channel can be
    155     // created
    156     private transient SIPTransaction firstTransaction;
    157 
    158     private transient SIPTransaction lastTransaction;
    159 
    160     private String dialogId;
    161 
    162     private transient String earlyDialogId;
    163 
    164     private long localSequenceNumber;
    165 
    166     private long remoteSequenceNumber;
    167 
    168     protected String myTag;
    169 
    170     protected String hisTag;
    171 
    172     private RouteList routeList;
    173 
    174     private transient SIPTransactionStack sipStack;
    175 
    176     private int dialogState;
    177 
    178     protected transient boolean ackSeen;
    179 
    180     private transient SIPRequest lastAckSent;
    181 
    182     private SIPRequest lastAckReceived;
    183 
    184     // could be set on recovery by examining the method looks like a duplicate of ackSeen
    185     protected transient boolean ackProcessed;
    186 
    187     protected transient DialogTimerTask timerTask;
    188 
    189     protected transient Long nextSeqno;
    190 
    191     private transient int retransmissionTicksLeft;
    192 
    193     private transient int prevRetransmissionTicks;
    194 
    195     private long originalLocalSequenceNumber;
    196 
    197     // This is for debugging only.
    198     private transient int ackLine;
    199 
    200     // Audit tag used by the SIP Stack audit
    201     public transient long auditTag = 0;
    202 
    203     // The following fields are extracted from the request that created the
    204     // Dialog.
    205 
    206     protected javax.sip.address.Address localParty;
    207 
    208     protected javax.sip.address.Address remoteParty;
    209 
    210     protected CallIdHeader callIdHeader;
    211 
    212     public final static int NULL_STATE = -1;
    213 
    214     public final static int EARLY_STATE = DialogState._EARLY;
    215 
    216     public final static int CONFIRMED_STATE = DialogState._CONFIRMED;
    217 
    218     public final static int TERMINATED_STATE = DialogState._TERMINATED;
    219 
    220     // the amount of time to keep this dialog around before the stack GC's it
    221 
    222     private static final int DIALOG_LINGER_TIME = 8;
    223 
    224     private boolean serverTransactionFlag;
    225 
    226     private transient SipProviderImpl sipProvider;
    227 
    228     private boolean terminateOnBye;
    229 
    230     private transient boolean byeSent; // Flag set when BYE is sent, to disallow new
    231 
    232     // requests
    233 
    234     private Address remoteTarget;
    235 
    236     private EventHeader eventHeader; // for Subscribe notify
    237 
    238     // Stores the last OK for the INVITE
    239     // Used in createAck.
    240     private transient long lastInviteOkReceived;
    241 
    242     private transient Semaphore ackSem = new Semaphore(1);
    243 
    244     private transient int reInviteWaitTime = 100;
    245 
    246     private transient DialogDeleteTask dialogDeleteTask;
    247 
    248 	private transient DialogDeleteIfNoAckSentTask dialogDeleteIfNoAckSentTask;
    249 
    250     private transient boolean isAcknowledged;
    251 
    252     private transient long highestSequenceNumberAcknowledged = -1;
    253 
    254     private boolean isBackToBackUserAgent;
    255 
    256     private boolean sequenceNumberValidation = true;
    257 
    258     // List of event listeners for this dialog
    259 	private transient Set<SIPDialogEventListener> eventListeners;
    260 	// added for Issue 248 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=248
    261 	private Semaphore timerTaskLock = new Semaphore(1);
    262 
    263 	// We store here the useful data from the first transaction without having to
    264 	// keep the whole transaction object for the duration of the dialog. It also
    265 	// contains the non-transient information used in the replication of dialogs.
    266 	protected boolean firstTransactionSecure;
    267 	protected boolean firstTransactionSeen;
    268     protected String firstTransactionMethod;
    269     protected String firstTransactionId;
    270     protected boolean firstTransactionIsServerTransaction;
    271     protected int firstTransactionPort = 5060;
    272     protected Contact contactHeader;
    273 
    274     // //////////////////////////////////////////////////////
    275     // Inner classes
    276     // //////////////////////////////////////////////////////
    277 
    278     /**
    279      * This task waits till a pending ACK has been recorded and then sends out a re-INVITE. This
    280      * is to prevent interleaving INVITEs ( which will result in a 493 from the UA that receives
    281      * the out of order INVITE). This is primarily for B2BUA support. A B2BUA may send a delayed
    282      * ACK while it does mid call codec renegotiation. In the meanwhile, it cannot send an intervening
    283      * re-INVITE otherwise the othr end will respond with a REQUEST_PENDING. We want to avoid this
    284      * condition. Hence we wait till the ACK for the previous re-INVITE has been sent before
    285      * sending the next re-INVITE.
    286      */
    287     public class ReInviteSender implements Runnable, Serializable {
    288         private static final long serialVersionUID = 1019346148741070635L;
    289         ClientTransaction ctx;
    290 
    291         public void terminate() {
    292             try {
    293                 ctx.terminate();
    294                 Thread.currentThread().interrupt();
    295             } catch (ObjectInUseException e) {
    296                 sipStack.getStackLogger().logError("unexpected error", e);
    297             }
    298         }
    299 
    300         public ReInviteSender(ClientTransaction ctx) {
    301             this.ctx = ctx;
    302         }
    303 
    304         public void run() {
    305             try {
    306                 long timeToWait = 0;
    307                 long startTime = System.currentTimeMillis();
    308 
    309                 if (!SIPDialog.this.takeAckSem()) {
    310                     /*
    311                      * Could not send re-INVITE fire a timeout on the INVITE.
    312                      */
    313                 	if (sipStack.isLoggingEnabled())
    314                 		sipStack.getStackLogger().logError(
    315                             "Could not send re-INVITE time out ClientTransaction");
    316                     ((SIPClientTransaction) ctx).fireTimeoutTimer();
    317                     /*
    318                      * Send BYE to the Dialog.
    319                      */
    320                     if ( sipProvider.getSipListener() != null && sipProvider.getSipListener() instanceof SipListenerExt ) {
    321                         raiseErrorEvent(SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT);
    322                     } else {
    323                         Request byeRequest = SIPDialog.this.createRequest(Request.BYE);
    324                         if ( MessageFactoryImpl.getDefaultUserAgentHeader() != null ) {
    325                             byeRequest.addHeader(MessageFactoryImpl.getDefaultUserAgentHeader());
    326                         }
    327                         ReasonHeader reasonHeader = new Reason();
    328                         reasonHeader.setCause(1024);
    329                         reasonHeader.setText("Timed out waiting to re-INVITE");
    330                         byeRequest.addHeader(reasonHeader);
    331                         ClientTransaction byeCtx = SIPDialog.this.getSipProvider().getNewClientTransaction(byeRequest);
    332                         SIPDialog.this.sendRequest(byeCtx);
    333                         return;
    334                     }
    335                 }
    336                 if (getState() != DialogState.TERMINATED) {
    337 
    338                     timeToWait = System.currentTimeMillis() - startTime;
    339                 }
    340 
    341                 /*
    342                  * If we had to wait for ACK then wait for the ACK to actually get to the other
    343                  * side. Wait for any ACK retransmissions to finish. Then send out the request.
    344                  * This is a hack in support of some UA that want re-INVITEs to be spaced out in
    345                  * time ( else they return a 400 error code ).
    346                  */
    347                 try {
    348                     if (timeToWait != 0) {
    349                         Thread.sleep(SIPDialog.this.reInviteWaitTime);
    350                     }
    351                 } catch (InterruptedException ex) {
    352                 	if (sipStack.isLoggingEnabled())
    353                 		sipStack.getStackLogger().logDebug("Interrupted sleep");
    354                     return;
    355                 }
    356                 if (SIPDialog.this.getState() != DialogState.TERMINATED) {
    357                     SIPDialog.this.sendRequest(ctx, true);
    358                 }
    359                 if (sipStack.isLoggingEnabled())
    360                 	sipStack.getStackLogger().logDebug("re-INVITE successfully sent");
    361             } catch (Exception ex) {
    362                 sipStack.getStackLogger().logError("Error sending re-INVITE", ex);
    363             } finally {
    364                 this.ctx = null;
    365             }
    366         }
    367     }
    368 
    369 	class LingerTimer extends SIPStackTimerTask implements Serializable {
    370 
    371         public LingerTimer() {
    372 
    373         }
    374 
    375         protected void runTask() {
    376             SIPDialog dialog = SIPDialog.this;
    377             if(eventListeners != null) {
    378             	eventListeners.clear();
    379             }
    380             timerTaskLock = null;
    381             sipStack.removeDialog(dialog);
    382         }
    383 
    384     }
    385 
    386     class DialogTimerTask extends SIPStackTimerTask implements Serializable {
    387         int nRetransmissions;
    388 
    389         SIPServerTransaction transaction;
    390 
    391         public DialogTimerTask(SIPServerTransaction transaction) {
    392             this.transaction = transaction;
    393             this.nRetransmissions = 0;
    394         }
    395 
    396         protected void runTask() {
    397             // If I ACK has not been seen on Dialog,
    398             // resend last response.
    399             SIPDialog dialog = SIPDialog.this;
    400             if (sipStack.isLoggingEnabled())
    401                 sipStack.getStackLogger().logDebug("Running dialog timer");
    402             nRetransmissions++;
    403             SIPServerTransaction transaction = this.transaction;
    404             /*
    405              * Issue 106. Section 13.3.1.4 RFC 3261 The 2xx response is passed to the transport
    406              * with an interval that starts at T1 seconds and doubles for each retransmission
    407              * until it reaches T2 seconds If the server retransmits the 2xx response for 64*T1
    408              * seconds without receiving an ACK, the dialog is confirmed, but the session SHOULD
    409              * be terminated.
    410              */
    411 
    412             if (nRetransmissions > 64 * SIPTransaction.T1) {
    413                 if (sipProvider.getSipListener() != null && sipProvider.getSipListener() instanceof SipListenerExt ) {
    414                     raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT);
    415                 } else  {
    416                     dialog.delete();
    417                 }
    418                 if (transaction != null
    419                         && transaction.getState() != javax.sip.TransactionState.TERMINATED) {
    420                     transaction.raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
    421                 }
    422             } else if ((!dialog.ackSeen) && (transaction != null)) {
    423                 // Retransmit to 200 until ack receivedialog.
    424                 SIPResponse response = transaction.getLastResponse();
    425                 if (response.getStatusCode() == 200) {
    426                     try {
    427 
    428                         // resend the last response.
    429                         if (dialog.toRetransmitFinalResponse(transaction.T2))
    430                             transaction.sendMessage(response);
    431 
    432                     } catch (IOException ex) {
    433 
    434                         raiseIOException(transaction.getPeerAddress(), transaction.getPeerPort(),
    435                                 transaction.getPeerProtocol());
    436 
    437                     } finally {
    438                         // Need to fire the timer so
    439                         // transaction will eventually
    440                         // time out whether or not
    441                         // the IOException occurs
    442                         // Note that this firing also
    443                         // drives Listener timeout.
    444                         SIPTransactionStack stack = dialog.sipStack;
    445                         if (stack.isLoggingEnabled()) {
    446                             stack.getStackLogger().logDebug("resend 200 response from " + dialog);
    447                         }
    448                         transaction.fireTimer();
    449                     }
    450                 }
    451             }
    452 
    453             // Stop running this timer if the dialog is in the
    454             // confirmed state or ack seen if retransmit filter on.
    455             if (dialog.isAckSeen() || dialog.dialogState == TERMINATED_STATE) {
    456                 this.transaction = null;
    457                 this.cancel();
    458 
    459             }
    460 
    461         }
    462 
    463     }
    464 
    465     /**
    466      * This timer task is used to garbage collect the dialog after some time.
    467      *
    468      */
    469 
    470     class DialogDeleteTask extends SIPStackTimerTask implements Serializable {
    471 
    472         protected void runTask() {
    473             delete();
    474         }
    475 
    476     }
    477 
    478     /**
    479      * This timer task is used to garbage collect the dialog after some time.
    480      *
    481      */
    482 
    483     class DialogDeleteIfNoAckSentTask extends SIPStackTimerTask implements Serializable {
    484         private long seqno;
    485 
    486         public DialogDeleteIfNoAckSentTask(long seqno) {
    487             this.seqno = seqno;
    488         }
    489 
    490         protected void runTask() {
    491             if (SIPDialog.this.highestSequenceNumberAcknowledged < seqno) {
    492                 /*
    493                  * Did not send ACK so we need to delete the dialog.
    494                  * B2BUA NOTE: we may want to send BYE to the Dialog at this
    495                  * point. Do we want to make this behavior tailorable?
    496                  */
    497             	dialogDeleteIfNoAckSentTask = null;
    498                 if ( !SIPDialog.this.isBackToBackUserAgent) {
    499                 	if (sipStack.isLoggingEnabled())
    500                 		sipStack.getStackLogger().logError("ACK Was not sent. killing dialog");
    501                 	if ( ((SipProviderImpl)sipProvider).getSipListener() instanceof SipListenerExt ){
    502                 	    raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT);
    503                 	} else {
    504                 	    delete();
    505                 	}
    506                 } else {
    507                 	if (sipStack.isLoggingEnabled())
    508                 		sipStack.getStackLogger().logError("ACK Was not sent. Sending BYE");
    509                 	   if ( ((SipProviderImpl)sipProvider).getSipListener() instanceof SipListenerExt ){
    510                 	       raiseErrorEvent(SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT);
    511                 	   } else {
    512 
    513                         /*
    514                          * Send BYE to the Dialog.
    515                          * This will be removed for the next spec revision.
    516                          */
    517                         try {
    518                             Request byeRequest = SIPDialog.this.createRequest(Request.BYE);
    519                             if ( MessageFactoryImpl.getDefaultUserAgentHeader() != null ) {
    520                                 byeRequest.addHeader(MessageFactoryImpl.getDefaultUserAgentHeader());
    521                             }
    522                             ReasonHeader reasonHeader = new Reason();
    523                             reasonHeader.setProtocol("SIP");
    524                             reasonHeader.setCause(1025);
    525                             reasonHeader.setText("Timed out waiting to send ACK");
    526                             byeRequest.addHeader(reasonHeader);
    527                             ClientTransaction byeCtx = SIPDialog.this.getSipProvider().getNewClientTransaction(byeRequest);
    528                             SIPDialog.this.sendRequest(byeCtx);
    529                             return;
    530                         } catch (Exception ex) {
    531                             SIPDialog.this.delete();
    532                         }
    533                     }
    534                 }
    535             }
    536         }
    537 
    538     }
    539 
    540     // ///////////////////////////////////////////////////////////
    541     // Constructors.
    542     // ///////////////////////////////////////////////////////////
    543     /**
    544      * Protected Dialog constructor.
    545      */
    546     private SIPDialog(SipProviderImpl provider) {
    547         this.terminateOnBye = true;
    548         this.routeList = new RouteList();
    549         this.dialogState = NULL_STATE; // not yet initialized.
    550         localSequenceNumber = 0;
    551         remoteSequenceNumber = -1;
    552         this.sipProvider = provider;
    553         eventListeners = new CopyOnWriteArraySet<SIPDialogEventListener>();
    554     }
    555 
    556     private void recordStackTrace() {
    557       StringWriter stringWriter = new StringWriter();
    558       PrintWriter writer = new PrintWriter(stringWriter);
    559       new Exception().printStackTrace(writer);
    560        this.stackTrace = stringWriter.getBuffer().toString();
    561     }
    562 
    563     /**
    564      * Constructor given the first transaction.
    565      *
    566      * @param transaction is the first transaction.
    567      */
    568     public SIPDialog(SIPTransaction transaction) {
    569         this(transaction.getSipProvider());
    570 
    571         SIPRequest sipRequest = (SIPRequest) transaction.getRequest();
    572         this.callIdHeader = sipRequest.getCallId();
    573         this.earlyDialogId = sipRequest.getDialogId(false);
    574         if (transaction == null)
    575             throw new NullPointerException("Null tx");
    576         this.sipStack = transaction.sipStack;
    577 
    578         // this.defaultRouter = new DefaultRouter((SipStack) sipStack,
    579         // sipStack.outboundProxy);
    580 
    581         this.sipProvider = (SipProviderImpl) transaction.getSipProvider();
    582         if (sipProvider == null)
    583             throw new NullPointerException("Null Provider!");
    584         this.addTransaction(transaction);
    585         if (sipStack.isLoggingEnabled()) {
    586             sipStack.getStackLogger().logDebug("Creating a dialog : " + this);
    587             sipStack.getStackLogger().logDebug(
    588                     "provider port = " + this.sipProvider.getListeningPoint().getPort());
    589             sipStack.getStackLogger().logStackTrace();
    590         }
    591         this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent;
    592         addEventListener(sipStack);
    593     }
    594 
    595     /**
    596      * Constructor given a transaction and a response.
    597      *
    598      * @param transaction -- the transaction ( client/server)
    599      * @param sipResponse -- response with the appropriate tags.
    600      */
    601     public SIPDialog(SIPClientTransaction transaction, SIPResponse sipResponse) {
    602         this(transaction);
    603         if (sipResponse == null)
    604             throw new NullPointerException("Null SipResponse");
    605         this.setLastResponse(transaction, sipResponse);
    606         this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent;
    607     }
    608 
    609     /**
    610      * create a sip dialog with a response ( no tx)
    611      */
    612     public SIPDialog(SipProviderImpl sipProvider, SIPResponse sipResponse) {
    613         this(sipProvider);
    614         this.sipStack = (SIPTransactionStack) sipProvider.getSipStack();
    615         this.setLastResponse(null, sipResponse);
    616         this.localSequenceNumber = sipResponse.getCSeq().getSeqNumber();
    617         this.originalLocalSequenceNumber = localSequenceNumber;
    618         this.myTag = sipResponse.getFrom().getTag();
    619         this.hisTag = sipResponse.getTo().getTag();
    620         this.localParty = sipResponse.getFrom().getAddress();
    621         this.remoteParty = sipResponse.getTo().getAddress();
    622         this.method = sipResponse.getCSeq().getMethod();
    623         this.callIdHeader = sipResponse.getCallId();
    624         this.serverTransactionFlag = false;
    625         if (sipStack.isLoggingEnabled()) {
    626             sipStack.getStackLogger().logDebug("Creating a dialog : " + this);
    627             sipStack.getStackLogger().logStackTrace();
    628         }
    629         this.isBackToBackUserAgent = sipStack.isBackToBackUserAgent;
    630         addEventListener(sipStack);
    631     }
    632 
    633     // ///////////////////////////////////////////////////////////
    634     // Private methods
    635     // ///////////////////////////////////////////////////////////
    636     /**
    637      * A debugging print routine.
    638      */
    639     private void printRouteList() {
    640         if (sipStack.isLoggingEnabled()) {
    641             sipStack.getStackLogger().logDebug("this : " + this);
    642             sipStack.getStackLogger().logDebug("printRouteList : " + this.routeList.encode());
    643         }
    644     }
    645 
    646     /**
    647      * Return true if this is a client dialog.
    648      *
    649      * @return true if the transaction that created this dialog is a client transaction and false
    650      *         otherwise.
    651      */
    652     private boolean isClientDialog() {
    653         SIPTransaction transaction = (SIPTransaction) this.getFirstTransaction();
    654         return transaction instanceof SIPClientTransaction;
    655     }
    656 
    657     /**
    658      * Raise an io exception for asyncrhonous retransmission of responses
    659      *
    660      * @param host -- host to where the io was headed
    661      * @param port -- remote port
    662      * @param protocol -- protocol (udp/tcp/tls)
    663      */
    664     private void raiseIOException(String host, int port, String protocol) {
    665         // Error occured in retransmitting response.
    666         // Deliver the error event to the listener
    667         // Kill the dialog.
    668 
    669         IOExceptionEvent ioError = new IOExceptionEvent(this, host, port, protocol);
    670         sipProvider.handleEvent(ioError, null);
    671 
    672         setState(SIPDialog.TERMINATED_STATE);
    673     }
    674 
    675     /**
    676      * Raise a dialog timeout if an ACK has not been sent or received
    677      *
    678      * @param dialogTimeoutError
    679      */
    680     private void raiseErrorEvent(int dialogTimeoutError) {
    681 		// Error event to send to all listeners
    682 		SIPDialogErrorEvent newErrorEvent;
    683 		// Iterator through the list of listeners
    684 		Iterator<SIPDialogEventListener> listenerIterator;
    685 		// Next listener in the list
    686 		SIPDialogEventListener nextListener;
    687 
    688 		// Create the error event
    689 		newErrorEvent = new SIPDialogErrorEvent(this, dialogTimeoutError);
    690 
    691 		// Loop through all listeners of this transaction
    692 		synchronized (eventListeners) {
    693 			listenerIterator = eventListeners.iterator();
    694 			while (listenerIterator.hasNext()) {
    695 				// Send the event to the next listener
    696 				nextListener = (SIPDialogEventListener) listenerIterator.next();
    697 				nextListener.dialogErrorEvent(newErrorEvent);
    698 			}
    699 		}
    700 		// Clear the event listeners after propagating the error.
    701 		eventListeners.clear();
    702 		// Errors always terminate a dialog except if a timeout has occured because an ACK was not sent or received, then it is the responsibility of the app to terminate
    703 		// the dialog, either by sending a BYE or by calling delete() on the dialog
    704 		if(dialogTimeoutError != SIPDialogErrorEvent.DIALOG_ACK_NOT_SENT_TIMEOUT &&
    705 		        dialogTimeoutError != SIPDialogErrorEvent.DIALOG_ACK_NOT_RECEIVED_TIMEOUT &&
    706 		        dialogTimeoutError != SIPDialogErrorEvent.DIALOG_REINVITE_TIMEOUT ) {
    707 			delete();
    708 		}
    709 		// we stop the timer in any case
    710 		stopTimer();
    711 	}
    712 
    713     /**
    714      * Set the remote party for this Dialog.
    715      *
    716      * @param sipMessage -- SIP Message to extract the relevant information from.
    717      */
    718     private void setRemoteParty(SIPMessage sipMessage) {
    719 
    720         if (!isServer()) {
    721 
    722             this.remoteParty = sipMessage.getTo().getAddress();
    723         } else {
    724             this.remoteParty = sipMessage.getFrom().getAddress();
    725 
    726         }
    727         if (sipStack.isLoggingEnabled()) {
    728             sipStack.getStackLogger().logDebug("settingRemoteParty " + this.remoteParty);
    729         }
    730     }
    731 
    732     /**
    733      * Add a route list extracted from a record route list. If this is a server dialog then we
    734      * assume that the record are added to the route list IN order. If this is a client dialog
    735      * then we assume that the record route headers give us the route list to add in reverse
    736      * order.
    737      *
    738      * @param recordRouteList -- the record route list from the incoming message.
    739      */
    740 
    741     private void addRoute(RecordRouteList recordRouteList) {
    742         try {
    743             if (this.isClientDialog()) {
    744                 // This is a client dialog so we extract the record
    745                 // route from the response and reverse its order to
    746                 // careate a route list.
    747                 this.routeList = new RouteList();
    748                 // start at the end of the list and walk backwards
    749 
    750                 ListIterator li = recordRouteList.listIterator(recordRouteList.size());
    751                 boolean addRoute = true;
    752                 while (li.hasPrevious()) {
    753                     RecordRoute rr = (RecordRoute) li.previous();
    754 
    755                     if (addRoute) {
    756                         Route route = new Route();
    757                         AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress())
    758                                 .clone());
    759 
    760                         route.setAddress(address);
    761                         route.setParameters((NameValueList) rr.getParameters().clone());
    762 
    763                         this.routeList.add(route);
    764                     }
    765                 }
    766             } else {
    767                 // This is a server dialog. The top most record route
    768                 // header is the one that is closest to us. We extract the
    769                 // route list in the same order as the addresses in the
    770                 // incoming request.
    771                 this.routeList = new RouteList();
    772                 ListIterator li = recordRouteList.listIterator();
    773                 boolean addRoute = true;
    774                 while (li.hasNext()) {
    775                     RecordRoute rr = (RecordRoute) li.next();
    776 
    777                     if (addRoute) {
    778                         Route route = new Route();
    779                         AddressImpl address = ((AddressImpl) ((AddressImpl) rr.getAddress())
    780                                 .clone());
    781                         route.setAddress(address);
    782                         route.setParameters((NameValueList) rr.getParameters().clone());
    783                         routeList.add(route);
    784                     }
    785                 }
    786             }
    787         } finally {
    788             if (sipStack.getStackLogger().isLoggingEnabled()) {
    789                 Iterator it = routeList.iterator();
    790 
    791                 while (it.hasNext()) {
    792                     SipURI sipUri = (SipURI) (((Route) it.next()).getAddress().getURI());
    793                     if (!sipUri.hasLrParam()) {
    794                     	if (sipStack.isLoggingEnabled()) {
    795                     		sipStack.getStackLogger().logWarning(
    796                                 "NON LR route in Route set detected for dialog : " + this);
    797                         	sipStack.getStackLogger().logStackTrace();
    798                     	}
    799                     }
    800                 }
    801             }
    802         }
    803     }
    804 
    805     /**
    806      * Add a route list extacted from the contact list of the incoming message.
    807      *
    808      * @param contactList -- contact list extracted from the incoming message.
    809      *
    810      */
    811 
    812     void setRemoteTarget(ContactHeader contact) {
    813         this.remoteTarget = contact.getAddress();
    814         if (sipStack.isLoggingEnabled()) {
    815             sipStack.getStackLogger().logDebug("Dialog.setRemoteTarget: " + this.remoteTarget);
    816             sipStack.getStackLogger().logStackTrace();
    817         }
    818 
    819     }
    820 
    821     /**
    822      * Extract the route information from this SIP Message and add the relevant information to the
    823      * route set.
    824      *
    825      * @param sipMessage is the SIP message for which we want to add the route.
    826      */
    827     private synchronized void addRoute(SIPResponse sipResponse) {
    828 
    829         try {
    830             if (sipStack.isLoggingEnabled()) {
    831                 sipStack.getStackLogger().logDebug(
    832                         "setContact: dialogState: " + this + "state = " + this.getState());
    833             }
    834             if (sipResponse.getStatusCode() == 100) {
    835                 // Do nothing for trying messages.
    836                 return;
    837             } else if (this.dialogState == TERMINATED_STATE) {
    838                 // Do nothing if the dialog state is terminated.
    839                 return;
    840             } else if (this.dialogState == CONFIRMED_STATE) {
    841                 // cannot add route list after the dialog is initialized.
    842                 // Remote target is updated on RE-INVITE but not
    843                 // the route list.
    844                 if (sipResponse.getStatusCode() / 100 == 2 && !this.isServer()) {
    845                     ContactList contactList = sipResponse.getContactHeaders();
    846                     if (contactList != null
    847                             && SIPRequest.isTargetRefresh(sipResponse.getCSeq().getMethod())) {
    848                         this.setRemoteTarget((ContactHeader) contactList.getFirst());
    849                     }
    850                 }
    851                 return;
    852             }
    853 
    854             // Update route list on response if I am a client dialog.
    855             if (!isServer()) {
    856 
    857                 // only update the route set if the dialog is not in the confirmed state.
    858                 if (this.getState() != DialogState.CONFIRMED
    859                         && this.getState() != DialogState.TERMINATED) {
    860                     RecordRouteList rrlist = sipResponse.getRecordRouteHeaders();
    861                     // Add the route set from the incoming response in reverse
    862                     // order for record route headers.
    863                     if (rrlist != null) {
    864                         this.addRoute(rrlist);
    865                     } else {
    866                         // Set the rotue list to the last seen route list.
    867                         this.routeList = new RouteList();
    868                     }
    869                 }
    870 
    871                 ContactList contactList = sipResponse.getContactHeaders();
    872                 if (contactList != null) {
    873                     this.setRemoteTarget((ContactHeader) contactList.getFirst());
    874                 }
    875             }
    876 
    877         } finally {
    878             if (sipStack.isLoggingEnabled()) {
    879                 sipStack.getStackLogger().logStackTrace();
    880             }
    881         }
    882     }
    883 
    884     /**
    885      * Get a cloned copy of route list for the Dialog.
    886      *
    887      * @return -- a cloned copy of the dialog route list.
    888      */
    889     private synchronized RouteList getRouteList() {
    890         if (sipStack.isLoggingEnabled())
    891             sipStack.getStackLogger().logDebug("getRouteList " + this);
    892         // Find the top via in the route list.
    893         ListIterator li;
    894         RouteList retval = new RouteList();
    895 
    896         retval = new RouteList();
    897         if (this.routeList != null) {
    898             li = routeList.listIterator();
    899             while (li.hasNext()) {
    900                 Route route = (Route) li.next();
    901                 retval.add((Route) route.clone());
    902             }
    903         }
    904 
    905         if (sipStack.isLoggingEnabled()) {
    906             sipStack.getStackLogger().logDebug("----- ");
    907             sipStack.getStackLogger().logDebug("getRouteList for " + this);
    908             if (retval != null)
    909                 sipStack.getStackLogger().logDebug("RouteList = " + retval.encode());
    910             if (routeList != null)
    911                 sipStack.getStackLogger().logDebug("myRouteList = " + routeList.encode());
    912             sipStack.getStackLogger().logDebug("----- ");
    913         }
    914         return retval;
    915     }
    916 
    917     void setRouteList(RouteList routeList) {
    918     	this.routeList = routeList;
    919     }
    920 
    921     /**
    922      * Sends ACK Request to the remote party of this Dialogue.
    923      *
    924      *
    925      * @param request the new ACK Request message to send.
    926      * @param throwIOExceptionAsSipException - throws SipException if IOEx encountered. Otherwise,
    927      *        no exception is propagated.
    928      * @param releaseAckSem - release ack semaphore.
    929      * @throws SipException if implementation cannot send the ACK Request for any other reason
    930      *
    931      */
    932     private void sendAck(Request request, boolean throwIOExceptionAsSipException)
    933             throws SipException {
    934         SIPRequest ackRequest = (SIPRequest) request;
    935         if (sipStack.isLoggingEnabled())
    936             sipStack.getStackLogger().logDebug("sendAck" + this);
    937 
    938         if (!ackRequest.getMethod().equals(Request.ACK))
    939             throw new SipException("Bad request method -- should be ACK");
    940         if (this.getState() == null || this.getState().getValue() == EARLY_STATE) {
    941             if (sipStack.isLoggingEnabled()) {
    942                 sipStack.getStackLogger().logError(
    943                         "Bad Dialog State for " + this + " dialogID = " + this.getDialogId());
    944             }
    945             throw new SipException("Bad dialog state " + this.getState());
    946         }
    947 
    948         if (!this.getCallId().getCallId().equals(((SIPRequest) request).getCallId().getCallId())) {
    949             if (sipStack.isLoggingEnabled()) {
    950                 sipStack.getStackLogger().logError("CallID " + this.getCallId());
    951                 sipStack.getStackLogger().logError(
    952                         "RequestCallID = " + ackRequest.getCallId().getCallId());
    953                 sipStack.getStackLogger().logError("dialog =  " + this);
    954             }
    955             throw new SipException("Bad call ID in request");
    956         }
    957         try {
    958             if (sipStack.isLoggingEnabled()) {
    959                 sipStack.getStackLogger().logDebug(
    960                         "setting from tag For outgoing ACK= " + this.getLocalTag());
    961                 sipStack.getStackLogger().logDebug(
    962                         "setting To tag for outgoing ACK = " + this.getRemoteTag());
    963                 sipStack.getStackLogger().logDebug("ack = " + ackRequest);
    964             }
    965             if (this.getLocalTag() != null)
    966                 ackRequest.getFrom().setTag(this.getLocalTag());
    967             if (this.getRemoteTag() != null)
    968                 ackRequest.getTo().setTag(this.getRemoteTag());
    969         } catch (ParseException ex) {
    970             throw new SipException(ex.getMessage());
    971         }
    972 
    973         Hop hop = sipStack.getNextHop(ackRequest);
    974         // Hop hop = defaultRouter.getNextHop(ackRequest);
    975         if (hop == null)
    976             throw new SipException("No route!");
    977         try {
    978             if (sipStack.isLoggingEnabled())
    979                 sipStack.getStackLogger().logDebug("hop = " + hop);
    980             ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider.getListeningPoint(hop
    981                     .getTransport());
    982             if (lp == null)
    983                 throw new SipException("No listening point for this provider registered at "
    984                         + hop);
    985             InetAddress inetAddress = InetAddress.getByName(hop.getHost());
    986             MessageChannel messageChannel = lp.getMessageProcessor().createMessageChannel(
    987                     inetAddress, hop.getPort());
    988             boolean releaseAckSem = false;
    989             long cseqNo = ((SIPRequest)request).getCSeq().getSeqNumber();
    990             if (!this.isAckSent(cseqNo)) {
    991                 releaseAckSem = true;
    992             }
    993 
    994             this.setLastAckSent(ackRequest);
    995             messageChannel.sendMessage(ackRequest);
    996             // Sent atleast one ACK.
    997             this.isAcknowledged = true;
    998             this.highestSequenceNumberAcknowledged = Math.max(this.highestSequenceNumberAcknowledged,
    999                     ((SIPRequest)ackRequest).getCSeq().getSeqNumber());
   1000             if (releaseAckSem && this.isBackToBackUserAgent) {
   1001                 this.releaseAckSem();
   1002             } else {
   1003                 if ( sipStack.isLoggingEnabled() ) {
   1004                     sipStack.getStackLogger().logDebug("Not releasing ack sem for " + this + " isAckSent " + releaseAckSem );
   1005                 }
   1006             }
   1007         } catch (IOException ex) {
   1008             if (throwIOExceptionAsSipException)
   1009                 throw new SipException("Could not send ack", ex);
   1010             this.raiseIOException(hop.getHost(), hop.getPort(), hop.getTransport());
   1011         } catch (SipException ex) {
   1012             if (sipStack.isLoggingEnabled())
   1013                 sipStack.getStackLogger().logException(ex);
   1014             throw ex;
   1015         } catch (Exception ex) {
   1016             if (sipStack.isLoggingEnabled())
   1017                 sipStack.getStackLogger().logException(ex);
   1018             throw new SipException("Could not create message channel", ex);
   1019         }
   1020         if (this.dialogDeleteTask != null) {
   1021             this.dialogDeleteTask.cancel();
   1022             this.dialogDeleteTask = null;
   1023         }
   1024         this.ackSeen = true;
   1025 
   1026     }
   1027 
   1028     // /////////////////////////////////////////////////////////////
   1029     // Package local methods
   1030     // /////////////////////////////////////////////////////////////
   1031 
   1032     /**
   1033      * Set the stack address. Prevent us from routing messages to ourselves.
   1034      *
   1035      * @param sipStack the address of the SIP stack.
   1036      *
   1037      */
   1038     void setStack(SIPTransactionStack sipStack) {
   1039         this.sipStack = sipStack;
   1040 
   1041     }
   1042 
   1043     /**
   1044      * Get the stack .
   1045      *
   1046      * @return sipStack the SIP stack of the dialog.
   1047      *
   1048      */
   1049     SIPTransactionStack getStack() {
   1050         return sipStack;
   1051     }
   1052 
   1053     /**
   1054      * Return True if this dialog is terminated on BYE.
   1055      *
   1056      */
   1057     boolean isTerminatedOnBye() {
   1058 
   1059         return this.terminateOnBye;
   1060     }
   1061 
   1062     /**
   1063      * Mark that the dialog has seen an ACK.
   1064      */
   1065     void ackReceived(SIPRequest sipRequest) {
   1066 
   1067         // Suppress retransmission of the final response
   1068         if (this.ackSeen)
   1069             return;
   1070         SIPServerTransaction tr = this.getInviteTransaction();
   1071         if (tr != null) {
   1072             if (tr.getCSeq() == sipRequest.getCSeq().getSeqNumber()) {
   1073             	acquireTimerTaskSem();
   1074             	try {
   1075 	                if (this.timerTask != null) {
   1076 	                	this.timerTask.cancel();
   1077 		                this.timerTask = null;
   1078 	                }
   1079             	} finally {
   1080             		releaseTimerTaskSem();
   1081             	}
   1082                 this.ackSeen = true;
   1083                 if (this.dialogDeleteTask != null) {
   1084                     this.dialogDeleteTask.cancel();
   1085                     this.dialogDeleteTask = null;
   1086                 }
   1087                 this.setLastAckReceived(sipRequest);
   1088                 if (sipStack.isLoggingEnabled()) {
   1089                     sipStack.getStackLogger().logDebug(
   1090                             "ackReceived for " + ((SIPTransaction) tr).getMethod());
   1091                     this.ackLine = sipStack.getStackLogger().getLineCount();
   1092                     this.printDebugInfo();
   1093                 }
   1094                 if (this.isBackToBackUserAgent) {
   1095                     this.releaseAckSem();
   1096                 }
   1097                 this.setState(CONFIRMED_STATE);
   1098             }
   1099         }
   1100     }
   1101 
   1102     /**
   1103      * Return true if a terminated event was delivered to the application as a result of the
   1104      * dialog termination.
   1105      *
   1106      */
   1107     synchronized boolean testAndSetIsDialogTerminatedEventDelivered() {
   1108         boolean retval = this.dialogTerminatedEventDelivered;
   1109         this.dialogTerminatedEventDelivered = true;
   1110         return retval;
   1111     }
   1112 
   1113     // /////////////////////////////////////////////////////////
   1114     // Public methods
   1115     // /////////////////////////////////////////////////////////
   1116 
   1117     /**
   1118 	 * Adds a new event listener to this dialog.
   1119 	 *
   1120 	 * @param newListener
   1121 	 *            Listener to add.
   1122 	 */
   1123 	public void addEventListener(SIPDialogEventListener newListener) {
   1124 		eventListeners.add(newListener);
   1125 	}
   1126 
   1127 	/**
   1128 	 * Removed an event listener from this dialog.
   1129 	 *
   1130 	 * @param oldListener
   1131 	 *            Listener to remove.
   1132 	 */
   1133 	public void removeEventListener(SIPDialogEventListener oldListener) {
   1134 		eventListeners.remove(oldListener);
   1135 	}
   1136 
   1137     /*
   1138      * @see javax.sip.Dialog#setApplicationData()
   1139      */
   1140     public void setApplicationData(Object applicationData) {
   1141         this.applicationData = applicationData;
   1142     }
   1143 
   1144     /*
   1145      * (non-Javadoc)
   1146      *
   1147      * @see javax.sip.Dialog#getApplicationData()
   1148      */
   1149     public Object getApplicationData() {
   1150         return this.applicationData;
   1151     }
   1152 
   1153     /**
   1154      * Updates the next consumable seqno.
   1155      *
   1156      */
   1157     public synchronized void requestConsumed() {
   1158         this.nextSeqno = Long.valueOf(this.getRemoteSeqNumber() + 1);
   1159 
   1160         if (sipStack.isLoggingEnabled()) {
   1161             this.sipStack.getStackLogger().logDebug(
   1162                     "Request Consumed -- next consumable Request Seqno = " + this.nextSeqno);
   1163         }
   1164 
   1165     }
   1166 
   1167     /**
   1168      * Return true if this request can be consumed by the dialog.
   1169      *
   1170      * @param dialogRequest is the request to check with the dialog.
   1171      * @return true if the dialogRequest sequence number matches the next consumable seqno.
   1172      */
   1173     public synchronized boolean isRequestConsumable(SIPRequest dialogRequest) {
   1174         // have not yet set remote seqno - this is a fresh
   1175         if (dialogRequest.getMethod().equals(Request.ACK))
   1176             throw new RuntimeException("Illegal method");
   1177 
   1178         // For loose validation this function is delegated to the application
   1179         if (!this.isSequnceNumberValidation()) {
   1180             return true;
   1181         }
   1182 
   1183         // JvB: Acceptable iff remoteCSeq < cseq. remoteCSeq==-1
   1184         // when not defined yet, so that works too
   1185         return remoteSequenceNumber < dialogRequest.getCSeq().getSeqNumber();
   1186     }
   1187 
   1188     /**
   1189      * This method is called when a forked dialog is created from the client side. It starts a
   1190      * timer task. If the timer task expires before an ACK is sent then the dialog is cancelled
   1191      * (i.e. garbage collected ).
   1192      *
   1193      */
   1194     public void doDeferredDelete() {
   1195         if (sipStack.getTimer() == null)
   1196             this.setState(TERMINATED_STATE);
   1197         else {
   1198             this.dialogDeleteTask = new DialogDeleteTask();
   1199             // Delete the transaction after the max ack timeout.
   1200             sipStack.getTimer().schedule(this.dialogDeleteTask,
   1201                     SIPTransaction.TIMER_H * SIPTransactionStack.BASE_TIMER_INTERVAL);
   1202         }
   1203 
   1204     }
   1205 
   1206     /**
   1207      * Set the state for this dialog.
   1208      *
   1209      * @param state is the state to set for the dialog.
   1210      */
   1211 
   1212     public void setState(int state) {
   1213         if (sipStack.isLoggingEnabled()) {
   1214             sipStack.getStackLogger().logDebug(
   1215                     "Setting dialog state for " + this + "newState = " + state);
   1216             sipStack.getStackLogger().logStackTrace();
   1217             if (state != NULL_STATE && state != this.dialogState)
   1218                 if (sipStack.isLoggingEnabled()) {
   1219                     sipStack.getStackLogger().logDebug(
   1220                             this + "  old dialog state is " + this.getState());
   1221                     sipStack.getStackLogger().logDebug(
   1222                             this + "  New dialog state is " + DialogState.getObject(state));
   1223                 }
   1224 
   1225         }
   1226         this.dialogState = state;
   1227         // Dialog is in terminated state set it up for GC.
   1228         if (state == TERMINATED_STATE) {
   1229             if (sipStack.getTimer() != null) { // may be null after shutdown
   1230                 sipStack.getTimer().schedule(new LingerTimer(), DIALOG_LINGER_TIME * 1000);
   1231             }
   1232             this.stopTimer();
   1233 
   1234         }
   1235     }
   1236 
   1237     /**
   1238      * Debugging print for the dialog.
   1239      */
   1240     public void printDebugInfo() {
   1241         if (sipStack.isLoggingEnabled()) {
   1242             sipStack.getStackLogger().logDebug("isServer = " + isServer());
   1243             sipStack.getStackLogger().logDebug("localTag = " + getLocalTag());
   1244             sipStack.getStackLogger().logDebug("remoteTag = " + getRemoteTag());
   1245             sipStack.getStackLogger().logDebug("localSequenceNumer = " + getLocalSeqNumber());
   1246             sipStack.getStackLogger().logDebug("remoteSequenceNumer = " + getRemoteSeqNumber());
   1247             sipStack.getStackLogger().logDebug("ackLine:" + this.getRemoteTag() + " " + ackLine);
   1248         }
   1249     }
   1250 
   1251     /**
   1252      * Return true if the dialog has already seen the ack.
   1253      *
   1254      * @return flag that records if the ack has been seen.
   1255      */
   1256     public boolean isAckSeen() {
   1257         return this.ackSeen;
   1258     }
   1259 
   1260     /**
   1261      * Get the last ACK for this transaction.
   1262      */
   1263     public SIPRequest getLastAckSent() {
   1264         return this.lastAckSent;
   1265     }
   1266 
   1267     /**
   1268      * Return true if ACK was sent ( for client tx ). For server tx, this is a NO-OP ( we dont
   1269      * send ACK).
   1270      */
   1271     public boolean isAckSent(long cseqNo) {
   1272         if (this.getLastTransaction() == null)
   1273             return true;
   1274         if (this.getLastTransaction() instanceof ClientTransaction) {
   1275             if (this.getLastAckSent() == null) {
   1276                 return false;
   1277             } else {
   1278                 return cseqNo <=((SIPRequest) this.getLastAckSent()).getCSeq().getSeqNumber();
   1279             }
   1280         } else {
   1281             return true;
   1282         }
   1283     }
   1284 
   1285     /**
   1286      * Get the transaction that created this dialog.
   1287      */
   1288     public Transaction getFirstTransaction() {
   1289         return this.firstTransaction;
   1290     }
   1291 
   1292 
   1293     /**
   1294      * Gets the route set for the dialog. When acting as an User Agent Server the route set MUST
   1295      * be set to the list of URIs in the Record-Route header field from the request, taken in
   1296      * order and preserving all URI parameters. When acting as an User Agent Client the route set
   1297      * MUST be set to the list of URIs in the Record-Route header field from the response, taken
   1298      * in reverse order and preserving all URI parameters. If no Record-Route header field is
   1299      * present in the request or response, the route set MUST be set to the empty set. This route
   1300      * set, even if empty, overrides any pre-existing route set for future requests in this
   1301      * dialog.
   1302      * <p>
   1303      * Requests within a dialog MAY contain Record-Route and Contact header fields. However, these
   1304      * requests do not cause the dialog's route set to be modified.
   1305      * <p>
   1306      * The User Agent Client uses the remote target and route set to build the Request-URI and
   1307      * Route header field of the request.
   1308      *
   1309      * @return an Iterator containing a list of route headers to be used for forwarding. Empty
   1310      *         iterator is returned if route has not been established.
   1311      */
   1312     public Iterator getRouteSet() {
   1313         if (this.routeList == null) {
   1314             return new LinkedList().listIterator();
   1315         } else {
   1316             return this.getRouteList().listIterator();
   1317         }
   1318     }
   1319 
   1320     /**
   1321      * Add a Route list extracted from a SIPRequest to this Dialog.
   1322      *
   1323      * @param sipRequest
   1324      */
   1325     public synchronized void addRoute(SIPRequest sipRequest) {
   1326         if (sipStack.isLoggingEnabled()) {
   1327             sipStack.getStackLogger().logDebug(
   1328                     "setContact: dialogState: " + this + "state = " + this.getState());
   1329         }
   1330 
   1331         if (this.dialogState == CONFIRMED_STATE
   1332                 && SIPRequest.isTargetRefresh(sipRequest.getMethod())) {
   1333             this.doTargetRefresh(sipRequest);
   1334         }
   1335         if (this.dialogState == CONFIRMED_STATE || this.dialogState == TERMINATED_STATE) {
   1336             return;
   1337         }
   1338 
   1339         // Fix for issue #225: mustn't learn Route set from mid-dialog requests
   1340         if ( sipRequest.getToTag()!=null ) return;
   1341 
   1342         // Incoming Request has the route list
   1343         RecordRouteList rrlist = sipRequest.getRecordRouteHeaders();
   1344         // Add the route set from the incoming response in reverse
   1345         // order
   1346         if (rrlist != null) {
   1347             this.addRoute(rrlist);
   1348         } else {
   1349             // Set the rotue list to the last seen route list.
   1350             this.routeList = new RouteList();
   1351         }
   1352 
   1353         // put the contact header from the incoming request into
   1354         // the route set. JvB: some duplication here, ref. doTargetRefresh
   1355         ContactList contactList = sipRequest.getContactHeaders();
   1356         if (contactList != null) {
   1357             this.setRemoteTarget((ContactHeader) contactList.getFirst());
   1358         }
   1359     }
   1360 
   1361     /**
   1362      * Set the dialog identifier.
   1363      */
   1364     public void setDialogId(String dialogId) {
   1365         this.dialogId = dialogId;
   1366     }
   1367 
   1368     /**
   1369      * Creates a new dialog based on a received NOTIFY. The dialog state is initialized
   1370      * appropriately. The NOTIFY differs in the From tag
   1371      *
   1372      * Made this a separate method to clearly distinguish what's happening here - this is a
   1373      * non-trivial case
   1374      *
   1375      * @param subscribeTx - the transaction started with the SUBSCRIBE that we sent
   1376      * @param notifyST - the ServerTransaction created for an incoming NOTIFY
   1377      * @return -- a new dialog created from the subscribe original SUBSCRIBE transaction.
   1378      *
   1379      *
   1380      */
   1381     public static SIPDialog createFromNOTIFY(SIPClientTransaction subscribeTx,
   1382             SIPTransaction notifyST) {
   1383         SIPDialog d = new SIPDialog(notifyST);
   1384         //
   1385         // The above sets d.firstTransaction to NOTIFY (ST), correct that
   1386         //
   1387         d.serverTransactionFlag = false;
   1388         // they share this one
   1389         d.lastTransaction = subscribeTx;
   1390         storeFirstTransactionInfo(d, subscribeTx);
   1391         d.terminateOnBye = false;
   1392         d.localSequenceNumber = subscribeTx.getCSeq();
   1393         SIPRequest not = (SIPRequest) notifyST.getRequest();
   1394         d.remoteSequenceNumber = not.getCSeq().getSeqNumber();
   1395         d.setDialogId(not.getDialogId(true));
   1396         d.setLocalTag(not.getToTag());
   1397         d.setRemoteTag(not.getFromTag());
   1398         // to properly create the Dialog object.
   1399         // If not the stack will throw an exception when creating the response.
   1400         d.setLastResponse(subscribeTx, subscribeTx.getLastResponse());
   1401 
   1402         // Dont use setLocal / setRemote here, they make other assumptions
   1403         d.localParty = not.getTo().getAddress();
   1404         d.remoteParty = not.getFrom().getAddress();
   1405 
   1406         // initialize d's route set based on the NOTIFY. Any proxies must have
   1407         // Record-Routed
   1408         d.addRoute(not);
   1409         d.setState(CONFIRMED_STATE); // set state, *after* setting route set!
   1410         return d;
   1411     }
   1412 
   1413     /**
   1414      * Return true if is server.
   1415      *
   1416      * @return true if is server transaction created this dialog.
   1417      */
   1418     public boolean isServer() {
   1419         if (this.firstTransactionSeen == false)
   1420             return this.serverTransactionFlag;
   1421         else
   1422             return this.firstTransactionIsServerTransaction;
   1423 
   1424     }
   1425 
   1426     /**
   1427      * Return true if this is a re-establishment of the dialog.
   1428      *
   1429      * @return true if the reInvite flag is set.
   1430      */
   1431     protected boolean isReInvite() {
   1432         return this.reInviteFlag;
   1433     }
   1434 
   1435     /**
   1436      * Get the id for this dialog.
   1437      *
   1438      * @return the string identifier for this dialog.
   1439      *
   1440      */
   1441     public String getDialogId() {
   1442 
   1443         if (this.dialogId == null && this.lastResponse != null)
   1444             this.dialogId = this.lastResponse.getDialogId(isServer());
   1445 
   1446         return this.dialogId;
   1447     }
   1448 
   1449     private static void storeFirstTransactionInfo(SIPDialog dialog, SIPTransaction transaction) {
   1450     	dialog.firstTransaction = transaction;
   1451     	dialog.firstTransactionSeen = true;
   1452     	dialog.firstTransactionIsServerTransaction = transaction.isServerTransaction();
   1453     	dialog.firstTransactionSecure = transaction.getRequest().getRequestURI().getScheme()
   1454         	.equalsIgnoreCase("sips");
   1455     	dialog.firstTransactionPort = transaction.getPort();
   1456     	dialog.firstTransactionId = transaction.getBranchId();
   1457     	dialog.firstTransactionMethod = transaction.getMethod();
   1458 
   1459         if (dialog.isServer()) {
   1460             SIPServerTransaction st = (SIPServerTransaction) transaction;
   1461             SIPResponse response = st.getLastResponse();
   1462             dialog.contactHeader = response != null ? response.getContactHeader() : null;
   1463         } else {
   1464             SIPClientTransaction ct = (SIPClientTransaction) transaction;
   1465             if (ct != null){
   1466             	SIPRequest sipRequest = ct.getOriginalRequest();
   1467             	dialog.contactHeader = sipRequest.getContactHeader();
   1468             }
   1469         }
   1470     }
   1471     /**
   1472      * Add a transaction record to the dialog.
   1473      *
   1474      * @param transaction is the transaction to add to the dialog.
   1475      */
   1476     public void addTransaction(SIPTransaction transaction) {
   1477 
   1478         SIPRequest sipRequest = (SIPRequest) transaction.getOriginalRequest();
   1479 
   1480         // Proessing a re-invite.
   1481         if (firstTransactionSeen && !firstTransactionId.equals(transaction.getBranchId())
   1482                 && transaction.getMethod().equals(firstTransactionMethod)) {
   1483             this.reInviteFlag = true;
   1484         }
   1485 
   1486         if (firstTransactionSeen == false) {
   1487             // Record the local and remote sequenc
   1488             // numbers and the from and to tags for future
   1489             // use on this dialog.
   1490         	storeFirstTransactionInfo(this, transaction);
   1491             if (sipRequest.getMethod().equals(Request.SUBSCRIBE))
   1492                 this.eventHeader = (EventHeader) sipRequest.getHeader(EventHeader.NAME);
   1493 
   1494             this.setLocalParty(sipRequest);
   1495             this.setRemoteParty(sipRequest);
   1496             this.setCallId(sipRequest);
   1497             if (this.originalRequest == null) {
   1498                 this.originalRequest = sipRequest;
   1499             }
   1500             if (this.method == null) {
   1501                 this.method = sipRequest.getMethod();
   1502             }
   1503 
   1504             if (transaction instanceof SIPServerTransaction) {
   1505                 this.hisTag = sipRequest.getFrom().getTag();
   1506                 // My tag is assigned when sending response
   1507             } else {
   1508                 setLocalSequenceNumber(sipRequest.getCSeq().getSeqNumber());
   1509                 this.originalLocalSequenceNumber = localSequenceNumber;
   1510                 this.myTag = sipRequest.getFrom().getTag();
   1511                 if (myTag == null)
   1512                 	if (sipStack.isLoggingEnabled())
   1513                 		sipStack.getStackLogger().logError(
   1514                             "The request's From header is missing the required Tag parameter.");
   1515             }
   1516         } else if (transaction.getMethod().equals(firstTransactionMethod)
   1517                 && firstTransactionIsServerTransaction != transaction.isServerTransaction()) {
   1518             // This case occurs when you are processing a re-invite.
   1519             // Switch from client side to server side for re-invite
   1520             // (put the other side on hold).
   1521 
   1522 			storeFirstTransactionInfo(this, transaction);
   1523 
   1524             this.setLocalParty(sipRequest);
   1525             this.setRemoteParty(sipRequest);
   1526             this.setCallId(sipRequest);
   1527             this.originalRequest = sipRequest;
   1528             this.method = sipRequest.getMethod();
   1529 
   1530         }
   1531         if (transaction instanceof SIPServerTransaction)
   1532             setRemoteSequenceNumber(sipRequest.getCSeq().getSeqNumber());
   1533 
   1534         // If this is a server transaction record the remote
   1535         // sequence number to avoid re-processing of requests
   1536         // with the same sequence number directed towards this
   1537         // dialog.
   1538 
   1539         this.lastTransaction = transaction;
   1540         // set a back ptr in the incoming dialog.
   1541         // CHECKME -- why is this here?
   1542         // transaction.setDialog(this,sipRequest);
   1543         if (sipStack.isLoggingEnabled()) {
   1544             sipStack.getStackLogger()
   1545                     .logDebug("Transaction Added " + this + myTag + "/" + hisTag);
   1546             sipStack.getStackLogger().logDebug(
   1547                     "TID = " + transaction.getTransactionId() + "/"
   1548                             + transaction.isServerTransaction());
   1549             sipStack.getStackLogger().logStackTrace();
   1550         }
   1551     }
   1552 
   1553     /**
   1554      * Set the remote tag.
   1555      *
   1556      * @param hisTag is the remote tag to set.
   1557      */
   1558     private void setRemoteTag(String hisTag) {
   1559         if (sipStack.isLoggingEnabled()) {
   1560             sipStack.getStackLogger().logDebug(
   1561                     "setRemoteTag(): " + this + " remoteTag = " + this.hisTag + " new tag = "
   1562                             + hisTag);
   1563         }
   1564         if (this.hisTag != null && hisTag != null && !hisTag.equals(this.hisTag)) {
   1565             if (this.getState() != DialogState.EARLY) {
   1566             	if (sipStack.isLoggingEnabled())
   1567             		sipStack.getStackLogger().logDebug(
   1568                         "Dialog is already established -- ignoring remote tag re-assignment");
   1569                 return;
   1570             } else if (sipStack.isRemoteTagReassignmentAllowed()) {
   1571             	if (sipStack.isLoggingEnabled())
   1572             		sipStack.getStackLogger().logDebug(
   1573                         "UNSAFE OPERATION !  tag re-assignment " + this.hisTag
   1574                                 + " trying to set to " + hisTag
   1575                                 + " can cause unexpected effects ");
   1576                 boolean removed = false;
   1577                 if (this.sipStack.getDialog(dialogId) == this) {
   1578                     this.sipStack.removeDialog(dialogId);
   1579                     removed = true;
   1580 
   1581                 }
   1582                 // Force recomputation of Dialog ID;
   1583                 this.dialogId = null;
   1584                 this.hisTag = hisTag;
   1585                 if (removed) {
   1586                 	if (sipStack.isLoggingEnabled())
   1587                 		sipStack.getStackLogger().logDebug("ReInserting Dialog");
   1588                     this.sipStack.putDialog(this);
   1589                 }
   1590             }
   1591         } else {
   1592             if (hisTag != null) {
   1593                 this.hisTag = hisTag;
   1594             } else {
   1595             	if (sipStack.isLoggingEnabled())
   1596             		sipStack.getStackLogger().logWarning("setRemoteTag : called with null argument ");
   1597             }
   1598         }
   1599     }
   1600 
   1601     /**
   1602      * Get the last transaction from the dialog.
   1603      */
   1604     public SIPTransaction getLastTransaction() {
   1605         return this.lastTransaction;
   1606     }
   1607 
   1608     /**
   1609      * Get the INVITE transaction (null if no invite transaction).
   1610      */
   1611     public SIPServerTransaction getInviteTransaction() {
   1612         DialogTimerTask t = this.timerTask;
   1613         if (t != null)
   1614             return t.transaction;
   1615         else
   1616             return null;
   1617     }
   1618 
   1619     /**
   1620      * Set the local sequece number for the dialog (defaults to 1 when the dialog is created).
   1621      *
   1622      * @param lCseq is the local cseq number.
   1623      *
   1624      */
   1625     private void setLocalSequenceNumber(long lCseq) {
   1626         if (sipStack.isLoggingEnabled())
   1627             sipStack.getStackLogger().logDebug(
   1628                     "setLocalSequenceNumber: original  " + this.localSequenceNumber + " new  = "
   1629                             + lCseq);
   1630         if (lCseq <= this.localSequenceNumber)
   1631             throw new RuntimeException("Sequence number should not decrease !");
   1632         this.localSequenceNumber = lCseq;
   1633     }
   1634 
   1635     /**
   1636      * Set the remote sequence number for the dialog.
   1637      *
   1638      * @param rCseq is the remote cseq number.
   1639      *
   1640      */
   1641     public void setRemoteSequenceNumber(long rCseq) {
   1642         if (sipStack.isLoggingEnabled())
   1643             sipStack.getStackLogger().logDebug("setRemoteSeqno " + this + "/" + rCseq);
   1644         this.remoteSequenceNumber = rCseq;
   1645     }
   1646 
   1647     /**
   1648      * Increment the local CSeq # for the dialog. This is useful for if you want to create a hole
   1649      * in the sequence number i.e. route a request outside the dialog and then resume within the
   1650      * dialog.
   1651      */
   1652     public void incrementLocalSequenceNumber() {
   1653         ++this.localSequenceNumber;
   1654     }
   1655 
   1656     /**
   1657      * Get the remote sequence number (for cseq assignment of outgoing requests within this
   1658      * dialog).
   1659      *
   1660      * @deprecated
   1661      * @return local sequence number.
   1662      */
   1663 
   1664     public int getRemoteSequenceNumber() {
   1665         return (int) this.remoteSequenceNumber;
   1666     }
   1667 
   1668     /**
   1669      * Get the local sequence number (for cseq assignment of outgoing requests within this
   1670      * dialog).
   1671      *
   1672      * @deprecated
   1673      * @return local sequence number.
   1674      */
   1675 
   1676     public int getLocalSequenceNumber() {
   1677         return (int) this.localSequenceNumber;
   1678     }
   1679 
   1680     /**
   1681      * Get the sequence number for the request that origianlly created the Dialog.
   1682      *
   1683      * @return -- the original starting sequence number for this dialog.
   1684      */
   1685     public long getOriginalLocalSequenceNumber() {
   1686         return this.originalLocalSequenceNumber;
   1687     }
   1688 
   1689     /*
   1690      * (non-Javadoc)
   1691      *
   1692      * @see javax.sip.Dialog#getLocalSequenceNumberLong()
   1693      */
   1694     public long getLocalSeqNumber() {
   1695         return this.localSequenceNumber;
   1696     }
   1697 
   1698     /*
   1699      * (non-Javadoc)
   1700      *
   1701      * @see javax.sip.Dialog#getRemoteSequenceNumberLong()
   1702      */
   1703     public long getRemoteSeqNumber() {
   1704         return this.remoteSequenceNumber;
   1705     }
   1706 
   1707     /*
   1708      * (non-Javadoc)
   1709      *
   1710      * @see javax.sip.Dialog#getLocalTag()
   1711      */
   1712     public String getLocalTag() {
   1713         return this.myTag;
   1714     }
   1715 
   1716     /*
   1717      * (non-Javadoc)
   1718      *
   1719      * @see javax.sip.Dialog#getRemoteTag()
   1720      */
   1721     public String getRemoteTag() {
   1722 
   1723         return hisTag;
   1724     }
   1725 
   1726     /**
   1727      * Set local tag for the transaction.
   1728      *
   1729      * @param mytag is the tag to use in From headers client transactions that belong to this
   1730      *        dialog and for generating To tags for Server transaction requests that belong to
   1731      *        this dialog.
   1732      */
   1733     private void setLocalTag(String mytag) {
   1734         if (sipStack.isLoggingEnabled()) {
   1735             sipStack.getStackLogger().logDebug("set Local tag " + mytag + " " + this.dialogId);
   1736             sipStack.getStackLogger().logStackTrace();
   1737         }
   1738 
   1739         this.myTag = mytag;
   1740 
   1741     }
   1742 
   1743     /*
   1744      * (non-Javadoc)
   1745      *
   1746      * @see javax.sip.Dialog#delete()
   1747      */
   1748 
   1749     public void delete() {
   1750         // the reaper will get him later.
   1751         this.setState(TERMINATED_STATE);
   1752     }
   1753 
   1754     /*
   1755      * (non-Javadoc)
   1756      *
   1757      * @see javax.sip.Dialog#getCallId()
   1758      */
   1759     public CallIdHeader getCallId() {
   1760         return this.callIdHeader;
   1761     }
   1762 
   1763     /**
   1764      * set the call id header for this dialog.
   1765      */
   1766     private void setCallId(SIPRequest sipRequest) {
   1767         this.callIdHeader = sipRequest.getCallId();
   1768     }
   1769 
   1770     /*
   1771      * (non-Javadoc)
   1772      *
   1773      * @see javax.sip.Dialog#getLocalParty()
   1774      */
   1775 
   1776     public javax.sip.address.Address getLocalParty() {
   1777         return this.localParty;
   1778     }
   1779 
   1780     private void setLocalParty(SIPMessage sipMessage) {
   1781         if (!isServer()) {
   1782             this.localParty = sipMessage.getFrom().getAddress();
   1783         } else {
   1784             this.localParty = sipMessage.getTo().getAddress();
   1785         }
   1786     }
   1787 
   1788     /**
   1789      * Returns the Address identifying the remote party. This is the value of the To header of
   1790      * locally initiated requests in this dialogue when acting as an User Agent Client.
   1791      * <p>
   1792      * This is the value of the From header of recieved responses in this dialogue when acting as
   1793      * an User Agent Server.
   1794      *
   1795      * @return the address object of the remote party.
   1796      */
   1797     public javax.sip.address.Address getRemoteParty() {
   1798 
   1799         if (sipStack.isLoggingEnabled()) {
   1800             sipStack.getStackLogger().logDebug("gettingRemoteParty " + this.remoteParty);
   1801         }
   1802         return this.remoteParty;
   1803 
   1804     }
   1805 
   1806     /*
   1807      * (non-Javadoc)
   1808      *
   1809      * @see javax.sip.Dialog#getRemoteTarget()
   1810      */
   1811     public javax.sip.address.Address getRemoteTarget() {
   1812 
   1813         return this.remoteTarget;
   1814     }
   1815 
   1816     /*
   1817      * (non-Javadoc)
   1818      *
   1819      * @see javax.sip.Dialog#getState()
   1820      */
   1821     public DialogState getState() {
   1822         if (this.dialogState == NULL_STATE)
   1823             return null; // not yet initialized
   1824         return DialogState.getObject(this.dialogState);
   1825     }
   1826 
   1827     /**
   1828      * Returns true if this Dialog is secure i.e. if the request arrived over TLS, and the
   1829      * Request-URI contained a SIPS URI, the "secure" flag is set to TRUE.
   1830      *
   1831      * @return <code>true</code> if this dialogue was established using a sips URI over TLS, and
   1832      *         <code>false</code> otherwise.
   1833      */
   1834     public boolean isSecure() {
   1835         return this.firstTransactionSecure;
   1836     }
   1837 
   1838     /*
   1839      * (non-Javadoc)
   1840      *
   1841      * @see javax.sip.Dialog#sendAck(javax.sip.message.Request)
   1842      */
   1843     public void sendAck(Request request) throws SipException {
   1844         this.sendAck(request, true);
   1845     }
   1846 
   1847     /*
   1848      * (non-Javadoc)
   1849      *
   1850      * @see javax.sip.Dialog#createRequest(java.lang.String)
   1851      */
   1852     public Request createRequest(String method) throws SipException {
   1853 
   1854         if (method.equals(Request.ACK) || method.equals(Request.PRACK)) {
   1855             throw new SipException("Invalid method specified for createRequest:" + method);
   1856         }
   1857         if (lastResponse != null)
   1858             return this.createRequest(method, this.lastResponse);
   1859         else
   1860             throw new SipException("Dialog not yet established -- no response!");
   1861     }
   1862 
   1863     /**
   1864      * The method that actually does the work of creating a request.
   1865      *
   1866      * @param method
   1867      * @param response
   1868      * @return
   1869      * @throws SipException
   1870      */
   1871     private Request createRequest(String method, SIPResponse sipResponse) throws SipException {
   1872         /*
   1873          * Check if the dialog is in the right state (RFC 3261 section 15). The caller's UA MAY
   1874          * send a BYE for either CONFIRMED or EARLY dialogs, and the callee's UA MAY send a BYE on
   1875          * CONFIRMED dialogs, but MUST NOT send a BYE on EARLY dialogs.
   1876          *
   1877          * Throw out cancel request.
   1878          */
   1879 
   1880         if (method == null || sipResponse == null)
   1881             throw new NullPointerException("null argument");
   1882 
   1883         if (method.equals(Request.CANCEL))
   1884             throw new SipException("Dialog.createRequest(): Invalid request");
   1885 
   1886         if (this.getState() == null
   1887                 || (this.getState().getValue() == TERMINATED_STATE && !method
   1888                         .equalsIgnoreCase(Request.BYE))
   1889                 || (this.isServer() && this.getState().getValue() == EARLY_STATE && method
   1890                         .equalsIgnoreCase(Request.BYE)))
   1891             throw new SipException("Dialog  " + getDialogId()
   1892                     + " not yet established or terminated " + this.getState());
   1893 
   1894         SipUri sipUri = null;
   1895         if (this.getRemoteTarget() != null)
   1896             sipUri = (SipUri) this.getRemoteTarget().getURI().clone();
   1897         else {
   1898             sipUri = (SipUri) this.getRemoteParty().getURI().clone();
   1899             sipUri.clearUriParms();
   1900         }
   1901 
   1902         CSeq cseq = new CSeq();
   1903         try {
   1904             cseq.setMethod(method);
   1905             cseq.setSeqNumber(this.getLocalSeqNumber());
   1906         } catch (Exception ex) {
   1907         	if (sipStack.isLoggingEnabled())
   1908         		sipStack.getStackLogger().logError("Unexpected error");
   1909             InternalErrorHandler.handleException(ex);
   1910         }
   1911         /*
   1912          * Add a via header for the outbound request based on the transport of the message
   1913          * processor.
   1914          */
   1915 
   1916         ListeningPointImpl lp = (ListeningPointImpl) this.sipProvider
   1917                 .getListeningPoint(sipResponse.getTopmostVia().getTransport());
   1918         if (lp == null) {
   1919             if (sipStack.isLoggingEnabled())
   1920                 sipStack.getStackLogger().logError(
   1921                         "Cannot find listening point for transport "
   1922                                 + sipResponse.getTopmostVia().getTransport());
   1923             throw new SipException("Cannot find listening point for transport "
   1924                     + sipResponse.getTopmostVia().getTransport());
   1925         }
   1926         Via via = lp.getViaHeader();
   1927 
   1928         From from = new From();
   1929         from.setAddress(this.localParty);
   1930         To to = new To();
   1931         to.setAddress(this.remoteParty);
   1932         SIPRequest sipRequest = sipResponse.createRequest(sipUri, via, cseq, from, to);
   1933 
   1934         /*
   1935          * The default contact header is obtained from the provider. The application can override
   1936          * this.
   1937          *
   1938          * JvB: Should only do this for target refresh requests, ie not for BYE, PRACK, etc
   1939          */
   1940 
   1941         if (SIPRequest.isTargetRefresh(method)) {
   1942             ContactHeader contactHeader = ((ListeningPointImpl) this.sipProvider
   1943                     .getListeningPoint(lp.getTransport())).createContactHeader();
   1944 
   1945             ((SipURI) contactHeader.getAddress().getURI()).setSecure(this.isSecure());
   1946             sipRequest.setHeader(contactHeader);
   1947         }
   1948 
   1949         try {
   1950             /*
   1951              * Guess of local sequence number - this is being re-set when the request is actually
   1952              * dispatched
   1953              */
   1954             cseq = (CSeq) sipRequest.getCSeq();
   1955             cseq.setSeqNumber(this.localSequenceNumber + 1);
   1956 
   1957         } catch (InvalidArgumentException ex) {
   1958             InternalErrorHandler.handleException(ex);
   1959         }
   1960 
   1961         if (method.equals(Request.SUBSCRIBE)) {
   1962 
   1963             if (eventHeader != null)
   1964                 sipRequest.addHeader(eventHeader);
   1965 
   1966         }
   1967 
   1968         /*
   1969          * RFC3261, section 12.2.1.1:
   1970          *
   1971          * The URI in the To field of the request MUST be set to the remote URI from the dialog
   1972          * state. The tag in the To header field of the request MUST be set to the remote tag of
   1973          * the dialog ID. The From URI of the request MUST be set to the local URI from the dialog
   1974          * state. The tag in the From header field of the request MUST be set to the local tag of
   1975          * the dialog ID. If the value of the remote or local tags is null, the tag parameter MUST
   1976          * be omitted from the To or From header fields, respectively.
   1977          */
   1978 
   1979         try {
   1980             if (this.getLocalTag() != null) {
   1981                 from.setTag(this.getLocalTag());
   1982             } else {
   1983                 from.removeTag();
   1984             }
   1985             if (this.getRemoteTag() != null) {
   1986                 to.setTag(this.getRemoteTag());
   1987             } else {
   1988                 to.removeTag();
   1989             }
   1990         } catch (ParseException ex) {
   1991             InternalErrorHandler.handleException(ex);
   1992         }
   1993 
   1994         // get the route list from the dialog.
   1995         this.updateRequest(sipRequest);
   1996 
   1997         return sipRequest;
   1998 
   1999     }
   2000 
   2001     /*
   2002      * (non-Javadoc)
   2003      *
   2004      * @see javax.sip.Dialog#sendRequest(javax.sip.ClientTransaction)
   2005      */
   2006 
   2007     public void sendRequest(ClientTransaction clientTransactionId)
   2008             throws TransactionDoesNotExistException, SipException {
   2009         this.sendRequest(clientTransactionId, !this.isBackToBackUserAgent);
   2010     }
   2011 
   2012     public void sendRequest(ClientTransaction clientTransactionId, boolean allowInterleaving)
   2013             throws TransactionDoesNotExistException, SipException {
   2014 
   2015         if ( (!allowInterleaving)
   2016                 && clientTransactionId.getRequest().getMethod().equals(Request.INVITE)) {
   2017             new Thread((new ReInviteSender(clientTransactionId))).start();
   2018             return;
   2019         }
   2020 
   2021         SIPRequest dialogRequest = ((SIPClientTransaction) clientTransactionId)
   2022                 .getOriginalRequest();
   2023 
   2024         if (sipStack.isLoggingEnabled())
   2025             sipStack.getStackLogger().logDebug(
   2026                     "dialog.sendRequest " + " dialog = " + this + "\ndialogRequest = \n"
   2027                             + dialogRequest);
   2028 
   2029         if (clientTransactionId == null)
   2030             throw new NullPointerException("null parameter");
   2031 
   2032         if (dialogRequest.getMethod().equals(Request.ACK)
   2033                 || dialogRequest.getMethod().equals(Request.CANCEL))
   2034             throw new SipException("Bad Request Method. " + dialogRequest.getMethod());
   2035 
   2036         // JvB: added, allow re-sending of BYE after challenge
   2037         if (byeSent && isTerminatedOnBye() && !dialogRequest.getMethod().equals(Request.BYE)) {
   2038             if (sipStack.isLoggingEnabled())
   2039                 sipStack.getStackLogger().logError("BYE already sent for " + this);
   2040             throw new SipException("Cannot send request; BYE already sent");
   2041         }
   2042 
   2043         if (dialogRequest.getTopmostVia() == null) {
   2044             Via via = ((SIPClientTransaction) clientTransactionId).getOutgoingViaHeader();
   2045             dialogRequest.addHeader(via);
   2046         }
   2047         if (!this.getCallId().getCallId().equalsIgnoreCase(dialogRequest.getCallId().getCallId())) {
   2048 
   2049             if (sipStack.isLoggingEnabled()) {
   2050                 sipStack.getStackLogger().logError("CallID " + this.getCallId());
   2051                 sipStack.getStackLogger().logError(
   2052                         "RequestCallID = " + dialogRequest.getCallId().getCallId());
   2053                 sipStack.getStackLogger().logError("dialog =  " + this);
   2054             }
   2055             throw new SipException("Bad call ID in request");
   2056         }
   2057 
   2058         // Set the dialog back pointer.
   2059         ((SIPClientTransaction) clientTransactionId).setDialog(this, this.dialogId);
   2060 
   2061         this.addTransaction((SIPTransaction) clientTransactionId);
   2062         // Enable the retransmission filter for the transaction
   2063 
   2064         ((SIPClientTransaction) clientTransactionId).isMapped = true;
   2065 
   2066         From from = (From) dialogRequest.getFrom();
   2067         To to = (To) dialogRequest.getTo();
   2068 
   2069         // Caller already did the tag assignment -- check to see if the
   2070         // tag assignment is OK.
   2071         if (this.getLocalTag() != null && from.getTag() != null
   2072                 && !from.getTag().equals(this.getLocalTag()))
   2073             throw new SipException("From tag mismatch expecting  " + this.getLocalTag());
   2074 
   2075         if (this.getRemoteTag() != null && to.getTag() != null
   2076                 && !to.getTag().equals(this.getRemoteTag())) {
   2077         	if (sipStack.isLoggingEnabled())
   2078         		this.sipStack.getStackLogger().logWarning(
   2079                     "To header tag mismatch expecting " + this.getRemoteTag());
   2080         }
   2081         /*
   2082          * The application is sending a NOTIFY before sending the response of the dialog.
   2083          */
   2084         if (this.getLocalTag() == null && dialogRequest.getMethod().equals(Request.NOTIFY)) {
   2085             if (!this.getMethod().equals(Request.SUBSCRIBE))
   2086                 throw new SipException("Trying to send NOTIFY without SUBSCRIBE Dialog!");
   2087             this.setLocalTag(from.getTag());
   2088 
   2089         }
   2090 
   2091         try {
   2092             if (this.getLocalTag() != null)
   2093                 from.setTag(this.getLocalTag());
   2094             if (this.getRemoteTag() != null)
   2095                 to.setTag(this.getRemoteTag());
   2096 
   2097         } catch (ParseException ex) {
   2098 
   2099             InternalErrorHandler.handleException(ex);
   2100 
   2101         }
   2102 
   2103         Hop hop = ((SIPClientTransaction) clientTransactionId).getNextHop();
   2104         if (sipStack.isLoggingEnabled()) {
   2105             sipStack.getStackLogger().logDebug(
   2106                     "Using hop = " + hop.getHost() + " : " + hop.getPort());
   2107         }
   2108 
   2109         try {
   2110             MessageChannel messageChannel = sipStack.createRawMessageChannel(this
   2111                     .getSipProvider().getListeningPoint(hop.getTransport()).getIPAddress(),
   2112                     this.firstTransactionPort, hop);
   2113 
   2114             MessageChannel oldChannel = ((SIPClientTransaction)
   2115             		clientTransactionId).getMessageChannel();
   2116 
   2117             // Remove this from the connection cache if it is in the
   2118             // connection
   2119             // cache and is not yet active.
   2120             oldChannel.uncache();
   2121 
   2122             // Not configured to cache client connections.
   2123             if (!sipStack.cacheClientConnections) {
   2124                 oldChannel.useCount--;
   2125                 if (sipStack.isLoggingEnabled())
   2126                     sipStack.getStackLogger().logDebug(
   2127                             "oldChannel: useCount " + oldChannel.useCount);
   2128 
   2129             }
   2130 
   2131             if (messageChannel == null) {
   2132                 /*
   2133                  * At this point the procedures of 8.1.2 and 12.2.1.1 of RFC3261 have been tried
   2134                  * but the resulting next hop cannot be resolved (recall that the exception thrown
   2135                  * is caught and ignored in SIPStack.createMessageChannel() so we end up here with
   2136                  * a null messageChannel instead of the exception handler below). All else
   2137                  * failing, try the outbound proxy in accordance with 8.1.2, in particular: This
   2138                  * ensures that outbound proxies that do not add Record-Route header field values
   2139                  * will drop out of the path of subsequent requests. It allows endpoints that
   2140                  * cannot resolve the first Route URI to delegate that task to an outbound proxy.
   2141                  *
   2142                  * if one considers the 'first Route URI' of a request constructed according to
   2143                  * 12.2.1.1 to be the request URI when the route set is empty.
   2144                  */
   2145                 if (sipStack.isLoggingEnabled())
   2146                     sipStack.getStackLogger().logDebug(
   2147                             "Null message channel using outbound proxy !");
   2148                 Hop outboundProxy = sipStack.getRouter(dialogRequest).getOutboundProxy();
   2149                 if (outboundProxy == null)
   2150                     throw new SipException("No route found! hop=" + hop);
   2151                 messageChannel = sipStack.createRawMessageChannel(this.getSipProvider()
   2152                         .getListeningPoint(outboundProxy.getTransport()).getIPAddress(),
   2153                         this.firstTransactionPort, outboundProxy);
   2154                 if (messageChannel != null)
   2155                     ((SIPClientTransaction) clientTransactionId)
   2156                             .setEncapsulatedChannel(messageChannel);
   2157             } else {
   2158                 ((SIPClientTransaction) clientTransactionId)
   2159                         .setEncapsulatedChannel(messageChannel);
   2160 
   2161                 if (sipStack.isLoggingEnabled()) {
   2162                     sipStack.getStackLogger().logDebug("using message channel " + messageChannel);
   2163 
   2164                 }
   2165 
   2166             }
   2167 
   2168             if (messageChannel != null) messageChannel.useCount++;
   2169 
   2170             // See if we need to release the previously mapped channel.
   2171             if ((!sipStack.cacheClientConnections) && oldChannel != null
   2172                     && oldChannel.useCount <= 0)
   2173                 oldChannel.close();
   2174         } catch (Exception ex) {
   2175             if (sipStack.isLoggingEnabled())
   2176                 sipStack.getStackLogger().logException(ex);
   2177             throw new SipException("Could not create message channel", ex);
   2178         }
   2179 
   2180         try {
   2181             // Increment before setting!!
   2182             localSequenceNumber++;
   2183             dialogRequest.getCSeq().setSeqNumber(getLocalSeqNumber());
   2184         } catch (InvalidArgumentException ex) {
   2185             sipStack.getStackLogger().logFatalError(ex.getMessage());
   2186         }
   2187 
   2188         try {
   2189             ((SIPClientTransaction) clientTransactionId).sendMessage(dialogRequest);
   2190             /*
   2191              * Note that if the BYE is rejected then the Dialog should bo back to the ESTABLISHED
   2192              * state so we only set state after successful send.
   2193              */
   2194             if (dialogRequest.getMethod().equals(Request.BYE)) {
   2195                 this.byeSent = true;
   2196                 /*
   2197                  * Dialog goes into TERMINATED state as soon as BYE is sent. ISSUE 182.
   2198                  */
   2199                 if (isTerminatedOnBye()) {
   2200                     this.setState(DialogState._TERMINATED);
   2201                 }
   2202             }
   2203         } catch (IOException ex) {
   2204             throw new SipException("error sending message", ex);
   2205         }
   2206 
   2207     }
   2208 
   2209     /**
   2210      * Return yes if the last response is to be retransmitted.
   2211      */
   2212     private boolean toRetransmitFinalResponse(int T2) {
   2213         if (--retransmissionTicksLeft == 0) {
   2214             if (2 * prevRetransmissionTicks <= T2)
   2215                 this.retransmissionTicksLeft = 2 * prevRetransmissionTicks;
   2216             else
   2217                 this.retransmissionTicksLeft = prevRetransmissionTicks;
   2218             this.prevRetransmissionTicks = retransmissionTicksLeft;
   2219             return true;
   2220         } else
   2221             return false;
   2222 
   2223     }
   2224 
   2225     protected void setRetransmissionTicks() {
   2226         this.retransmissionTicksLeft = 1;
   2227         this.prevRetransmissionTicks = 1;
   2228     }
   2229 
   2230     /**
   2231      * Resend the last ack.
   2232      */
   2233     public void resendAck() throws SipException {
   2234         // Check for null.
   2235 
   2236         if (this.getLastAckSent() != null) {
   2237             if (getLastAckSent().getHeader(TimeStampHeader.NAME) != null
   2238                     && sipStack.generateTimeStampHeader) {
   2239                 TimeStamp ts = new TimeStamp();
   2240                 try {
   2241                     ts.setTimeStamp(System.currentTimeMillis());
   2242                     getLastAckSent().setHeader(ts);
   2243                 } catch (InvalidArgumentException e) {
   2244 
   2245                 }
   2246             }
   2247             this.sendAck(getLastAckSent(), false);
   2248         }
   2249 
   2250     }
   2251 
   2252     /**
   2253      * Get the method of the request/response that resulted in the creation of the Dialog.
   2254      *
   2255      * @return -- the method of the dialog.
   2256      */
   2257     public String getMethod() {
   2258         // Method of the request or response used to create this dialog
   2259         return this.method;
   2260     }
   2261 
   2262     /**
   2263      * Start the dialog timer.
   2264      *
   2265      * @param transaction
   2266      */
   2267 
   2268     protected void startTimer(SIPServerTransaction transaction) {
   2269         if (this.timerTask != null && timerTask.transaction == transaction) {
   2270         	if (sipStack.isLoggingEnabled())
   2271         		sipStack.getStackLogger().logDebug("Timer already running for " + getDialogId());
   2272             return;
   2273         }
   2274         if (sipStack.isLoggingEnabled())
   2275             sipStack.getStackLogger().logDebug("Starting dialog timer for " + getDialogId());
   2276         this.ackSeen = false;
   2277 
   2278 		acquireTimerTaskSem();
   2279 		try {
   2280 	        if (this.timerTask != null) {
   2281 	            this.timerTask.transaction = transaction;
   2282 	        } else {
   2283 	            this.timerTask = new DialogTimerTask(transaction);
   2284 	            sipStack.getTimer().schedule(timerTask, SIPTransactionStack.BASE_TIMER_INTERVAL,
   2285 	                    SIPTransactionStack.BASE_TIMER_INTERVAL);
   2286 	        }
   2287 		} finally {
   2288 			releaseTimerTaskSem();
   2289 		}
   2290 
   2291         this.setRetransmissionTicks();
   2292     }
   2293 
   2294     /**
   2295      * Stop the dialog timer. This is called when the dialog is terminated.
   2296      *
   2297      */
   2298     protected void stopTimer() {
   2299         try {
   2300         	acquireTimerTaskSem();
   2301         	try {
   2302 	            if (this.timerTask != null) {
   2303 	            	this.timerTask.cancel();
   2304 		            this.timerTask = null;
   2305 	            }
   2306         	} finally {
   2307         		releaseTimerTaskSem();
   2308         	}
   2309         } catch (Exception ex) {
   2310         }
   2311     }
   2312 
   2313     /*
   2314      * (non-Javadoc) Retransmissions of the reliable provisional response cease when a matching
   2315      * PRACK is received by the UA core. PRACK is like any other request within a dialog, and the
   2316      * UAS core processes it according to the procedures of Sections 8.2 and 12.2.2 of RFC 3261. A
   2317      * matching PRACK is defined as one within the same dialog as the response, and whose method,
   2318      * CSeq-num, and response-num in the RAck header field match, respectively, the method from
   2319      * the CSeq, the sequence number from the CSeq, and the sequence number from the RSeq of the
   2320      * reliable provisional response.
   2321      *
   2322      * @see javax.sip.Dialog#createPrack(javax.sip.message.Response)
   2323      */
   2324     public Request createPrack(Response relResponse) throws DialogDoesNotExistException,
   2325             SipException {
   2326 
   2327         if (this.getState() == null || this.getState().equals(DialogState.TERMINATED))
   2328             throw new DialogDoesNotExistException("Dialog not initialized or terminated");
   2329 
   2330         if ((RSeq) relResponse.getHeader(RSeqHeader.NAME) == null) {
   2331             throw new SipException("Missing RSeq Header");
   2332         }
   2333 
   2334         try {
   2335             SIPResponse sipResponse = (SIPResponse) relResponse;
   2336             SIPRequest sipRequest = (SIPRequest) this.createRequest(Request.PRACK,
   2337                     (SIPResponse) relResponse);
   2338             String toHeaderTag = sipResponse.getTo().getTag();
   2339             sipRequest.setToTag(toHeaderTag);
   2340             RAck rack = new RAck();
   2341             RSeq rseq = (RSeq) relResponse.getHeader(RSeqHeader.NAME);
   2342             rack.setMethod(sipResponse.getCSeq().getMethod());
   2343             rack.setCSequenceNumber((int) sipResponse.getCSeq().getSeqNumber());
   2344             rack.setRSequenceNumber(rseq.getSeqNumber());
   2345             sipRequest.setHeader(rack);
   2346             return (Request) sipRequest;
   2347         } catch (Exception ex) {
   2348             InternalErrorHandler.handleException(ex);
   2349             return null;
   2350         }
   2351 
   2352     }
   2353 
   2354     private void updateRequest(SIPRequest sipRequest) {
   2355 
   2356         RouteList rl = this.getRouteList();
   2357         if (rl.size() > 0) {
   2358             sipRequest.setHeader(rl);
   2359         } else {
   2360             sipRequest.removeHeader(RouteHeader.NAME);
   2361         }
   2362         if (MessageFactoryImpl.getDefaultUserAgentHeader() != null) {
   2363             sipRequest.setHeader(MessageFactoryImpl.getDefaultUserAgentHeader());
   2364         }
   2365 
   2366     }
   2367 
   2368     /*
   2369      * (non-Javadoc) The UAC core MUST generate an ACK request for each 2xx received from the
   2370      * transaction layer. The header fields of the ACK are constructed in the same way as for any
   2371      * request sent within a dialog (see Section 12) with the exception of the CSeq and the header
   2372      * fields related to authentication. The sequence number of the CSeq header field MUST be the
   2373      * same as the INVITE being acknowledged, but the CSeq method MUST be ACK. The ACK MUST
   2374      * contain the same credentials as the INVITE. If the 2xx contains an offer (based on the
   2375      * rules above), the ACK MUST carry an answer in its body. If the offer in the 2xx response is
   2376      * not acceptable, the UAC core MUST generate a valid answer in the ACK and then send a BYE
   2377      * immediately.
   2378      *
   2379      * Note that for the case of forked requests, you can create multiple outgoing invites each
   2380      * with a different cseq and hence you need to supply the invite.
   2381      *
   2382      * @see javax.sip.Dialog#createAck(long)
   2383      */
   2384     public Request createAck(long cseqno) throws InvalidArgumentException, SipException {
   2385 
   2386         // JvB: strictly speaking it is allowed to start a dialog with
   2387         // SUBSCRIBE,
   2388         // then send INVITE+ACK later on
   2389         if (!method.equals(Request.INVITE))
   2390             throw new SipException("Dialog was not created with an INVITE" + method);
   2391 
   2392         if (cseqno <= 0)
   2393             throw new InvalidArgumentException("bad cseq <= 0 ");
   2394         else if (cseqno > ((((long) 1) << 32) - 1))
   2395             throw new InvalidArgumentException("bad cseq > " + ((((long) 1) << 32) - 1));
   2396 
   2397         if (this.remoteTarget == null) {
   2398             throw new SipException("Cannot create ACK - no remote Target!");
   2399         }
   2400 
   2401         if (this.sipStack.isLoggingEnabled()) {
   2402             this.sipStack.getStackLogger().logDebug("createAck " + this + " cseqno " + cseqno);
   2403         }
   2404 
   2405         // MUST ack in the same order that the OKs were received. This traps
   2406         // out of order ACK sending. Old ACKs seqno's can always be ACKed.
   2407         if (lastInviteOkReceived < cseqno) {
   2408         	if (sipStack.isLoggingEnabled()) {
   2409         		this.sipStack.getStackLogger().logDebug(
   2410                     "WARNING : Attempt to crete ACK without OK " + this);
   2411             	this.sipStack.getStackLogger().logDebug("LAST RESPONSE = " + this.lastResponse);
   2412         	}
   2413             throw new SipException("Dialog not yet established -- no OK response!");
   2414         }
   2415 
   2416         try {
   2417 
   2418             // JvB: Transport from first entry in route set, or remote Contact
   2419             // if none
   2420             // Only used to find correct LP & create correct Via
   2421             SipURI uri4transport = null;
   2422 
   2423             if (this.routeList != null && !this.routeList.isEmpty()) {
   2424                 Route r = (Route) this.routeList.getFirst();
   2425                 uri4transport = ((SipURI) r.getAddress().getURI());
   2426             } else { // should be !=null, checked above
   2427                 uri4transport = ((SipURI) this.remoteTarget.getURI());
   2428             }
   2429 
   2430             String transport = uri4transport.getTransportParam();
   2431             if (transport == null) {
   2432                 // JvB fix: also support TLS
   2433                 transport = uri4transport.isSecure() ? ListeningPoint.TLS : ListeningPoint.UDP;
   2434             }
   2435             ListeningPointImpl lp = (ListeningPointImpl) sipProvider.getListeningPoint(transport);
   2436             if (lp == null) {
   2437             	if (sipStack.isLoggingEnabled()) {
   2438             		sipStack.getStackLogger().logError(
   2439                         "remoteTargetURI " + this.remoteTarget.getURI());
   2440                 	sipStack.getStackLogger().logError("uri4transport = " + uri4transport);
   2441                 	sipStack.getStackLogger().logError("No LP found for transport=" + transport);
   2442             	}
   2443                 throw new SipException(
   2444                         "Cannot create ACK - no ListeningPoint for transport towards next hop found:"
   2445                                 + transport);
   2446             }
   2447             SIPRequest sipRequest = new SIPRequest();
   2448             sipRequest.setMethod(Request.ACK);
   2449             sipRequest.setRequestURI((SipUri) getRemoteTarget().getURI().clone());
   2450             sipRequest.setCallId(this.callIdHeader);
   2451             sipRequest.setCSeq(new CSeq(cseqno, Request.ACK));
   2452             List<Via> vias = new ArrayList<Via>();
   2453             // Via via = lp.getViaHeader();
   2454             // The user may have touched the sentby for the response.
   2455             // so use the via header extracted from the response for the ACK =>
   2456             // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=205
   2457             // strip the params from the via of the response and use the params from the
   2458             // original request
   2459             Via via = this.lastResponse.getTopmostVia();
   2460             via.removeParameters();
   2461             if (originalRequest != null && originalRequest.getTopmostVia() != null) {
   2462                 NameValueList originalRequestParameters = originalRequest.getTopmostVia()
   2463                         .getParameters();
   2464                 if (originalRequestParameters != null && originalRequestParameters.size() > 0) {
   2465                     via.setParameters((NameValueList) originalRequestParameters.clone());
   2466                 }
   2467             }
   2468             via.setBranch(Utils.getInstance().generateBranchId()); // new branch
   2469             vias.add(via);
   2470             sipRequest.setVia(vias);
   2471             From from = new From();
   2472             from.setAddress(this.localParty);
   2473             from.setTag(this.myTag);
   2474             sipRequest.setFrom(from);
   2475             To to = new To();
   2476             to.setAddress(this.remoteParty);
   2477             if (hisTag != null)
   2478                 to.setTag(this.hisTag);
   2479             sipRequest.setTo(to);
   2480             sipRequest.setMaxForwards(new MaxForwards(70));
   2481 
   2482             if (this.originalRequest != null) {
   2483                 Authorization authorization = this.originalRequest.getAuthorization();
   2484                 if (authorization != null)
   2485                     sipRequest.setHeader(authorization);
   2486             }
   2487 
   2488             // ACKs for 2xx responses
   2489             // use the Route values learned from the Record-Route of the 2xx
   2490             // responses.
   2491             this.updateRequest(sipRequest);
   2492 
   2493             return sipRequest;
   2494         } catch (Exception ex) {
   2495             InternalErrorHandler.handleException(ex);
   2496             throw new SipException("unexpected exception ", ex);
   2497         }
   2498 
   2499     }
   2500 
   2501     /**
   2502      * Get the provider for this Dialog.
   2503      *
   2504      * SPEC_REVISION
   2505      *
   2506      * @return -- the SIP Provider associated with this transaction.
   2507      */
   2508     public SipProviderImpl getSipProvider() {
   2509         return this.sipProvider;
   2510     }
   2511 
   2512     /**
   2513      * @param sipProvider the sipProvider to set
   2514      */
   2515     public void setSipProvider(SipProviderImpl sipProvider) {
   2516         this.sipProvider = sipProvider;
   2517     }
   2518 
   2519     /**
   2520      * Check the tags of the response against the tags of the Dialog. Return true if the respnse
   2521      * matches the tags of the dialog. We do this check wehn sending out a response.
   2522      *
   2523      * @param sipResponse -- the response to check.
   2524      *
   2525      */
   2526     public void setResponseTags(SIPResponse sipResponse) {
   2527         if (this.getLocalTag() != null || this.getRemoteTag() != null) {
   2528             return;
   2529         }
   2530         String responseFromTag = sipResponse.getFromTag();
   2531         if ( responseFromTag != null ) {
   2532             if (responseFromTag.equals(this.getLocalTag())) {
   2533                 sipResponse.setToTag(this.getRemoteTag());
   2534             } else if (responseFromTag.equals(this.getRemoteTag())) {
   2535                 sipResponse.setToTag(this.getLocalTag());
   2536             }
   2537         } else {
   2538         	if (sipStack.isLoggingEnabled())
   2539         		sipStack.getStackLogger().logWarning("No from tag in response! Not RFC 3261 compatible.");
   2540         }
   2541 
   2542     }
   2543 
   2544     /**
   2545      * Set the last response for this dialog. This method is called for updating the dialog state
   2546      * when a response is either sent or received from within a Dialog.
   2547      *
   2548      * @param transaction -- the transaction associated with the response
   2549      * @param sipResponse -- the last response to set.
   2550      */
   2551     public void setLastResponse(SIPTransaction transaction, SIPResponse sipResponse) {
   2552         this.callIdHeader = sipResponse.getCallId();
   2553         int statusCode = sipResponse.getStatusCode();
   2554         if (statusCode == 100) {
   2555         	if (sipStack.isLoggingEnabled())
   2556         		sipStack.getStackLogger().logWarning(
   2557                     "Invalid status code - 100 in setLastResponse - ignoring");
   2558             return;
   2559         }
   2560 
   2561         this.lastResponse = sipResponse;
   2562         this.setAssigned();
   2563         // Adjust state of the Dialog state machine.
   2564         if (sipStack.isLoggingEnabled()) {
   2565             sipStack.getStackLogger().logDebug(
   2566                     "sipDialog: setLastResponse:" + this + " lastResponse = "
   2567                             + this.lastResponse.getFirstLine());
   2568         }
   2569         if (this.getState() == DialogState.TERMINATED) {
   2570             if (sipStack.isLoggingEnabled()) {
   2571                 sipStack.getStackLogger().logDebug(
   2572                         "sipDialog: setLastResponse -- dialog is terminated - ignoring ");
   2573             }
   2574             // Capture the OK response for later use in createAck
   2575             // This is handy for late arriving OK's that we want to ACK.
   2576             if (sipResponse.getCSeq().getMethod().equals(Request.INVITE) && statusCode == 200) {
   2577 
   2578                 this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(),
   2579                         this.lastInviteOkReceived);
   2580             }
   2581             return;
   2582         }
   2583         String cseqMethod = sipResponse.getCSeq().getMethod();
   2584         if (sipStack.isLoggingEnabled()) {
   2585             sipStack.getStackLogger().logStackTrace();
   2586             sipStack.getStackLogger().logDebug("cseqMethod = " + cseqMethod);
   2587             sipStack.getStackLogger().logDebug("dialogState = " + this.getState());
   2588             sipStack.getStackLogger().logDebug("method = " + this.getMethod());
   2589             sipStack.getStackLogger().logDebug("statusCode = " + statusCode);
   2590             sipStack.getStackLogger().logDebug("transaction = " + transaction);
   2591         }
   2592 
   2593         // JvB: don't use "!this.isServer" here
   2594         // note that the transaction can be null for forked
   2595         // responses.
   2596         if (transaction == null || transaction instanceof ClientTransaction) {
   2597             if (sipStack.isDialogCreated(cseqMethod)) {
   2598                 // Make a final tag assignment.
   2599                 if (getState() == null && (statusCode / 100 == 1)) {
   2600                     /*
   2601                      * Guard aginst slipping back into early state from confirmed state.
   2602                      */
   2603                     // Was (sipResponse.getToTag() != null || sipStack.rfc2543Supported)
   2604                     setState(SIPDialog.EARLY_STATE);
   2605                     if ((sipResponse.getToTag() != null || sipStack.rfc2543Supported)
   2606                             && this.getRemoteTag() == null) {
   2607                         setRemoteTag(sipResponse.getToTag());
   2608                         this.setDialogId(sipResponse.getDialogId(false));
   2609                         sipStack.putDialog(this);
   2610                         this.addRoute(sipResponse);
   2611                     }
   2612                 } else if (getState() != null && getState().equals(DialogState.EARLY)
   2613                         && statusCode / 100 == 1) {
   2614                     /*
   2615                      * This case occurs for forked dialog responses. The To tag can change as a
   2616                      * result of the forking. The remote target can also change as a result of the
   2617                      * forking.
   2618                      */
   2619                     if (cseqMethod.equals(getMethod()) && transaction != null
   2620                             && (sipResponse.getToTag() != null || sipStack.rfc2543Supported)) {
   2621                         setRemoteTag(sipResponse.getToTag());
   2622                         this.setDialogId(sipResponse.getDialogId(false));
   2623                         sipStack.putDialog(this);
   2624                         this.addRoute(sipResponse);
   2625                     }
   2626                 } else if (statusCode / 100 == 2) {
   2627                     // This is a dialog creating method (such as INVITE).
   2628                     // 2xx response -- set the state to the confirmed
   2629                     // state. To tag is MANDATORY for the response.
   2630 
   2631                     // Only do this if method equals initial request!
   2632 
   2633                     if (cseqMethod.equals(getMethod())
   2634                             && (sipResponse.getToTag() != null || sipStack.rfc2543Supported)
   2635                             && this.getState() != DialogState.CONFIRMED) {
   2636                         setRemoteTag(sipResponse.getToTag());
   2637                         this.setDialogId(sipResponse.getDialogId(false));
   2638                         sipStack.putDialog(this);
   2639                         this.addRoute(sipResponse);
   2640 
   2641                         setState(SIPDialog.CONFIRMED_STATE);
   2642                     }
   2643 
   2644                     // Capture the OK response for later use in createAck
   2645                     if (cseqMethod.equals(Request.INVITE)) {
   2646                         this.lastInviteOkReceived = Math.max(sipResponse.getCSeq().getSeqNumber(),
   2647                                 this.lastInviteOkReceived);
   2648                     }
   2649 
   2650                 } else if (statusCode >= 300
   2651                         && statusCode <= 699
   2652                         && (getState() == null || (cseqMethod.equals(getMethod()) && getState()
   2653                                 .getValue() == SIPDialog.EARLY_STATE))) {
   2654                     /*
   2655                      * This case handles 3xx, 4xx, 5xx and 6xx responses. RFC 3261 Section 12.3 -
   2656                      * dialog termination. Independent of the method, if a request outside of a
   2657                      * dialog generates a non-2xx final response, any early dialogs created
   2658                      * through provisional responses to that request are terminated.
   2659                      */
   2660                     setState(SIPDialog.TERMINATED_STATE);
   2661                 }
   2662 
   2663                 /*
   2664                  * This code is in support of "proxy" servers that are constructed as back to back
   2665                  * user agents. This could be a dialog in the middle of the call setup path
   2666                  * somewhere. Hence the incoming invite has record route headers in it. The
   2667                  * response will have additional record route headers. However, for this dialog
   2668                  * only the downstream record route headers matter. Ideally proxy servers should
   2669                  * not be constructed as Back to Back User Agents. Remove all the record routes
   2670                  * that are present in the incoming INVITE so you only have the downstream Route
   2671                  * headers present in the dialog. Note that for an endpoint - you will have no
   2672                  * record route headers present in the original request so the loop will not
   2673                  * execute.
   2674                  */
   2675                 if ( this.getState() != DialogState.CONFIRMED && this.getState() != DialogState.TERMINATED ) {
   2676                     if (originalRequest != null) {
   2677                         RecordRouteList rrList = originalRequest.getRecordRouteHeaders();
   2678                         if (rrList != null) {
   2679                             ListIterator<RecordRoute> it = rrList.listIterator(rrList.size());
   2680                             while (it.hasPrevious()) {
   2681                                 RecordRoute rr = (RecordRoute) it.previous();
   2682                                 Route route = (Route) routeList.getFirst();
   2683                                 if (route != null && rr.getAddress().equals(route.getAddress())) {
   2684                                     routeList.removeFirst();
   2685                                 } else
   2686                                     break;
   2687                             }
   2688                         }
   2689                     }
   2690                 }
   2691 
   2692             } else if (cseqMethod.equals(Request.NOTIFY)
   2693                     && (this.getMethod().equals(Request.SUBSCRIBE) || this.getMethod().equals(
   2694                             Request.REFER)) && sipResponse.getStatusCode() / 100 == 2
   2695                     && this.getState() == null) {
   2696                 // This is a notify response.
   2697                 this.setDialogId(sipResponse.getDialogId(true));
   2698                 sipStack.putDialog(this);
   2699                 this.setState(SIPDialog.CONFIRMED_STATE);
   2700 
   2701             } else if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2
   2702                     && isTerminatedOnBye()) {
   2703                 // Dialog will be terminated when the transction is terminated.
   2704                 setState(SIPDialog.TERMINATED_STATE);
   2705             }
   2706         } else {
   2707             // Processing Server Dialog.
   2708 
   2709             if (cseqMethod.equals(Request.BYE) && statusCode / 100 == 2
   2710                     && this.isTerminatedOnBye()) {
   2711                 /*
   2712                  * Only transition to terminated state when 200 OK is returned for the BYE. Other
   2713                  * status codes just result in leaving the state in COMPLETED state.
   2714                  */
   2715                 this.setState(SIPDialog.TERMINATED_STATE);
   2716             } else {
   2717                 boolean doPutDialog = false;
   2718 
   2719                 if (getLocalTag() == null && sipResponse.getTo().getTag() != null
   2720                         && sipStack.isDialogCreated(cseqMethod) && cseqMethod.equals(getMethod())) {
   2721                     setLocalTag(sipResponse.getTo().getTag());
   2722 
   2723                     doPutDialog = true;
   2724                 }
   2725 
   2726                 if (statusCode / 100 != 2) {
   2727                     if (statusCode / 100 == 1) {
   2728                         if (doPutDialog) {
   2729 
   2730                             setState(SIPDialog.EARLY_STATE);
   2731                             this.setDialogId(sipResponse.getDialogId(true));
   2732                             sipStack.putDialog(this);
   2733                         }
   2734                     } else {
   2735                         /*
   2736                          * RFC 3265 chapter 3.1.4.1 "Non-200 class final responses indicate that
   2737                          * no subscription or dialog has been created, and no subsequent NOTIFY
   2738                          * message will be sent. All non-200 class" + responses (with the
   2739                          * exception of "489", described herein) have the same meanings and
   2740                          * handling as described in SIP"
   2741                          */
   2742                         // Bug Fix by Jens tinfors
   2743                         // see https://jain-sip.dev.java.net/servlets/ReadMsg?list=users&msgNo=797
   2744                         if (statusCode == 489
   2745                                 && (cseqMethod.equals(Request.NOTIFY) || cseqMethod
   2746                                         .equals(Request.SUBSCRIBE))) {
   2747                         	if (sipStack.isLoggingEnabled())
   2748                         		sipStack.getStackLogger().logDebug(
   2749                                     "RFC 3265 : Not setting dialog to TERMINATED for 489");
   2750                         } else {
   2751                             // baranowb: simplest fix to
   2752                             // https://jain-sip.dev.java.net/issues/show_bug.cgi?id=175
   2753                             // application is responsible for terminating in this case
   2754                             // see rfc 5057 for better explanation
   2755                             if (!this.isReInvite() && getState() != DialogState.CONFIRMED) {
   2756                                 this.setState(SIPDialog.TERMINATED_STATE);
   2757                             }
   2758                         }
   2759                     }
   2760 
   2761                 } else {
   2762 
   2763                     /*
   2764                      * JvB: RFC4235 says that when sending 2xx on UAS side, state should move to
   2765                      * CONFIRMED
   2766                      */
   2767                     if (this.dialogState <= SIPDialog.EARLY_STATE
   2768                             && (cseqMethod.equals(Request.INVITE)
   2769                                     || cseqMethod.equals(Request.SUBSCRIBE) || cseqMethod
   2770                                     .equals(Request.REFER))) {
   2771                         this.setState(SIPDialog.CONFIRMED_STATE);
   2772                     }
   2773 
   2774                     if (doPutDialog) {
   2775                         this.setDialogId(sipResponse.getDialogId(true));
   2776                         sipStack.putDialog(this);
   2777                     }
   2778                     /*
   2779                      * We put the dialog into the table. We must wait for ACK before re-INVITE is
   2780                      * sent
   2781                      */
   2782                     if (transaction.getState() != TransactionState.TERMINATED
   2783                             && sipResponse.getStatusCode() == Response.OK
   2784                             && cseqMethod.equals(Request.INVITE)
   2785                             && this.isBackToBackUserAgent) {
   2786                             /*
   2787                              * Acquire the flag for re-INVITE so that we cannot re-INVITE before
   2788                              * ACK is received.
   2789                              */
   2790                             if (!this.takeAckSem()) {
   2791                                 if (sipStack.isLoggingEnabled()) {
   2792                                     sipStack.getStackLogger().logDebug(
   2793                                             "Delete dialog -- cannot acquire ackSem");
   2794                                 }
   2795                                 this.delete();
   2796                                 return;
   2797                             }
   2798 
   2799                     }
   2800                 }
   2801             }
   2802 
   2803         }
   2804 
   2805     }
   2806 
   2807     /**
   2808      * Start the retransmit timer.
   2809      *
   2810      * @param sipServerTx -- server transaction on which the response was sent
   2811      * @param response - response that was sent.
   2812      */
   2813     public void startRetransmitTimer(SIPServerTransaction sipServerTx, Response response) {
   2814         if (sipServerTx.getRequest().getMethod().equals(Request.INVITE)
   2815                 && response.getStatusCode() / 100 == 2) {
   2816             this.startTimer(sipServerTx);
   2817         }
   2818     }
   2819 
   2820     /**
   2821      * @return -- the last response associated with the dialog.
   2822      */
   2823     public SIPResponse getLastResponse() {
   2824 
   2825         return lastResponse;
   2826     }
   2827 
   2828     /**
   2829      * Do taget refresh dialog state updates.
   2830      *
   2831      * RFC 3261: Requests within a dialog MAY contain Record-Route and Contact header fields.
   2832      * However, these requests do not cause the dialog's route set to be modified, although they
   2833      * may modify the remote target URI. Specifically, requests that are not target refresh
   2834      * requests do not modify the dialog's remote target URI, and requests that are target refresh
   2835      * requests do. For dialogs that have been established with an
   2836      *
   2837      * INVITE, the only target refresh request defined is re-INVITE (see Section 14). Other
   2838      * extensions may define different target refresh requests for dialogs established in other
   2839      * ways.
   2840      */
   2841     private void doTargetRefresh(SIPMessage sipMessage) {
   2842 
   2843         ContactList contactList = sipMessage.getContactHeaders();
   2844 
   2845         /*
   2846          * INVITE is the target refresh for INVITE dialogs. SUBSCRIBE is the target refresh for
   2847          * subscribe dialogs from the client side. This modifies the remote target URI potentially
   2848          */
   2849         if (contactList != null) {
   2850 
   2851             Contact contact = (Contact) contactList.getFirst();
   2852             this.setRemoteTarget(contact);
   2853 
   2854         }
   2855 
   2856     }
   2857 
   2858     private static final boolean optionPresent(ListIterator l, String option) {
   2859         while (l.hasNext()) {
   2860             OptionTag opt = (OptionTag) l.next();
   2861             if (opt != null && option.equalsIgnoreCase(opt.getOptionTag()))
   2862                 return true;
   2863         }
   2864         return false;
   2865     }
   2866 
   2867     /*
   2868      * (non-Javadoc)
   2869      *
   2870      * @see javax.sip.Dialog#createReliableProvisionalResponse(int)
   2871      */
   2872     public Response createReliableProvisionalResponse(int statusCode)
   2873             throws InvalidArgumentException, SipException {
   2874 
   2875         if (!(firstTransactionIsServerTransaction)) {
   2876             throw new SipException("Not a Server Dialog!");
   2877 
   2878         }
   2879         /*
   2880          * A UAS MUST NOT attempt to send a 100 (Trying) response reliably. Only provisional
   2881          * responses numbered 101 to 199 may be sent reliably. If the request did not include
   2882          * either a Supported or Require header field indicating this feature, the UAS MUST NOT
   2883          * send the provisional response reliably.
   2884          */
   2885         if (statusCode <= 100 || statusCode > 199)
   2886             throw new InvalidArgumentException("Bad status code ");
   2887         SIPRequest request = this.originalRequest;
   2888         if (!request.getMethod().equals(Request.INVITE))
   2889             throw new SipException("Bad method");
   2890 
   2891         ListIterator<SIPHeader> list = request.getHeaders(SupportedHeader.NAME);
   2892         if (list == null || !optionPresent(list, "100rel")) {
   2893             list = request.getHeaders(RequireHeader.NAME);
   2894             if (list == null || !optionPresent(list, "100rel")) {
   2895                 throw new SipException("No Supported/Require 100rel header in the request");
   2896             }
   2897         }
   2898 
   2899         SIPResponse response = request.createResponse(statusCode);
   2900         /*
   2901          * The provisional response to be sent reliably is constructed by the UAS core according
   2902          * to the procedures of Section 8.2.6 of RFC 3261. In addition, it MUST contain a Require
   2903          * header field containing the option tag 100rel, and MUST include an RSeq header field.
   2904          * The value of the header field for the first reliable provisional response in a
   2905          * transaction MUST be between 1 and 2**31 - 1. It is RECOMMENDED that it be chosen
   2906          * uniformly in this range. The RSeq numbering space is within a single transaction. This
   2907          * means that provisional responses for different requests MAY use the same values for the
   2908          * RSeq number.
   2909          */
   2910         Require require = new Require();
   2911         try {
   2912             require.setOptionTag("100rel");
   2913         } catch (Exception ex) {
   2914             InternalErrorHandler.handleException(ex);
   2915         }
   2916         response.addHeader(require);
   2917         RSeq rseq = new RSeq();
   2918         /*
   2919          * set an arbitrary sequence number. This is actually set when the response is sent out
   2920          */
   2921         rseq.setSeqNumber(1L);
   2922         /*
   2923          * Copy the record route headers from the request to the response ( Issue 160 ). Note that
   2924          * other 1xx headers do not get their Record Route headers copied over but reliable
   2925          * provisional responses do. See RFC 3262 Table 2.
   2926          */
   2927         RecordRouteList rrl = request.getRecordRouteHeaders();
   2928         if (rrl != null) {
   2929             RecordRouteList rrlclone = (RecordRouteList) rrl.clone();
   2930             response.setHeader(rrlclone);
   2931         }
   2932 
   2933         return response;
   2934     }
   2935 
   2936     /**
   2937      * Do the processing necessary for the PRACK
   2938      *
   2939      * @param prackRequest
   2940      * @return true if this is the first time the tx has seen the prack ( and hence needs to be
   2941      *         passed up to the TU)
   2942      */
   2943     public boolean handlePrack(SIPRequest prackRequest) {
   2944         /*
   2945          * The RAck header is sent in a PRACK request to support reliability of provisional
   2946          * responses. It contains two numbers and a method tag. The first number is the value from
   2947          * the RSeq header in the provisional response that is being acknowledged. The next
   2948          * number, and the method, are copied from the CSeq in the response that is being
   2949          * acknowledged. The method name in the RAck header is case sensitive.
   2950          */
   2951         if (!this.isServer()) {
   2952             if (sipStack.isLoggingEnabled())
   2953                 sipStack.getStackLogger().logDebug("Dropping Prack -- not a server Dialog");
   2954             return false;
   2955         }
   2956         SIPServerTransaction sipServerTransaction = (SIPServerTransaction) this
   2957                 .getFirstTransaction();
   2958         SIPResponse sipResponse = sipServerTransaction.getReliableProvisionalResponse();
   2959 
   2960         if (sipResponse == null) {
   2961             if (sipStack.isLoggingEnabled())
   2962                 sipStack.getStackLogger()
   2963                         .logDebug("Dropping Prack -- ReliableResponse not found");
   2964             return false;
   2965         }
   2966 
   2967         RAck rack = (RAck) prackRequest.getHeader(RAckHeader.NAME);
   2968 
   2969         if (rack == null) {
   2970             if (sipStack.isLoggingEnabled())
   2971                 sipStack.getStackLogger().logDebug("Dropping Prack -- rack header not found");
   2972             return false;
   2973         }
   2974         CSeq cseq = (CSeq) sipResponse.getCSeq();
   2975 
   2976         if (!rack.getMethod().equals(cseq.getMethod())) {
   2977             if (sipStack.isLoggingEnabled())
   2978                 sipStack.getStackLogger().logDebug(
   2979                         "Dropping Prack -- CSeq Header does not match PRACK");
   2980             return false;
   2981         }
   2982 
   2983         if (rack.getCSeqNumberLong() != cseq.getSeqNumber()) {
   2984             if (sipStack.isLoggingEnabled())
   2985                 sipStack.getStackLogger().logDebug(
   2986                         "Dropping Prack -- CSeq Header does not match PRACK");
   2987             return false;
   2988         }
   2989 
   2990         RSeq rseq = (RSeq) sipResponse.getHeader(RSeqHeader.NAME);
   2991 
   2992         if (rack.getRSequenceNumber() != rseq.getSeqNumber()) {
   2993             if (sipStack.isLoggingEnabled())
   2994                 sipStack.getStackLogger().logDebug(
   2995                         "Dropping Prack -- RSeq Header does not match PRACK");
   2996             return false;
   2997         }
   2998 
   2999         return sipServerTransaction.prackRecieved();
   3000     }
   3001 
   3002     /*
   3003      * (non-Javadoc)
   3004      *
   3005      * @see javax.sip.Dialog#sendReliableProvisionalResponse(javax.sip.message.Response)
   3006      */
   3007     public void sendReliableProvisionalResponse(Response relResponse) throws SipException {
   3008         if (!this.isServer()) {
   3009             throw new SipException("Not a Server Dialog");
   3010         }
   3011 
   3012         SIPResponse sipResponse = (SIPResponse) relResponse;
   3013 
   3014         if (relResponse.getStatusCode() == 100)
   3015             throw new SipException("Cannot send 100 as a reliable provisional response");
   3016 
   3017         if (relResponse.getStatusCode() / 100 > 2)
   3018             throw new SipException(
   3019                     "Response code is not a 1xx response - should be in the range 101 to 199 ");
   3020 
   3021         /*
   3022          * Do a little checking on the outgoing response.
   3023          */
   3024         if (sipResponse.getToTag() == null) {
   3025             throw new SipException(
   3026                     "Badly formatted response -- To tag mandatory for Reliable Provisional Response");
   3027         }
   3028         ListIterator requireList = (ListIterator) relResponse.getHeaders(RequireHeader.NAME);
   3029         boolean found = false;
   3030 
   3031         if (requireList != null) {
   3032 
   3033             while (requireList.hasNext() && !found) {
   3034                 RequireHeader rh = (RequireHeader) requireList.next();
   3035                 if (rh.getOptionTag().equalsIgnoreCase("100rel")) {
   3036                     found = true;
   3037                 }
   3038             }
   3039         }
   3040 
   3041         if (!found) {
   3042             Require require = new Require("100rel");
   3043             relResponse.addHeader(require);
   3044             if (sipStack.isLoggingEnabled()) {
   3045                 sipStack.getStackLogger().logDebug(
   3046                         "Require header with optionTag 100rel is needed -- adding one");
   3047             }
   3048 
   3049         }
   3050 
   3051         SIPServerTransaction serverTransaction = (SIPServerTransaction) this
   3052                 .getFirstTransaction();
   3053         /*
   3054          * put into the dialog table before sending the response so as to avoid race condition
   3055          * with PRACK
   3056          */
   3057         this.setLastResponse(serverTransaction, sipResponse);
   3058 
   3059         this.setDialogId(sipResponse.getDialogId(true));
   3060 
   3061         serverTransaction.sendReliableProvisionalResponse(relResponse);
   3062 
   3063         this.startRetransmitTimer(serverTransaction, relResponse);
   3064 
   3065     }
   3066 
   3067     /*
   3068      * (non-Javadoc)
   3069      *
   3070      * @see javax.sip.Dialog#terminateOnBye(boolean)
   3071      */
   3072     public void terminateOnBye(boolean terminateFlag) throws SipException {
   3073 
   3074         this.terminateOnBye = terminateFlag;
   3075     }
   3076 
   3077     /**
   3078      * Set the "assigned" flag to true. We do this when inserting the dialog into the dialog table
   3079      * of the stack.
   3080      *
   3081      */
   3082     public void setAssigned() {
   3083         this.isAssigned = true;
   3084     }
   3085 
   3086     /**
   3087      * Return true if the dialog has already been mapped to a transaction.
   3088      *
   3089      */
   3090 
   3091     public boolean isAssigned() {
   3092         return this.isAssigned;
   3093     }
   3094 
   3095     /**
   3096      * Get the contact header that the owner of this dialog assigned. Subsequent Requests are
   3097      * considered to belong to the dialog if the dialog identifier matches and the contact header
   3098      * matches the ip address and port on which the request is received.
   3099      *
   3100      * @return contact header belonging to the dialog.
   3101      */
   3102     public Contact getMyContactHeader() {
   3103     	return contactHeader;
   3104     }
   3105 
   3106     /**
   3107      * Do the necessary processing to handle an ACK directed at this Dialog.
   3108      *
   3109      * @param ackTransaction -- the ACK transaction that was directed at this dialog.
   3110      * @return -- true if the ACK was successfully consumed by the Dialog and resulted in the
   3111      *         dialog state being changed.
   3112      */
   3113     public boolean handleAck(SIPServerTransaction ackTransaction) {
   3114         SIPRequest sipRequest = ackTransaction.getOriginalRequest();
   3115 
   3116         if (isAckSeen() && getRemoteSeqNumber() == sipRequest.getCSeq().getSeqNumber()) {
   3117 
   3118             if (sipStack.isLoggingEnabled()) {
   3119                 sipStack.getStackLogger().logDebug(
   3120                         "ACK already seen by dialog -- dropping Ack" + " retransmission");
   3121             }
   3122             acquireTimerTaskSem();
   3123             try {
   3124             	if (this.timerTask != null) {
   3125 	                this.timerTask.cancel();
   3126 	                this.timerTask = null;
   3127             	}
   3128             } finally {
   3129         		releaseTimerTaskSem();
   3130         	}
   3131             return false;
   3132         } else if (this.getState() == DialogState.TERMINATED) {
   3133             if (sipStack.isLoggingEnabled())
   3134                 sipStack.getStackLogger().logDebug("Dialog is terminated -- dropping ACK");
   3135             return false;
   3136 
   3137         } else {
   3138 
   3139             /*
   3140              * This could be a re-invite processing. check to see if the ack matches with the last
   3141              * transaction. s
   3142              */
   3143 
   3144             SIPServerTransaction tr = getInviteTransaction();
   3145 
   3146             SIPResponse sipResponse = (tr != null ? tr.getLastResponse() : null);
   3147 
   3148             // Idiot check for sending ACK from the wrong side!
   3149             if (tr != null
   3150                     && sipResponse != null
   3151                     && sipResponse.getStatusCode() / 100 == 2
   3152                     && sipResponse.getCSeq().getMethod().equals(Request.INVITE)
   3153                     && sipResponse.getCSeq().getSeqNumber() == sipRequest.getCSeq()
   3154                             .getSeqNumber()) {
   3155 
   3156                 ackTransaction.setDialog(this, sipResponse.getDialogId(false));
   3157                 /*
   3158                  * record that we already saw an ACK for this dialog.
   3159                  */
   3160 
   3161                 ackReceived(sipRequest);
   3162                 if (sipStack.isLoggingEnabled())
   3163                 	sipStack.getStackLogger().logDebug("ACK for 2XX response --- sending to TU ");
   3164                 return true;
   3165 
   3166             } else {
   3167                 /*
   3168                  * This happens when the ACK is re-transmitted and arrives too late to be
   3169                  * processed.
   3170                  */
   3171 
   3172                 if (sipStack.isLoggingEnabled())
   3173                     sipStack.getStackLogger().logDebug(
   3174                             " INVITE transaction not found  -- Discarding ACK");
   3175                 return false;
   3176             }
   3177         }
   3178     }
   3179 
   3180     void setEarlyDialogId(String earlyDialogId) {
   3181         this.earlyDialogId = earlyDialogId;
   3182     }
   3183 
   3184     String getEarlyDialogId() {
   3185         return earlyDialogId;
   3186     }
   3187 
   3188     /**
   3189      * Release the semaphore for ACK processing so the next re-INVITE may proceed.
   3190      */
   3191     void releaseAckSem() {
   3192         if (this.isBackToBackUserAgent) {
   3193             if (sipStack.isLoggingEnabled()) {
   3194                 sipStack.getStackLogger().logDebug("releaseAckSem]" + this);
   3195             }
   3196             this.ackSem.release();
   3197         }
   3198 
   3199     }
   3200 
   3201     boolean takeAckSem() {
   3202         if (sipStack.isLoggingEnabled()) {
   3203             sipStack.getStackLogger().logDebug("[takeAckSem " + this);
   3204         }
   3205         try {
   3206             if (!this.ackSem.tryAcquire(2, TimeUnit.SECONDS)) {
   3207                 if (sipStack.isLoggingEnabled()) {
   3208                     sipStack.getStackLogger().logError("Cannot aquire ACK semaphore");
   3209                 }
   3210 
   3211                 if ( sipStack.isLoggingEnabled() ) {
   3212                     sipStack.getStackLogger().logDebug("Semaphore previously acquired at " + this.stackTrace);
   3213                     sipStack.getStackLogger().logStackTrace();
   3214 
   3215                 }
   3216                 return false;
   3217             }
   3218 
   3219             if ( sipStack.isLoggingEnabled() ) {
   3220 
   3221                 this.recordStackTrace();
   3222             }
   3223 
   3224         } catch (InterruptedException ex) {
   3225             sipStack.getStackLogger().logError("Cannot aquire ACK semaphore");
   3226             return false;
   3227 
   3228         }
   3229         return true;
   3230 
   3231     }
   3232 
   3233     /**
   3234      * @param lastAckReceived the lastAckReceived to set
   3235      */
   3236     private void setLastAckReceived(SIPRequest lastAckReceived) {
   3237         this.lastAckReceived = lastAckReceived;
   3238     }
   3239 
   3240     /**
   3241      * @return the lastAckReceived
   3242      */
   3243     protected SIPRequest getLastAckReceived() {
   3244         return lastAckReceived;
   3245     }
   3246 
   3247     /**
   3248      * @param lastAckSent the lastAckSent to set
   3249      */
   3250     private void setLastAckSent(SIPRequest lastAckSent) {
   3251         this.lastAckSent = lastAckSent;
   3252     }
   3253 
   3254     /**
   3255      * @return true if an ack was ever sent for this Dialog
   3256      */
   3257     public boolean isAtleastOneAckSent() {
   3258         return this.isAcknowledged;
   3259     }
   3260 
   3261 
   3262 
   3263     public boolean isBackToBackUserAgent() {
   3264         return this.isBackToBackUserAgent;
   3265     }
   3266 
   3267     public synchronized void doDeferredDeleteIfNoAckSent(long seqno) {
   3268 		if (sipStack.getTimer() == null) {
   3269 			this.setState(TERMINATED_STATE);
   3270 		} else if(dialogDeleteIfNoAckSentTask == null){
   3271 			// Delete the transaction after the max ack timeout.
   3272 			dialogDeleteIfNoAckSentTask = new DialogDeleteIfNoAckSentTask(seqno);
   3273 			sipStack.getTimer().schedule(
   3274 					dialogDeleteIfNoAckSentTask,
   3275 					SIPTransaction.TIMER_J
   3276 							* SIPTransactionStack.BASE_TIMER_INTERVAL);
   3277 		}
   3278 	}
   3279 
   3280     /*
   3281      * (non-Javadoc)
   3282      * @see gov.nist.javax.sip.DialogExt#setBackToBackUserAgent(boolean)
   3283      */
   3284     public void setBackToBackUserAgent() {
   3285         this.isBackToBackUserAgent = true;
   3286     }
   3287 
   3288 	/**
   3289 	 * @return the eventHeader
   3290 	 */
   3291 	EventHeader getEventHeader() {
   3292 		return eventHeader;
   3293 	}
   3294 
   3295 	/**
   3296 	 * @param eventHeader the eventHeader to set
   3297 	 */
   3298 	void setEventHeader(EventHeader eventHeader) {
   3299 		this.eventHeader = eventHeader;
   3300 	}
   3301 
   3302 	/**
   3303 	 * @param serverTransactionFlag the serverTransactionFlag to set
   3304 	 */
   3305 	void setServerTransactionFlag(boolean serverTransactionFlag) {
   3306 		this.serverTransactionFlag = serverTransactionFlag;
   3307 	}
   3308 
   3309 	/**
   3310 	 * @param reInviteFlag the reinviteFlag to set
   3311 	 */
   3312 	void setReInviteFlag(boolean reInviteFlag) {
   3313 		this.reInviteFlag = reInviteFlag;
   3314 	}
   3315 
   3316 
   3317 	public boolean isSequnceNumberValidation() {
   3318 	    return this.sequenceNumberValidation;
   3319 	}
   3320 
   3321     public void disableSequenceNumberValidation() {
   3322         this.sequenceNumberValidation = false;
   3323     }
   3324 
   3325 
   3326     public void acquireTimerTaskSem() {
   3327     	boolean acquired = false;
   3328         try {
   3329             acquired = this.timerTaskLock.tryAcquire(10, TimeUnit.SECONDS);
   3330         } catch ( InterruptedException ex) {
   3331             acquired = false;
   3332         }
   3333         if(!acquired) {
   3334         	throw new IllegalStateException("Impossible to acquire the dialog timer task lock");
   3335         }
   3336     }
   3337 
   3338     public void releaseTimerTaskSem() {
   3339         this.timerTaskLock.release();
   3340     }
   3341 
   3342 
   3343 }
   3344