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 */
26package gov.nist.javax.sip.stack;
27
28import gov.nist.core.InternalErrorHandler;
29import gov.nist.javax.sip.SIPConstants;
30import gov.nist.javax.sip.ServerTransactionExt;
31import gov.nist.javax.sip.SipProviderImpl;
32import gov.nist.javax.sip.Utils;
33import gov.nist.javax.sip.header.Expires;
34import gov.nist.javax.sip.header.ParameterNames;
35import gov.nist.javax.sip.header.RSeq;
36import gov.nist.javax.sip.header.Via;
37import gov.nist.javax.sip.header.ViaList;
38import gov.nist.javax.sip.message.SIPMessage;
39import gov.nist.javax.sip.message.SIPRequest;
40import gov.nist.javax.sip.message.SIPResponse;
41
42import java.io.IOException;
43import java.text.ParseException;
44import java.util.TimerTask;
45import java.util.concurrent.Semaphore;
46import java.util.concurrent.TimeUnit;
47
48import javax.sip.Dialog;
49import javax.sip.DialogState;
50import javax.sip.DialogTerminatedEvent;
51import javax.sip.ObjectInUseException;
52import javax.sip.SipException;
53import javax.sip.Timeout;
54import javax.sip.TimeoutEvent;
55import javax.sip.TransactionState;
56import javax.sip.address.Hop;
57import javax.sip.header.ContactHeader;
58import javax.sip.header.ExpiresHeader;
59import javax.sip.header.RSeqHeader;
60import javax.sip.message.Request;
61import 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 */
173public 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
219        public RetransmissionAlertTimerTask(String dialogId) {
220
221            this.ticks = SIPTransaction.T1;
222            this.ticksLeft = this.ticks;
223        }
224
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
243        public ProvisionalResponseTask() {
244            this.ticks = SIPTransaction.T1;
245            this.ticksLeft = this.ticks;
246        }
247
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
298        ListenerExecutionMaxTimer() {
299        }
300
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
323        protected SendTrying() {
324            if (sipStack.isLoggingEnabled())
325                sipStack.getStackLogger().logDebug("scheduled timer for " + SIPServerTransaction.this);
326
327        }
328
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
355        public TransactionTimer() {
356            if (sipStack.isLoggingEnabled()) {
357                sipStack.getStackLogger().logDebug("TransactionTimer() : " + getTransactionId());
358            }
359
360        }
361
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
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     */
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     */
524    public void setRequestInterface(ServerRequestInterface newRequestOf) {
525
526        requestOf = newRequestOf;
527
528    }
529
530    /**
531     * Returns this transaction.
532     */
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     */
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     */
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     */
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     */
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     */
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
1094    public String getViaHost() {
1095
1096        return getMessageChannel().getViaHost();
1097
1098    }
1099
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     */
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
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     */
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     */
1216    public SIPResponse getLastResponse() {
1217        return this.lastResponse;
1218    }
1219
1220    /**
1221     * Set the original request.
1222     */
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     */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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
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
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     */
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
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
1621    public boolean isRetransmissionAlertEnabled() {
1622        return this.retransmissionAlertEnabled;
1623    }
1624
1625    /**
1626     * Disable retransmission Alerts and cancel associated timers.
1627     *
1628     */
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     */
1645    public void setAckSeen() {
1646        this.isAckSeen = true;
1647    }
1648
1649    /**
1650     * This is book-keeping for retransmission filter management.
1651     */
1652    public boolean ackSeen() {
1653        return this.isAckSeen;
1654    }
1655
1656    public void setMapped(boolean b) {
1657        this.isMapped = true;
1658
1659    }
1660
1661    public void setPendingSubscribe(SIPClientTransaction pendingSubscribeClientTx) {
1662        this.pendingSubscribeTransaction = pendingSubscribeClientTx;
1663
1664    }
1665
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     */
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     */
1698    public SIPServerTransaction getCanceledInviteTransaction() {
1699        return this.inviteTransaction;
1700    }
1701
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