1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Conditions Of Use
3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software was developed by employees of the National Institute of
5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Standards and Technology (NIST), an agency of the Federal Government.
6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Pursuant to title 15 Untied States Code Section 105, works of NIST
7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * employees are not subject to copyright protection in the United States
8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * and are considered to be in the public domain.  As a result, a formal
9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * license is not needed to use the software.
10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This software is provided by NIST as a service and is expressly
12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * AND DATA ACCURACY.  NIST does not warrant or make any representations
16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * regarding the use of the software or the results thereof, including but
17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * not limited to the correctness, accuracy, reliability or usefulness of
18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the software.
19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Permission to use this software is contingent upon your acceptance
21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * of the terms of this agreement
22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * .
24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.stack;
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.core.InternalErrorHandler;
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SIPConstants;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SipProviderImpl;
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.CallID;
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Event;
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.From;
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.To;
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.Via;
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.ViaList;
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPMessage;
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest;
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPResponse;
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.io.IOException;
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.net.InetAddress;
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Collections;
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.HashSet;
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator;
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Set;
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.Semaphore;
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.TimeUnit;
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.concurrent.atomic.AtomicBoolean;
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.net.ssl.SSLPeerUnverifiedException;
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.Dialog;
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.IOExceptionEvent;
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ServerTransaction;
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.TransactionState;
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Request;
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Response;
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Modifications for TLS Support added by Daniel J. Martinez Manzano
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * <dani@dif.um.es> Bug fixes by Jeroen van Bemmel (JvB) and others.
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/**
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Abstract class to support both client and server transactions. Provides an
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * encapsulation of a message channel, handles timer events, and creation of the
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Via header for a message.
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author Jeff Keyser
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @version 1.2 $Revision: 1.71 $ $Date: 2009/11/29 04:31:29 $
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic abstract class SIPTransaction extends MessageChannel implements
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        javax.sip.Transaction, gov.nist.javax.sip.TransactionExt {
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected boolean toListener; // Flag to indicate that the listener gets
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // to see the event.
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int BASE_TIMER_INTERVAL = SIPTransactionStack.BASE_TIMER_INTERVAL;
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * 5 sec Maximum duration a message will remain in the network
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int T4 = 5000 / BASE_TIMER_INTERVAL;
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * The maximum retransmit interval for non-INVITE requests and INVITE
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * responses
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int T2 = 4000 / BASE_TIMER_INTERVAL;
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int TIMER_I = T4;
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int TIMER_K = T4;
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int TIMER_D = 32000 / BASE_TIMER_INTERVAL;
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // protected static final int TIMER_C = 3 * 60 * 1000 / BASE_TIMER_INTERVAL;
100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * One timer tick.
103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int T1 = 1;
105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * INVITE request retransmit interval, for UDP only
108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int TIMER_A = 1;
110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * INVITE transaction timeout timer
113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int TIMER_B = 64;
115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int TIMER_J = 64;
117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int TIMER_F = 64;
119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int TIMER_H = 64;
121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Proposed feature for next release.
123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected transient Object applicationData;
124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected SIPResponse lastResponse;
126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // private SIPDialog dialog;
128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected boolean isMapped;
130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private Semaphore semaphore;
132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected boolean isSemaphoreAquired;
134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // protected boolean eventPending; // indicate that an event is pending
136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // here.
137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String transactionId; // Transaction Id.
139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Audit tag used by the SIP Stack audit
141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public long auditTag = 0;
142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Initialized but no state assigned.
145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState INITIAL_STATE = null;
147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Trying state.
150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState TRYING_STATE = TransactionState.TRYING;
152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * CALLING State.
155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState CALLING_STATE = TransactionState.CALLING;
157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Proceeding state.
160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState PROCEEDING_STATE = TransactionState.PROCEEDING;
162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Completed state.
165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState COMPLETED_STATE = TransactionState.COMPLETED;
167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Confirmed state.
170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState CONFIRMED_STATE = TransactionState.CONFIRMED;
172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Terminated state.
175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public static final TransactionState TERMINATED_STATE = TransactionState.TERMINATED;
177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Maximum number of ticks between retransmissions.
180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected static final int MAXIMUM_RETRANSMISSION_TICK_COUNT = 8;
182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Parent stack for this transaction
184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected transient SIPTransactionStack sipStack;
185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Original request that is being handled by this transaction
187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected SIPRequest originalRequest;
188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Underlying channel being used to send messages for this transaction
190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private transient MessageChannel encapsulatedChannel;
191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Port of peer
193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int peerPort;
194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Address of peer
196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected InetAddress peerInetAddress;
197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Address of peer as a string
199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String peerAddress;
200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Protocol of peer
202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String peerProtocol;
203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // @@@ hagai - NAT changes
205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Source port extracted from peer packet
206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int peerPacketSourcePort;
207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected InetAddress peerPacketSourceAddress;
209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected AtomicBoolean transactionTimerStarted = new AtomicBoolean(false);
211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Transaction branch ID
213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private String branch;
214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Method of the Request used to create the transaction.
216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private String method;
217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Sequence number of request used to create the transaction
219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private long cSeq;
220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Current transaction state
222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private TransactionState currentState;
223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Number of ticks the retransmission timer was set to last
225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private transient int retransmissionTimerLastTickCount;
226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Number of ticks before the message is retransmitted
228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private transient int retransmissionTimerTicksLeft;
229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Number of ticks before the transaction times out
231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int timeoutTimerTicksLeft;
232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // List of event listeners for this transaction
234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private transient Set<SIPTransactionEventListener> eventListeners;
235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Hang on to these - we clear out the request URI after
237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // transaction goes to final state. Pointers to these are kept around
238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // for transaction matching as long as the transaction is in
239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // the transaction table.
240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected From from;
241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected To to;
243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected Event event;
245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected CallID callId;
247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Back ptr to the JAIN layer.
249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // private Object wrapper;
250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Counter for caching of connections.
252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // Connection lingers for collectionTime
253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // after the Transaction goes to terminated state.
254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected int collectionTime;
255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String toTag;
257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String fromTag;
259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private boolean terminatedEventDelivered;
261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getBranchId() {
263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.branch;
264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * The linger timer is used to remove the transaction from the transaction
268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * table after it goes into terminated state. This allows connection caching
269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * and also takes care of race conditins.
270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    class LingerTimer extends SIPStackTimerTask {
274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        public LingerTimer() {
276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPTransaction sipTransaction = SIPTransaction.this;
277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("LingerTimer : "
279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        + sipTransaction.getTransactionId());
280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        protected void runTask() {
285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPTransaction transaction = SIPTransaction.this;
286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // release the connection associated with this transaction.
287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPTransactionStack sipStack = transaction.getSIPStack();
288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("LingerTimer: run() : "
291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        + getTransactionId());
292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (transaction instanceof SIPClientTransaction) {
295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.removeTransaction(transaction);
296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                transaction.close();
297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (transaction instanceof ServerTransaction) {
299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Remove it from the set
300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (sipStack.isLoggingEnabled())
301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipStack.getStackLogger().logDebug("removing" + transaction);
302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.removeTransaction(transaction);
303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ((!sipStack.cacheServerConnections)
304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && --transaction.encapsulatedChannel.useCount <= 0) {
305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // Close the encapsulated socket if stack is configured
306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transaction.close();
307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (sipStack.isLoggingEnabled()
309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            && (!sipStack.cacheServerConnections)
310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            && transaction.isReliable()) {
311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        int useCount = transaction.encapsulatedChannel.useCount;
312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sipStack.getStackLogger().logDebug("Use Count = " + useCount);
313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Transaction constructor.
322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param newParentStack
324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Parent stack for this transaction.
325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param newEncapsulatedChannel
326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Underlying channel for this transaction.
327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected SIPTransaction(SIPTransactionStack newParentStack,
329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            MessageChannel newEncapsulatedChannel) {
330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        sipStack = newParentStack;
332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.semaphore = new Semaphore(1,true);
333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        encapsulatedChannel = newEncapsulatedChannel;
335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Record this to check if the address has changed before sending
336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // message to avoid possible race condition.
337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerPort = newEncapsulatedChannel.getPeerPort();
338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerAddress = newEncapsulatedChannel.getPeerAddress();
339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerInetAddress = newEncapsulatedChannel.getPeerInetAddress();
340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // @@@ hagai
341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerPacketSourcePort = newEncapsulatedChannel
342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getPeerPacketSourcePort();
343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerPacketSourceAddress = newEncapsulatedChannel
344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getPeerPacketSourceAddress();
345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerProtocol = newEncapsulatedChannel.getPeerProtocol();
346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.isReliable()) {
347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                encapsulatedChannel.useCount++;
348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (sipStack.isLoggingEnabled())
349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipStack.getStackLogger()
350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            .logDebug("use count for encapsulated channel"
351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                    + this
352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                    + " "
353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                    + encapsulatedChannel.useCount );
354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.currentState = null;
357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        disableRetransmissionTimer();
359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        disableTimeoutTimer();
360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        eventListeners = Collections.synchronizedSet(new HashSet<SIPTransactionEventListener>());
361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Always add the parent stack as a listener
363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // of this transaction
364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        addEventListener(newParentStack);
365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Sets the request message that this transaction handles.
370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param newOriginalRequest
372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Request being handled.
373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setOriginalRequest(SIPRequest newOriginalRequest) {
375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Branch value of topmost Via header
377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String newBranch;
378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.originalRequest != null
380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                && (!this.originalRequest.getTransactionId().equals(
381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        newOriginalRequest.getTransactionId()))) {
382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.removeTransactionHash(this);
383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // This will be cleared later.
385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.originalRequest = newOriginalRequest;
387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // just cache the control information so the
389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // original request can be released later.
390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.method = newOriginalRequest.getMethod();
391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.from = (From) newOriginalRequest.getFrom();
392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.to = (To) newOriginalRequest.getTo();
393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Save these to avoid concurrent modification exceptions!
394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.toTag = this.to.getTag();
395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.fromTag = this.from.getTag();
396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.callId = (CallID) newOriginalRequest.getCallId();
397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.cSeq = newOriginalRequest.getCSeq().getSeqNumber();
398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.event = (Event) newOriginalRequest.getHeader("Event");
399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.transactionId = newOriginalRequest.getTransactionId();
400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        originalRequest.setTransaction(this);
402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // If the message has an explicit branch value set,
404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        newBranch = ((Via) newOriginalRequest.getViaHeaders().getFirst())
405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getBranch();
406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (newBranch != null) {
407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled())
408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("Setting Branch id : " + newBranch);
409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Override the default branch with the one
411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // set by the message
412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            setBranch(newBranch);
413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled())
416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("Branch id is null - compute TID!"
417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        + newOriginalRequest.encode());
418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            setBranch(newOriginalRequest.getTransactionId());
419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Gets the request being handled by this transaction.
424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return -- the original Request associated with this transaction.
426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public SIPRequest getOriginalRequest() {
428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return originalRequest;
429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the original request but cast to a Request structure.
433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the request that generated this transaction.
435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Request getRequest() {
437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return (Request) originalRequest;
438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Returns a flag stating whether this transaction is for an INVITE request
442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * or not.
443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return -- true if this is an INVITE request, false if not.
445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final boolean isInviteTransaction() {
447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return getMethod().equals(Request.INVITE);
448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Return true if the transaction corresponds to a CANCEL message.
452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return -- true if the transaciton is a CANCEL transaction.
454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final boolean isCancelTransaction() {
456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return getMethod().equals(Request.CANCEL);
457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Return a flag that states if this is a BYE transaction.
461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return true if the transaciton is a BYE transaction.
463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final boolean isByeTransaction() {
465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return getMethod().equals(Request.BYE);
466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
469600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Returns the message channel used for transmitting/receiving messages for
470600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * this transaction. Made public in support of JAIN dual transaction model.
471600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
472600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return Encapsulated MessageChannel.
473600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
474600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
475600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public MessageChannel getMessageChannel() {
476600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel;
477600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
478600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
479600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
480600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Sets the Via header branch parameter used to identify this transaction.
481600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
482600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param newBranch
483600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            New string used as the branch for this transaction.
484600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
485600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final void setBranch(String newBranch) {
486600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        branch = newBranch;
487600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
488600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
489600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
490600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Gets the current setting for the branch parameter of this transaction.
491600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
492600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return Branch parameter for this transaction.
493600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
494600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final String getBranch() {
495600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.branch == null) {
496600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.branch = getOriginalRequest().getTopmostVia().getBranch();
497600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
498600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return branch;
499600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
500600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
501600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
502600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the method of the request used to create this transaction.
503600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
504600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the method of the request for the transaction.
505600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
506600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final String getMethod() {
507600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.method;
508600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
509600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
510600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
511600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the Sequence number of the request used to create the transaction.
512600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
513600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the cseq of the request used to create the transaction.
514600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
515600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final long getCSeq() {
516600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.cSeq;
517600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
518600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
519600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
520600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Changes the state of this transaction.
521600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
522600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param newState
523600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            New state of this transaction.
524600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
525600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setState(TransactionState newState) {
526600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // PATCH submitted by sribeyron
527600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (currentState == TransactionState.COMPLETED) {
528600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (newState != TransactionState.TERMINATED
529600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    && newState != TransactionState.CONFIRMED)
530600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                newState = TransactionState.COMPLETED;
531600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
532600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (currentState == TransactionState.CONFIRMED) {
533600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (newState != TransactionState.TERMINATED)
534600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                newState = TransactionState.CONFIRMED;
535600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
536600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (currentState != TransactionState.TERMINATED)
537600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            currentState = newState;
538600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else
539600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            newState = currentState;
540600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // END OF PATCH
541600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled()) {
542600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug("Transaction:setState " + newState
543600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    + " " + this + " branchID = " + this.getBranch()
544600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    + " isClient = " + (this instanceof SIPClientTransaction));
545600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logStackTrace();
546600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
547600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
548600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
549600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
550600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Gets the current state of this transaction.
551600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
552600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return Current state of this transaction.
553600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
554600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public TransactionState getState() {
555600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.currentState;
556600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
557600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
558600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
559600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Enables retransmission timer events for this transaction to begin in one
560600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * tick.
561600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
562600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected final void enableRetransmissionTimer() {
563600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        enableRetransmissionTimer(1);
564600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
565600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
566600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
567600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Enables retransmission timer events for this transaction to begin after
568600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * the number of ticks passed to this routine.
569600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
570600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param tickCount
571600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Number of ticks before the next retransmission timer event
572600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            occurs.
573600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
574600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected final void enableRetransmissionTimer(int tickCount) {
575600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // For INVITE Client transactions, double interval each time
576600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (isInviteTransaction() && (this instanceof SIPClientTransaction)) {
577600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            retransmissionTimerTicksLeft = tickCount;
578600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else {
579600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // non-INVITE transactions and 3xx-6xx responses are capped at T2
580600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            retransmissionTimerTicksLeft = Math.min(tickCount,
581600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    MAXIMUM_RETRANSMISSION_TICK_COUNT);
582600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
583600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        retransmissionTimerLastTickCount = retransmissionTimerTicksLeft;
584600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
585600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
586600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
587600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Turns off retransmission events for this transaction.
588600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
589600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected final void disableRetransmissionTimer() {
590600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        retransmissionTimerTicksLeft = -1;
591600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
592600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
593600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
594600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Enables a timeout event to occur for this transaction after the number of
595600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * ticks passed to this method.
596600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
597600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param tickCount
598600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Number of ticks before this transaction times out.
599600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
600600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected final void enableTimeoutTimer(int tickCount) {
601600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled())
602600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug("enableTimeoutTimer " + this
603600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    + " tickCount " + tickCount + " currentTickCount = "
604600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    + timeoutTimerTicksLeft);
605600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
606600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        timeoutTimerTicksLeft = tickCount;
607600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
608600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
609600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
610600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Disabled the timeout timer.
611600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
612600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected final void disableTimeoutTimer() {
613600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        timeoutTimerTicksLeft = -1;
614600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
615600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
616600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
617600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Fired after each timer tick. Checks the retransmission and timeout timers
618600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * of this transaction, and fired these events if necessary.
619600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
620600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    final void fireTimer() {
621600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // If the timeout timer is enabled,
622600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
623600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (timeoutTimerTicksLeft != -1) {
624600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Count down the timer, and if it has run out,
625600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (--timeoutTimerTicksLeft == 0) {
626600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Fire the timeout timer
627600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                fireTimeoutTimer();
628600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
629600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
630600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
631600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // If the retransmission timer is enabled,
632600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (retransmissionTimerTicksLeft != -1) {
633600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Count down the timer, and if it has run out,
634600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (--retransmissionTimerTicksLeft == 0) {
635600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Enable this timer to fire again after
636600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // twice the original time
637600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                enableRetransmissionTimer(retransmissionTimerLastTickCount * 2);
638600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Fire the timeout timer
639600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                fireRetransmissionTimer();
640600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
641600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
642600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
643600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
644600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
645600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Tests if this transaction has terminated.
646600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
647600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return Trus if this transaction is terminated, false if not.
648600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
649600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public final boolean isTerminated() {
650600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return getState() == TERMINATED_STATE;
651600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
652600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
653600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getHost() {
654600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel.getHost();
655600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
656600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
657600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getKey() {
658600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel.getKey();
659600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
660600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
661600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int getPort() {
662600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel.getPort();
663600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
664600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
665600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public SIPTransactionStack getSIPStack() {
666600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return (SIPTransactionStack) sipStack;
667600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
668600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
669600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getPeerAddress() {
670600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.peerAddress;
671600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
672600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
673600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int getPeerPort() {
674600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.peerPort;
675600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
676600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
677600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    // @@@ hagai
678600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int getPeerPacketSourcePort() {
679600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.peerPacketSourcePort;
680600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
681600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
682600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public InetAddress getPeerPacketSourceAddress() {
683600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.peerPacketSourceAddress;
684600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
685600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
686600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected InetAddress getPeerInetAddress() {
687600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.peerInetAddress;
688600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
689600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
690600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected String getPeerProtocol() {
691600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.peerProtocol;
692600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
693600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
694600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getTransport() {
695600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel.getTransport();
696600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
697600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
698600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean isReliable() {
699600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel.isReliable();
700600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
701600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
702600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
703600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Returns the Via header for this channel. Gets the Via header of the
704600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * underlying message channel, and adds a branch parameter to it for this
705600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * transaction.
706600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
707600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Via getViaHeader() {
708600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Via header of the encapulated channel
709600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Via channelViaHeader;
710600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
711600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Add the branch parameter to the underlying
712600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // channel's Via header
713600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        channelViaHeader = super.getViaHeader();
714600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
715600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            channelViaHeader.setBranch(branch);
716600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (java.text.ParseException ex) {
717600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
718600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return channelViaHeader;
719600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
720600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
721600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
722600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
723600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Process the message through the transaction and sends it to the SIP peer.
724600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
725600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param messageToSend
726600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Message to send to the SIP peer.
727600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
728600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void sendMessage(SIPMessage messageToSend) throws IOException {
729600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Use the peer address, port and transport
730600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // that was specified when the transaction was
731600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // created. Bug was noted by Bruce Evangelder
732600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // soleo communications.
733600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
734600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            encapsulatedChannel.sendMessage(messageToSend,
735600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    this.peerInetAddress, this.peerPort);
736600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } finally {
737600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.startTransactionTimer();
738600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
739600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
740600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
741600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
742600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Parse the byte array as a message, process it through the transaction,
743600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * and send it to the SIP peer. This is just a placeholder method -- calling
744600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * it will result in an IO exception.
745600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
746600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param messageBytes
747600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Bytes of the message to send.
748600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param receiverAddress
749600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Address of the target peer.
750600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param receiverPort
751600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Network port of the target peer.
752600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
753600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @throws IOException
754600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *             If called.
755600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
756600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void sendMessage(byte[] messageBytes,
757600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            InetAddress receiverAddress, int receiverPort, boolean retry)
758600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws IOException {
759600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        throw new IOException(
760600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                "Cannot send unparsed message through Transaction Channel!");
761600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
762600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
763600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
764600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Adds a new event listener to this transaction.
765600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
766600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param newListener
767600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Listener to add.
768600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
769600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void addEventListener(SIPTransactionEventListener newListener) {
770600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        eventListeners.add(newListener);
771600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
772600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
773600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
774600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Removed an event listener from this transaction.
775600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
776600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param oldListener
777600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            Listener to remove.
778600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
779600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void removeEventListener(SIPTransactionEventListener oldListener) {
780600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        eventListeners.remove(oldListener);
781600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
782600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
783600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
784600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Creates a SIPTransactionErrorEvent and sends it to all of the listeners
785600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * of this transaction. This method also flags the transaction as
786600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * terminated.
787600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
788600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param errorEventID
789600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            ID of the error to raise.
790600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
791600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void raiseErrorEvent(int errorEventID) {
792600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
793600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Error event to send to all listeners
794600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPTransactionErrorEvent newErrorEvent;
795600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Iterator through the list of listeners
796600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Iterator<SIPTransactionEventListener> listenerIterator;
797600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Next listener in the list
798600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPTransactionEventListener nextListener;
799600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
800600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Create the error event
801600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        newErrorEvent = new SIPTransactionErrorEvent(this, errorEventID);
802600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
803600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Loop through all listeners of this transaction
804600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        synchronized (eventListeners) {
805600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            listenerIterator = eventListeners.iterator();
806600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (listenerIterator.hasNext()) {
807600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // Send the event to the next listener
808600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                nextListener = (SIPTransactionEventListener) listenerIterator
809600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        .next();
810600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                nextListener.transactionErrorEvent(newErrorEvent);
811600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
812600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
813600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Clear the event listeners after propagating the error.
814600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Retransmit notifications are just an alert to the
815600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // application (they are not an error).
816600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (errorEventID != SIPTransactionErrorEvent.TIMEOUT_RETRANSMIT) {
817600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            eventListeners.clear();
818600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
819600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Errors always terminate a transaction
820600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.setState(TransactionState.TERMINATED);
821600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
822600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (this instanceof SIPServerTransaction && this.isByeTransaction()
823600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    && this.getDialog() != null)
824600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                ((SIPDialog) this.getDialog())
825600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        .setState(SIPDialog.TERMINATED_STATE);
826600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
827600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
828600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
829600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
830600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * A shortcut way of telling if we are a server transaction.
831600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
832600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected boolean isServerTransaction() {
833600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this instanceof SIPServerTransaction;
834600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
835600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
836600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
837600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Gets the dialog object of this Transaction object. This object returns
838600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * null if no dialog exists. A dialog only exists for a transaction when a
839600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * session is setup between a User Agent Client and a User Agent Server,
840600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * either by a 1xx Provisional Response for an early dialog or a 200OK
841600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Response for a committed dialog.
842600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
843600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the Dialog Object of this Transaction object.
844600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see Dialog
845600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
846600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public abstract Dialog getDialog();
847600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
848600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
849600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * set the dialog object.
850600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
851600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param sipDialog --
852600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            the dialog to set.
853600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param dialogId --
854600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            the dialog id ot associate with the dialog.s
855600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
856600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public abstract void setDialog(SIPDialog sipDialog, String dialogId);
857600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
858600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
859600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Returns the current value of the retransmit timer in milliseconds used to
860600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * retransmit messages over unreliable transports.
861600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
862600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the integer value of the retransmit timer in milliseconds.
863600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
864600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int getRetransmitTimer() {
865600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return SIPTransactionStack.BASE_TIMER_INTERVAL;
866600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
867600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
868600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
869600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the host to assign for an outgoing Request via header.
870600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
871600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getViaHost() {
872600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.getViaHeader().getHost();
873600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
874600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
875600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
876600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
877600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the last response. This is used internally by the implementation.
878600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Dont rely on it.
879600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
880600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the last response received (for client transactions) or sent (for
881600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *         server transactions).
882600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
883600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public SIPResponse getLastResponse() {
884600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.lastResponse;
885600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
886600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
887600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
888600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the JAIN interface response
889600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
890600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Response getResponse() {
891600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return (Response) this.lastResponse;
892600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
893600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
894600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
895600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the transaction Id.
896600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
897600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getTransactionId() {
898600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.transactionId;
899600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
900600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
901600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
902600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Hashcode method for fast hashtable lookup.
903600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
904600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int hashCode() {
905600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.transactionId == null)
906600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return -1;
907600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        else
908600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return this.transactionId.hashCode();
909600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
910600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
911600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
912600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the port to assign for the via header of an outgoing message.
913600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
914600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public int getViaPort() {
915600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.getViaHeader().getPort();
916600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
917600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
918600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
919600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * A method that can be used to test if an incoming request belongs to this
920600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * transction. This does not take the transaction state into account when
921600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * doing the check otherwise it is identical to isMessagePartOfTransaction.
922600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * This is useful for checking if a CANCEL belongs to this transaction.
923600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
924600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param requestToTest
925600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            is the request to test.
926600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return true if the the request belongs to the transaction.
927600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
928600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
929600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean doesCancelMatchTransaction(SIPRequest requestToTest) {
930600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
931600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // List of Via headers in the message to test
932600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ViaList viaHeaders;
933600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Topmost Via header in the list
934600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Via topViaHeader;
935600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Branch code in the topmost Via header
936600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String messageBranch;
937600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Flags whether the select message is part of this transaction
938600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        boolean transactionMatches;
939600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
940600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        transactionMatches = false;
941600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
942600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.getOriginalRequest() == null
943600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                || this.getOriginalRequest().getMethod().equals(Request.CANCEL))
944600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
945600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // Get the topmost Via header and its branch parameter
946600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        viaHeaders = requestToTest.getViaHeaders();
947600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (viaHeaders != null) {
948600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
949600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            topViaHeader = (Via) viaHeaders.getFirst();
950600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            messageBranch = topViaHeader.getBranch();
951600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (messageBranch != null) {
952600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
953600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // If the branch parameter exists but
954600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // does not start with the magic cookie,
955600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (!messageBranch.toLowerCase().startsWith(SIPConstants.BRANCH_MAGIC_COOKIE_LOWER_CASE)) {
956600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
957600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // Flags this as old
958600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // (RFC2543-compatible) client
959600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // version
960600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    messageBranch = null;
961600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
962600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
963600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
964600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
965600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
966600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // If a new branch parameter exists,
967600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (messageBranch != null && this.getBranch() != null) {
968600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
969600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // If the branch equals the branch in
970600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // this message,
971600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (getBranch().equalsIgnoreCase(messageBranch)
972600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && topViaHeader.getSentBy().equals(
973600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                ((Via) getOriginalRequest().getViaHeaders()
974600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                        .getFirst()).getSentBy())) {
975600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transactionMatches = true;
976600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (sipStack.isLoggingEnabled())
977600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        sipStack.getStackLogger().logDebug("returning  true");
978600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
979600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
980600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
981600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // If this is an RFC2543-compliant message,
982600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // If RequestURI, To tag, From tag,
983600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // CallID, CSeq number, and top Via
984600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                // headers are the same,
985600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (sipStack.isLoggingEnabled())
986600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipStack.getStackLogger().logDebug("testing against "
987600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            + getOriginalRequest());
988600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
989600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (getOriginalRequest().getRequestURI().equals(
990600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        requestToTest.getRequestURI())
991600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && getOriginalRequest().getTo().equals(
992600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                requestToTest.getTo())
993600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && getOriginalRequest().getFrom().equals(
994600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                requestToTest.getFrom())
995600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && getOriginalRequest().getCallId().getCallId().equals(
996600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                requestToTest.getCallId().getCallId())
997600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && getOriginalRequest().getCSeq().getSeqNumber() == requestToTest
998600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                .getCSeq().getSeqNumber()
999600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        && topViaHeader.equals(getOriginalRequest()
1000600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                .getViaHeaders().getFirst())) {
1001600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1002600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    transactionMatches = true;
1003600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
1004600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1005600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
1006600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1007600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1008600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1009600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // JvB: Need to pass the CANCEL to the listener! Retransmitted INVITEs
1010600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // set it to false
1011600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (transactionMatches) {
1012600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.setPassToListener();
1013600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1014600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return transactionMatches;
1015600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1016600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1017600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1018600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Sets the value of the retransmit timer to the newly supplied timer value.
1019600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * The retransmit timer is expressed in milliseconds and its default value
1020600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * is 500ms. This method allows the application to change the transaction
1021600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * retransmit behavior for different networks. Take the gateway proxy as an
1022600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * example. The internal intranet is likely to be reatively uncongested and
1023600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * the endpoints will be relatively close. The external network is the
1024600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * general Internet. This functionality allows different retransmit times
1025600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * for either side.
1026600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1027600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param retransmitTimer -
1028600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            the new integer value of the retransmit timer in milliseconds.
1029600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1030600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setRetransmitTimer(int retransmitTimer) {
1031600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1032600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (retransmitTimer <= 0)
1033600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new IllegalArgumentException(
1034600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Retransmit timer must be positive!");
1035600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.transactionTimerStarted.get())
1036600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new IllegalStateException(
1037600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Transaction timer is already started");
1038600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        BASE_TIMER_INTERVAL = retransmitTimer;
1039600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        T4 = 5000 / BASE_TIMER_INTERVAL;
1040600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1041600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        T2 = 4000 / BASE_TIMER_INTERVAL;
1042600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        TIMER_I = T4;
1043600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1044600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        TIMER_K = T4;
1045600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1046600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        TIMER_D = 32000 / BASE_TIMER_INTERVAL;
1047600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1048600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1049600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1050600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1051600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Close the encapsulated channel.
1052600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1053600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void close() {
1054600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.encapsulatedChannel.close();
1055600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled())
1056600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug("Closing " + this.encapsulatedChannel);
1057600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1058600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1059600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1060600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean isSecure() {
1061600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return encapsulatedChannel.isSecure();
1062600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1063600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1064600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public MessageProcessor getMessageProcessor() {
1065600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.encapsulatedChannel.getMessageProcessor();
1066600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1067600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1068600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1069600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Set the application data pointer. This is un-interpreted by the stack.
1070600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * This is provided as a conveniant way of keeping book-keeping data for
1071600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * applications. Note that null clears the application data pointer
1072600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (releases it).
1073600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1074600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param applicationData --
1075600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            application data pointer to set. null clears the applicationd
1076600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *            data pointer.
1077600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1078600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1079600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1080600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setApplicationData(Object applicationData) {
1081600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.applicationData = applicationData;
1082600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1083600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1084600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1085600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Get the application data associated with this transaction.
1086600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1087600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return stored application data.
1088600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1089600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public Object getApplicationData() {
1090600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.applicationData;
1091600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1092600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1093600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1094600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Set the encapsuated channel. The peer inet address and port are set equal
1095600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * to the message channel.
1096600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1097600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setEncapsulatedChannel(MessageChannel messageChannel) {
1098600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.encapsulatedChannel = messageChannel;
1099600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerInetAddress = messageChannel.getPeerInetAddress();
1100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.peerPort = messageChannel.getPeerPort();
1101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Return the SipProvider for which the transaction is assigned.
1105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return the SipProvider for the transaction.
1107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public SipProviderImpl getSipProvider() {
1109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return this.getMessageProcessor().getListeningPoint().getProvider();
1111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Raise an IO Exception event - this is used for reporting asynchronous IO
1115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Exceptions that are attributable to this transaction.
1116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void raiseIOExceptionEvent() {
1119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        setState(TransactionState.TERMINATED);
1120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String host = getPeerAddress();
1121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        int port = getPeerPort();
1122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String transport = getTransport();
1123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        IOExceptionEvent exceptionEvent = new IOExceptionEvent(this, host,
1124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                port, transport);
1125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        getSipProvider().handleEvent(exceptionEvent, this);
1126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * A given tx can process only a single outstanding event at a time. This
1130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * semaphore gaurds re-entrancy to the transaction.
1131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean acquireSem() {
1134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        boolean retval = false;
1135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
1136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.getStackLogger().isLoggingEnabled()) {
1137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("acquireSem [[[[" + this);
1138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logStackTrace();
1139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
1140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            retval = this.semaphore.tryAcquire(1000, TimeUnit.MILLISECONDS);
1141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if ( sipStack.isLoggingEnabled())
1142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug(
1143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "acquireSem() returning : " + retval);
1144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return retval;
1145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (Exception ex) {
1146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logError("Unexpected exception acquiring sem",
1147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ex);
1148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            InternalErrorHandler.handleException(ex);
1149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return false;
1150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } finally {
1151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.isSemaphoreAquired = retval;
1152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Release the transaction semaphore.
1158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void releaseSem() {
1161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
1162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.toListener = false;
1164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.semRelease();
1165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (Exception ex) {
1167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logError("Unexpected exception releasing sem",
1168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ex);
1169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected void semRelease() {
1175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
1176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
1177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("semRelease ]]]]" + this);
1178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logStackTrace();
1179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
1180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.isSemaphoreAquired = false;
1181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            this.semaphore.release();
1182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (Exception ex) {
1184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logError("Unexpected exception releasing sem",
1185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    ex);
1186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Set true to pass the request up to the listener. False otherwise.
1192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public boolean passToListener() {
1196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return toListener;
1197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Set the passToListener flag to true.
1201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setPassToListener() {
1203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (sipStack.isLoggingEnabled()) {
1204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logDebug("setPassToListener()");
1205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
1206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.toListener = true;
1207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Flag to test if the terminated event is delivered.
1212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return
1214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected synchronized boolean testAndSetTransactionTerminatedEvent() {
1216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        boolean retval = !this.terminatedEventDelivered;
1217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.terminatedEventDelivered = true;
1218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return retval;
1219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public String getCipherSuite() throws UnsupportedOperationException {
1222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return null;
1225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return null;
1227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getCipherSuite();
1228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else throw new UnsupportedOperationException("Not a TLS channel");
1229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public java.security.cert.Certificate[] getLocalCertificates() throws UnsupportedOperationException {
1234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang         if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return null;
1237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return null;
1239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getLocalCertificates();
1240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else throw new UnsupportedOperationException("Not a TLS channel");
1241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public java.security.cert.Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
1245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (this.getMessageChannel() instanceof TLSMessageChannel ) {
1246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (  ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener() == null )
1247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return null;
1248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else if ( ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent() == null)
1249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                return null;
1250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            else return ((TLSMessageChannel) this.getMessageChannel()).getHandshakeCompletedListener().getHandshakeCompletedEvent().getPeerCertificates();
1251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } else throw new UnsupportedOperationException("Not a TLS channel");
1252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
1254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Start the timer that runs the transaction state machine.
1258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected abstract void startTransactionTimer();
1262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Tests a message to see if it is part of this transaction.
1265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
1266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return True if the message is part of this transaction, false if not.
1267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public abstract boolean isMessagePartOfTransaction(SIPMessage messageToTest);
1269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * This method is called when this transaction's retransmission timer has
1272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * fired.
1273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected abstract void fireRetransmissionTimer();
1275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
1277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * This method is called when this transaction's timeout timer has fired.
1278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
1279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    protected abstract void fireTimeoutTimer();
1280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
1281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
1282