• 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.javax.sip.SIPConstants;
30 import gov.nist.javax.sip.ServerTransactionExt;
31 import gov.nist.javax.sip.SipProviderImpl;
32 import gov.nist.javax.sip.Utils;
33 import gov.nist.javax.sip.header.Expires;
34 import gov.nist.javax.sip.header.ParameterNames;
35 import gov.nist.javax.sip.header.RSeq;
36 import gov.nist.javax.sip.header.Via;
37 import gov.nist.javax.sip.header.ViaList;
38 import gov.nist.javax.sip.message.SIPMessage;
39 import gov.nist.javax.sip.message.SIPRequest;
40 import gov.nist.javax.sip.message.SIPResponse;
41 
42 import java.io.IOException;
43 import java.text.ParseException;
44 import java.util.TimerTask;
45 import java.util.concurrent.Semaphore;
46 import java.util.concurrent.TimeUnit;
47 
48 import javax.sip.Dialog;
49 import javax.sip.DialogState;
50 import javax.sip.DialogTerminatedEvent;
51 import javax.sip.ObjectInUseException;
52 import javax.sip.SipException;
53 import javax.sip.Timeout;
54 import javax.sip.TimeoutEvent;
55 import javax.sip.TransactionState;
56 import javax.sip.address.Hop;
57 import javax.sip.header.ContactHeader;
58 import javax.sip.header.ExpiresHeader;
59 import javax.sip.header.RSeqHeader;
60 import javax.sip.message.Request;
61 import javax.sip.message.Response;
62 
63 /*
64  * Bug fixes / enhancements:Emil Ivov, Antonis Karydas, Daniel J. Martinez Manzano, Daniel, Hagai
65  * Sela, Vazques-Illa, Bill Roome, Thomas Froment and Pierre De Rop, Christophe Anzille and Jeroen
66  * van Bemmel, Frank Reif.
67  * Carolyn Beeton ( Avaya ).
68  *
69  */
70 
71 /**
72  * Represents a server transaction. Implements the following state machines.
73  *
74  * <pre>
75  *
76  *
77  *
78  *                                                                      |INVITE
79  *                                                                      |pass INV to TU
80  *                                                   INVITE             V send 100 if TU won't in 200ms
81  *                                                   send response+-----------+
82  *                                                       +--------|           |--------+101-199 from TU
83  *                                                       |        | Proceeding|        |send response
84  *                                                       +-------&gt;|           |&lt;-------+
85  *                                                                |           |          Transport Err.
86  *                                                                |           |          Inform TU
87  *                                                                |           |---------------&gt;+
88  *                                                                +-----------+                |
89  *                                                   300-699 from TU |     |2xx from TU        |
90  *                                                   send response   |     |send response      |
91  *                                                                   |     +------------------&gt;+
92  *                                                                   |                         |
93  *                                                   INVITE          V          Timer G fires  |
94  *                                                   send response+-----------+ send response  |
95  *                                                       +--------|           |--------+       |
96  *                                                       |        | Completed |        |       |
97  *                                                       +-------&gt;|           |&lt;-------+       |
98  *                                                                +-----------+                |
99  *                                                                   |     |                   |
100  *                                                               ACK |     |                   |
101  *                                                               -   |     +------------------&gt;+
102  *                                                                   |        Timer H fires    |
103  *                                                                   V        or Transport Err.|
104  *                                                                +-----------+  Inform TU     |
105  *                                                                |           |                |
106  *                                                                | Confirmed |                |
107  *                                                                |           |                |
108  *                                                                +-----------+                |
109  *                                                                      |                      |
110  *                                                                      |Timer I fires         |
111  *                                                                      |-                     |
112  *                                                                      |                      |
113  *                                                                      V                      |
114  *                                                                +-----------+                |
115  *                                                                |           |                |
116  *                                                                | Terminated|&lt;---------------+
117  *                                                                |           |
118  *                                                                +-----------+
119  *
120  *                                                     Figure 7: INVITE server transaction
121  *                                                         Request received
122  *                                                                         |pass to TU
123  *
124  *                                                                         V
125  *                                                                   +-----------+
126  *                                                                   |           |
127  *                                                                   | Trying    |-------------+
128  *                                                                   |           |             |
129  *                                                                   +-----------+             |200-699 from TU
130  *                                                                         |                   |send response
131  *                                                                         |1xx from TU        |
132  *                                                                         |send response      |
133  *                                                                         |                   |
134  *                                                      Request            V      1xx from TU  |
135  *                                                      send response+-----------+send response|
136  *                                                          +--------|           |--------+    |
137  *                                                          |        | Proceeding|        |    |
138  *                                                          +-------&gt;|           |&lt;-------+    |
139  *                                                   +&lt;--------------|           |             |
140  *                                                   |Trnsprt Err    +-----------+             |
141  *                                                   |Inform TU            |                   |
142  *                                                   |                     |                   |
143  *                                                   |                     |200-699 from TU    |
144  *                                                   |                     |send response      |
145  *                                                   |  Request            V                   |
146  *                                                   |  send response+-----------+             |
147  *                                                   |      +--------|           |             |
148  *                                                   |      |        | Completed |&lt;------------+
149  *                                                   |      +-------&gt;|           |
150  *                                                   +&lt;--------------|           |
151  *                                                   |Trnsprt Err    +-----------+
152  *                                                   |Inform TU            |
153  *                                                   |                     |Timer J fires
154  *                                                   |                     |-
155  *                                                   |                     |
156  *                                                   |                     V
157  *                                                   |               +-----------+
158  *                                                   |               |           |
159  *                                                   +--------------&gt;| Terminated|
160  *                                                                   |           |
161  *                                                                   +-----------+
162  *
163  *
164  *
165  *
166  *
167  * </pre>
168  *
169  * @version 1.2 $Revision: 1.118 $ $Date: 2010/01/10 00:13:14 $
170  * @author M. Ranganathan
171  *
172  */
173 public class SIPServerTransaction extends SIPTransaction implements ServerRequestInterface,
174         javax.sip.ServerTransaction, ServerTransactionExt {
175 
176     // force the listener to see transaction
177 
178     private int rseqNumber;
179 
180     // private LinkedList pendingRequests;
181 
182     // Real RequestInterface to pass messages to
183     private transient ServerRequestInterface requestOf;
184 
185     private SIPDialog dialog;
186 
187     // the unacknowledged SIPResponse
188 
189     private SIPResponse pendingReliableResponse;
190 
191     // The pending reliable Response Timer
192     private ProvisionalResponseTask provisionalResponseTask;
193 
194     private boolean retransmissionAlertEnabled;
195 
196     private RetransmissionAlertTimerTask retransmissionAlertTimerTask;
197 
198     protected boolean isAckSeen;
199 
200     private SIPClientTransaction pendingSubscribeTransaction;
201 
202     private SIPServerTransaction inviteTransaction;
203 
204     private Semaphore provisionalResponseSem = new Semaphore(1);
205 
206     /**
207      * This timer task is used for alerting the application to send retransmission alerts.
208      *
209      *
210      */
211     class RetransmissionAlertTimerTask extends SIPStackTimerTask {
212 
213         String dialogId;
214 
215         int ticks;
216 
217         int ticksLeft;
218 
RetransmissionAlertTimerTask(String dialogId)219         public RetransmissionAlertTimerTask(String dialogId) {
220 
221             this.ticks = SIPTransaction.T1;
222             this.ticksLeft = this.ticks;
223         }
224 
runTask()225         protected void runTask() {
226             SIPServerTransaction serverTransaction = SIPServerTransaction.this;
227             ticksLeft--;
228             if (ticksLeft == -1) {
229                 serverTransaction.fireRetransmissionTimer();
230                 this.ticksLeft = 2 * ticks;
231             }
232 
233         }
234 
235     }
236 
237     class ProvisionalResponseTask extends SIPStackTimerTask {
238 
239         int ticks;
240 
241         int ticksLeft;
242 
ProvisionalResponseTask()243         public ProvisionalResponseTask() {
244             this.ticks = SIPTransaction.T1;
245             this.ticksLeft = this.ticks;
246         }
247 
runTask()248         protected void runTask() {
249             SIPServerTransaction serverTransaction = SIPServerTransaction.this;
250             /*
251              * The reliable provisional response is passed to the transaction layer periodically
252              * with an interval that starts at T1 seconds and doubles for each retransmission (T1
253              * is defined in Section 17 of RFC 3261). Once passed to the server transaction, it is
254              * added to an internal list of unacknowledged reliable provisional responses. The
255              * transaction layer will forward each retransmission passed from the UAS core.
256              *
257              * This differs from retransmissions of 2xx responses, whose intervals cap at T2
258              * seconds. This is because retransmissions of ACK are triggered on receipt of a 2xx,
259              * but retransmissions of PRACK take place independently of reception of 1xx.
260              */
261             // If the transaction has terminated,
262             if (serverTransaction.isTerminated()) {
263 
264                 this.cancel();
265 
266             } else {
267                 ticksLeft--;
268                 if (ticksLeft == -1) {
269                     serverTransaction.fireReliableResponseRetransmissionTimer();
270                     this.ticksLeft = 2 * ticks;
271                     this.ticks = this.ticksLeft;
272                     // timer H MUST be set to fire in 64*T1 seconds for all transports. Timer H
273                     // determines when the server
274                     // transaction abandons retransmitting the response
275                     if (this.ticksLeft >= SIPTransaction.TIMER_H) {
276                         this.cancel();
277                         setState(TERMINATED_STATE);
278                         fireTimeoutTimer();
279                     }
280                 }
281 
282             }
283 
284         }
285 
286     }
287 
288     /**
289      * This timer task will terminate the transaction if the listener does not respond in a
290      * pre-determined time period. This helps prevent buggy listeners (who fail to respond) from
291      * causing memory leaks. This allows a container to protect itself from buggy code ( that
292      * fails to respond to a server transaction).
293      *
294      */
295     class ListenerExecutionMaxTimer extends SIPStackTimerTask {
296         SIPServerTransaction serverTransaction = SIPServerTransaction.this;
297 
ListenerExecutionMaxTimer()298         ListenerExecutionMaxTimer() {
299         }
300 
runTask()301         protected void runTask() {
302             try {
303                 if (serverTransaction.getState() == null) {
304                     serverTransaction.terminate();
305                     SIPTransactionStack sipStack = serverTransaction.getSIPStack();
306                     sipStack.removePendingTransaction(serverTransaction);
307                     sipStack.removeTransaction(serverTransaction);
308 
309                 }
310             } catch (Exception ex) {
311                 sipStack.getStackLogger().logError("unexpected exception", ex);
312             }
313         }
314     }
315 
316     /**
317      * This timer task is for INVITE server transactions. It will send a trying in 200 ms. if the
318      * TU does not do so.
319      *
320      */
321     class SendTrying extends SIPStackTimerTask {
322 
SendTrying()323         protected SendTrying() {
324             if (sipStack.isLoggingEnabled())
325                 sipStack.getStackLogger().logDebug("scheduled timer for " + SIPServerTransaction.this);
326 
327         }
328 
runTask()329         protected void runTask() {
330             SIPServerTransaction serverTransaction = SIPServerTransaction.this;
331 
332             TransactionState realState = serverTransaction.getRealState();
333 
334             if (realState == null || TransactionState.TRYING == realState) {
335                 if (sipStack.isLoggingEnabled())
336                     sipStack.getStackLogger().logDebug(" sending Trying current state = "
337                             + serverTransaction.getRealState());
338                 try {
339                     serverTransaction.sendMessage(serverTransaction.getOriginalRequest()
340                             .createResponse(100, "Trying"));
341                     if (sipStack.isLoggingEnabled())
342                         sipStack.getStackLogger().logDebug(" trying sent "
343                                 + serverTransaction.getRealState());
344                 } catch (IOException ex) {
345                     if (sipStack.isLoggingEnabled())
346                         sipStack.getStackLogger().logError("IO error sending  TRYING");
347                 }
348             }
349 
350         }
351     }
352 
353     class TransactionTimer extends SIPStackTimerTask {
354 
TransactionTimer()355         public TransactionTimer() {
356             if (sipStack.isLoggingEnabled()) {
357                 sipStack.getStackLogger().logDebug("TransactionTimer() : " + getTransactionId());
358             }
359 
360         }
361 
runTask()362         protected void runTask() {
363             // If the transaction has terminated,
364             if (isTerminated()) {
365                 // Keep the transaction hanging around in the transaction table
366                 // to catch the incoming ACK -- this is needed for tcp only.
367                 // Note that the transaction record is actually removed in
368                 // the connection linger timer.
369                 try {
370                     this.cancel();
371                 } catch (IllegalStateException ex) {
372                     if (!sipStack.isAlive())
373                         return;
374                 }
375 
376                 // Oneshot timer that garbage collects the SeverTransaction
377                 // after a scheduled amount of time. The linger timer allows
378                 // the client side of the tx to use the same connection to
379                 // send an ACK and prevents a race condition for creation
380                 // of new server tx
381                 TimerTask myTimer = new LingerTimer();
382 
383                 sipStack.getTimer().schedule(myTimer,
384                         SIPTransactionStack.CONNECTION_LINGER_TIME * 1000);
385 
386             } else {
387                 // Add to the fire list -- needs to be moved
388                 // outside the synchronized block to prevent
389                 // deadlock.
390                 fireTimer();
391 
392             }
393         }
394 
395     }
396 
397     /**
398      * Send a response.
399      *
400      * @param transactionResponse -- the response to send
401      *
402      */
403 
sendResponse(SIPResponse transactionResponse)404     private void sendResponse(SIPResponse transactionResponse) throws IOException {
405 
406         try {
407             // RFC18.2.2. Sending Responses
408             // The server transport uses the value of the top Via header field
409             // in
410             // order
411             // to determine where to send a response.
412             // It MUST follow the following process:
413             // If the "sent-protocol" is a reliable transport
414             // protocol such as TCP or SCTP,
415             // or TLS over those, the response MUST be
416             // sent using the existing connection
417             // to the source of the original request
418             // that created the transaction, if that connection is still open.
419             if (isReliable()) {
420 
421                 getMessageChannel().sendMessage(transactionResponse);
422 
423                 // TODO If that connection attempt fails, the server SHOULD
424                 // use SRV 3263 procedures
425                 // for servers in order to determine the IP address
426                 // and port to open the connection and send the response to.
427 
428             } else {
429                 Via via = transactionResponse.getTopmostVia();
430                 String transport = via.getTransport();
431                 if (transport == null)
432                     throw new IOException("missing transport!");
433                 // @@@ hagai Symmetric NAT support
434                 int port = via.getRPort();
435                 if (port == -1)
436                     port = via.getPort();
437                 if (port == -1) {
438                     if (transport.equalsIgnoreCase("TLS"))
439                         port = 5061;
440                     else
441                         port = 5060;
442                 }
443 
444                 // Otherwise, if the Via header field value contains a
445                 // "maddr" parameter, the response MUST be forwarded to
446                 // the address listed there, using the port indicated in
447                 // "sent-by",
448                 // or port 5060 if none is present. If the address is a
449                 // multicast
450                 // address, the response SHOULD be sent using
451                 // the TTL indicated in the "ttl" parameter, or with a
452                 // TTL of 1 if that parameter is not present.
453                 String host = null;
454                 if (via.getMAddr() != null) {
455                     host = via.getMAddr();
456                 } else {
457                     // Otherwise (for unreliable unicast transports),
458                     // if the top Via has a "received" parameter, the response
459                     // MUST
460                     // be sent to the
461                     // address in the "received" parameter, using the port
462                     // indicated
463                     // in the
464                     // "sent-by" value, or using port 5060 if none is specified
465                     // explicitly.
466                     host = via.getParameter(Via.RECEIVED);
467                     if (host == null) {
468                         // Otherwise, if it is not receiver-tagged, the response
469                         // MUST be
470                         // sent to the address indicated by the "sent-by" value,
471                         // using the procedures in Section 5
472                         // RFC 3263 PROCEDURE TO BE DONE HERE
473                         host = via.getHost();
474                     }
475                 }
476 
477                 Hop hop = sipStack.addressResolver.resolveAddress(new HopImpl(host, port,
478                         transport));
479 
480                 MessageChannel messageChannel = ((SIPTransactionStack) getSIPStack())
481                         .createRawMessageChannel(this.getSipProvider().getListeningPoint(
482                                 hop.getTransport()).getIPAddress(), this.getPort(), hop);
483                 if (messageChannel != null)
484                     messageChannel.sendMessage(transactionResponse);
485                 else
486                     throw new IOException("Could not create a message channel for " + hop);
487 
488             }
489         } finally {
490             this.startTransactionTimer();
491         }
492     }
493 
494     /**
495      * Creates a new server transaction.
496      *
497      * @param sipStack Transaction stack this transaction belongs to.
498      * @param newChannelToUse Channel to encapsulate.
499      */
SIPServerTransaction(SIPTransactionStack sipStack, MessageChannel newChannelToUse)500     protected SIPServerTransaction(SIPTransactionStack sipStack, MessageChannel newChannelToUse) {
501 
502         super(sipStack, newChannelToUse);
503 
504         if (sipStack.maxListenerResponseTime != -1) {
505             sipStack.getTimer().schedule(new ListenerExecutionMaxTimer(),
506                     sipStack.maxListenerResponseTime * 1000);
507         }
508 
509         this.rseqNumber = (int) (Math.random() * 1000);
510         // Only one outstanding request for a given server tx.
511 
512         if (sipStack.isLoggingEnabled()) {
513             sipStack.getStackLogger().logDebug("Creating Server Transaction" + this.getBranchId());
514             sipStack.getStackLogger().logStackTrace();
515         }
516 
517     }
518 
519     /**
520      * Sets the real RequestInterface this transaction encapsulates.
521      *
522      * @param newRequestOf RequestInterface to send messages to.
523      */
setRequestInterface(ServerRequestInterface newRequestOf)524     public void setRequestInterface(ServerRequestInterface newRequestOf) {
525 
526         requestOf = newRequestOf;
527 
528     }
529 
530     /**
531      * Returns this transaction.
532      */
getResponseChannel()533     public MessageChannel getResponseChannel() {
534 
535         return this;
536 
537     }
538 
539 
540 
541     /**
542      * Determines if the message is a part of this transaction.
543      *
544      * @param messageToTest Message to check if it is part of this transaction.
545      *
546      * @return True if the message is part of this transaction, false if not.
547      */
isMessagePartOfTransaction(SIPMessage messageToTest)548     public boolean isMessagePartOfTransaction(SIPMessage messageToTest) {
549 
550         // List of Via headers in the message to test
551         ViaList viaHeaders;
552         // Topmost Via header in the list
553         Via topViaHeader;
554         // Branch code in the topmost Via header
555         String messageBranch;
556         // Flags whether the select message is part of this transaction
557         boolean transactionMatches;
558 
559         transactionMatches = false;
560 
561         String method = messageToTest.getCSeq().getMethod();
562         // Invite Server transactions linger in the terminated state in the
563         // transaction
564         // table and are matched to compensate for
565         // http://bugs.sipit.net/show_bug.cgi?id=769
566         if ((method.equals(Request.INVITE) || !isTerminated())) {
567 
568             // Get the topmost Via header and its branch parameter
569             viaHeaders = messageToTest.getViaHeaders();
570             if (viaHeaders != null) {
571 
572                 topViaHeader = (Via) viaHeaders.getFirst();
573                 messageBranch = topViaHeader.getBranch();
574                 if (messageBranch != null) {
575 
576                     // If the branch parameter exists but
577                     // does not start with the magic cookie,
578                     if (!messageBranch.toLowerCase().startsWith(
579                             SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) {
580 
581                         // Flags this as old
582                         // (RFC2543-compatible) client
583                         // version
584                         messageBranch = null;
585 
586                     }
587 
588                 }
589 
590                 // If a new branch parameter exists,
591                 if (messageBranch != null && this.getBranch() != null) {
592                     if (method.equals(Request.CANCEL)) {
593                         // Cancel is handled as a special case because it
594                         // shares the same same branch id of the invite
595                         // that it is trying to cancel.
596                         transactionMatches = this.getMethod().equals(Request.CANCEL)
597                                 && getBranch().equalsIgnoreCase(messageBranch)
598                                 && topViaHeader.getSentBy().equals(
599                                         ((Via) getOriginalRequest().getViaHeaders().getFirst())
600                                                 .getSentBy());
601 
602                     } else {
603                         // Matching server side transaction with only the
604                         // branch parameter.
605                         transactionMatches = getBranch().equalsIgnoreCase(messageBranch)
606                                 && topViaHeader.getSentBy().equals(
607                                         ((Via) getOriginalRequest().getViaHeaders().getFirst())
608                                                 .getSentBy());
609 
610                     }
611 
612                 } else {
613                     // This is an RFC2543-compliant message; this code is here
614                     // for backwards compatibility.
615                     // It is a weak check.
616                     // If RequestURI, To tag, From tag, CallID, CSeq number, and
617                     // top Via headers are the same, the
618                     // SIPMessage matches this transaction. An exception is for
619                     // a CANCEL request, which is not deemed
620                     // to be part of an otherwise-matching INVITE transaction.
621                     String originalFromTag = super.fromTag;
622 
623                     String thisFromTag = messageToTest.getFrom().getTag();
624 
625                     boolean skipFrom = (originalFromTag == null || thisFromTag == null);
626 
627                     String originalToTag = super.toTag;
628 
629                     String thisToTag = messageToTest.getTo().getTag();
630 
631                     boolean skipTo = (originalToTag == null || thisToTag == null);
632                     boolean isResponse = (messageToTest instanceof SIPResponse);
633                     // Issue #96: special case handling for a CANCEL request -
634                     // the CSeq method of the original request must
635                     // be CANCEL for it to have a chance at matching.
636                     if (messageToTest.getCSeq().getMethod().equalsIgnoreCase(Request.CANCEL)
637                             && !getOriginalRequest().getCSeq().getMethod().equalsIgnoreCase(
638                                     Request.CANCEL)) {
639                         transactionMatches = false;
640                     } else if ((isResponse || getOriginalRequest().getRequestURI().equals(
641                             ((SIPRequest) messageToTest).getRequestURI()))
642                             && (skipFrom || originalFromTag != null && originalFromTag.equalsIgnoreCase(thisFromTag))
643                             && (skipTo || originalToTag != null && originalToTag.equalsIgnoreCase(thisToTag))
644                             && getOriginalRequest().getCallId().getCallId().equalsIgnoreCase(
645                                     messageToTest.getCallId().getCallId())
646                             && getOriginalRequest().getCSeq().getSeqNumber() == messageToTest
647                                     .getCSeq().getSeqNumber()
648                             && ((!messageToTest.getCSeq().getMethod().equals(Request.CANCEL)) || getOriginalRequest()
649                                     .getMethod().equals(messageToTest.getCSeq().getMethod()))
650                             && topViaHeader.equals(getOriginalRequest().getViaHeaders()
651                                     .getFirst())) {
652 
653                         transactionMatches = true;
654                     }
655 
656                 }
657 
658             }
659 
660         }
661         return transactionMatches;
662 
663     }
664 
665     /**
666      * Send out a trying response (only happens when the transaction is mapped). Otherwise the
667      * transaction is not known to the stack.
668      */
map()669     protected void map() {
670         // note that TRYING is a pseudo-state for invite transactions
671 
672         TransactionState realState = getRealState();
673 
674         if (realState == null || realState == TransactionState.TRYING) {
675             // JvB: Removed the condition 'dialog!=null'. Trying should also
676             // be
677             // sent by intermediate proxies. This fixes some TCK tests
678             // null check added as the stack may be stopped.
679             if (isInviteTransaction() && !this.isMapped && sipStack.getTimer() != null) {
680                 this.isMapped = true;
681                 // Schedule a timer to fire in 200 ms if the
682                 // TU did not send a trying in that time.
683                 sipStack.getTimer().schedule(new SendTrying(), 200);
684 
685             } else {
686                 isMapped = true;
687             }
688         }
689 
690         // Pull it out of the pending transactions list.
691         sipStack.removePendingTransaction(this);
692     }
693 
694     /**
695      * Return true if the transaction is known to stack.
696      */
isTransactionMapped()697     public boolean isTransactionMapped() {
698         return this.isMapped;
699     }
700 
701     /**
702      * Process a new request message through this transaction. If necessary, this message will
703      * also be passed onto the TU.
704      *
705      * @param transactionRequest Request to process.
706      * @param sourceChannel Channel that received this message.
707      */
processRequest(SIPRequest transactionRequest, MessageChannel sourceChannel)708     public void processRequest(SIPRequest transactionRequest, MessageChannel sourceChannel) {
709         boolean toTu = false;
710 
711         // Can only process a single request directed to the
712         // transaction at a time. For a given server transaction
713         // the listener sees only one event at a time.
714 
715         if (sipStack.isLoggingEnabled()) {
716             sipStack.getStackLogger().logDebug("processRequest: " + transactionRequest.getFirstLine());
717             sipStack.getStackLogger().logDebug("tx state = " + this.getRealState());
718         }
719 
720         try {
721 
722             // If this is the first request for this transaction,
723             if (getRealState() == null) {
724                 // Save this request as the one this
725                 // transaction is handling
726                 setOriginalRequest(transactionRequest);
727                 this.setState(TransactionState.TRYING);
728                 toTu = true;
729                 this.setPassToListener();
730 
731                 // Rsends the TRYING on retransmission of the request.
732                 if (isInviteTransaction() && this.isMapped) {
733                     // JvB: also
734                     // proxies need
735                     // to do this
736 
737                     // Has side-effect of setting
738                     // state to "Proceeding"
739                     sendMessage(transactionRequest.createResponse(100, "Trying"));
740 
741                 }
742                 // If an invite transaction is ACK'ed while in
743                 // the completed state,
744             } else if (isInviteTransaction() && TransactionState.COMPLETED == getRealState()
745                     && transactionRequest.getMethod().equals(Request.ACK)) {
746 
747                 // @jvB bug fix
748                 this.setState(TransactionState.CONFIRMED);
749                 disableRetransmissionTimer();
750                 if (!isReliable()) {
751                     enableTimeoutTimer(TIMER_I);
752 
753                 } else {
754 
755                     this.setState(TransactionState.TERMINATED);
756 
757                 }
758 
759                 // JvB: For the purpose of testing a TI, added a property to
760                 // pass it anyway
761                 if (sipStack.isNon2XXAckPassedToListener()) {
762                     // This is useful for test applications that want to see
763                     // all messages.
764                     requestOf.processRequest(transactionRequest, this);
765                 } else {
766                     // According to RFC3261 Application should not Ack in
767                     // CONFIRMED state
768                     if (sipStack.isLoggingEnabled()) {
769                         sipStack.getStackLogger().logDebug("ACK received for server Tx "
770                                 + this.getTransactionId() + " not delivering to application!");
771 
772                     }
773 
774                     this.semRelease();
775                 }
776                 return;
777 
778                 // If we receive a retransmission of the original
779                 // request,
780             } else if (transactionRequest.getMethod().equals(getOriginalRequest().getMethod())) {
781 
782                 if (TransactionState.PROCEEDING == getRealState()
783                         || TransactionState.COMPLETED == getRealState()) {
784                     this.semRelease();
785                     // Resend the last response to
786                     // the client
787                     if (lastResponse != null) {
788 
789                         // Send the message to the client
790                         super.sendMessage(lastResponse);
791 
792                     }
793                 } else if (transactionRequest.getMethod().equals(Request.ACK)) {
794                     // This is passed up to the TU to suppress
795                     // retransmission of OK
796                     if (requestOf != null)
797                         requestOf.processRequest(transactionRequest, this);
798                     else
799                         this.semRelease();
800                 }
801                 if (sipStack.isLoggingEnabled())
802                 	sipStack.getStackLogger().logDebug("completed processing retransmitted request : "
803                         + transactionRequest.getFirstLine() + this + " txState = "
804                         + this.getState() + " lastResponse = " + this.getLastResponse());
805                 return;
806 
807             }
808 
809             // Pass message to the TU
810             if (TransactionState.COMPLETED != getRealState()
811                     && TransactionState.TERMINATED != getRealState() && requestOf != null) {
812                 if (getOriginalRequest().getMethod().equals(transactionRequest.getMethod())) {
813                     // Only send original request to TU once!
814                     if (toTu) {
815                         requestOf.processRequest(transactionRequest, this);
816                     } else
817                         this.semRelease();
818                 } else {
819                     if (requestOf != null)
820                         requestOf.processRequest(transactionRequest, this);
821                     else
822                         this.semRelease();
823                 }
824             } else {
825                 // This seems like a common bug so I am allowing it through!
826                 if (((SIPTransactionStack) getSIPStack()).isDialogCreated(getOriginalRequest()
827                         .getMethod())
828                         && getRealState() == TransactionState.TERMINATED
829                         && transactionRequest.getMethod().equals(Request.ACK)
830                         && requestOf != null) {
831                     SIPDialog thisDialog = (SIPDialog) this.dialog;
832 
833                     if (thisDialog == null || !thisDialog.ackProcessed) {
834                         // Filter out duplicate acks
835                         if (thisDialog != null) {
836                             thisDialog.ackReceived(transactionRequest);
837                             thisDialog.ackProcessed = true;
838                         }
839                         requestOf.processRequest(transactionRequest, this);
840                     } else {
841                         this.semRelease();
842                     }
843 
844                 } else if (transactionRequest.getMethod().equals(Request.CANCEL)) {
845                     if (sipStack.isLoggingEnabled())
846                         sipStack.getStackLogger().logDebug("Too late to cancel Transaction");
847                     this.semRelease();
848                     // send OK and just ignore the CANCEL.
849                     try {
850                         this.sendMessage(transactionRequest.createResponse(Response.OK));
851                     } catch (IOException ex) {
852                         // Transaction is already terminated
853                         // just ignore the IOException.
854                     }
855                 }
856                 if (sipStack.isLoggingEnabled())
857                 	sipStack.getStackLogger().logDebug("Dropping request " + getRealState());
858             }
859 
860         } catch (IOException e) {
861         	if (sipStack.isLoggingEnabled())
862         		sipStack.getStackLogger().logError("IOException " ,e);
863             this.semRelease();
864             this.raiseIOExceptionEvent();
865         }
866 
867     }
868 
869     /**
870      * Send a response message through this transactionand onto the client. The response drives
871      * the state machine.
872      *
873      * @param messageToSend Response to process and send.
874      */
sendMessage(SIPMessage messageToSend)875     public void sendMessage(SIPMessage messageToSend) throws IOException {
876         try {
877             // Message typecast as a response
878             SIPResponse transactionResponse;
879             // Status code of the response being sent to the client
880             int statusCode;
881 
882             // Get the status code from the response
883             transactionResponse = (SIPResponse) messageToSend;
884             statusCode = transactionResponse.getStatusCode();
885 
886             try {
887                 // Provided we have set the banch id for this we set the BID for
888                 // the
889                 // outgoing via.
890                 if (this.getOriginalRequest().getTopmostVia().getBranch() != null)
891                     transactionResponse.getTopmostVia().setBranch(this.getBranch());
892                 else
893                     transactionResponse.getTopmostVia().removeParameter(ParameterNames.BRANCH);
894 
895                 // Make the topmost via headers match identically for the
896                 // transaction rsponse.
897                 if (!this.getOriginalRequest().getTopmostVia().hasPort())
898                     transactionResponse.getTopmostVia().removePort();
899             } catch (ParseException ex) {
900                 ex.printStackTrace();
901             }
902 
903             // Method of the response does not match the request used to
904             // create the transaction - transaction state does not change.
905             if (!transactionResponse.getCSeq().getMethod().equals(
906                     getOriginalRequest().getMethod())) {
907                 sendResponse(transactionResponse);
908                 return;
909             }
910 
911             // If the TU sends a provisional response while in the
912             // trying state,
913 
914             if (getRealState() == TransactionState.TRYING) {
915                 if (statusCode / 100 == 1) {
916                     this.setState(TransactionState.PROCEEDING);
917                 } else if (200 <= statusCode && statusCode <= 699) {
918                     // INVITE ST has TRYING as a Pseudo state
919                     // (See issue 76). We are using the TRYING
920                     // pseudo state invite Transactions
921                     // to signal if the application
922                     // has sent trying or not and hence this
923                     // check is necessary.
924                     if (!isInviteTransaction()) {
925                         if (!isReliable()) {
926                             // Linger in the completed state to catch
927                             // retransmissions if the transport is not
928                             // reliable.
929                             this.setState(TransactionState.COMPLETED);
930                             // Note that Timer J is only set for Unreliable
931                             // transports -- see Issue 75.
932                             /*
933                              * From RFC 3261 Section 17.2.2 (non-invite server transaction)
934                              *
935                              * When the server transaction enters the "Completed" state, it MUST
936                              * set Timer J to fire in 64*T1 seconds for unreliable transports, and
937                              * zero seconds for reliable transports. While in the "Completed"
938                              * state, the server transaction MUST pass the final response to the
939                              * transport layer for retransmission whenever a retransmission of the
940                              * request is received. Any other final responses passed by the TU to
941                              * the server transaction MUST be discarded while in the "Completed"
942                              * state. The server transaction remains in this state until Timer J
943                              * fires, at which point it MUST transition to the "Terminated" state.
944                              */
945                             enableTimeoutTimer(TIMER_J);
946                         } else {
947                             this.setState(TransactionState.TERMINATED);
948                         }
949                     } else {
950                         // This is the case for INVITE server transactions.
951                         // essentially, it duplicates the code in the
952                         // PROCEEDING case below. There is no TRYING state for INVITE
953                         // transactions in the RFC. We are using it to signal whether the
954                         // application has sent a provisional response or not. Hence
955                         // this is treated the same as as Proceeding.
956                         if (statusCode / 100 == 2) {
957                             // Status code is 2xx means that the
958                             // transaction transitions to TERMINATED
959                             // for both Reliable as well as unreliable
960                             // transports. Note that the dialog layer
961                             // takes care of retransmitting 2xx final
962                             // responses.
963                             /*
964                              * RFC 3261 Section 13.3.1.4 Note, however, that the INVITE server
965                              * transaction will be destroyed as soon as it receives this final
966                              * response and passes it to the transport. Therefore, it is necessary
967                              * to periodically pass the response directly to the transport until
968                              * the ACK arrives. The 2xx response is passed to the transport with
969                              * an interval that starts at T1 seconds and doubles for each
970                              * retransmission until it reaches T2 seconds (T1 and T2 are defined
971                              * in Section 17). Response retransmissions cease when an ACK request
972                              * for the response is received. This is independent of whatever
973                              * transport protocols are used to send the response.
974                              */
975                             this.disableRetransmissionTimer();
976                             this.disableTimeoutTimer();
977                             this.collectionTime = TIMER_J;
978                             this.setState(TransactionState.TERMINATED);
979                             if (this.dialog != null)
980                                 this.dialog.setRetransmissionTicks();
981                         } else {
982                             // This an error final response.
983                             this.setState(TransactionState.COMPLETED);
984                             if (!isReliable()) {
985                                 /*
986                                  * RFC 3261
987                                  *
988                                  * While in the "Proceeding" state, if the TU passes a response
989                                  * with status code from 300 to 699 to the server transaction, the
990                                  * response MUST be passed to the transport layer for
991                                  * transmission, and the state machine MUST enter the "Completed"
992                                  * state. For unreliable transports, timer G is set to fire in T1
993                                  * seconds, and is not set to fire for reliable transports.
994                                  */
995 
996                                 enableRetransmissionTimer();
997 
998                             }
999                             enableTimeoutTimer(TIMER_H);
1000                         }
1001                     }
1002 
1003                 }
1004 
1005                 // If the transaction is in the proceeding state,
1006             } else if (getRealState() == TransactionState.PROCEEDING) {
1007 
1008                 if (isInviteTransaction()) {
1009 
1010                     // If the response is a failure message,
1011                     if (statusCode / 100 == 2) {
1012                         // Set up to catch returning ACKs
1013                         // The transaction lingers in the
1014                         // terminated state for some time
1015                         // to catch retransmitted INVITEs
1016                         this.disableRetransmissionTimer();
1017                         this.disableTimeoutTimer();
1018                         this.collectionTime = TIMER_J;
1019                         this.setState(TransactionState.TERMINATED);
1020                         if (this.dialog != null)
1021                             this.dialog.setRetransmissionTicks();
1022 
1023                     } else if (300 <= statusCode && statusCode <= 699) {
1024 
1025                         // Set up to catch returning ACKs
1026                         this.setState(TransactionState.COMPLETED);
1027                         if (!isReliable()) {
1028                             /*
1029                              * While in the "Proceeding" state, if the TU passes a response with
1030                              * status code from 300 to 699 to the server transaction, the response
1031                              * MUST be passed to the transport layer for transmission, and the
1032                              * state machine MUST enter the "Completed" state. For unreliable
1033                              * transports, timer G is set to fire in T1 seconds, and is not set to
1034                              * fire for reliable transports.
1035                              */
1036 
1037                             enableRetransmissionTimer();
1038 
1039                         }
1040                         enableTimeoutTimer(TIMER_H);
1041 
1042                     }
1043 
1044                     // If the transaction is not an invite transaction
1045                     // and this is a final response,
1046                 } else if (200 <= statusCode && statusCode <= 699) {
1047                     // This is for Non-invite server transactions.
1048 
1049                     // Set up to retransmit this response,
1050                     // or terminate the transaction
1051                     this.setState(TransactionState.COMPLETED);
1052                     if (!isReliable()) {
1053 
1054                         disableRetransmissionTimer();
1055                         enableTimeoutTimer(TIMER_J);
1056 
1057                     } else {
1058 
1059                         this.setState(TransactionState.TERMINATED);
1060 
1061                     }
1062 
1063                 }
1064 
1065                 // If the transaction has already completed,
1066             } else if (TransactionState.COMPLETED == this.getRealState()) {
1067 
1068                 return;
1069             }
1070 
1071             try {
1072                 // Send the message to the client.
1073                 // Record the last message sent out.
1074                 if (sipStack.isLoggingEnabled()) {
1075                     sipStack.getStackLogger().logDebug(
1076                             "sendMessage : tx = " + this + " getState = " + this.getState());
1077                 }
1078                 lastResponse = transactionResponse;
1079                 this.sendResponse(transactionResponse);
1080 
1081             } catch (IOException e) {
1082 
1083                 this.setState(TransactionState.TERMINATED);
1084                 this.collectionTime = 0;
1085                 throw e;
1086 
1087             }
1088         } finally {
1089             this.startTransactionTimer();
1090         }
1091 
1092     }
1093 
getViaHost()1094     public String getViaHost() {
1095 
1096         return getMessageChannel().getViaHost();
1097 
1098     }
1099 
getViaPort()1100     public int getViaPort() {
1101 
1102         return getMessageChannel().getViaPort();
1103 
1104     }
1105 
1106     /**
1107      * Called by the transaction stack when a retransmission timer fires. This retransmits the
1108      * last response when the retransmission filter is enabled.
1109      */
fireRetransmissionTimer()1110     protected void fireRetransmissionTimer() {
1111 
1112         try {
1113             if (sipStack.isLoggingEnabled()) {
1114                 sipStack.getStackLogger().logDebug("fireRetransmissionTimer() -- ");
1115             }
1116             // Resend the last response sent by this transaction
1117             if (isInviteTransaction() && lastResponse != null) {
1118                 // null can happen if this is terminating when the timer fires.
1119                 if (!this.retransmissionAlertEnabled || sipStack.isTransactionPendingAck(this) ) {
1120                     // Retransmit last response until ack.
1121                     if (lastResponse.getStatusCode() / 100 > 2 && !this.isAckSeen)
1122                         super.sendMessage(lastResponse);
1123                 } else {
1124                     // alert the application to retransmit the last response
1125                     SipProviderImpl sipProvider = (SipProviderImpl) this.getSipProvider();
1126                     TimeoutEvent txTimeout = new TimeoutEvent(sipProvider, this,
1127                             Timeout.RETRANSMIT);
1128                     sipProvider.handleEvent(txTimeout, this);
1129                 }
1130 
1131             }
1132         } catch (IOException e) {
1133             if (sipStack.isLoggingEnabled())
1134                 sipStack.getStackLogger().logException(e);
1135             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
1136 
1137         }
1138 
1139     }
1140 
fireReliableResponseRetransmissionTimer()1141     private void fireReliableResponseRetransmissionTimer() {
1142         try {
1143 
1144             super.sendMessage(this.pendingReliableResponse);
1145 
1146         } catch (IOException e) {
1147             if (sipStack.isLoggingEnabled())
1148                 sipStack.getStackLogger().logException(e);
1149             this.setState(TransactionState.TERMINATED);
1150             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
1151 
1152         }
1153     }
1154 
1155     /**
1156      * Called by the transaction stack when a timeout timer fires.
1157      */
fireTimeoutTimer()1158     protected void fireTimeoutTimer() {
1159 
1160         if (sipStack.isLoggingEnabled())
1161             sipStack.getStackLogger().logDebug("SIPServerTransaction.fireTimeoutTimer this = " + this
1162                     + " current state = " + this.getRealState() + " method = "
1163                     + this.getOriginalRequest().getMethod());
1164 
1165         if ( this.getMethod().equals(Request.INVITE) && sipStack.removeTransactionPendingAck(this) ) {
1166             if ( sipStack.isLoggingEnabled() ) {
1167                 sipStack.getStackLogger().logDebug("Found tx pending ACK - returning");
1168             }
1169             return;
1170 
1171         }
1172         SIPDialog dialog = (SIPDialog) this.dialog;
1173         if (((SIPTransactionStack) getSIPStack()).isDialogCreated(this.getOriginalRequest()
1174                 .getMethod())
1175                 && (TransactionState.CALLING == this.getRealState() || TransactionState.TRYING == this
1176                         .getRealState())) {
1177             dialog.setState(SIPDialog.TERMINATED_STATE);
1178         } else if (getOriginalRequest().getMethod().equals(Request.BYE)) {
1179             if (dialog != null && dialog.isTerminatedOnBye())
1180                 dialog.setState(SIPDialog.TERMINATED_STATE);
1181         }
1182 
1183         if (TransactionState.COMPLETED == this.getRealState() && isInviteTransaction()) {
1184             raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
1185             this.setState(TransactionState.TERMINATED);
1186             sipStack.removeTransaction(this);
1187 
1188         } else if (TransactionState.COMPLETED == this.getRealState() && !isInviteTransaction()) {
1189             this.setState(TransactionState.TERMINATED);
1190             sipStack.removeTransaction(this);
1191 
1192         } else if (TransactionState.CONFIRMED == this.getRealState() && isInviteTransaction()) {
1193             // TIMER_I should not generate a timeout
1194             // exception to the application when the
1195             // Invite transaction is in Confirmed state.
1196             // Just transition to Terminated state.
1197             this.setState(TransactionState.TERMINATED);
1198             sipStack.removeTransaction(this);
1199         } else if (!isInviteTransaction()
1200                 && (TransactionState.COMPLETED == this.getRealState() || TransactionState.CONFIRMED == this
1201                         .getRealState())) {
1202             this.setState(TransactionState.TERMINATED);
1203         } else if (isInviteTransaction() && TransactionState.TERMINATED == this.getRealState()) {
1204             // This state could be reached when retransmitting
1205 
1206             raiseErrorEvent(SIPTransactionErrorEvent.TIMEOUT_ERROR);
1207             if (dialog != null)
1208                 dialog.setState(SIPDialog.TERMINATED_STATE);
1209         }
1210 
1211     }
1212 
1213     /**
1214      * Get the last response.
1215      */
getLastResponse()1216     public SIPResponse getLastResponse() {
1217         return this.lastResponse;
1218     }
1219 
1220     /**
1221      * Set the original request.
1222      */
setOriginalRequest(SIPRequest originalRequest)1223     public void setOriginalRequest(SIPRequest originalRequest) {
1224         super.setOriginalRequest(originalRequest);
1225 
1226     }
1227 
1228     /*
1229      * (non-Javadoc)
1230      *
1231      * @see javax.sip.ServerTransaction#sendResponse(javax.sip.message.Response)
1232      */
sendResponse(Response response)1233     public void sendResponse(Response response) throws SipException {
1234         SIPResponse sipResponse = (SIPResponse) response;
1235 
1236         SIPDialog dialog = this.dialog;
1237         if (response == null)
1238             throw new NullPointerException("null response");
1239 
1240         try {
1241             sipResponse.checkHeaders();
1242         } catch (ParseException ex) {
1243             throw new SipException(ex.getMessage());
1244         }
1245 
1246         // check for meaningful response.
1247         if (!sipResponse.getCSeq().getMethod().equals(this.getMethod())) {
1248             throw new SipException(
1249                     "CSeq method does not match Request method of request that created the tx.");
1250         }
1251 
1252         /*
1253          * 200-class responses to SUBSCRIBE requests also MUST contain an "Expires" header. The
1254          * period of time in the response MAY be shorter but MUST NOT be longer than specified in
1255          * the request.
1256          */
1257         if (this.getMethod().equals(Request.SUBSCRIBE) && response.getStatusCode() / 100 == 2) {
1258 
1259             if (response.getHeader(ExpiresHeader.NAME) == null) {
1260                 throw new SipException("Expires header is mandatory in 2xx response of SUBSCRIBE");
1261             } else {
1262                 Expires requestExpires = (Expires) this.getOriginalRequest().getExpires();
1263                 Expires responseExpires = (Expires) response.getExpires();
1264                 /*
1265                  * If no "Expires" header is present in a SUBSCRIBE request, the implied default
1266                  * is defined by the event package being used.
1267                  */
1268                 if (requestExpires != null
1269                         && responseExpires.getExpires() > requestExpires.getExpires()) {
1270                     throw new SipException(
1271                             "Response Expires time exceeds request Expires time : See RFC 3265 3.1.1");
1272                 }
1273             }
1274 
1275         }
1276 
1277         // Check for mandatory header.
1278         if (sipResponse.getStatusCode() == 200
1279                 && sipResponse.getCSeq().getMethod().equals(Request.INVITE)
1280                 && sipResponse.getHeader(ContactHeader.NAME) == null)
1281             throw new SipException("Contact Header is mandatory for the OK to the INVITE");
1282 
1283         if (!this.isMessagePartOfTransaction((SIPMessage) response)) {
1284             throw new SipException("Response does not belong to this transaction.");
1285         }
1286 
1287         // Fix up the response if the dialog has already been established.
1288         try {
1289             /*
1290              * The UAS MAY send a final response to the initial request before
1291              * having received PRACKs for all unacknowledged reliable provisional responses,
1292              * unless the final response is 2xx and any of the unacknowledged reliable provisional
1293              * responses contained a session description. In that case, it MUST NOT send a final
1294              * response until those provisional responses are acknowledged.
1295              */
1296             if (this.pendingReliableResponse != null
1297                     && this.getDialog() != null
1298                     && this.getState() != TransactionState.TERMINATED
1299                     && ((SIPResponse)response).getContentTypeHeader() != null
1300                     && response.getStatusCode() / 100 == 2
1301                     && ((SIPResponse)response).getContentTypeHeader().getContentType()
1302                             .equalsIgnoreCase("application")
1303                     && ((SIPResponse)response).getContentTypeHeader().getContentSubType()
1304                             .equalsIgnoreCase("sdp")) {
1305                 try {
1306                     boolean acquired = this.provisionalResponseSem.tryAcquire(1,TimeUnit.SECONDS);
1307                     if (!acquired ) {
1308                         throw new SipException("cannot send response -- unacked povisional");
1309                     }
1310                 } catch (Exception ex) {
1311                     this.sipStack.getStackLogger().logError("Could not acquire PRACK sem ", ex);
1312                 }
1313             } else {
1314                 // Sending the final response cancels the
1315                 // pending response task.
1316                 if (this.pendingReliableResponse != null && sipResponse.isFinalResponse()) {
1317                     this.provisionalResponseTask.cancel();
1318                     this.provisionalResponseTask = null;
1319                 }
1320             }
1321 
1322             // Dialog checks. These make sure that the response
1323             // being sent makes sense.
1324             if (dialog != null) {
1325                 if (sipResponse.getStatusCode() / 100 == 2
1326                         && sipStack.isDialogCreated(sipResponse.getCSeq().getMethod())) {
1327                     if (dialog.getLocalTag() == null && sipResponse.getTo().getTag() == null) {
1328                         // Trying to send final response and user forgot to set
1329                         // to
1330                         // tag on the response -- be nice and assign the tag for
1331                         // the user.
1332                         sipResponse.getTo().setTag(Utils.getInstance().generateTag());
1333                     } else if (dialog.getLocalTag() != null && sipResponse.getToTag() == null) {
1334                         sipResponse.setToTag(dialog.getLocalTag());
1335                     } else if (dialog.getLocalTag() != null && sipResponse.getToTag() != null
1336                             && !dialog.getLocalTag().equals(sipResponse.getToTag())) {
1337                         throw new SipException("Tag mismatch dialogTag is "
1338                                 + dialog.getLocalTag() + " responseTag is "
1339                                 + sipResponse.getToTag());
1340                     }
1341                 }
1342 
1343                 if (!sipResponse.getCallId().getCallId().equals(dialog.getCallId().getCallId())) {
1344                     throw new SipException("Dialog mismatch!");
1345                 }
1346             }
1347 
1348 
1349 
1350             // Backward compatibility slippery slope....
1351             // Only set the from tag in the response when the
1352             // incoming request has a from tag.
1353             String fromTag = ((SIPRequest) this.getRequest()).getFrom().getTag();
1354             if (fromTag != null && sipResponse.getFromTag() != null
1355                     && !sipResponse.getFromTag().equals(fromTag)) {
1356                 throw new SipException("From tag of request does not match response from tag");
1357             } else if (fromTag != null) {
1358                 sipResponse.getFrom().setTag(fromTag);
1359             } else {
1360                 if (sipStack.isLoggingEnabled())
1361                     sipStack.getStackLogger().logDebug("WARNING -- Null From tag in request!!");
1362             }
1363 
1364 
1365 
1366             // See if the dialog needs to be inserted into the dialog table
1367             // or if the state of the dialog needs to be changed.
1368             if (dialog != null && response.getStatusCode() != 100) {
1369                 dialog.setResponseTags(sipResponse);
1370                 DialogState oldState = dialog.getState();
1371                 dialog.setLastResponse(this, (SIPResponse) response);
1372                 if (oldState == null && dialog.getState() == DialogState.TERMINATED) {
1373                     DialogTerminatedEvent event = new DialogTerminatedEvent(dialog
1374                             .getSipProvider(), dialog);
1375 
1376                     // Provide notification to the listener that the dialog has
1377                     // ended.
1378                     dialog.getSipProvider().handleEvent(event, this);
1379 
1380                 }
1381 
1382             } else if (dialog == null && this.getMethod().equals(Request.INVITE)
1383                     && this.retransmissionAlertEnabled
1384                     && this.retransmissionAlertTimerTask == null
1385                     && response.getStatusCode() / 100 == 2) {
1386                 String dialogId = ((SIPResponse) response).getDialogId(true);
1387 
1388                 this.retransmissionAlertTimerTask = new RetransmissionAlertTimerTask(dialogId);
1389                 sipStack.retransmissionAlertTransactions.put(dialogId, this);
1390                 sipStack.getTimer().schedule(this.retransmissionAlertTimerTask, 0,
1391                         SIPTransactionStack.BASE_TIMER_INTERVAL);
1392 
1393             }
1394 
1395             // Send message after possibly inserting the Dialog
1396             // into the dialog table to avoid a possible race condition.
1397 
1398             this.sendMessage((SIPResponse) response);
1399 
1400             if ( dialog != null ) {
1401                 dialog.startRetransmitTimer(this, (SIPResponse)response);
1402             }
1403 
1404         } catch (IOException ex) {
1405             if (sipStack.isLoggingEnabled())
1406                 sipStack.getStackLogger().logException(ex);
1407             this.setState(TransactionState.TERMINATED);
1408             raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
1409             throw new SipException(ex.getMessage());
1410         } catch (java.text.ParseException ex1) {
1411             if (sipStack.isLoggingEnabled())
1412                 sipStack.getStackLogger().logException(ex1);
1413             this.setState(TransactionState.TERMINATED);
1414             throw new SipException(ex1.getMessage());
1415         }
1416     }
1417 
1418     /**
1419      * Return the book-keeping information that we actually use.
1420      */
getRealState()1421     private TransactionState getRealState() {
1422         return super.getState();
1423     }
1424 
1425     /**
1426      * Return the current transaction state according to the RFC 3261 transaction state machine.
1427      * Invite transactions do not have a trying state. We just use this as a pseudo state for
1428      * processing requests.
1429      *
1430      * @return the state of the transaction.
1431      */
getState()1432     public TransactionState getState() {
1433         // Trying is a pseudo state for INVITE transactions.
1434         if (this.isInviteTransaction() && TransactionState.TRYING == super.getState())
1435             return TransactionState.PROCEEDING;
1436         else
1437             return super.getState();
1438     }
1439 
1440     /**
1441      * Sets a timeout after which the connection is closed (provided the server does not use the
1442      * connection for outgoing requests in this time period) and calls the superclass to set
1443      * state.
1444      */
setState(TransactionState newState)1445     public void setState(TransactionState newState) {
1446         // Set this timer for connection caching
1447         // of incoming connections.
1448         if (newState == TransactionState.TERMINATED && this.isReliable()
1449                 && (!getSIPStack().cacheServerConnections)) {
1450             // Set a time after which the connection
1451             // is closed.
1452             this.collectionTime = TIMER_J;
1453         }
1454 
1455         super.setState(newState);
1456 
1457     }
1458 
1459     /**
1460      * Start the timer task.
1461      */
startTransactionTimer()1462     protected void startTransactionTimer() {
1463         if (this.transactionTimerStarted.compareAndSet(false, true)) {
1464         	if (sipStack.getTimer() != null) {
1465                 // The timer is set to null when the Stack is
1466                 // shutting down.
1467                 TimerTask myTimer = new TransactionTimer();
1468                 sipStack.getTimer().schedule(myTimer, BASE_TIMER_INTERVAL, BASE_TIMER_INTERVAL);
1469             }
1470         }
1471     }
1472 
equals(Object other)1473     public boolean equals(Object other) {
1474         if (!other.getClass().equals(this.getClass())) {
1475             return false;
1476         }
1477         SIPServerTransaction sst = (SIPServerTransaction) other;
1478         return this.getBranch().equalsIgnoreCase(sst.getBranch());
1479     }
1480 
1481     /*
1482      * (non-Javadoc)
1483      *
1484      * @see gov.nist.javax.sip.stack.SIPTransaction#getDialog()
1485      */
getDialog()1486     public Dialog getDialog() {
1487 
1488         return this.dialog;
1489     }
1490 
1491     /*
1492      * (non-Javadoc)
1493      *
1494      * @see gov.nist.javax.sip.stack.SIPTransaction#setDialog(gov.nist.javax.sip.stack.SIPDialog,
1495      *      gov.nist.javax.sip.message.SIPMessage)
1496      */
setDialog(SIPDialog sipDialog, String dialogId)1497     public void setDialog(SIPDialog sipDialog, String dialogId) {
1498         if (sipStack.isLoggingEnabled())
1499             sipStack.getStackLogger().logDebug("setDialog " + this + " dialog = " + sipDialog);
1500         this.dialog = sipDialog;
1501         if (dialogId != null)
1502             this.dialog.setAssigned();
1503         if (this.retransmissionAlertEnabled && this.retransmissionAlertTimerTask != null) {
1504             this.retransmissionAlertTimerTask.cancel();
1505             if (this.retransmissionAlertTimerTask.dialogId != null) {
1506                 sipStack.retransmissionAlertTransactions
1507                         .remove(this.retransmissionAlertTimerTask.dialogId);
1508             }
1509             this.retransmissionAlertTimerTask = null;
1510         }
1511 
1512         this.retransmissionAlertEnabled = false;
1513 
1514     }
1515 
1516     /*
1517      * (non-Javadoc)
1518      *
1519      * @see javax.sip.Transaction#terminate()
1520      */
terminate()1521     public void terminate() throws ObjectInUseException {
1522         this.setState(TransactionState.TERMINATED);
1523         if (this.retransmissionAlertTimerTask != null) {
1524             this.retransmissionAlertTimerTask.cancel();
1525             if (retransmissionAlertTimerTask.dialogId != null) {
1526                 this.sipStack.retransmissionAlertTransactions
1527                         .remove(retransmissionAlertTimerTask.dialogId);
1528             }
1529             this.retransmissionAlertTimerTask = null;
1530 
1531         }
1532 
1533     }
1534 
sendReliableProvisionalResponse(Response relResponse)1535     protected void sendReliableProvisionalResponse(Response relResponse) throws SipException {
1536 
1537         /*
1538          * After the first reliable provisional response for a request has been acknowledged, the
1539          * UAS MAY send additional reliable provisional responses. The UAS MUST NOT send a second
1540          * reliable provisional response until the first is acknowledged.
1541          */
1542         if (this.pendingReliableResponse != null) {
1543             throw new SipException("Unacknowledged response");
1544 
1545         } else
1546             this.pendingReliableResponse = (SIPResponse) relResponse;
1547         /*
1548          * In addition, it MUST contain a Require header field containing the option tag 100rel,
1549          * and MUST include an RSeq header field.
1550          */
1551         RSeq rseq = (RSeq) relResponse.getHeader(RSeqHeader.NAME);
1552         if (relResponse.getHeader(RSeqHeader.NAME) == null) {
1553             rseq = new RSeq();
1554             relResponse.setHeader(rseq);
1555         }
1556 
1557         try {
1558             this.rseqNumber++;
1559             rseq.setSeqNumber(this.rseqNumber);
1560 
1561             // start the timer task which will retransmit the reliable response
1562             // until the PRACK is received
1563             this.lastResponse = (SIPResponse) relResponse;
1564             if ( this.getDialog() != null ) {
1565                 boolean acquired = this.provisionalResponseSem.tryAcquire(1, TimeUnit.SECONDS);
1566                 if (!acquired) {
1567                     throw new SipException("Unacknowledged response");
1568                 }
1569             }
1570             this.sendMessage((SIPMessage) relResponse);
1571             this.provisionalResponseTask = new ProvisionalResponseTask();
1572             this.sipStack.getTimer().schedule(provisionalResponseTask, 0,
1573                     SIPTransactionStack.BASE_TIMER_INTERVAL);
1574 
1575 
1576         } catch (Exception ex) {
1577             InternalErrorHandler.handleException(ex);
1578         }
1579 
1580     }
1581 
getReliableProvisionalResponse()1582     public SIPResponse getReliableProvisionalResponse() {
1583 
1584         return this.pendingReliableResponse;
1585     }
1586 
1587     /**
1588      * Cancel the retransmit timer for the provisional response task.
1589      *
1590      * @return true if the tx has seen the prack for the first time and false otherwise.
1591      *
1592      */
prackRecieved()1593     public boolean prackRecieved() {
1594 
1595         if (this.pendingReliableResponse == null)
1596             return false;
1597         if(provisionalResponseTask != null)
1598         	this.provisionalResponseTask.cancel();
1599         this.pendingReliableResponse = null;
1600         this.provisionalResponseSem.release();
1601         return true;
1602     }
1603 
1604     /*
1605      * (non-Javadoc)
1606      *
1607      * @see javax.sip.ServerTransaction#enableRetransmissionAlerts()
1608      */
1609 
enableRetransmissionAlerts()1610     public void enableRetransmissionAlerts() throws SipException {
1611         if (this.getDialog() != null)
1612             throw new SipException("Dialog associated with tx");
1613 
1614         else if (!this.getMethod().equals(Request.INVITE))
1615             throw new SipException("Request Method must be INVITE");
1616 
1617         this.retransmissionAlertEnabled = true;
1618 
1619     }
1620 
isRetransmissionAlertEnabled()1621     public boolean isRetransmissionAlertEnabled() {
1622         return this.retransmissionAlertEnabled;
1623     }
1624 
1625     /**
1626      * Disable retransmission Alerts and cancel associated timers.
1627      *
1628      */
disableRetransmissionAlerts()1629     public void disableRetransmissionAlerts() {
1630         if (this.retransmissionAlertTimerTask != null && this.retransmissionAlertEnabled) {
1631             this.retransmissionAlertTimerTask.cancel();
1632             this.retransmissionAlertEnabled = false;
1633 
1634             String dialogId = this.retransmissionAlertTimerTask.dialogId;
1635             if (dialogId != null) {
1636                 sipStack.retransmissionAlertTransactions.remove(dialogId);
1637             }
1638             this.retransmissionAlertTimerTask = null;
1639         }
1640     }
1641 
1642     /**
1643      * This is book-keeping for retransmission filter management.
1644      */
setAckSeen()1645     public void setAckSeen() {
1646         this.isAckSeen = true;
1647     }
1648 
1649     /**
1650      * This is book-keeping for retransmission filter management.
1651      */
ackSeen()1652     public boolean ackSeen() {
1653         return this.isAckSeen;
1654     }
1655 
setMapped(boolean b)1656     public void setMapped(boolean b) {
1657         this.isMapped = true;
1658 
1659     }
1660 
setPendingSubscribe(SIPClientTransaction pendingSubscribeClientTx)1661     public void setPendingSubscribe(SIPClientTransaction pendingSubscribeClientTx) {
1662         this.pendingSubscribeTransaction = pendingSubscribeClientTx;
1663 
1664     }
1665 
releaseSem()1666     public void releaseSem() {
1667         if (this.pendingSubscribeTransaction != null) {
1668             /*
1669              * When a notify is being processed we take a lock on the subscribe to avoid racing
1670              * with the OK of the subscribe.
1671              */
1672             pendingSubscribeTransaction.releaseSem();
1673         } else if (this.inviteTransaction != null && this.getMethod().equals(Request.CANCEL)) {
1674             /*
1675              * When a CANCEL is being processed we take a nested lock on the associated INVITE
1676              * server tx.
1677              */
1678             this.inviteTransaction.releaseSem();
1679         }
1680         super.releaseSem();
1681     }
1682 
1683     /**
1684      * The INVITE Server Transaction corresponding to a CANCEL Server Transaction.
1685      *
1686      * @param st -- the invite server tx corresponding to the cancel server transaction.
1687      */
setInviteTransaction(SIPServerTransaction st)1688     public void setInviteTransaction(SIPServerTransaction st) {
1689         this.inviteTransaction = st;
1690 
1691     }
1692 
1693     /**
1694      * TODO -- this method has to be added to the api.
1695      *
1696      * @return
1697      */
getCanceledInviteTransaction()1698     public SIPServerTransaction getCanceledInviteTransaction() {
1699         return this.inviteTransaction;
1700     }
1701 
scheduleAckRemoval()1702     public void scheduleAckRemoval() throws IllegalStateException {
1703         if (this.getMethod() == null || !this.getMethod().equals(Request.ACK)) {
1704             throw new IllegalStateException("Method is null[" + (getMethod() == null)
1705                     + "] or method is not ACK[" + this.getMethod() + "]");
1706         }
1707 
1708         this.startTransactionTimer();
1709     }
1710 
1711 }
1712