• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Conditions Of Use
3  *
4  * This software was developed by employees of the National Institute of
5  * Standards and Technology (NIST), an agency of the Federal Government.
6  * Pursuant to title 15 Untied States Code Section 105, works of NIST
7  * employees are not subject to copyright protection in the United States
8  * and are considered to be in the public domain.  As a result, a formal
9  * license is not needed to use the software.
10  *
11  * This software is provided by NIST as a service and is expressly
12  * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13  * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15  * AND DATA ACCURACY.  NIST does not warrant or make any representations
16  * regarding the use of the software or the results thereof, including but
17  * not limited to the correctness, accuracy, reliability or usefulness of
18  * the software.
19  *
20  * Permission to use this software is contingent upon your acceptance
21  * of the terms of this agreement
22  *
23  * .
24  *
25  */
26 /**************************************************************************/
27 /* Product of NIST Advanced Networking Technologies Division      */
28 /**************************************************************************/
29 package gov.nist.javax.sip.stack;
30 
31 import gov.nist.core.InternalErrorHandler;
32 import gov.nist.core.NameValueList;
33 import gov.nist.javax.sip.DialogExt;
34 import gov.nist.javax.sip.ListeningPointImpl;
35 import gov.nist.javax.sip.SipListenerExt;
36 import gov.nist.javax.sip.SipProviderImpl;
37 import gov.nist.javax.sip.Utils;
38 import gov.nist.javax.sip.address.AddressImpl;
39 import gov.nist.javax.sip.address.SipUri;
40 import gov.nist.javax.sip.header.Authorization;
41 import gov.nist.javax.sip.header.CSeq;
42 import gov.nist.javax.sip.header.Contact;
43 import gov.nist.javax.sip.header.ContactList;
44 import gov.nist.javax.sip.header.From;
45 import gov.nist.javax.sip.header.MaxForwards;
46 import gov.nist.javax.sip.header.RAck;
47 import gov.nist.javax.sip.header.RSeq;
48 import gov.nist.javax.sip.header.Reason;
49 import gov.nist.javax.sip.header.RecordRoute;
50 import gov.nist.javax.sip.header.RecordRouteList;
51 import gov.nist.javax.sip.header.Require;
52 import gov.nist.javax.sip.header.Route;
53 import gov.nist.javax.sip.header.RouteList;
54 import gov.nist.javax.sip.header.SIPHeader;
55 import gov.nist.javax.sip.header.TimeStamp;
56 import gov.nist.javax.sip.header.To;
57 import gov.nist.javax.sip.header.Via;
58 import gov.nist.javax.sip.message.MessageFactoryImpl;
59 import gov.nist.javax.sip.message.SIPMessage;
60 import gov.nist.javax.sip.message.SIPRequest;
61 import gov.nist.javax.sip.message.SIPResponse;
62 
63 import java.io.IOException;
64 import java.io.PrintWriter;
65 import java.io.Serializable;
66 import java.io.StringWriter;
67 import java.net.InetAddress;
68 import java.text.ParseException;
69 import java.util.ArrayList;
70 import java.util.Iterator;
71 import java.util.LinkedList;
72 import java.util.List;
73 import java.util.ListIterator;
74 import java.util.Set;
75 import java.util.concurrent.CopyOnWriteArraySet;
76 import java.util.concurrent.Semaphore;
77 import java.util.concurrent.TimeUnit;
78 
79 import javax.sip.ClientTransaction;
80 import javax.sip.DialogDoesNotExistException;
81 import javax.sip.DialogState;
82 import javax.sip.IOExceptionEvent;
83 import javax.sip.InvalidArgumentException;
84 import javax.sip.ListeningPoint;
85 import javax.sip.ObjectInUseException;
86 import javax.sip.SipException;
87 import javax.sip.Transaction;
88 import javax.sip.TransactionDoesNotExistException;
89 import javax.sip.TransactionState;
90 import javax.sip.address.Address;
91 import javax.sip.address.Hop;
92 import javax.sip.address.SipURI;
93 import javax.sip.header.CallIdHeader;
94 import javax.sip.header.ContactHeader;
95 import javax.sip.header.EventHeader;
96 import javax.sip.header.OptionTag;
97 import javax.sip.header.RAckHeader;
98 import javax.sip.header.RSeqHeader;
99 import javax.sip.header.ReasonHeader;
100 import javax.sip.header.RequireHeader;
101 import javax.sip.header.RouteHeader;
102 import javax.sip.header.SupportedHeader;
103 import javax.sip.header.TimeStampHeader;
104 import javax.sip.message.Request;
105 import javax.sip.message.Response;
106 
107 /*
108  * Acknowledgements:
109  *
110  * Bugs in this class were reported by Antonis Karydas, Brad Templeton, Jeff Adams, Alex Rootham ,
111  * Martin Le Clerk, Christophe Anzille, Andreas Bystrom, Lebing Xie, Jeroen van Bemmel. Hagai Sela
112  * reported a bug in updating the route set (on RE-INVITE). Jens Tinfors submitted a bug fix and
113  * the .equals method. Jan Schaumloeffel contributed a buf fix ( memory leak was happening when
114  * 180 contained a To tag.
115  *
116  */
117 
118 /**
119  * Tracks dialogs. A dialog is a peer to peer association of communicating SIP entities. For
120  * INVITE transactions, a Dialog is created when a success message is received (i.e. a response
121  * that has a To tag). The SIP Protocol stores enough state in the message structure to extract a
122  * dialog identifier that can be used to retrieve this structure from the SipStack.
123  *
124  * @version 1.2 $Revision: 1.159 $ $Date: 2010/01/08 15:14:12 $
125  *
126  * @author M. Ranganathan
127  *
128  *
129  */
130 
131 public class SIPDialog implements javax.sip.Dialog, DialogExt {
132 
133     private static final long serialVersionUID = -1429794423085204069L;
134 
135     private transient boolean dialogTerminatedEventDelivered; // prevent duplicate
136 
137     private transient String stackTrace; // for semaphore debugging.
138 
139     private String method;
140 
141     // delivery of the event
142     private transient boolean isAssigned;
143 
144     private boolean reInviteFlag;
145 
146     private transient Object applicationData; // Opaque pointer to application data.
147 
148     private transient SIPRequest originalRequest;
149 
150     // Last response (JvB: either sent or received).
151     private SIPResponse lastResponse;
152 
153     // Should be transient, in case the dialog is serialized it will be null
154     // so when a subsequent request will be sent it will be set and a new message channel can be
155     // created
156     private transient SIPTransaction firstTransaction;
157 
158     private transient SIPTransaction lastTransaction;
159 
160     private String dialogId;
161 
162     private transient String earlyDialogId;
163 
164     private long localSequenceNumber;
165 
166     private long remoteSequenceNumber;
167 
168     protected String myTag;
169 
170     protected String hisTag;
171 
172     private RouteList routeList;
173 
174     private transient SIPTransactionStack sipStack;
175 
176     private int dialogState;
177 
178     protected transient boolean ackSeen;
179 
180     private transient SIPRequest lastAckSent;
181 
182     private SIPRequest lastAckReceived;
183 
184     // could be set on recovery by examining the method looks like a duplicate of ackSeen
185     protected transient boolean ackProcessed;
186 
187     protected transient DialogTimerTask timerTask;
188 
189     protected transient Long nextSeqno;
190 
191     private transient int retransmissionTicksLeft;
192 
193     private transient int prevRetransmissionTicks;
194 
195     private long originalLocalSequenceNumber;
196 
197     // This is for debugging only.
198     private transient int ackLine;
199 
200     // Audit tag used by the SIP Stack audit
201     public transient long auditTag = 0;
202 
203     // The following fields are extracted from the request that created the
204     // Dialog.
205 
206     protected javax.sip.address.Address localParty;
207 
208     protected javax.sip.address.Address remoteParty;
209 
210     protected CallIdHeader callIdHeader;
211 
212     public final static int NULL_STATE = -1;
213 
214     public final static int EARLY_STATE = DialogState._EARLY;
215 
216     public final static int CONFIRMED_STATE = DialogState._CONFIRMED;
217 
218     public final static int TERMINATED_STATE = DialogState._TERMINATED;
219 
220     // the amount of time to keep this dialog around before the stack GC's it
221 
222     private static final int DIALOG_LINGER_TIME = 8;
223 
224     private boolean serverTransactionFlag;
225 
226     private transient SipProviderImpl sipProvider;
227 
228     private boolean terminateOnBye;
229 
230     private transient boolean byeSent; // Flag set when BYE is sent, to disallow new
231 
232     // requests
233 
234     private Address remoteTarget;
235 
236     private EventHeader eventHeader; // for Subscribe notify
237 
238     // Stores the last OK for the INVITE
239     // Used in createAck.
240     private transient long lastInviteOkReceived;
241 
242     private transient Semaphore ackSem = new Semaphore(1);
243 
244     private transient int reInviteWaitTime = 100;
245 
246     private transient DialogDeleteTask dialogDeleteTask;
247 
248 	private transient DialogDeleteIfNoAckSentTask dialogDeleteIfNoAckSentTask;
249 
250     private transient boolean isAcknowledged;
251 
252     private transient long highestSequenceNumberAcknowledged = -1;
253 
254     private boolean isBackToBackUserAgent;
255 
256     private boolean sequenceNumberValidation = true;
257 
258     // List of event listeners for this dialog
259 	private transient Set<SIPDialogEventListener> eventListeners;
260 	// added for Issue 248 : https://jain-sip.dev.java.net/issues/show_bug.cgi?id=248
261 	private Semaphore timerTaskLock = new Semaphore(1);
262 
263 	// We store here the useful data from the first transaction without having to
264 	// keep the whole transaction object for the duration of the dialog. It also
265 	// contains the non-transient information used in the replication of dialogs.
266 	protected boolean firstTransactionSecure;
267 	protected boolean firstTransactionSeen;
268     protected String firstTransactionMethod;
269     protected String firstTransactionId;
270     protected boolean firstTransactionIsServerTransaction;
271     protected int firstTransactionPort = 5060;
272     protected Contact contactHeader;
273 
274     // //////////////////////////////////////////////////////
275     // Inner classes
276     // //////////////////////////////////////////////////////
277 
278     /**
279      * This task waits till a pending ACK has been recorded and then sends out a re-INVITE. This
280      * is to prevent interleaving INVITEs ( which will result in a 493 from the UA that receives
281      * the out of order INVITE). This is primarily for B2BUA support. A B2BUA may send a delayed
282      * ACK while it does mid call codec renegotiation. In the meanwhile, it cannot send an intervening
283      * re-INVITE otherwise the othr end will respond with a REQUEST_PENDING. We want to avoid this
284      * condition. Hence we wait till the ACK for the previous re-INVITE has been sent before
285      * sending the next re-INVITE.
286      */
287     public class ReInviteSender implements Runnable, Serializable {
288         private static final long serialVersionUID = 1019346148741070635L;
289         ClientTransaction ctx;
290 
terminate()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 
ReInviteSender(ClientTransaction ctx)300         public ReInviteSender(ClientTransaction ctx) {
301             this.ctx = ctx;
302         }
303 
run()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 
LingerTimer()371         public LingerTimer() {
372 
373         }
374 
runTask()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 
DialogTimerTask(SIPServerTransaction transaction)391         public DialogTimerTask(SIPServerTransaction transaction) {
392             this.transaction = transaction;
393             this.nRetransmissions = 0;
394         }
395 
runTask()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 
runTask()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 
DialogDeleteIfNoAckSentTask(long seqno)486         public DialogDeleteIfNoAckSentTask(long seqno) {
487             this.seqno = seqno;
488         }
489 
runTask()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      */
SIPDialog(SipProviderImpl provider)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 
recordStackTrace()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      */
SIPDialog(SIPTransaction transaction)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      */
SIPDialog(SIPClientTransaction transaction, SIPResponse sipResponse)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      */
SIPDialog(SipProviderImpl sipProvider, SIPResponse sipResponse)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      */
printRouteList()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      */
isClientDialog()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      */
raiseIOException(String host, int port, String protocol)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      */
raiseErrorEvent(int dialogTimeoutError)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      */
setRemoteParty(SIPMessage sipMessage)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 
addRoute(RecordRouteList recordRouteList)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 
setRemoteTarget(ContactHeader contact)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      */
addRoute(SIPResponse sipResponse)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      */
getRouteList()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 
setRouteList(RouteList routeList)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      */
sendAck(Request request, boolean throwIOExceptionAsSipException)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      */
setStack(SIPTransactionStack sipStack)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      */
getStack()1049     SIPTransactionStack getStack() {
1050         return sipStack;
1051     }
1052 
1053     /**
1054      * Return True if this dialog is terminated on BYE.
1055      *
1056      */
isTerminatedOnBye()1057     boolean isTerminatedOnBye() {
1058 
1059         return this.terminateOnBye;
1060     }
1061 
1062     /**
1063      * Mark that the dialog has seen an ACK.
1064      */
ackReceived(SIPRequest sipRequest)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      */
testAndSetIsDialogTerminatedEventDelivered()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 	 */
addEventListener(SIPDialogEventListener newListener)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 	 */
removeEventListener(SIPDialogEventListener oldListener)1133 	public void removeEventListener(SIPDialogEventListener oldListener) {
1134 		eventListeners.remove(oldListener);
1135 	}
1136 
1137     /*
1138      * @see javax.sip.Dialog#setApplicationData()
1139      */
setApplicationData(Object applicationData)1140     public void setApplicationData(Object applicationData) {
1141         this.applicationData = applicationData;
1142     }
1143 
1144     /*
1145      * (non-Javadoc)
1146      *
1147      * @see javax.sip.Dialog#getApplicationData()
1148      */
getApplicationData()1149     public Object getApplicationData() {
1150         return this.applicationData;
1151     }
1152 
1153     /**
1154      * Updates the next consumable seqno.
1155      *
1156      */
requestConsumed()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      */
isRequestConsumable(SIPRequest dialogRequest)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      */
doDeferredDelete()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 
setState(int state)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      */
printDebugInfo()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      */
isAckSeen()1256     public boolean isAckSeen() {
1257         return this.ackSeen;
1258     }
1259 
1260     /**
1261      * Get the last ACK for this transaction.
1262      */
getLastAckSent()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      */
isAckSent(long cseqNo)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      */
getFirstTransaction()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      */
getRouteSet()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      */
addRoute(SIPRequest sipRequest)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      */
setDialogId(String dialogId)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      */
createFromNOTIFY(SIPClientTransaction subscribeTx, SIPTransaction notifyST)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      */
isServer()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      */
isReInvite()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      */
getDialogId()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 
storeFirstTransactionInfo(SIPDialog dialog, SIPTransaction transaction)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      */
addTransaction(SIPTransaction transaction)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      */
setRemoteTag(String hisTag)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      */
getLastTransaction()1604     public SIPTransaction getLastTransaction() {
1605         return this.lastTransaction;
1606     }
1607 
1608     /**
1609      * Get the INVITE transaction (null if no invite transaction).
1610      */
getInviteTransaction()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      */
setLocalSequenceNumber(long lCseq)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      */
setRemoteSequenceNumber(long rCseq)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      */
incrementLocalSequenceNumber()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 
getRemoteSequenceNumber()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 
getLocalSequenceNumber()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      */
getOriginalLocalSequenceNumber()1685     public long getOriginalLocalSequenceNumber() {
1686         return this.originalLocalSequenceNumber;
1687     }
1688 
1689     /*
1690      * (non-Javadoc)
1691      *
1692      * @see javax.sip.Dialog#getLocalSequenceNumberLong()
1693      */
getLocalSeqNumber()1694     public long getLocalSeqNumber() {
1695         return this.localSequenceNumber;
1696     }
1697 
1698     /*
1699      * (non-Javadoc)
1700      *
1701      * @see javax.sip.Dialog#getRemoteSequenceNumberLong()
1702      */
getRemoteSeqNumber()1703     public long getRemoteSeqNumber() {
1704         return this.remoteSequenceNumber;
1705     }
1706 
1707     /*
1708      * (non-Javadoc)
1709      *
1710      * @see javax.sip.Dialog#getLocalTag()
1711      */
getLocalTag()1712     public String getLocalTag() {
1713         return this.myTag;
1714     }
1715 
1716     /*
1717      * (non-Javadoc)
1718      *
1719      * @see javax.sip.Dialog#getRemoteTag()
1720      */
getRemoteTag()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      */
setLocalTag(String mytag)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 
delete()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      */
getCallId()1759     public CallIdHeader getCallId() {
1760         return this.callIdHeader;
1761     }
1762 
1763     /**
1764      * set the call id header for this dialog.
1765      */
setCallId(SIPRequest sipRequest)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 
getLocalParty()1776     public javax.sip.address.Address getLocalParty() {
1777         return this.localParty;
1778     }
1779 
setLocalParty(SIPMessage sipMessage)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      */
getRemoteParty()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      */
getRemoteTarget()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      */
getState()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      */
isSecure()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      */
sendAck(Request request)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      */
createRequest(String method)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      */
createRequest(String method, SIPResponse sipResponse)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 
sendRequest(ClientTransaction clientTransactionId)2007     public void sendRequest(ClientTransaction clientTransactionId)
2008             throws TransactionDoesNotExistException, SipException {
2009         this.sendRequest(clientTransactionId, !this.isBackToBackUserAgent);
2010     }
2011 
sendRequest(ClientTransaction clientTransactionId, boolean allowInterleaving)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      */
toRetransmitFinalResponse(int T2)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 
setRetransmissionTicks()2225     protected void setRetransmissionTicks() {
2226         this.retransmissionTicksLeft = 1;
2227         this.prevRetransmissionTicks = 1;
2228     }
2229 
2230     /**
2231      * Resend the last ack.
2232      */
resendAck()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      */
getMethod()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 
startTimer(SIPServerTransaction transaction)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      */
stopTimer()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      */
createPrack(Response relResponse)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 
updateRequest(SIPRequest sipRequest)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      */
createAck(long cseqno)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      */
getSipProvider()2508     public SipProviderImpl getSipProvider() {
2509         return this.sipProvider;
2510     }
2511 
2512     /**
2513      * @param sipProvider the sipProvider to set
2514      */
setSipProvider(SipProviderImpl sipProvider)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      */
setResponseTags(SIPResponse sipResponse)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      */
setLastResponse(SIPTransaction transaction, SIPResponse sipResponse)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      */
startRetransmitTimer(SIPServerTransaction sipServerTx, Response response)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      */
getLastResponse()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      */
doTargetRefresh(SIPMessage sipMessage)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 
optionPresent(ListIterator l, String option)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      */
createReliableProvisionalResponse(int statusCode)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      */
handlePrack(SIPRequest prackRequest)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      */
sendReliableProvisionalResponse(Response relResponse)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      */
terminateOnBye(boolean terminateFlag)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      */
setAssigned()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 
isAssigned()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      */
getMyContactHeader()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      */
handleAck(SIPServerTransaction ackTransaction)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 
setEarlyDialogId(String earlyDialogId)3180     void setEarlyDialogId(String earlyDialogId) {
3181         this.earlyDialogId = earlyDialogId;
3182     }
3183 
getEarlyDialogId()3184     String getEarlyDialogId() {
3185         return earlyDialogId;
3186     }
3187 
3188     /**
3189      * Release the semaphore for ACK processing so the next re-INVITE may proceed.
3190      */
releaseAckSem()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 
takeAckSem()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      */
setLastAckReceived(SIPRequest lastAckReceived)3236     private void setLastAckReceived(SIPRequest lastAckReceived) {
3237         this.lastAckReceived = lastAckReceived;
3238     }
3239 
3240     /**
3241      * @return the lastAckReceived
3242      */
getLastAckReceived()3243     protected SIPRequest getLastAckReceived() {
3244         return lastAckReceived;
3245     }
3246 
3247     /**
3248      * @param lastAckSent the lastAckSent to set
3249      */
setLastAckSent(SIPRequest lastAckSent)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      */
isAtleastOneAckSent()3257     public boolean isAtleastOneAckSent() {
3258         return this.isAcknowledged;
3259     }
3260 
3261 
3262 
isBackToBackUserAgent()3263     public boolean isBackToBackUserAgent() {
3264         return this.isBackToBackUserAgent;
3265     }
3266 
doDeferredDeleteIfNoAckSent(long seqno)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      */
setBackToBackUserAgent()3284     public void setBackToBackUserAgent() {
3285         this.isBackToBackUserAgent = true;
3286     }
3287 
3288 	/**
3289 	 * @return the eventHeader
3290 	 */
getEventHeader()3291 	EventHeader getEventHeader() {
3292 		return eventHeader;
3293 	}
3294 
3295 	/**
3296 	 * @param eventHeader the eventHeader to set
3297 	 */
setEventHeader(EventHeader eventHeader)3298 	void setEventHeader(EventHeader eventHeader) {
3299 		this.eventHeader = eventHeader;
3300 	}
3301 
3302 	/**
3303 	 * @param serverTransactionFlag the serverTransactionFlag to set
3304 	 */
setServerTransactionFlag(boolean serverTransactionFlag)3305 	void setServerTransactionFlag(boolean serverTransactionFlag) {
3306 		this.serverTransactionFlag = serverTransactionFlag;
3307 	}
3308 
3309 	/**
3310 	 * @param reInviteFlag the reinviteFlag to set
3311 	 */
setReInviteFlag(boolean reInviteFlag)3312 	void setReInviteFlag(boolean reInviteFlag) {
3313 		this.reInviteFlag = reInviteFlag;
3314 	}
3315 
3316 
isSequnceNumberValidation()3317 	public boolean isSequnceNumberValidation() {
3318 	    return this.sequenceNumberValidation;
3319 	}
3320 
disableSequenceNumberValidation()3321     public void disableSequenceNumberValidation() {
3322         this.sequenceNumberValidation = false;
3323     }
3324 
3325 
acquireTimerTaskSem()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 
releaseTimerTaskSem()3338     public void releaseTimerTaskSem() {
3339         this.timerTaskLock.release();
3340     }
3341 
3342 
3343 }
3344