• 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 package gov.nist.javax.sip.stack;
27 
28 import gov.nist.core.InternalErrorHandler;
29 import gov.nist.core.NameValueList;
30 import gov.nist.javax.sip.SIPConstants;
31 import gov.nist.javax.sip.Utils;
32 import gov.nist.javax.sip.address.AddressImpl;
33 import gov.nist.javax.sip.header.Contact;
34 import gov.nist.javax.sip.header.RecordRoute;
35 import gov.nist.javax.sip.header.RecordRouteList;
36 import gov.nist.javax.sip.header.Route;
37 import gov.nist.javax.sip.header.RouteList;
38 import gov.nist.javax.sip.header.TimeStamp;
39 import gov.nist.javax.sip.header.To;
40 import gov.nist.javax.sip.header.Via;
41 import gov.nist.javax.sip.header.ViaList;
42 import gov.nist.javax.sip.message.SIPMessage;
43 import gov.nist.javax.sip.message.SIPRequest;
44 import gov.nist.javax.sip.message.SIPResponse;
45 
46 import java.io.IOException;
47 import java.security.cert.X509Certificate;
48 import java.text.ParseException;
49 import java.util.ListIterator;
50 import java.util.TimerTask;
51 import java.util.concurrent.ConcurrentHashMap;
52 
53 import javax.net.ssl.SSLPeerUnverifiedException;
54 import javax.sip.Dialog;
55 import javax.sip.DialogState;
56 import javax.sip.InvalidArgumentException;
57 import javax.sip.ObjectInUseException;
58 import javax.sip.SipException;
59 import javax.sip.Timeout;
60 import javax.sip.TimeoutEvent;
61 import javax.sip.TransactionState;
62 import javax.sip.address.Hop;
63 import javax.sip.address.SipURI;
64 import javax.sip.header.ExpiresHeader;
65 import javax.sip.header.RouteHeader;
66 import javax.sip.header.TimeStampHeader;
67 import javax.sip.message.Request;
68 
69 /*
70  * Jeff Keyser -- initial. Daniel J. Martinez Manzano --Added support for TLS message channel.
71  * Emil Ivov -- bug fixes. Chris Beardshear -- bug fix. Andreas Bystrom -- bug fixes. Matt Keller
72  * (Motorolla) -- bug fix.
73  */
74 
75 /**
76  * Represents a client transaction. Implements the following state machines. (From RFC 3261)
77  *
78  * <pre>
79  *
80  *
81  *
82  *
83  *
84  *
85  *                                                     |INVITE from TU
86  *                                   Timer A fires     |INVITE sent
87  *                                   Reset A,          V                      Timer B fires
88  *                                   INVITE sent +-----------+                or Transport Err.
89  *                                     +---------|           |---------------+inform TU
90  *                                     |         |  Calling  |               |
91  *                                     +--------&gt;|           |--------------&gt;|
92  *                                               +-----------+ 2xx           |
93  *                                                  |  |       2xx to TU     |
94  *                                                  |  |1xx                  |
95  *                          300-699 +---------------+  |1xx to TU            |
96  *                         ACK sent |                  |                     |
97  *                      resp. to TU |  1xx             V                     |
98  *                                  |  1xx to TU  -----------+               |
99  *                                  |  +---------|           |               |
100  *                                  |  |         |Proceeding |--------------&gt;|
101  *                                  |  +--------&gt;|           | 2xx           |
102  *                                  |            +-----------+ 2xx to TU     |
103  *                                  |       300-699    |                     |
104  *                                  |       ACK sent,  |                     |
105  *                                  |       resp. to TU|                     |
106  *                                  |                  |                     |      NOTE:
107  *                                  |  300-699         V                     |
108  *                                  |  ACK sent  +-----------+Transport Err. |  transitions
109  *                                  |  +---------|           |Inform TU      |  labeled with
110  *                                  |  |         | Completed |--------------&gt;|  the event
111  *                                  |  +--------&gt;|           |               |  over the action
112  *                                  |            +-----------+               |  to take
113  *                                  |              &circ;   |                     |
114  *                                  |              |   | Timer D fires       |
115  *                                  +--------------+   | -                   |
116  *                                                     |                     |
117  *                                                     V                     |
118  *                                               +-----------+               |
119  *                                               |           |               |
120  *                                               | Terminated|&lt;--------------+
121  *                                               |           |
122  *                                               +-----------+
123  *
124  *                                       Figure 5: INVITE client transaction
125  *
126  *
127  *                                                         |Request from TU
128  *                                                         |send request
129  *                                     Timer E             V
130  *                                     send request  +-----------+
131  *                                         +---------|           |-------------------+
132  *                                         |         |  Trying   |  Timer F          |
133  *                                         +--------&gt;|           |  or Transport Err.|
134  *                                                   +-----------+  inform TU        |
135  *                                      200-699         |  |                         |
136  *                                      resp. to TU     |  |1xx                      |
137  *                                      +---------------+  |resp. to TU              |
138  *                                      |                  |                         |
139  *                                      |   Timer E        V       Timer F           |
140  *                                      |   send req +-----------+ or Transport Err. |
141  *                                      |  +---------|           | inform TU         |
142  *                                      |  |         |Proceeding |------------------&gt;|
143  *                                      |  +--------&gt;|           |-----+             |
144  *                                      |            +-----------+     |1xx          |
145  *                                      |              |      &circ;        |resp to TU   |
146  *                                      | 200-699      |      +--------+             |
147  *                                      | resp. to TU  |                             |
148  *                                      |              |                             |
149  *                                      |              V                             |
150  *                                      |            +-----------+                   |
151  *                                      |            |           |                   |
152  *                                      |            | Completed |                   |
153  *                                      |            |           |                   |
154  *                                      |            +-----------+                   |
155  *                                      |              &circ;   |                         |
156  *                                      |              |   | Timer K                 |
157  *                                      +--------------+   | -                       |
158  *                                                         |                         |
159  *                                                         V                         |
160  *                                   NOTE:           +-----------+                   |
161  *                                                   |           |                   |
162  *                               transitions         | Terminated|&lt;------------------+
163  *                               labeled with        |           |
164  *                               the event           +-----------+
165  *                               over the action
166  *                               to take
167  *
168  *                                       Figure 6: non-INVITE client transaction
169  *
170  *
171  *
172  *
173  *
174  *
175  * </pre>
176  *
177  *
178  * @author M. Ranganathan
179  *
180  * @version 1.2 $Revision: 1.122 $ $Date: 2009/12/17 23:33:52 $
181  */
182 public class SIPClientTransaction extends SIPTransaction implements ServerResponseInterface,
183         javax.sip.ClientTransaction, gov.nist.javax.sip.ClientTransactionExt {
184 
185     // a SIP Client transaction may belong simultaneously to multiple
186     // dialogs in the early state. These dialogs all have
187     // the same call ID and same From tag but different to tags.
188 
189     private ConcurrentHashMap<String,SIPDialog> sipDialogs;
190 
191     private SIPRequest lastRequest;
192 
193     private int viaPort;
194 
195     private String viaHost;
196 
197     // Real ResponseInterface to pass messages to
198     private transient ServerResponseInterface respondTo;
199 
200     private SIPDialog defaultDialog;
201 
202     private Hop nextHop;
203 
204     private boolean notifyOnRetransmit;
205 
206     private boolean timeoutIfStillInCallingState;
207 
208     private int callingStateTimeoutCount;
209 
210     public class TransactionTimer extends SIPStackTimerTask {
211 
TransactionTimer()212         public TransactionTimer() {
213 
214         }
215 
runTask()216         protected void runTask() {
217             SIPClientTransaction clientTransaction;
218             SIPTransactionStack sipStack;
219             clientTransaction = SIPClientTransaction.this;
220             sipStack = clientTransaction.sipStack;
221 
222             // If the transaction has terminated,
223             if (clientTransaction.isTerminated()) {
224 
225                 if (sipStack.isLoggingEnabled()) {
226                     sipStack.getStackLogger().logDebug(
227                             "removing  = " + clientTransaction + " isReliable "
228                                     + clientTransaction.isReliable());
229                 }
230 
231                 sipStack.removeTransaction(clientTransaction);
232 
233                 try {
234                     this.cancel();
235 
236                 } catch (IllegalStateException ex) {
237                     if (!sipStack.isAlive())
238                         return;
239                 }
240 
241                 // Client transaction terminated. Kill connection if
242                 // this is a TCP after the linger timer has expired.
243                 // The linger timer is needed to allow any pending requests to
244                 // return responses.
245                 if ((!sipStack.cacheClientConnections) && clientTransaction.isReliable()) {
246 
247                     int newUseCount = --clientTransaction.getMessageChannel().useCount;
248                     if (newUseCount <= 0) {
249                         // Let the connection linger for a while and then close
250                         // it.
251                         TimerTask myTimer = new LingerTimer();
252                         sipStack.getTimer().schedule(myTimer,
253                                 SIPTransactionStack.CONNECTION_LINGER_TIME * 1000);
254                     }
255 
256                 } else {
257                     // Cache the client connections so dont close the
258                     // connection. This keeps the connection open permanently
259                     // until the client disconnects.
260                     if (sipStack.isLoggingEnabled() && clientTransaction.isReliable()) {
261                        	int useCount = clientTransaction.getMessageChannel().useCount;
262                        	if (sipStack.isLoggingEnabled())
263                        		sipStack.getStackLogger().logDebug("Client Use Count = " + useCount);
264                     }
265                 }
266 
267             } else {
268                 // If this transaction has not
269                 // terminated,
270                 // Fire the transaction timer.
271                 clientTransaction.fireTimer();
272 
273             }
274 
275         }
276 
277     }
278 
279     /**
280      * Creates a new client transaction.
281      *
282      * @param newSIPStack Transaction stack this transaction belongs to.
283      * @param newChannelToUse Channel to encapsulate.
284      * @return the created client transaction.
285      */
SIPClientTransaction(SIPTransactionStack newSIPStack, MessageChannel newChannelToUse)286     protected SIPClientTransaction(SIPTransactionStack newSIPStack, MessageChannel newChannelToUse) {
287         super(newSIPStack, newChannelToUse);
288         // Create a random branch parameter for this transaction
289         // setBranch( SIPConstants.BRANCH_MAGIC_COOKIE +
290         // Integer.toHexString( hashCode( ) ) );
291         setBranch(Utils.getInstance().generateBranchId());
292         this.messageProcessor = newChannelToUse.messageProcessor;
293         this.setEncapsulatedChannel(newChannelToUse);
294         this.notifyOnRetransmit = false;
295         this.timeoutIfStillInCallingState = false;
296 
297         // This semaphore guards the listener from being
298         // re-entered for this transaction. That is
299         // for a give tx, the listener is called at most
300         // once with an outstanding request.
301 
302         if (sipStack.isLoggingEnabled()) {
303             sipStack.getStackLogger().logDebug("Creating clientTransaction " + this);
304             sipStack.getStackLogger().logStackTrace();
305         }
306         // this.startTransactionTimer();
307         this.sipDialogs = new ConcurrentHashMap();
308     }
309 
310     /**
311      * Sets the real ResponseInterface this transaction encapsulates.
312      *
313      * @param newRespondTo ResponseInterface to send messages to.
314      */
setResponseInterface(ServerResponseInterface newRespondTo)315     public void setResponseInterface(ServerResponseInterface newRespondTo) {
316         if (sipStack.isLoggingEnabled()) {
317             sipStack.getStackLogger().logDebug(
318                     "Setting response interface for " + this + " to " + newRespondTo);
319             if (newRespondTo == null) {
320                 sipStack.getStackLogger().logStackTrace();
321                 sipStack.getStackLogger().logDebug("WARNING -- setting to null!");
322             }
323         }
324 
325         respondTo = newRespondTo;
326 
327     }
328 
329     /**
330      * Returns this transaction.
331      */
getRequestChannel()332     public MessageChannel getRequestChannel() {
333 
334         return this;
335 
336     }
337 
338     /**
339      * Deterines if the message is a part of this transaction.
340      *
341      * @param messageToTest Message to check if it is part of this transaction.
342      *
343      * @return true if the message is part of this transaction, false if not.
344      */
isMessagePartOfTransaction(SIPMessage messageToTest)345     public boolean isMessagePartOfTransaction(SIPMessage messageToTest) {
346 
347         // List of Via headers in the message to test
348         ViaList viaHeaders = messageToTest.getViaHeaders();
349         // Flags whether the select message is part of this transaction
350         boolean transactionMatches;
351         String messageBranch = ((Via) viaHeaders.getFirst()).getBranch();
352         boolean rfc3261Compliant = getBranch() != null
353                 && messageBranch != null
354                 && getBranch().toLowerCase().startsWith(
355                         SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)
356                 && messageBranch.toLowerCase().startsWith(
357                         SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE);
358 
359         transactionMatches = false;
360         if (TransactionState.COMPLETED == this.getState()) {
361             if (rfc3261Compliant) {
362                 transactionMatches = getBranch().equalsIgnoreCase(
363                         ((Via) viaHeaders.getFirst()).getBranch())
364                         && getMethod().equals(messageToTest.getCSeq().getMethod());
365             } else {
366                 transactionMatches = getBranch().equals(messageToTest.getTransactionId());
367             }
368         } else if (!isTerminated()) {
369             if (rfc3261Compliant) {
370                 if (viaHeaders != null) {
371                     // If the branch parameter is the
372                     // same as this transaction and the method is the same,
373                     if (getBranch().equalsIgnoreCase(((Via) viaHeaders.getFirst()).getBranch())) {
374                         transactionMatches = getOriginalRequest().getCSeq().getMethod().equals(
375                                 messageToTest.getCSeq().getMethod());
376 
377                     }
378                 }
379             } else {
380                 // not RFC 3261 compliant.
381                 if (getBranch() != null) {
382                     transactionMatches = getBranch().equalsIgnoreCase(
383                             messageToTest.getTransactionId());
384                 } else {
385                     transactionMatches = getOriginalRequest().getTransactionId()
386                             .equalsIgnoreCase(messageToTest.getTransactionId());
387                 }
388 
389             }
390 
391         }
392         return transactionMatches;
393 
394     }
395 
396     /**
397      * Send a request message through this transaction and onto the client.
398      *
399      * @param messageToSend Request to process and send.
400      */
sendMessage(SIPMessage messageToSend)401     public void sendMessage(SIPMessage messageToSend) throws IOException {
402 
403         try {
404             // Message typecast as a request
405             SIPRequest transactionRequest;
406 
407             transactionRequest = (SIPRequest) messageToSend;
408 
409             // Set the branch id for the top via header.
410             Via topVia = (Via) transactionRequest.getViaHeaders().getFirst();
411             // Tack on a branch identifier to match responses.
412             try {
413                 topVia.setBranch(getBranch());
414             } catch (java.text.ParseException ex) {
415             }
416 
417             if (sipStack.isLoggingEnabled()) {
418                 sipStack.getStackLogger().logDebug("Sending Message " + messageToSend);
419                 sipStack.getStackLogger().logDebug("TransactionState " + this.getState());
420             }
421             // If this is the first request for this transaction,
422             if (TransactionState.PROCEEDING == getState()
423                     || TransactionState.CALLING == getState()) {
424 
425                 // If this is a TU-generated ACK request,
426                 if (transactionRequest.getMethod().equals(Request.ACK)) {
427 
428                     // Send directly to the underlying
429                     // transport and close this transaction
430                     if (isReliable()) {
431                         this.setState(TransactionState.TERMINATED);
432                     } else {
433                         this.setState(TransactionState.COMPLETED);
434                     }
435                     // BUGBUG -- This suppresses sending the ACK uncomment this
436                     // to
437                     // test 4xx retransmission
438                     // if (transactionRequest.getMethod() != Request.ACK)
439                     super.sendMessage(transactionRequest);
440                     return;
441 
442                 }
443 
444             }
445             try {
446 
447                 // Send the message to the server
448                 lastRequest = transactionRequest;
449                 if (getState() == null) {
450                     // Save this request as the one this transaction
451                     // is handling
452                     setOriginalRequest(transactionRequest);
453                     // Change to trying/calling state
454                     // Set state first to avoid race condition..
455 
456                     if (transactionRequest.getMethod().equals(Request.INVITE)) {
457                         this.setState(TransactionState.CALLING);
458                     } else if (transactionRequest.getMethod().equals(Request.ACK)) {
459                         // Acks are never retransmitted.
460                         this.setState(TransactionState.TERMINATED);
461                     } else {
462                         this.setState(TransactionState.TRYING);
463                     }
464                     if (!isReliable()) {
465                         enableRetransmissionTimer();
466                     }
467                     if (isInviteTransaction()) {
468                         enableTimeoutTimer(TIMER_B);
469                     } else {
470                         enableTimeoutTimer(TIMER_F);
471                     }
472                 }
473                 // BUGBUG This supresses sending ACKS -- uncomment to test
474                 // 4xx retransmission.
475                 // if (transactionRequest.getMethod() != Request.ACK)
476                 super.sendMessage(transactionRequest);
477 
478             } catch (IOException e) {
479 
480                 this.setState(TransactionState.TERMINATED);
481                 throw e;
482 
483             }
484         } finally {
485             this.isMapped = true;
486             this.startTransactionTimer();
487 
488         }
489 
490     }
491 
492     /**
493      * Process a new response message through this transaction. If necessary, this message will
494      * also be passed onto the TU.
495      *
496      * @param transactionResponse Response to process.
497      * @param sourceChannel Channel that received this message.
498      */
processResponse(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog dialog)499     public synchronized void processResponse(SIPResponse transactionResponse,
500             MessageChannel sourceChannel, SIPDialog dialog) {
501 
502         // If the state has not yet been assigned then this is a
503         // spurious response.
504 
505         if (getState() == null)
506             return;
507 
508         // Ignore 1xx
509         if ((TransactionState.COMPLETED == this.getState() || TransactionState.TERMINATED == this
510                 .getState())
511                 && transactionResponse.getStatusCode() / 100 == 1) {
512             return;
513         }
514 
515         if (sipStack.isLoggingEnabled()) {
516             sipStack.getStackLogger().logDebug(
517                     "processing " + transactionResponse.getFirstLine() + "current state = "
518                             + getState());
519             sipStack.getStackLogger().logDebug("dialog = " + dialog);
520         }
521 
522         this.lastResponse = transactionResponse;
523 
524         /*
525          * JvB: this is now duplicate with code in the other processResponse
526          *
527          * if (dialog != null && transactionResponse.getStatusCode() != 100 &&
528          * (transactionResponse.getTo().getTag() != null || sipStack .isRfc2543Supported())) { //
529          * add the route before you process the response. dialog.setLastResponse(this,
530          * transactionResponse); this.setDialog(dialog, transactionResponse.getDialogId(false)); }
531          */
532 
533         try {
534             if (isInviteTransaction())
535                 inviteClientTransaction(transactionResponse, sourceChannel, dialog);
536             else
537                 nonInviteClientTransaction(transactionResponse, sourceChannel, dialog);
538         } catch (IOException ex) {
539             if (sipStack.isLoggingEnabled())
540                 sipStack.getStackLogger().logException(ex);
541             this.setState(TransactionState.TERMINATED);
542             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
543         }
544     }
545 
546     /**
547      * Implements the state machine for invite client transactions.
548      *
549      * <pre>
550      *
551      *
552      *
553      *
554      *
555      *                                                         |Request from TU
556      *                                                         |send request
557      *                                     Timer E             V
558      *                                     send request  +-----------+
559      *                                         +---------|           |-------------------+
560      *                                         |         |  Trying   |  Timer F          |
561      *                                         +--------&gt;|           |  or Transport Err.|
562      *                                                   +-----------+  inform TU        |
563      *                                      200-699         |  |                         |
564      *                                      resp. to TU     |  |1xx                      |
565      *                                      +---------------+  |resp. to TU              |
566      *                                      |                  |                         |
567      *                                      |   Timer E        V       Timer F           |
568      *                                      |   send req +-----------+ or Transport Err. |
569      *                                      |  +---------|           | inform TU         |
570      *                                      |  |         |Proceeding |------------------&gt;|
571      *                                      |  +--------&gt;|           |-----+             |
572      *                                      |            +-----------+     |1xx          |
573      *                                      |              |      &circ;        |resp to TU   |
574      *                                      | 200-699      |      +--------+             |
575      *                                      | resp. to TU  |                             |
576      *                                      |              |                             |
577      *                                      |              V                             |
578      *                                      |            +-----------+                   |
579      *                                      |            |           |                   |
580      *                                      |            | Completed |                   |
581      *                                      |            |           |                   |
582      *                                      |            +-----------+                   |
583      *                                      |              &circ;   |                         |
584      *                                      |              |   | Timer K                 |
585      *                                      +--------------+   | -                       |
586      *                                                         |                         |
587      *                                                         V                         |
588      *                                   NOTE:           +-----------+                   |
589      *                                                   |           |                   |
590      *                               transitions         | Terminated|&lt;------------------+
591      *                               labeled with        |           |
592      *                               the event           +-----------+
593      *                               over the action
594      *                               to take
595      *
596      *                                       Figure 6: non-INVITE client transaction
597      *
598      *
599      *
600      *
601      * </pre>
602      *
603      * @param transactionResponse -- transaction response received.
604      * @param sourceChannel - source channel on which the response was received.
605      */
nonInviteClientTransaction(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog sipDialog)606     private void nonInviteClientTransaction(SIPResponse transactionResponse,
607             MessageChannel sourceChannel, SIPDialog sipDialog) throws IOException {
608         int statusCode = transactionResponse.getStatusCode();
609         if (TransactionState.TRYING == this.getState()) {
610             if (statusCode / 100 == 1) {
611                 this.setState(TransactionState.PROCEEDING);
612                 enableRetransmissionTimer(MAXIMUM_RETRANSMISSION_TICK_COUNT);
613                 enableTimeoutTimer(TIMER_F);
614                 // According to RFC, the TU has to be informed on
615                 // this transition.
616                 if (respondTo != null) {
617                     respondTo.processResponse(transactionResponse, this, sipDialog);
618                 } else {
619                     this.semRelease();
620                 }
621             } else if (200 <= statusCode && statusCode <= 699) {
622                 // Send the response up to the TU.
623                 if (respondTo != null) {
624                     respondTo.processResponse(transactionResponse, this, sipDialog);
625                 } else {
626                     this.semRelease();
627                 }
628                 if (!isReliable()) {
629                     this.setState(TransactionState.COMPLETED);
630                     enableTimeoutTimer(TIMER_K);
631                 } else {
632                     this.setState(TransactionState.TERMINATED);
633                 }
634             }
635         } else if (TransactionState.PROCEEDING == this.getState()) {
636             if (statusCode / 100 == 1) {
637                 if (respondTo != null) {
638                     respondTo.processResponse(transactionResponse, this, sipDialog);
639                 } else {
640                     this.semRelease();
641                 }
642             } else if (200 <= statusCode && statusCode <= 699) {
643                 if (respondTo != null) {
644                     respondTo.processResponse(transactionResponse, this, sipDialog);
645                 } else {
646                     this.semRelease();
647                 }
648                 disableRetransmissionTimer();
649                 disableTimeoutTimer();
650                 if (!isReliable()) {
651                     this.setState(TransactionState.COMPLETED);
652                     enableTimeoutTimer(TIMER_K);
653                 } else {
654                     this.setState(TransactionState.TERMINATED);
655                 }
656             }
657         } else {
658             if (sipStack.isLoggingEnabled()) {
659                 sipStack.getStackLogger().logDebug(
660                         " Not sending response to TU! " + getState());
661             }
662             this.semRelease();
663         }
664     }
665 
666     /**
667      * Implements the state machine for invite client transactions.
668      *
669      * <pre>
670      *
671      *
672      *
673      *
674      *
675      *                                                     |INVITE from TU
676      *                                   Timer A fires     |INVITE sent
677      *                                   Reset A,          V                      Timer B fires
678      *                                   INVITE sent +-----------+                or Transport Err.
679      *                                     +---------|           |---------------+inform TU
680      *                                     |         |  Calling  |               |
681      *                                     +--------&gt;|           |--------------&gt;|
682      *                                               +-----------+ 2xx           |
683      *                                                  |  |       2xx to TU     |
684      *                                                  |  |1xx                  |
685      *                          300-699 +---------------+  |1xx to TU            |
686      *                         ACK sent |                  |                     |
687      *                      resp. to TU |  1xx             V                     |
688      *                                  |  1xx to TU  -----------+               |
689      *                                  |  +---------|           |               |
690      *                                  |  |         |Proceeding |--------------&gt;|
691      *                                  |  +--------&gt;|           | 2xx           |
692      *                                  |            +-----------+ 2xx to TU     |
693      *                                  |       300-699    |                     |
694      *                                  |       ACK sent,  |                     |
695      *                                  |       resp. to TU|                     |
696      *                                  |                  |                     |      NOTE:
697      *                                  |  300-699         V                     |
698      *                                  |  ACK sent  +-----------+Transport Err. |  transitions
699      *                                  |  +---------|           |Inform TU      |  labeled with
700      *                                  |  |         | Completed |--------------&gt;|  the event
701      *                                  |  +--------&gt;|           |               |  over the action
702      *                                  |            +-----------+               |  to take
703      *                                  |              &circ;   |                     |
704      *                                  |              |   | Timer D fires       |
705      *                                  +--------------+   | -                   |
706      *                                                     |                     |
707      *                                                     V                     |
708      *                                               +-----------+               |
709      *                                               |           |               |
710      *                                               | Terminated|&lt;--------------+
711      *                                               |           |
712      *                                               +-----------+
713      *
714      *
715      *
716      *
717      * </pre>
718      *
719      * @param transactionResponse -- transaction response received.
720      * @param sourceChannel - source channel on which the response was received.
721      */
722 
inviteClientTransaction(SIPResponse transactionResponse, MessageChannel sourceChannel, SIPDialog dialog)723     private void inviteClientTransaction(SIPResponse transactionResponse,
724             MessageChannel sourceChannel, SIPDialog dialog) throws IOException {
725         int statusCode = transactionResponse.getStatusCode();
726 
727         if (TransactionState.TERMINATED == this.getState()) {
728             boolean ackAlreadySent = false;
729             if (dialog != null && dialog.isAckSeen() && dialog.getLastAckSent() != null) {
730                 if (dialog.getLastAckSent().getCSeq().getSeqNumber() == transactionResponse.getCSeq()
731                         .getSeqNumber()
732                         && transactionResponse.getFromTag().equals(
733                                 dialog.getLastAckSent().getFromTag())) {
734                     // the last ack sent corresponded to this response
735                     ackAlreadySent = true;
736                 }
737             }
738             // retransmit the ACK for this response.
739             if (dialog!= null && ackAlreadySent
740                     && transactionResponse.getCSeq().getMethod().equals(dialog.getMethod())) {
741                 try {
742                     // Found the dialog - resend the ACK and
743                     // dont pass up the null transaction
744                     if (sipStack.isLoggingEnabled())
745                         sipStack.getStackLogger().logDebug("resending ACK");
746 
747                     dialog.resendAck();
748                 } catch (SipException ex) {
749                     // What to do here ?? kill the dialog?
750                 }
751             }
752 
753             this.semRelease();
754             return;
755         } else if (TransactionState.CALLING == this.getState()) {
756             if (statusCode / 100 == 2) {
757 
758                 // JvB: do this ~before~ calling the application, to avoid
759                 // retransmissions
760                 // of the INVITE after app sends ACK
761                 disableRetransmissionTimer();
762                 disableTimeoutTimer();
763                 this.setState(TransactionState.TERMINATED);
764 
765                 // 200 responses are always seen by TU.
766                 if (respondTo != null)
767                     respondTo.processResponse(transactionResponse, this, dialog);
768                 else {
769                     this.semRelease();
770                 }
771 
772             } else if (statusCode / 100 == 1) {
773                 disableRetransmissionTimer();
774                 disableTimeoutTimer();
775                 this.setState(TransactionState.PROCEEDING);
776 
777                 if (respondTo != null)
778                     respondTo.processResponse(transactionResponse, this, dialog);
779                 else {
780                     this.semRelease();
781                 }
782 
783             } else if (300 <= statusCode && statusCode <= 699) {
784                 // Send back an ACK request
785 
786                 try {
787                     sendMessage((SIPRequest) createErrorAck());
788 
789                 } catch (Exception ex) {
790                     sipStack.getStackLogger().logError(
791                             "Unexpected Exception sending ACK -- sending error AcK ", ex);
792 
793                 }
794 
795                 /*
796                  * When in either the "Calling" or "Proceeding" states, reception of response with
797                  * status code from 300-699 MUST cause the client transaction to transition to
798                  * "Completed". The client transaction MUST pass the received response up to the
799                  * TU, and the client transaction MUST generate an ACK request.
800                  */
801 
802                 if (respondTo != null) {
803                     respondTo.processResponse(transactionResponse, this, dialog);
804                 } else {
805                     this.semRelease();
806                 }
807 
808                 if (this.getDialog() != null &&  ((SIPDialog)this.getDialog()).isBackToBackUserAgent()) {
809                     ((SIPDialog) this.getDialog()).releaseAckSem();
810                 }
811 
812                 if (!isReliable()) {
813                     this.setState(TransactionState.COMPLETED);
814                     enableTimeoutTimer(TIMER_D);
815                 } else {
816                     // Proceed immediately to the TERMINATED state.
817                     this.setState(TransactionState.TERMINATED);
818                 }
819             }
820         } else if (TransactionState.PROCEEDING == this.getState()) {
821             if (statusCode / 100 == 1) {
822                 if (respondTo != null) {
823                     respondTo.processResponse(transactionResponse, this, dialog);
824                 } else {
825                     this.semRelease();
826                 }
827             } else if (statusCode / 100 == 2) {
828                 this.setState(TransactionState.TERMINATED);
829                 if (respondTo != null) {
830                     respondTo.processResponse(transactionResponse, this, dialog);
831                 } else {
832                     this.semRelease();
833                 }
834 
835             } else if (300 <= statusCode && statusCode <= 699) {
836                 // Send back an ACK request
837                 try {
838                     sendMessage((SIPRequest) createErrorAck());
839                 } catch (Exception ex) {
840                     InternalErrorHandler.handleException(ex);
841                 }
842 
843                 if (this.getDialog() != null) {
844                     ((SIPDialog) this.getDialog()).releaseAckSem();
845                 }
846                 // JvB: update state before passing to app
847                 if (!isReliable()) {
848                     this.setState(TransactionState.COMPLETED);
849                     this.enableTimeoutTimer(TIMER_D);
850                 } else {
851                     this.setState(TransactionState.TERMINATED);
852                 }
853 
854                 // Pass up to the TU for processing.
855                 if (respondTo != null)
856                     respondTo.processResponse(transactionResponse, this, dialog);
857                 else {
858                     this.semRelease();
859                 }
860 
861                 // JvB: duplicate with line 874
862                 // if (!isReliable()) {
863                 // enableTimeoutTimer(TIMER_D);
864                 // }
865             }
866         } else if (TransactionState.COMPLETED == this.getState()) {
867             if (300 <= statusCode && statusCode <= 699) {
868                 // Send back an ACK request
869                 try {
870                     sendMessage((SIPRequest) createErrorAck());
871                 } catch (Exception ex) {
872                     InternalErrorHandler.handleException(ex);
873                 } finally {
874                     this.semRelease();
875                 }
876             }
877 
878         }
879 
880     }
881 
882     /*
883      * (non-Javadoc)
884      *
885      * @see javax.sip.ClientTransaction#sendRequest()
886      */
sendRequest()887     public void sendRequest() throws SipException {
888         SIPRequest sipRequest = this.getOriginalRequest();
889 
890         if (this.getState() != null)
891             throw new SipException("Request already sent");
892 
893         if (sipStack.isLoggingEnabled()) {
894             sipStack.getStackLogger().logDebug("sendRequest() " + sipRequest);
895         }
896 
897         try {
898             sipRequest.checkHeaders();
899         } catch (ParseException ex) {
900         	if (sipStack.isLoggingEnabled())
901         		sipStack.getStackLogger().logError("missing required header");
902             throw new SipException(ex.getMessage());
903         }
904 
905         if (getMethod().equals(Request.SUBSCRIBE)
906                 && sipRequest.getHeader(ExpiresHeader.NAME) == null) {
907             /*
908              * If no "Expires" header is present in a SUBSCRIBE request, the implied default is
909              * defined by the event package being used.
910              *
911              */
912         	if (sipStack.isLoggingEnabled())
913         		sipStack.getStackLogger().logWarning(
914                     "Expires header missing in outgoing subscribe --"
915                             + " Notifier will assume implied value on event package");
916         }
917         try {
918             /*
919              * This check is removed because it causes problems for load balancers ( See issue
920              * 136) reported by Raghav Ramesh ( BT )
921              *
922              */
923             if (this.getOriginalRequest().getMethod().equals(Request.CANCEL)
924                     && sipStack.isCancelClientTransactionChecked()) {
925                 SIPClientTransaction ct = (SIPClientTransaction) sipStack.findCancelTransaction(
926                         this.getOriginalRequest(), false);
927                 if (ct == null) {
928                     /*
929                      * If the original request has generated a final response, the CANCEL SHOULD
930                      * NOT be sent, as it is an effective no-op, since CANCEL has no effect on
931                      * requests that have already generated a final response.
932                      */
933                     throw new SipException("Could not find original tx to cancel. RFC 3261 9.1");
934                 } else if (ct.getState() == null) {
935                     throw new SipException(
936                             "State is null no provisional response yet -- cannot cancel RFC 3261 9.1");
937                 } else if (!ct.getMethod().equals(Request.INVITE)) {
938                     throw new SipException("Cannot cancel non-invite requests RFC 3261 9.1");
939                 }
940             } else
941 
942             if (this.getOriginalRequest().getMethod().equals(Request.BYE)
943                     || this.getOriginalRequest().getMethod().equals(Request.NOTIFY)) {
944                 SIPDialog dialog = sipStack.getDialog(this.getOriginalRequest()
945                         .getDialogId(false));
946                 // I want to behave like a user agent so send the BYE using the
947                 // Dialog
948                 if (this.getSipProvider().isAutomaticDialogSupportEnabled() && dialog != null) {
949                     throw new SipException(
950                             "Dialog is present and AutomaticDialogSupport is enabled for "
951                                     + " the provider -- Send the Request using the Dialog.sendRequest(transaction)");
952                 }
953             }
954             // Only map this after the fist request is sent out.
955             if (this.getMethod().equals(Request.INVITE)) {
956                 SIPDialog dialog = this.getDefaultDialog();
957 
958                 if (dialog != null && dialog.isBackToBackUserAgent()) {
959                     // Block sending re-INVITE till we see the ACK.
960                     if ( ! dialog.takeAckSem() ) {
961                         throw new SipException ("Failed to take ACK semaphore");
962                     }
963 
964                 }
965             }
966             this.isMapped = true;
967             this.sendMessage(sipRequest);
968 
969         } catch (IOException ex) {
970             this.setState(TransactionState.TERMINATED);
971             throw new SipException("IO Error sending request", ex);
972 
973         }
974 
975     }
976 
977     /**
978      * Called by the transaction stack when a retransmission timer fires.
979      */
fireRetransmissionTimer()980     protected void fireRetransmissionTimer() {
981 
982         try {
983 
984             // Resend the last request sent
985             if (this.getState() == null || !this.isMapped)
986                 return;
987 
988             boolean inv = isInviteTransaction();
989             TransactionState s = this.getState();
990 
991             // JvB: INVITE CTs only retransmit in CALLING, non-INVITE in both TRYING and
992             // PROCEEDING
993             // Bug-fix for non-INVITE transactions not retransmitted when 1xx response received
994             if ((inv && TransactionState.CALLING == s)
995                     || (!inv && (TransactionState.TRYING == s || TransactionState.PROCEEDING == s))) {
996                 // If the retransmission filter is disabled then
997                 // retransmission of the INVITE is the application
998                 // responsibility.
999 
1000                 if (lastRequest != null) {
1001                     if (sipStack.generateTimeStampHeader
1002                             && lastRequest.getHeader(TimeStampHeader.NAME) != null) {
1003                         long milisec = System.currentTimeMillis();
1004                         TimeStamp timeStamp = new TimeStamp();
1005                         try {
1006                             timeStamp.setTimeStamp(milisec);
1007                         } catch (InvalidArgumentException ex) {
1008                             InternalErrorHandler.handleException(ex);
1009                         }
1010                         lastRequest.setHeader(timeStamp);
1011                     }
1012                     super.sendMessage(lastRequest);
1013                     if (this.notifyOnRetransmit) {
1014                         TimeoutEvent txTimeout = new TimeoutEvent(this.getSipProvider(), this,
1015                                 Timeout.RETRANSMIT);
1016                         this.getSipProvider().handleEvent(txTimeout, this);
1017                     }
1018                     if (this.timeoutIfStillInCallingState
1019                             && this.getState() == TransactionState.CALLING) {
1020                         this.callingStateTimeoutCount--;
1021                         if (callingStateTimeoutCount == 0) {
1022                             TimeoutEvent timeoutEvent = new TimeoutEvent(this.getSipProvider(),
1023                                     this, Timeout.RETRANSMIT);
1024                             this.getSipProvider().handleEvent(timeoutEvent, this);
1025                             this.timeoutIfStillInCallingState = false;
1026                         }
1027 
1028                     }
1029                 }
1030 
1031             }
1032         } catch (IOException e) {
1033             this.raiseIOExceptionEvent();
1034             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
1035         }
1036 
1037     }
1038 
1039     /**
1040      * Called by the transaction stack when a timeout timer fires.
1041      */
fireTimeoutTimer()1042     protected void fireTimeoutTimer() {
1043 
1044         if (sipStack.isLoggingEnabled())
1045             sipStack.getStackLogger().logDebug("fireTimeoutTimer " + this);
1046 
1047         SIPDialog dialog = (SIPDialog) this.getDialog();
1048         if (TransactionState.CALLING == this.getState()
1049                 || TransactionState.TRYING == this.getState()
1050                 || TransactionState.PROCEEDING == this.getState()) {
1051             // Timeout occured. If this is asociated with a transaction
1052             // creation then kill the dialog.
1053             if (dialog != null
1054                     && (dialog.getState() == null || dialog.getState() == DialogState.EARLY)) {
1055                 if (((SIPTransactionStack) getSIPStack()).isDialogCreated(this
1056                         .getOriginalRequest().getMethod())) {
1057                     // If this is a re-invite we do not delete the dialog even
1058                     // if the
1059                     // reinvite times out. Else
1060                     // terminate the enclosing dialog.
1061                     dialog.delete();
1062                 }
1063             } else if (dialog != null) {
1064                 // Guard against the case of BYE time out.
1065 
1066                 if (getOriginalRequest().getMethod().equalsIgnoreCase(Request.BYE)
1067                         && dialog.isTerminatedOnBye()) {
1068                     // Terminate the associated dialog on BYE Timeout.
1069                     dialog.delete();
1070                 }
1071             }
1072         }
1073         if (TransactionState.COMPLETED != this.getState()) {
1074             raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
1075             // Got a timeout error on a cancel.
1076             if (this.getOriginalRequest().getMethod().equalsIgnoreCase(Request.CANCEL)) {
1077                 SIPClientTransaction inviteTx = (SIPClientTransaction) this.getOriginalRequest()
1078                         .getInviteTransaction();
1079                 if (inviteTx != null
1080                         && ((inviteTx.getState() == TransactionState.CALLING || inviteTx
1081                                 .getState() == TransactionState.PROCEEDING))
1082                         && inviteTx.getDialog() != null) {
1083                     /*
1084                      * A proxy server should have started TIMER C and take care of the Termination
1085                      * using transaction.terminate() by itself (i.e. this is not the job of the
1086                      * stack at this point but we do it to be nice.
1087                      */
1088                     inviteTx.setState(TransactionState.TERMINATED);
1089 
1090                 }
1091             }
1092 
1093         } else {
1094             this.setState(TransactionState.TERMINATED);
1095         }
1096 
1097     }
1098 
1099     /*
1100      * (non-Javadoc)
1101      *
1102      * @see javax.sip.ClientTransaction#createCancel()
1103      */
createCancel()1104     public Request createCancel() throws SipException {
1105         SIPRequest originalRequest = this.getOriginalRequest();
1106         if (originalRequest == null)
1107             throw new SipException("Bad state " + getState());
1108         if (!originalRequest.getMethod().equals(Request.INVITE))
1109             throw new SipException("Only INIVTE may be cancelled");
1110 
1111         if (originalRequest.getMethod().equalsIgnoreCase(Request.ACK))
1112             throw new SipException("Cannot Cancel ACK!");
1113         else {
1114             SIPRequest cancelRequest = originalRequest.createCancelRequest();
1115             cancelRequest.setInviteTransaction(this);
1116             return cancelRequest;
1117         }
1118     }
1119 
1120     /*
1121      * (non-Javadoc)
1122      *
1123      * @see javax.sip.ClientTransaction#createAck()
1124      */
createAck()1125     public Request createAck() throws SipException {
1126         SIPRequest originalRequest = this.getOriginalRequest();
1127         if (originalRequest == null)
1128             throw new SipException("bad state " + getState());
1129         if (getMethod().equalsIgnoreCase(Request.ACK)) {
1130             throw new SipException("Cannot ACK an ACK!");
1131         } else if (lastResponse == null) {
1132             throw new SipException("bad Transaction state");
1133         } else if (lastResponse.getStatusCode() < 200) {
1134             if (sipStack.isLoggingEnabled()) {
1135                 sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
1136             }
1137             throw new SipException("Cannot ACK a provisional response!");
1138         }
1139         SIPRequest ackRequest = originalRequest.createAckRequest((To) lastResponse.getTo());
1140         // Pull the record route headers from the last reesponse.
1141         RecordRouteList recordRouteList = lastResponse.getRecordRouteHeaders();
1142         if (recordRouteList == null) {
1143             // If the record route list is null then we can
1144             // construct the ACK from the specified contact header.
1145             // Note the 3xx check here because 3xx is a redirect.
1146             // The contact header for the 3xx is the redirected
1147             // location so we cannot use that to construct the
1148             // request URI.
1149             if (lastResponse.getContactHeaders() != null
1150                     && lastResponse.getStatusCode() / 100 != 3) {
1151                 Contact contact = (Contact) lastResponse.getContactHeaders().getFirst();
1152                 javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI()
1153                         .clone();
1154                 ackRequest.setRequestURI(uri);
1155             }
1156             return ackRequest;
1157         }
1158 
1159         ackRequest.removeHeader(RouteHeader.NAME);
1160         RouteList routeList = new RouteList();
1161         // start at the end of the list and walk backwards
1162         ListIterator<RecordRoute> li = recordRouteList.listIterator(recordRouteList.size());
1163         while (li.hasPrevious()) {
1164             RecordRoute rr = (RecordRoute) li.previous();
1165 
1166             Route route = new Route();
1167             route.setAddress((AddressImpl) ((AddressImpl) rr.getAddress()).clone());
1168             route.setParameters((NameValueList) rr.getParameters().clone());
1169             routeList.add(route);
1170         }
1171 
1172         Contact contact = null;
1173         if (lastResponse.getContactHeaders() != null) {
1174             contact = (Contact) lastResponse.getContactHeaders().getFirst();
1175         }
1176 
1177         if (!((SipURI) ((Route) routeList.getFirst()).getAddress().getURI()).hasLrParam()) {
1178 
1179             // Contact may not yet be there (bug reported by Andreas B).
1180 
1181             Route route = null;
1182             if (contact != null) {
1183                 route = new Route();
1184                 route.setAddress((AddressImpl) ((AddressImpl) (contact.getAddress())).clone());
1185             }
1186 
1187             Route firstRoute = (Route) routeList.getFirst();
1188             routeList.removeFirst();
1189             javax.sip.address.URI uri = firstRoute.getAddress().getURI();
1190             ackRequest.setRequestURI(uri);
1191 
1192             if (route != null)
1193                 routeList.add(route);
1194 
1195             ackRequest.addHeader(routeList);
1196         } else {
1197             if (contact != null) {
1198                 javax.sip.address.URI uri = (javax.sip.address.URI) contact.getAddress().getURI()
1199                         .clone();
1200                 ackRequest.setRequestURI(uri);
1201                 ackRequest.addHeader(routeList);
1202             }
1203         }
1204         return ackRequest;
1205 
1206     }
1207 
1208     /*
1209      * Creates an ACK for an error response, according to RFC3261 section 17.1.1.3
1210      *
1211      * Note that this is different from an ACK for 2xx
1212      */
createErrorAck()1213     private final Request createErrorAck() throws SipException, ParseException {
1214         SIPRequest originalRequest = this.getOriginalRequest();
1215         if (originalRequest == null)
1216             throw new SipException("bad state " + getState());
1217         if (!getMethod().equals(Request.INVITE)) {
1218             throw new SipException("Can only ACK an INVITE!");
1219         } else if (lastResponse == null) {
1220             throw new SipException("bad Transaction state");
1221         } else if (lastResponse.getStatusCode() < 200) {
1222             if (sipStack.isLoggingEnabled()) {
1223                 sipStack.getStackLogger().logDebug("lastResponse = " + lastResponse);
1224             }
1225             throw new SipException("Cannot ACK a provisional response!");
1226         }
1227         return originalRequest.createErrorAck((To) lastResponse.getTo());
1228     }
1229 
1230     /**
1231      * Set the port of the recipient.
1232      */
setViaPort(int port)1233     protected void setViaPort(int port) {
1234         this.viaPort = port;
1235     }
1236 
1237     /**
1238      * Set the port of the recipient.
1239      */
setViaHost(String host)1240     protected void setViaHost(String host) {
1241         this.viaHost = host;
1242     }
1243 
1244     /**
1245      * Get the port of the recipient.
1246      */
getViaPort()1247     public int getViaPort() {
1248         return this.viaPort;
1249     }
1250 
1251     /**
1252      * Get the host of the recipient.
1253      */
getViaHost()1254     public String getViaHost() {
1255         return this.viaHost;
1256     }
1257 
1258     /**
1259      * get the via header for an outgoing request.
1260      */
getOutgoingViaHeader()1261     public Via getOutgoingViaHeader() {
1262         return this.getMessageProcessor().getViaHeader();
1263     }
1264 
1265     /**
1266      * This is called by the stack after a non-invite client transaction goes to completed state.
1267      */
clearState()1268     public void clearState() {
1269         // reduce the state to minimum
1270         // This assumes that the application will not need
1271         // to access the request once the transaction is
1272         // completed.
1273         // TODO -- revisit this - results in a null pointer
1274         // occuring occasionally.
1275         // this.lastRequest = null;
1276         // this.originalRequest = null;
1277         // this.lastResponse = null;
1278     }
1279 
1280     /**
1281      * Sets a timeout after which the connection is closed (provided the server does not use the
1282      * connection for outgoing requests in this time period) and calls the superclass to set
1283      * state.
1284      */
setState(TransactionState newState)1285     public void setState(TransactionState newState) {
1286         // Set this timer for connection caching
1287         // of incoming connections.
1288         if (newState == TransactionState.TERMINATED && this.isReliable()
1289                 && (!getSIPStack().cacheClientConnections)) {
1290             // Set a time after which the connection
1291             // is closed.
1292             this.collectionTime = TIMER_J;
1293 
1294         }
1295         if (super.getState() != TransactionState.COMPLETED
1296                 && (newState == TransactionState.COMPLETED || newState == TransactionState.TERMINATED)) {
1297             sipStack.decrementActiveClientTransactionCount();
1298         }
1299         super.setState(newState);
1300     }
1301 
1302     /**
1303      * Start the timer task.
1304      */
startTransactionTimer()1305     protected  void startTransactionTimer() {
1306         if (this.transactionTimerStarted.compareAndSet(false, true)) {
1307 	        TimerTask myTimer = new TransactionTimer();
1308 	        if ( sipStack.getTimer() != null ) {
1309 	            sipStack.getTimer().schedule(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL);
1310 	        }
1311         }
1312     }
1313 
1314     /*
1315      * Terminate a transaction. This marks the tx as terminated The tx scanner will run and remove
1316      * the tx. (non-Javadoc)
1317      *
1318      * @see javax.sip.Transaction#terminate()
1319      */
terminate()1320     public void terminate() throws ObjectInUseException {
1321         this.setState(TransactionState.TERMINATED);
1322 
1323     }
1324 
1325     /**
1326      * Check if the From tag of the response matches the from tag of the original message. A
1327      * Response with a tag mismatch should be dropped if a Dialog has been created for the
1328      * original request.
1329      *
1330      * @param sipResponse the response to check.
1331      * @return true if the check passes.
1332      */
checkFromTag(SIPResponse sipResponse)1333     public boolean checkFromTag(SIPResponse sipResponse) {
1334         String originalFromTag = ((SIPRequest) this.getRequest()).getFromTag();
1335         if (this.defaultDialog != null) {
1336             if (originalFromTag == null ^ sipResponse.getFrom().getTag() == null) {
1337             	if (sipStack.isLoggingEnabled())
1338             		sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
1339                 return false;
1340             }
1341             if (originalFromTag != null
1342                     && !originalFromTag.equalsIgnoreCase(sipResponse.getFrom().getTag())) {
1343             	if (sipStack.isLoggingEnabled())
1344             		sipStack.getStackLogger().logDebug("From tag mismatch -- dropping response");
1345                 return false;
1346             }
1347         }
1348         return true;
1349 
1350     }
1351 
1352     /*
1353      * (non-Javadoc)
1354      *
1355      * @see gov.nist.javax.sip.stack.ServerResponseInterface#processResponse(gov.nist.javax.sip.message.SIPResponse,
1356      *      gov.nist.javax.sip.stack.MessageChannel)
1357      */
processResponse(SIPResponse sipResponse, MessageChannel incomingChannel)1358     public void processResponse(SIPResponse sipResponse, MessageChannel incomingChannel) {
1359 
1360         // If a dialog has already been created for this response,
1361         // pass it up.
1362         SIPDialog dialog = null;
1363         String method = sipResponse.getCSeq().getMethod();
1364         String dialogId = sipResponse.getDialogId(false);
1365         if (method.equals(Request.CANCEL) && lastRequest != null) {
1366             // JvB for CANCEL: use invite CT in CANCEL request to get dialog
1367             // (instead of stripping tag)
1368             SIPClientTransaction ict = (SIPClientTransaction) lastRequest.getInviteTransaction();
1369             if (ict != null) {
1370                 dialog = ict.defaultDialog;
1371             }
1372         } else {
1373             dialog = this.getDialog(dialogId);
1374         }
1375 
1376         // JvB: Check all conditions required for creating a new Dialog
1377         if (dialog == null) {
1378             int code = sipResponse.getStatusCode();
1379             if ((code > 100 && code < 300)
1380             /* skip 100 (may have a to tag */
1381             && (sipResponse.getToTag() != null || sipStack.isRfc2543Supported())
1382                     && sipStack.isDialogCreated(method)) {
1383 
1384                 /*
1385                  * Dialog cannot be found for the response. This must be a forked response. no
1386                  * dialog assigned to this response but a default dialog has been assigned. Note
1387                  * that if automatic dialog support is configured then a default dialog is always
1388                  * created.
1389                  */
1390 
1391                 synchronized (this) {
1392                     /*
1393                      * We need synchronization here because two responses may compete for the
1394                      * default dialog simultaneously
1395                      */
1396                     if (defaultDialog != null) {
1397                         if (sipResponse.getFromTag() != null) {
1398                             SIPResponse dialogResponse = defaultDialog.getLastResponse();
1399                             String defaultDialogId = defaultDialog.getDialogId();
1400                             if (dialogResponse == null
1401                                     || (method.equals(Request.SUBSCRIBE)
1402                                             && dialogResponse.getCSeq().getMethod().equals(
1403                                                     Request.NOTIFY) && defaultDialogId
1404                                             .equals(dialogId))) {
1405                                 // The default dialog has not been claimed yet.
1406                                 defaultDialog.setLastResponse(this, sipResponse);
1407                                 dialog = defaultDialog;
1408                             } else {
1409                                 /*
1410                                  * check if we have created one previously (happens in the case of
1411                                  * REINVITE processing. JvB: should not happen, this.defaultDialog
1412                                  * should then get set in Dialog#sendRequest line 1662
1413                                  */
1414 
1415                                 dialog = sipStack.getDialog(dialogId);
1416                                 if (dialog == null) {
1417                                     if (defaultDialog.isAssigned()) {
1418                                         /*
1419                                          * Nop we dont have one. so go ahead and allocate a new
1420                                          * one.
1421                                          */
1422                                         dialog = sipStack.createDialog(this, sipResponse);
1423 
1424                                     }
1425                                 }
1426 
1427                             }
1428                             if ( dialog != null ) {
1429                                 this.setDialog(dialog, dialog.getDialogId());
1430                             } else {
1431                                 sipStack.getStackLogger().logError("dialog is unexpectedly null",new NullPointerException());
1432                             }
1433                         } else {
1434                             throw new RuntimeException("Response without from-tag");
1435                         }
1436                     } else {
1437                         // Need to create a new Dialog, this becomes default
1438                         // JvB: not sure if this ever gets executed
1439                         if (sipStack.isAutomaticDialogSupportEnabled) {
1440                             dialog = sipStack.createDialog(this, sipResponse);
1441                             this.setDialog(dialog, dialog.getDialogId());
1442                         }
1443                     }
1444                 } // synchronized
1445             } else {
1446                 dialog = defaultDialog;
1447             }
1448         } else {
1449             dialog.setLastResponse(this, sipResponse);
1450         }
1451         this.processResponse(sipResponse, incomingChannel, dialog);
1452     }
1453 
1454     /*
1455      * (non-Javadoc)
1456      *
1457      * @see gov.nist.javax.sip.stack.SIPTransaction#getDialog()
1458      */
getDialog()1459     public  Dialog getDialog() {
1460         // This is for backwards compatibility.
1461         Dialog retval = null;
1462         if (this.lastResponse != null && this.lastResponse.getFromTag() != null
1463                 && this.lastResponse.getToTag() != null
1464                 && this.lastResponse.getStatusCode() != 100) {
1465             String dialogId = this.lastResponse.getDialogId(false);
1466             retval = (Dialog) getDialog(dialogId);
1467         }
1468 
1469         if (retval == null) {
1470             retval = (Dialog) this.defaultDialog;
1471 
1472         }
1473         if (sipStack.isLoggingEnabled()) {
1474             sipStack.getStackLogger().logDebug(
1475                     " sipDialogs =  " + sipDialogs + " default dialog " + this.defaultDialog
1476                             + " retval " + retval);
1477         }
1478         return retval;
1479 
1480     }
1481 
1482     /*
1483      * (non-Javadoc)
1484      *
1485      * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog,
1486      *      gov.nist.javax.sip.message.SIPMessage)
1487      */
getDialog(String dialogId)1488     public SIPDialog getDialog(String dialogId) {
1489         SIPDialog retval = (SIPDialog) this.sipDialogs.get(dialogId);
1490         return retval;
1491 
1492     }
1493 
1494     /*
1495      * (non-Javadoc)
1496      *
1497      * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog,
1498      *      gov.nist.javax.sip.message.SIPMessage)
1499      */
setDialog(SIPDialog sipDialog, String dialogId)1500     public void setDialog(SIPDialog sipDialog, String dialogId) {
1501         if (sipStack.isLoggingEnabled())
1502             sipStack.getStackLogger().logDebug(
1503                     "setDialog: " + dialogId + "sipDialog = " + sipDialog);
1504 
1505         if (sipDialog == null) {
1506         	if (sipStack.isLoggingEnabled())
1507         		sipStack.getStackLogger().logError("NULL DIALOG!!");
1508             throw new NullPointerException("bad dialog null");
1509         }
1510         if (this.defaultDialog == null) {
1511             this.defaultDialog = sipDialog;
1512             if ( this.getMethod().equals(Request.INVITE) && this.getSIPStack().maxForkTime != 0) {
1513                 this.getSIPStack().addForkedClientTransaction(this);
1514             }
1515         }
1516         if (dialogId != null && sipDialog.getDialogId() != null) {
1517             this.sipDialogs.put(dialogId, sipDialog);
1518 
1519         }
1520 
1521     }
1522 
getDefaultDialog()1523     public SIPDialog getDefaultDialog() {
1524         return this.defaultDialog;
1525     }
1526 
1527     /**
1528      * Set the next hop ( if it has already been computed).
1529      *
1530      * @param hop -- the hop that has been previously computed.
1531      */
setNextHop(Hop hop)1532     public void setNextHop(Hop hop) {
1533         this.nextHop = hop;
1534 
1535     }
1536 
1537     /**
1538      * Reeturn the previously computed next hop (avoid computing it twice).
1539      *
1540      * @return -- next hop previously computed.
1541      */
getNextHop()1542     public Hop getNextHop() {
1543         return nextHop;
1544     }
1545 
1546     /**
1547      * Set this flag if you want your Listener to get Timeout.RETRANSMIT notifications each time a
1548      * retransmission occurs.
1549      *
1550      * @param notifyOnRetransmit the notifyOnRetransmit to set
1551      */
setNotifyOnRetransmit(boolean notifyOnRetransmit)1552     public void setNotifyOnRetransmit(boolean notifyOnRetransmit) {
1553         this.notifyOnRetransmit = notifyOnRetransmit;
1554     }
1555 
1556     /**
1557      * @return the notifyOnRetransmit
1558      */
isNotifyOnRetransmit()1559     public boolean isNotifyOnRetransmit() {
1560         return notifyOnRetransmit;
1561     }
1562 
alertIfStillInCallingStateBy(int count)1563     public void alertIfStillInCallingStateBy(int count) {
1564         this.timeoutIfStillInCallingState = true;
1565         this.callingStateTimeoutCount = count;
1566     }
1567 
1568 
1569 
1570 }
1571