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