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/**************************************************************************/
29package gov.nist.javax.sip.stack;
30
31import gov.nist.core.InternalErrorHandler;
32import gov.nist.core.NameValueList;
33import gov.nist.javax.sip.DialogExt;
34import gov.nist.javax.sip.ListeningPointImpl;
35import gov.nist.javax.sip.SipListenerExt;
36import gov.nist.javax.sip.SipProviderImpl;
37import gov.nist.javax.sip.Utils;
38import gov.nist.javax.sip.address.AddressImpl;
39import gov.nist.javax.sip.address.SipUri;
40import gov.nist.javax.sip.header.Authorization;
41import gov.nist.javax.sip.header.CSeq;
42import gov.nist.javax.sip.header.Contact;
43import gov.nist.javax.sip.header.ContactList;
44import gov.nist.javax.sip.header.From;
45import gov.nist.javax.sip.header.MaxForwards;
46import gov.nist.javax.sip.header.RAck;
47import gov.nist.javax.sip.header.RSeq;
48import gov.nist.javax.sip.header.Reason;
49import gov.nist.javax.sip.header.RecordRoute;
50import gov.nist.javax.sip.header.RecordRouteList;
51import gov.nist.javax.sip.header.Require;
52import gov.nist.javax.sip.header.Route;
53import gov.nist.javax.sip.header.RouteList;
54import gov.nist.javax.sip.header.SIPHeader;
55import gov.nist.javax.sip.header.TimeStamp;
56import gov.nist.javax.sip.header.To;
57import gov.nist.javax.sip.header.Via;
58import gov.nist.javax.sip.message.MessageFactoryImpl;
59import gov.nist.javax.sip.message.SIPMessage;
60import gov.nist.javax.sip.message.SIPRequest;
61import gov.nist.javax.sip.message.SIPResponse;
62
63import java.io.IOException;
64import java.io.PrintWriter;
65import java.io.Serializable;
66import java.io.StringWriter;
67import java.net.InetAddress;
68import java.text.ParseException;
69import java.util.ArrayList;
70import java.util.Iterator;
71import java.util.LinkedList;
72import java.util.List;
73import java.util.ListIterator;
74import java.util.Set;
75import java.util.concurrent.CopyOnWriteArraySet;
76import java.util.concurrent.Semaphore;
77import java.util.concurrent.TimeUnit;
78
79import javax.sip.ClientTransaction;
80import javax.sip.DialogDoesNotExistException;
81import javax.sip.DialogState;
82import javax.sip.IOExceptionEvent;
83import javax.sip.InvalidArgumentException;
84import javax.sip.ListeningPoint;
85import javax.sip.ObjectInUseException;
86import javax.sip.SipException;
87import javax.sip.Transaction;
88import javax.sip.TransactionDoesNotExistException;
89import javax.sip.TransactionState;
90import javax.sip.address.Address;
91import javax.sip.address.Hop;
92import javax.sip.address.SipURI;
93import javax.sip.header.CallIdHeader;
94import javax.sip.header.ContactHeader;
95import javax.sip.header.EventHeader;
96import javax.sip.header.OptionTag;
97import javax.sip.header.RAckHeader;
98import javax.sip.header.RSeqHeader;
99import javax.sip.header.ReasonHeader;
100import javax.sip.header.RequireHeader;
101import javax.sip.header.RouteHeader;
102import javax.sip.header.SupportedHeader;
103import javax.sip.header.TimeStampHeader;
104import javax.sip.message.Request;
105import 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
131public 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