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