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.SipProviderImpl;
31import gov.nist.javax.sip.header.CallID;
32import gov.nist.javax.sip.header.Event;
33import gov.nist.javax.sip.header.From;
34import gov.nist.javax.sip.header.To;
35import gov.nist.javax.sip.header.Via;
36import gov.nist.javax.sip.header.ViaList;
37import gov.nist.javax.sip.message.SIPMessage;
38import gov.nist.javax.sip.message.SIPRequest;
39import gov.nist.javax.sip.message.SIPResponse;
40
41import java.io.IOException;
42import java.net.InetAddress;
43import java.util.Collections;
44import java.util.HashSet;
45import java.util.Iterator;
46import java.util.Set;
47import java.util.concurrent.Semaphore;
48import java.util.concurrent.TimeUnit;
49import java.util.concurrent.atomic.AtomicBoolean;
50
51import javax.net.ssl.SSLPeerUnverifiedException;
52import javax.sip.Dialog;
53import javax.sip.IOExceptionEvent;
54import javax.sip.ServerTransaction;
55import javax.sip.TransactionState;
56import javax.sip.message.Request;
57import javax.sip.message.Response;
58
59/*
60 * Modifications for TLS Support added by Daniel J. Martinez Manzano
61 * <dani@dif.um.es> Bug fixes by Jeroen van Bemmel (JvB) and others.
62 */
63
64/**
65 * Abstract class to support both client and server transactions. Provides an
66 * encapsulation of a message channel, handles timer events, and creation of the
67 * Via header for a message.
68 *
69 * @author Jeff Keyser
70 * @author M. Ranganathan
71 *
72 *
73 * @version 1.2 $Revision: 1.71 $ $Date: 2009/11/29 04:31:29 $
74 */
75public abstract class SIPTransaction extends MessageChannel implements
76        javax.sip.Transaction, gov.nist.javax.sip.TransactionExt {
77
78    protected boolean toListener; // Flag to indicate that the listener gets
79
80    // to see the event.
81
82    protected int BASE_TIMER_INTERVAL = SIPTransactionStack.BASE_TIMER_INTERVAL;
83    /**
84     * 5 sec Maximum duration a message will remain in the network
85     */
86    protected int T4 = 5000 / BASE_TIMER_INTERVAL;
87
88    /**
89     * The maximum retransmit interval for non-INVITE requests and INVITE
90     * responses
91     */
92    protected int T2 = 4000 / BASE_TIMER_INTERVAL;
93    protected int TIMER_I = T4;
94
95    protected int TIMER_K = T4;
96
97    protected int TIMER_D = 32000 / BASE_TIMER_INTERVAL;
98
99    // protected static final int TIMER_C = 3 * 60 * 1000 / BASE_TIMER_INTERVAL;
100
101    /**
102     * One timer tick.
103     */
104    protected static final int T1 = 1;
105
106    /**
107     * INVITE request retransmit interval, for UDP only
108     */
109    protected static final int TIMER_A = 1;
110
111    /**
112     * INVITE transaction timeout timer
113     */
114    protected static final int TIMER_B = 64;
115
116    protected static final int TIMER_J = 64;
117
118    protected static final int TIMER_F = 64;
119
120    protected static final int TIMER_H = 64;
121
122    // Proposed feature for next release.
123    protected transient Object applicationData;
124
125    protected SIPResponse lastResponse;
126
127    // private SIPDialog dialog;
128
129    protected boolean isMapped;
130
131    private Semaphore semaphore;
132
133    protected boolean isSemaphoreAquired;
134
135    // protected boolean eventPending; // indicate that an event is pending
136    // here.
137
138    protected String transactionId; // Transaction Id.
139
140    // Audit tag used by the SIP Stack audit
141    public long auditTag = 0;
142
143    /**
144     * Initialized but no state assigned.
145     */
146    public static final TransactionState INITIAL_STATE = null;
147
148    /**
149     * Trying state.
150     */
151    public static final TransactionState TRYING_STATE = TransactionState.TRYING;
152
153    /**
154     * CALLING State.
155     */
156    public static final TransactionState CALLING_STATE = TransactionState.CALLING;
157
158    /**
159     * Proceeding state.
160     */
161    public static final TransactionState PROCEEDING_STATE = TransactionState.PROCEEDING;
162
163    /**
164     * Completed state.
165     */
166    public static final TransactionState COMPLETED_STATE = TransactionState.COMPLETED;
167
168    /**
169     * Confirmed state.
170     */
171    public static final TransactionState CONFIRMED_STATE = TransactionState.CONFIRMED;
172
173    /**
174     * Terminated state.
175     */
176    public static final TransactionState TERMINATED_STATE = TransactionState.TERMINATED;
177
178    /**
179     * Maximum number of ticks between retransmissions.
180     */
181    protected static final int MAXIMUM_RETRANSMISSION_TICK_COUNT = 8;
182
183    // Parent stack for this transaction
184    protected transient SIPTransactionStack sipStack;
185
186    // Original request that is being handled by this transaction
187    protected SIPRequest originalRequest;
188
189    // Underlying channel being used to send messages for this transaction
190    private transient MessageChannel encapsulatedChannel;
191
192    // Port of peer
193    protected int peerPort;
194
195    // Address of peer
196    protected InetAddress peerInetAddress;
197
198    // Address of peer as a string
199    protected String peerAddress;
200
201    // Protocol of peer
202    protected String peerProtocol;
203
204    // @@@ hagai - NAT changes
205    // Source port extracted from peer packet
206    protected int peerPacketSourcePort;
207
208    protected InetAddress peerPacketSourceAddress;
209
210    protected AtomicBoolean transactionTimerStarted = new AtomicBoolean(false);
211
212    // Transaction branch ID
213    private String branch;
214
215    // Method of the Request used to create the transaction.
216    private String method;
217
218    // Sequence number of request used to create the transaction
219    private long cSeq;
220
221    // Current transaction state
222    private TransactionState currentState;
223
224    // Number of ticks the retransmission timer was set to last
225    private transient int retransmissionTimerLastTickCount;
226
227    // Number of ticks before the message is retransmitted
228    private transient int retransmissionTimerTicksLeft;
229
230    // Number of ticks before the transaction times out
231    protected int timeoutTimerTicksLeft;
232
233    // List of event listeners for this transaction
234    private transient Set<SIPTransactionEventListener> eventListeners;
235
236    // Hang on to these - we clear out the request URI after
237    // transaction goes to final state. Pointers to these are kept around
238    // for transaction matching as long as the transaction is in
239    // the transaction table.
240    protected From from;
241
242    protected To to;
243
244    protected Event event;
245
246    protected CallID callId;
247
248    // Back ptr to the JAIN layer.
249    // private Object wrapper;
250
251    // Counter for caching of connections.
252    // Connection lingers for collectionTime
253    // after the Transaction goes to terminated state.
254    protected int collectionTime;
255
256    protected String toTag;
257
258    protected String fromTag;
259
260    private boolean terminatedEventDelivered;
261
262    public String getBranchId() {
263        return this.branch;
264    }
265
266    /**
267     * The linger timer is used to remove the transaction from the transaction
268     * table after it goes into terminated state. This allows connection caching
269     * and also takes care of race conditins.
270     *
271     *
272     */
273    class LingerTimer extends SIPStackTimerTask {
274
275        public LingerTimer() {
276            SIPTransaction sipTransaction = SIPTransaction.this;
277            if (sipStack.isLoggingEnabled()) {
278                sipStack.getStackLogger().logDebug("LingerTimer : "
279                        + sipTransaction.getTransactionId());
280            }
281
282        }
283
284        protected void runTask() {
285            SIPTransaction transaction = SIPTransaction.this;
286            // release the connection associated with this transaction.
287            SIPTransactionStack sipStack = transaction.getSIPStack();
288
289            if (sipStack.isLoggingEnabled()) {
290                sipStack.getStackLogger().logDebug("LingerTimer: run() : "
291                        + getTransactionId());
292            }
293
294            if (transaction instanceof SIPClientTransaction) {
295                sipStack.removeTransaction(transaction);
296                transaction.close();
297
298            } else if (transaction instanceof ServerTransaction) {
299                // Remove it from the set
300                if (sipStack.isLoggingEnabled())
301                    sipStack.getStackLogger().logDebug("removing" + transaction);
302                sipStack.removeTransaction(transaction);
303                if ((!sipStack.cacheServerConnections)
304                        && --transaction.encapsulatedChannel.useCount <= 0) {
305                    // Close the encapsulated socket if stack is configured
306                    transaction.close();
307                } else {
308                    if (sipStack.isLoggingEnabled()
309                            && (!sipStack.cacheServerConnections)
310                            && transaction.isReliable()) {
311                        int useCount = transaction.encapsulatedChannel.useCount;
312                        sipStack.getStackLogger().logDebug("Use Count = " + useCount);
313                    }
314                }
315            }
316
317        }
318    }
319
320    /**
321     * Transaction constructor.
322     *
323     * @param newParentStack
324     *            Parent stack for this transaction.
325     * @param newEncapsulatedChannel
326     *            Underlying channel for this transaction.
327     */
328    protected SIPTransaction(SIPTransactionStack newParentStack,
329            MessageChannel newEncapsulatedChannel) {
330
331        sipStack = newParentStack;
332        this.semaphore = new Semaphore(1,true);
333
334        encapsulatedChannel = newEncapsulatedChannel;
335        // Record this to check if the address has changed before sending
336        // message to avoid possible race condition.
337        this.peerPort = newEncapsulatedChannel.getPeerPort();
338        this.peerAddress = newEncapsulatedChannel.getPeerAddress();
339        this.peerInetAddress = newEncapsulatedChannel.getPeerInetAddress();
340        // @@@ hagai
341        this.peerPacketSourcePort = newEncapsulatedChannel
342                .getPeerPacketSourcePort();
343        this.peerPacketSourceAddress = newEncapsulatedChannel
344                .getPeerPacketSourceAddress();
345        this.peerProtocol = newEncapsulatedChannel.getPeerProtocol();
346        if (this.isReliable()) {
347                encapsulatedChannel.useCount++;
348                if (sipStack.isLoggingEnabled())
349                    sipStack.getStackLogger()
350                            .logDebug("use count for encapsulated channel"
351                                    + this
352                                    + " "
353                                    + encapsulatedChannel.useCount );
354        }
355
356        this.currentState = null;
357
358        disableRetransmissionTimer();
359        disableTimeoutTimer();
360        eventListeners = Collections.synchronizedSet(new HashSet<SIPTransactionEventListener>());
361
362        // Always add the parent stack as a listener
363        // of this transaction
364        addEventListener(newParentStack);
365
366    }
367
368    /**
369     * Sets the request message that this transaction handles.
370     *
371     * @param newOriginalRequest
372     *            Request being handled.
373     */
374    public void setOriginalRequest(SIPRequest newOriginalRequest) {
375
376        // Branch value of topmost Via header
377        String newBranch;
378
379        if (this.originalRequest != null
380                && (!this.originalRequest.getTransactionId().equals(
381                        newOriginalRequest.getTransactionId()))) {
382            sipStack.removeTransactionHash(this);
383        }
384        // This will be cleared later.
385
386        this.originalRequest = newOriginalRequest;
387
388        // just cache the control information so the
389        // original request can be released later.
390        this.method = newOriginalRequest.getMethod();
391        this.from = (From) newOriginalRequest.getFrom();
392        this.to = (To) newOriginalRequest.getTo();
393        // Save these to avoid concurrent modification exceptions!
394        this.toTag = this.to.getTag();
395        this.fromTag = this.from.getTag();
396        this.callId = (CallID) newOriginalRequest.getCallId();
397        this.cSeq = newOriginalRequest.getCSeq().getSeqNumber();
398        this.event = (Event) newOriginalRequest.getHeader("Event");
399        this.transactionId = newOriginalRequest.getTransactionId();
400
401        originalRequest.setTransaction(this);
402
403        // If the message has an explicit branch value set,
404        newBranch = ((Via) newOriginalRequest.getViaHeaders().getFirst())
405                .getBranch();
406        if (newBranch != null) {
407            if (sipStack.isLoggingEnabled())
408                sipStack.getStackLogger().logDebug("Setting Branch id : " + newBranch);
409
410            // Override the default branch with the one
411            // set by the message
412            setBranch(newBranch);
413
414        } else {
415            if (sipStack.isLoggingEnabled())
416                sipStack.getStackLogger().logDebug("Branch id is null - compute TID!"
417                        + newOriginalRequest.encode());
418            setBranch(newOriginalRequest.getTransactionId());
419        }
420    }
421
422    /**
423     * Gets the request being handled by this transaction.
424     *
425     * @return -- the original Request associated with this transaction.
426     */
427    public SIPRequest getOriginalRequest() {
428        return originalRequest;
429    }
430
431    /**
432     * Get the original request but cast to a Request structure.
433     *
434     * @return the request that generated this transaction.
435     */
436    public Request getRequest() {
437        return (Request) originalRequest;
438    }
439
440    /**
441     * Returns a flag stating whether this transaction is for an INVITE request
442     * or not.
443     *
444     * @return -- true if this is an INVITE request, false if not.
445     */
446    public final boolean isInviteTransaction() {
447        return getMethod().equals(Request.INVITE);
448    }
449
450    /**
451     * Return true if the transaction corresponds to a CANCEL message.
452     *
453     * @return -- true if the transaciton is a CANCEL transaction.
454     */
455    public final boolean isCancelTransaction() {
456        return getMethod().equals(Request.CANCEL);
457    }
458
459    /**
460     * Return a flag that states if this is a BYE transaction.
461     *
462     * @return true if the transaciton is a BYE transaction.
463     */
464    public final boolean isByeTransaction() {
465        return getMethod().equals(Request.BYE);
466    }
467
468    /**
469     * Returns the message channel used for transmitting/receiving messages for
470     * this transaction. Made public in support of JAIN dual transaction model.
471     *
472     * @return Encapsulated MessageChannel.
473     *
474     */
475    public MessageChannel getMessageChannel() {
476        return encapsulatedChannel;
477    }
478
479    /**
480     * Sets the Via header branch parameter used to identify this transaction.
481     *
482     * @param newBranch
483     *            New string used as the branch for this transaction.
484     */
485    public final void setBranch(String newBranch) {
486        branch = newBranch;
487    }
488
489    /**
490     * Gets the current setting for the branch parameter of this transaction.
491     *
492     * @return Branch parameter for this transaction.
493     */
494    public final String getBranch() {
495        if (this.branch == null) {
496            this.branch = getOriginalRequest().getTopmostVia().getBranch();
497        }
498        return branch;
499    }
500
501    /**
502     * Get the method of the request used to create this transaction.
503     *
504     * @return the method of the request for the transaction.
505     */
506    public final String getMethod() {
507        return this.method;
508    }
509
510    /**
511     * Get the Sequence number of the request used to create the transaction.
512     *
513     * @return the cseq of the request used to create the transaction.
514     */
515    public final long getCSeq() {
516        return this.cSeq;
517    }
518
519    /**
520     * Changes the state of this transaction.
521     *
522     * @param newState
523     *            New state of this transaction.
524     */
525    public void setState(TransactionState newState) {
526        // PATCH submitted by sribeyron
527        if (currentState == TransactionState.COMPLETED) {
528            if (newState != TransactionState.TERMINATED
529                    && newState != TransactionState.CONFIRMED)
530                newState = TransactionState.COMPLETED;
531        }
532        if (currentState == TransactionState.CONFIRMED) {
533            if (newState != TransactionState.TERMINATED)
534                newState = TransactionState.CONFIRMED;
535        }
536        if (currentState != TransactionState.TERMINATED)
537            currentState = newState;
538        else
539            newState = currentState;
540        // END OF PATCH
541        if (sipStack.isLoggingEnabled()) {
542            sipStack.getStackLogger().logDebug("Transaction:setState " + newState
543                    + " " + this + " branchID = " + this.getBranch()
544                    + " isClient = " + (this instanceof SIPClientTransaction));
545            sipStack.getStackLogger().logStackTrace();
546        }
547    }
548
549    /**
550     * Gets the current state of this transaction.
551     *
552     * @return Current state of this transaction.
553     */
554    public TransactionState getState() {
555        return this.currentState;
556    }
557
558    /**
559     * Enables retransmission timer events for this transaction to begin in one
560     * tick.
561     */
562    protected final void enableRetransmissionTimer() {
563        enableRetransmissionTimer(1);
564    }
565
566    /**
567     * Enables retransmission timer events for this transaction to begin after
568     * the number of ticks passed to this routine.
569     *
570     * @param tickCount
571     *            Number of ticks before the next retransmission timer event
572     *            occurs.
573     */
574    protected final void enableRetransmissionTimer(int tickCount) {
575        // For INVITE Client transactions, double interval each time
576        if (isInviteTransaction() && (this instanceof SIPClientTransaction)) {
577            retransmissionTimerTicksLeft = tickCount;
578        } else {
579            // non-INVITE transactions and 3xx-6xx responses are capped at T2
580            retransmissionTimerTicksLeft = Math.min(tickCount,
581                    MAXIMUM_RETRANSMISSION_TICK_COUNT);
582        }
583        retransmissionTimerLastTickCount = retransmissionTimerTicksLeft;
584    }
585
586    /**
587     * Turns off retransmission events for this transaction.
588     */
589    protected final void disableRetransmissionTimer() {
590        retransmissionTimerTicksLeft = -1;
591    }
592
593    /**
594     * Enables a timeout event to occur for this transaction after the number of
595     * ticks passed to this method.
596     *
597     * @param tickCount
598     *            Number of ticks before this transaction times out.
599     */
600    protected final void enableTimeoutTimer(int tickCount) {
601        if (sipStack.isLoggingEnabled())
602            sipStack.getStackLogger().logDebug("enableTimeoutTimer " + this
603                    + " tickCount " + tickCount + " currentTickCount = "
604                    + timeoutTimerTicksLeft);
605
606        timeoutTimerTicksLeft = tickCount;
607    }
608
609    /**
610     * Disabled the timeout timer.
611     */
612    protected final void disableTimeoutTimer() {
613        timeoutTimerTicksLeft = -1;
614    }
615
616    /**
617     * Fired after each timer tick. Checks the retransmission and timeout timers
618     * of this transaction, and fired these events if necessary.
619     */
620    final void fireTimer() {
621        // If the timeout timer is enabled,
622
623        if (timeoutTimerTicksLeft != -1) {
624            // Count down the timer, and if it has run out,
625            if (--timeoutTimerTicksLeft == 0) {
626                // Fire the timeout timer
627                fireTimeoutTimer();
628            }
629        }
630
631        // If the retransmission timer is enabled,
632        if (retransmissionTimerTicksLeft != -1) {
633            // Count down the timer, and if it has run out,
634            if (--retransmissionTimerTicksLeft == 0) {
635                // Enable this timer to fire again after
636                // twice the original time
637                enableRetransmissionTimer(retransmissionTimerLastTickCount * 2);
638                // Fire the timeout timer
639                fireRetransmissionTimer();
640            }
641        }
642    }
643
644    /**
645     * Tests if this transaction has terminated.
646     *
647     * @return Trus if this transaction is terminated, false if not.
648     */
649    public final boolean isTerminated() {
650        return getState() == TERMINATED_STATE;
651    }
652
653    public String getHost() {
654        return encapsulatedChannel.getHost();
655    }
656
657    public String getKey() {
658        return encapsulatedChannel.getKey();
659    }
660
661    public int getPort() {
662        return encapsulatedChannel.getPort();
663    }
664
665    public SIPTransactionStack getSIPStack() {
666        return (SIPTransactionStack) sipStack;
667    }
668
669    public String getPeerAddress() {
670        return this.peerAddress;
671    }
672
673    public int getPeerPort() {
674        return this.peerPort;
675    }
676
677    // @@@ hagai
678    public int getPeerPacketSourcePort() {
679        return this.peerPacketSourcePort;
680    }
681
682    public InetAddress getPeerPacketSourceAddress() {
683        return this.peerPacketSourceAddress;
684    }
685
686    protected InetAddress getPeerInetAddress() {
687        return this.peerInetAddress;
688    }
689
690    protected String getPeerProtocol() {
691        return this.peerProtocol;
692    }
693
694    public String getTransport() {
695        return encapsulatedChannel.getTransport();
696    }
697
698    public boolean isReliable() {
699        return encapsulatedChannel.isReliable();
700    }
701
702    /**
703     * Returns the Via header for this channel. Gets the Via header of the
704     * underlying message channel, and adds a branch parameter to it for this
705     * transaction.
706     */
707    public Via getViaHeader() {
708        // Via header of the encapulated channel
709        Via channelViaHeader;
710
711        // Add the branch parameter to the underlying
712        // channel's Via header
713        channelViaHeader = super.getViaHeader();
714        try {
715            channelViaHeader.setBranch(branch);
716        } catch (java.text.ParseException ex) {
717        }
718        return channelViaHeader;
719
720    }
721
722    /**
723     * Process the message through the transaction and sends it to the SIP peer.
724     *
725     * @param messageToSend
726     *            Message to send to the SIP peer.
727     */
728    public void sendMessage(SIPMessage messageToSend) throws IOException {
729        // Use the peer address, port and transport
730        // that was specified when the transaction was
731        // created. Bug was noted by Bruce Evangelder
732        // soleo communications.
733        try {
734            encapsulatedChannel.sendMessage(messageToSend,
735                    this.peerInetAddress, this.peerPort);
736        } finally {
737            this.startTransactionTimer();
738        }
739    }
740
741    /**
742     * Parse the byte array as a message, process it through the transaction,
743     * and send it to the SIP peer. This is just a placeholder method -- calling
744     * it will result in an IO exception.
745     *
746     * @param messageBytes
747     *            Bytes of the message to send.
748     * @param receiverAddress
749     *            Address of the target peer.
750     * @param receiverPort
751     *            Network port of the target peer.
752     *
753     * @throws IOException
754     *             If called.
755     */
756    protected void sendMessage(byte[] messageBytes,
757            InetAddress receiverAddress, int receiverPort, boolean retry)
758            throws IOException {
759        throw new IOException(
760                "Cannot send unparsed message through Transaction Channel!");
761    }
762
763    /**
764     * Adds a new event listener to this transaction.
765     *
766     * @param newListener
767     *            Listener to add.
768     */
769    public void addEventListener(SIPTransactionEventListener newListener) {
770        eventListeners.add(newListener);
771    }
772
773    /**
774     * Removed an event listener from this transaction.
775     *
776     * @param oldListener
777     *            Listener to remove.
778     */
779    public void removeEventListener(SIPTransactionEventListener oldListener) {
780        eventListeners.remove(oldListener);
781    }
782
783    /**
784     * Creates a SIPTransactionErrorEvent and sends it to all of the listeners
785     * of this transaction. This method also flags the transaction as
786     * terminated.
787     *
788     * @param errorEventID
789     *            ID of the error to raise.
790     */
791    protected void raiseErrorEvent(int errorEventID) {
792
793        // Error event to send to all listeners
794        SIPTransactionErrorEvent newErrorEvent;
795        // Iterator through the list of listeners
796        Iterator<SIPTransactionEventListener> listenerIterator;
797        // Next listener in the list
798        SIPTransactionEventListener nextListener;
799
800        // Create the error event
801        newErrorEvent = new SIPTransactionErrorEvent(this, errorEventID);
802
803        // Loop through all listeners of this transaction
804        synchronized (eventListeners) {
805            listenerIterator = eventListeners.iterator();
806            while (listenerIterator.hasNext()) {
807                // Send the event to the next listener
808                nextListener = (SIPTransactionEventListener) listenerIterator
809                        .next();
810                nextListener.transactionErrorEvent(newErrorEvent);
811            }
812        }
813        // Clear the event listeners after propagating the error.
814        // Retransmit notifications are just an alert to the
815        // application (they are not an error).
816        if (errorEventID != SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) {
817            eventListeners.clear();
818
819            // Errors always terminate a transaction
820            this.setState(TransactionState.TERMINATED);
821
822            if (this instanceof SIPServerTransaction && this.isByeTransaction()
823                    && this.getDialog() != null)
824                ((SIPDialog) this.getDialog())
825                        .setState(SIPDialog.TERMINATED_STATE);
826        }
827    }
828
829    /**
830     * A shortcut way of telling if we are a server transaction.
831     */
832    protected boolean isServerTransaction() {
833        return this instanceof SIPServerTransaction;
834    }
835
836    /**
837     * Gets the dialog object of this Transaction object. This object returns
838     * null if no dialog exists. A dialog only exists for a transaction when a
839     * session is setup between a User Agent Client and a User Agent Server,
840     * either by a 1xx Provisional Response for an early dialog or a 200OK
841     * Response for a committed dialog.
842     *
843     * @return the Dialog Object of this Transaction object.
844     * @see Dialog
845     */
846    public abstract Dialog getDialog();
847
848    /**
849     * set the dialog object.
850     *
851     * @param sipDialog --
852     *            the dialog to set.
853     * @param dialogId --
854     *            the dialog id ot associate with the dialog.s
855     */
856    public abstract void setDialog(SIPDialog sipDialog, String dialogId);
857
858    /**
859     * Returns the current value of the retransmit timer in milliseconds used to
860     * retransmit messages over unreliable transports.
861     *
862     * @return the integer value of the retransmit timer in milliseconds.
863     */
864    public int getRetransmitTimer() {
865        return SIPTransactionStack.BASE_TIMER_INTERVAL;
866    }
867
868    /**
869     * Get the host to assign for an outgoing Request via header.
870     */
871    public String getViaHost() {
872        return this.getViaHeader().getHost();
873
874    }
875
876    /**
877     * Get the last response. This is used internally by the implementation.
878     * Dont rely on it.
879     *
880     * @return the last response received (for client transactions) or sent (for
881     *         server transactions).
882     */
883    public SIPResponse getLastResponse() {
884        return this.lastResponse;
885    }
886
887    /**
888     * Get the JAIN interface response
889     */
890    public Response getResponse() {
891        return (Response) this.lastResponse;
892    }
893
894    /**
895     * Get the transaction Id.
896     */
897    public String getTransactionId() {
898        return this.transactionId;
899    }
900
901    /**
902     * Hashcode method for fast hashtable lookup.
903     */
904    public int hashCode() {
905        if (this.transactionId == null)
906            return -1;
907        else
908            return this.transactionId.hashCode();
909    }
910
911    /**
912     * Get the port to assign for the via header of an outgoing message.
913     */
914    public int getViaPort() {
915        return this.getViaHeader().getPort();
916    }
917
918    /**
919     * A method that can be used to test if an incoming request belongs to this
920     * transction. This does not take the transaction state into account when
921     * doing the check otherwise it is identical to isMessagePartOfTransaction.
922     * This is useful for checking if a CANCEL belongs to this transaction.
923     *
924     * @param requestToTest
925     *            is the request to test.
926     * @return true if the the request belongs to the transaction.
927     *
928     */
929    public boolean doesCancelMatchTransaction(SIPRequest requestToTest) {
930
931        // List of Via headers in the message to test
932        ViaList viaHeaders;
933        // Topmost Via header in the list
934        Via topViaHeader;
935        // Branch code in the topmost Via header
936        String messageBranch;
937        // Flags whether the select message is part of this transaction
938        boolean transactionMatches;
939
940        transactionMatches = false;
941
942        if (this.getOriginalRequest() == null
943                || this.getOriginalRequest().getMethod().equals(Request.CANCEL))
944            return false;
945        // Get the topmost Via header and its branch parameter
946        viaHeaders = requestToTest.getViaHeaders();
947        if (viaHeaders != null) {
948
949            topViaHeader = (Via) viaHeaders.getFirst();
950            messageBranch = topViaHeader.getBranch();
951            if (messageBranch != null) {
952
953                // If the branch parameter exists but
954                // does not start with the magic cookie,
955                if (!messageBranch.toLowerCase().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) {
956
957                    // Flags this as old
958                    // (RFC2543-compatible) client
959                    // version
960                    messageBranch = null;
961
962                }
963
964            }
965
966            // If a new branch parameter exists,
967            if (messageBranch != null && this.getBranch() != null) {
968
969                // If the branch equals the branch in
970                // this message,
971                if (getBranch().equalsIgnoreCase(messageBranch)
972                        && topViaHeader.getSentBy().equals(
973                                ((Via) getOriginalRequest().getViaHeaders()
974                                        .getFirst()).getSentBy())) {
975                    transactionMatches = true;
976                    if (sipStack.isLoggingEnabled())
977                        sipStack.getStackLogger().logDebug("returning  true");
978                }
979
980            } else {
981                // If this is an RFC2543-compliant message,
982                // If RequestURI, To tag, From tag,
983                // CallID, CSeq number, and top Via
984                // headers are the same,
985                if (sipStack.isLoggingEnabled())
986                    sipStack.getStackLogger().logDebug("testing against "
987                            + getOriginalRequest());
988
989                if (getOriginalRequest().getRequestURI().equals(
990                        requestToTest.getRequestURI())
991                        && getOriginalRequest().getTo().equals(
992                                requestToTest.getTo())
993                        && getOriginalRequest().getFrom().equals(
994                                requestToTest.getFrom())
995                        && getOriginalRequest().getCallId().getCallId().equals(
996                                requestToTest.getCallId().getCallId())
997                        && getOriginalRequest().getCSeq().getSeqNumber() == requestToTest
998                                .getCSeq().getSeqNumber()
999                        && topViaHeader.equals(getOriginalRequest()
1000                                .getViaHeaders().getFirst())) {
1001
1002                    transactionMatches = true;
1003                }
1004
1005            }
1006
1007        }
1008
1009        // JvB: Need to pass the CANCEL to the listener! Retransmitted INVITEs
1010        // set it to false
1011        if (transactionMatches) {
1012            this.setPassToListener();
1013        }
1014        return transactionMatches;
1015    }
1016
1017    /**
1018     * Sets the value of the retransmit timer to the newly supplied timer value.
1019     * The retransmit timer is expressed in milliseconds and its default value
1020     * is 500ms. This method allows the application to change the transaction
1021     * retransmit behavior for different networks. Take the gateway proxy as an
1022     * example. The internal intranet is likely to be reatively uncongested and
1023     * the endpoints will be relatively close. The external network is the
1024     * general Internet. This functionality allows different retransmit times
1025     * for either side.
1026     *
1027     * @param retransmitTimer -
1028     *            the new integer value of the retransmit timer in milliseconds.
1029     */
1030    public void setRetransmitTimer(int retransmitTimer) {
1031
1032        if (retransmitTimer <= 0)
1033            throw new IllegalArgumentException(
1034                    "Retransmit timer must be positive!");
1035        if (this.transactionTimerStarted.get())
1036            throw new IllegalStateException(
1037                    "Transaction timer is already started");
1038        BASE_TIMER_INTERVAL = retransmitTimer;
1039        T4 = 5000 / BASE_TIMER_INTERVAL;
1040
1041        T2 = 4000 / BASE_TIMER_INTERVAL;
1042        TIMER_I = T4;
1043
1044        TIMER_K = T4;
1045
1046        TIMER_D = 32000 / BASE_TIMER_INTERVAL;
1047
1048    }
1049
1050    /**
1051     * Close the encapsulated channel.
1052     */
1053    public void close() {
1054        this.encapsulatedChannel.close();
1055        if (sipStack.isLoggingEnabled())
1056            sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel);
1057
1058    }
1059
1060    public boolean isSecure() {
1061        return encapsulatedChannel.isSecure();
1062    }
1063
1064    public MessageProcessor getMessageProcessor() {
1065        return this.encapsulatedChannel.getMessageProcessor();
1066    }
1067
1068    /**
1069     * Set the application data pointer. This is un-interpreted by the stack.
1070     * This is provided as a conveniant way of keeping book-keeping data for
1071     * applications. Note that null clears the application data pointer
1072     * (releases it).
1073     *
1074     * @param applicationData --
1075     *            application data pointer to set. null clears the applicationd
1076     *            data pointer.
1077     *
1078     */
1079
1080    public void setApplicationData(Object applicationData) {
1081        this.applicationData = applicationData;
1082    }
1083
1084    /**
1085     * Get the application data associated with this transaction.
1086     *
1087     * @return stored application data.
1088     */
1089    public Object getApplicationData() {
1090        return this.applicationData;
1091    }
1092
1093    /**
1094     * Set the encapsuated channel. The peer inet address and port are set equal
1095     * to the message channel.
1096     */
1097    public void setEncapsulatedChannel(MessageChannel messageChannel) {
1098        this.encapsulatedChannel = messageChannel;
1099        this.peerInetAddress = messageChannel.getPeerInetAddress();
1100        this.peerPort = messageChannel.getPeerPort();
1101    }
1102
1103    /**
1104     * Return the SipProvider for which the transaction is assigned.
1105     *
1106     * @return the SipProvider for the transaction.
1107     */
1108    public SipProviderImpl getSipProvider() {
1109
1110        return this.getMessageProcessor().getListeningPoint().getProvider();
1111    }
1112
1113    /**
1114     * Raise an IO Exception event - this is used for reporting asynchronous IO
1115     * Exceptions that are attributable to this transaction.
1116     *
1117     */
1118    public void raiseIOExceptionEvent() {
1119        setState(TransactionState.TERMINATED);
1120        String host = getPeerAddress();
1121        int port = getPeerPort();
1122        String transport = getTransport();
1123        IOExceptionEvent exceptionEvent = new IOExceptionEvent(this, host,
1124                port, transport);
1125        getSipProvider().handleEvent(exceptionEvent, this);
1126    }
1127
1128    /**
1129     * A given tx can process only a single outstanding event at a time. This
1130     * semaphore gaurds re-entrancy to the transaction.
1131     *
1132     */
1133    public boolean acquireSem() {
1134        boolean retval = false;
1135        try {
1136            if (sipStack.getStackLogger().isLoggingEnabled()) {
1137                sipStack.getStackLogger().logDebug("acquireSem [[[[" + this);
1138                sipStack.getStackLogger().logStackTrace();
1139            }
1140            retval = this.semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS);
1141            if ( sipStack.isLoggingEnabled())
1142                sipStack.getStackLogger().logDebug(
1143                    "acquireSem() returning : " + retval);
1144            return retval;
1145        } catch (Exception ex) {
1146            sipStack.getStackLogger().logError("Unexpected exception acquiring sem",
1147                    ex);
1148            InternalErrorHandler.handleException(ex);
1149            return false;
1150        } finally {
1151            this.isSemaphoreAquired = retval;
1152        }
1153
1154    }
1155
1156    /**
1157     * Release the transaction semaphore.
1158     *
1159     */
1160    public void releaseSem() {
1161        try {
1162
1163            this.toListener = false;
1164            this.semRelease();
1165
1166        } catch (Exception ex) {
1167            sipStack.getStackLogger().logError("Unexpected exception releasing sem",
1168                    ex);
1169
1170        }
1171
1172    }
1173
1174    protected void semRelease() {
1175        try {
1176            if (sipStack.isLoggingEnabled()) {
1177                sipStack.getStackLogger().logDebug("semRelease ]]]]" + this);
1178                sipStack.getStackLogger().logStackTrace();
1179            }
1180            this.isSemaphoreAquired = false;
1181            this.semaphore.release();
1182
1183        } catch (Exception ex) {
1184            sipStack.getStackLogger().logError("Unexpected exception releasing sem",
1185                    ex);
1186
1187        }
1188    }
1189
1190    /**
1191     * Set true to pass the request up to the listener. False otherwise.
1192     *
1193     */
1194
1195    public boolean passToListener() {
1196        return toListener;
1197    }
1198
1199    /**
1200     * Set the passToListener flag to true.
1201     */
1202    public void setPassToListener() {
1203        if (sipStack.isLoggingEnabled()) {
1204            sipStack.getStackLogger().logDebug("setPassToListener()");
1205        }
1206        this.toListener = true;
1207
1208    }
1209
1210    /**
1211     * Flag to test if the terminated event is delivered.
1212     *
1213     * @return
1214     */
1215    protected synchronized boolean testAndSetTransactionTerminatedEvent() {
1216        boolean retval = !this.terminatedEventDelivered;
1217        this.terminatedEventDelivered = true;
1218        return retval;
1219    }
1220
1221    public String getCipherSuite() throws UnsupportedOperationException {
1222        if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1223            if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1224                return null;
1225            else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1226                return null;
1227            else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getCipherSuite();
1228        } else throw new UnsupportedOperationException("Not a TLS channel");
1229
1230    }
1231
1232
1233    public java.security.cert.Certificate[] getLocalCertificates() throws UnsupportedOperationException {
1234         if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1235            if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1236                return null;
1237            else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1238                return null;
1239            else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getLocalCertificates();
1240        } else throw new UnsupportedOperationException("Not a TLS channel");
1241    }
1242
1243
1244    public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
1245        if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1246            if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1247                return null;
1248            else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1249                return null;
1250            else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getPeerCertificates();
1251        } else throw new UnsupportedOperationException("Not a TLS channel");
1252
1253    }
1254
1255
1256    /**
1257     * Start the timer that runs the transaction state machine.
1258     *
1259     */
1260
1261    protected abstract void startTransactionTimer();
1262
1263    /**
1264     * Tests a message to see if it is part of this transaction.
1265     *
1266     * @return True if the message is part of this transaction, false if not.
1267     */
1268    public abstract boolean isMessagePartOfTransaction(SIPMessage messageToTest);
1269
1270    /**
1271     * This method is called when this transaction's retransmission timer has
1272     * fired.
1273     */
1274    protected abstract void fireRetransmissionTimer();
1275
1276    /**
1277     * This method is called when this transaction's timeout timer has fired.
1278     */
1279    protected abstract void fireTimeoutTimer();
1280
1281}
1282